Changeset 65782 in webkit
- Timestamp:
- Aug 22, 2010 12:30:48 AM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r65779 r65782 1 2010-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 1 23 2010-08-21 Eric Carlson <eric.carlson@apple.com> 2 24 -
trunk/WebCore/platform/graphics/GraphicsContext.h
r65661 r65782 49 49 #elif PLATFORM(QT) 50 50 #include <QPainter> 51 namespace WebCore { 52 class ContextShadow; 53 } 51 54 typedef QPainter PlatformGraphicsContext; 52 55 #elif PLATFORM(WX) … … 397 400 QPen pen(); 398 401 static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op); 402 ContextShadow* contextShadow(); 399 403 #endif 400 404 -
trunk/WebCore/platform/graphics/qt/ContextShadow.cpp
r65776 r65782 268 268 } 269 269 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()) 270 QPainter* 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()) 286 282 #if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0) 287 283 clipRect = p->clipBoundingRect(); 288 284 #else 289 285 clipRect = p->clipRegion().boundingRect(); 290 286 #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); 320 301 } 321 302 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 317 void 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 59 59 void clear(); 60 60 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); 66 85 86 private: 87 QRect m_layerRect; 88 QImage m_layerImage; 89 QPainter* m_layerPainter; 67 90 }; 68 91 -
trunk/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
r65655 r65782 696 696 m_data->solidColor.setColor(color); 697 697 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); 703 717 } 704 718 … … 740 754 { 741 755 return &m_data->currentPath; 756 } 757 758 ContextShadow* GraphicsContext::contextShadow() 759 { 760 return &m_data->shadow; 742 761 } 743 762
Note: See TracChangeset
for help on using the changeset viewer.