Changeset 74040 in webkit
- Timestamp:
- Dec 14, 2010 10:30:34 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 10 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r74039 r74040 1 2010-12-14 Helder Correia <helder@sencha.com> 2 3 Reviewed by Ariya Hidayat. 4 5 [Qt] Canvas shadow offset should not be affected by any transformation 6 https://bugs.webkit.org/show_bug.cgi?id=50422 7 8 On a canvas context, shadows are currently affected by all 9 transformations except scaling. According to the spec: 10 http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#shadows 11 12 "The shadowOffsetX and shadowOffsetY attributes specify the distance 13 that the shadow will be offset in the positive horizontal and positive 14 vertical distance respectively. Their values are in coordinate space 15 units. They are not affected by the current transformation matrix." 16 17 NOTE: this applies only to canvas, not to box shadows. 18 19 Add new test to ensure that shadows are correctly transformed keeping 20 the relative offset to the shape. 21 22 * fast/canvas/canvas-scale-strokePath-shadow-expected.txt: 23 * fast/canvas/canvas-transforms-fillRect-shadow-expected.txt: Added. 24 * fast/canvas/canvas-transforms-fillRect-shadow.html: Added. 25 * fast/canvas/script-tests/canvas-scale-fillPath-shadow.js: 26 * fast/canvas/script-tests/canvas-scale-fillRect-shadow.js: 27 * fast/canvas/script-tests/canvas-scale-strokePath-shadow.js: Now using 28 a lineWidth > 1 to make it easier to test and more fair among all 29 ports, since there can be different transformation smoothness or 30 aliasing settings. 31 * fast/canvas/script-tests/canvas-transforms-fillRect-shadow.js: Added. 32 1 33 2010-12-14 Pavel Feldman <pfeldman@chromium.org> 2 34 -
trunk/LayoutTests/fast/canvas/canvas-scale-strokePath-shadow-expected.txt
r72900 r74040 31 31 PASS d[1] is 0 32 32 PASS d[2] is 0 33 PASS d[3] is around 2033 PASS d[3] is around 149 34 34 PASS d[0] is 255 35 35 PASS d[1] is 0 36 36 PASS d[2] is 0 37 PASS d[3] is around 2237 PASS d[3] is around 116 38 38 PASS d[0] is 255 39 39 PASS d[1] is 0 40 40 PASS d[2] is 0 41 PASS d[3] is around 2841 PASS d[3] is around 115 42 42 PASS d[0] is 255 43 43 PASS d[1] is 0 44 44 PASS d[2] is 0 45 PASS d[3] is around 2245 PASS d[3] is around 70 46 46 PASS d[0] is 255 47 47 PASS d[1] is 0 48 48 PASS d[2] is 0 49 PASS d[3] is around 1549 PASS d[3] is around 70 50 50 PASS d[0] is 255 51 51 PASS d[1] is 0 52 52 PASS d[2] is 0 53 PASS d[3] is around 1753 PASS d[3] is around 69 54 54 PASS successfullyParsed is true 55 55 -
trunk/LayoutTests/fast/canvas/canvas-transforms-fillRect-shadow-expected.txt
r74039 r74040 1 Ensure correct behavior of canvas with path stroke + shadow afterscaling. A blue and red checkered pattern should be displayed.1 Ensure correct behavior of canvas with fillRect+shadow after translation+rotation+scaling. A blue and red checkered pattern should be displayed. 2 2 3 3 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". … … 19 19 PASS d[1] is 0 20 20 PASS d[2] is 0 21 PASS d[3] is around 7621 PASS d[3] is around 127 22 22 PASS d[0] is 255 23 23 PASS d[1] is 0 24 24 PASS d[2] is 0 25 PASS d[3] is around 7625 PASS d[3] is around 127 26 26 PASS d[0] is 255 27 27 PASS d[1] is 0 28 28 PASS d[2] is 0 29 PASS d[3] is around 7629 PASS d[3] is around 127 30 30 PASS d[0] is 255 31 31 PASS d[1] is 0 32 32 PASS d[2] is 0 33 PASS d[3] is around 2033 PASS d[3] is around 106 34 34 PASS d[0] is 255 35 35 PASS d[1] is 0 36 36 PASS d[2] is 0 37 PASS d[3] is around 2237 PASS d[3] is around 106 38 38 PASS d[0] is 255 39 39 PASS d[1] is 0 40 40 PASS d[2] is 0 41 PASS d[3] is around 2841 PASS d[3] is around 83 42 42 PASS d[0] is 255 43 43 PASS d[1] is 0 44 44 PASS d[2] is 0 45 PASS d[3] is around 2245 PASS d[3] is around 36 46 46 PASS d[0] is 255 47 47 PASS d[1] is 0 48 48 PASS d[2] is 0 49 PASS d[3] is around 1549 PASS d[3] is around 36 50 50 PASS d[0] is 255 51 51 PASS d[1] is 0 52 52 PASS d[2] is 0 53 PASS d[3] is around 1753 PASS d[3] is around 36 54 54 PASS successfullyParsed is true 55 55 -
trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-fillPath-shadow.js
r72898 r74040 80 80 shouldBe('d[3]', '255'); 81 81 82 d = ctx.getImageData(29 9, 295, 1, 1).data;82 d = ctx.getImageData(298, 295, 1, 1).data; 83 83 shouldBe('d[0]', '255'); 84 84 shouldBe('d[1]', '0'); … … 86 86 shouldBe('d[3]', '255'); 87 87 88 d = ctx.getImageData(200, 29 9, 1, 1).data;88 d = ctx.getImageData(200, 298, 1, 1).data; 89 89 shouldBe('d[0]', '255'); 90 90 shouldBe('d[1]', '0'); … … 99 99 shouldBeAround('d[3]', '76'); 100 100 101 d = ctx.getImageData(29 9, 405, 1, 1).data;101 d = ctx.getImageData(298, 405, 1, 1).data; 102 102 shouldBe('d[0]', '255'); 103 103 shouldBe('d[1]', '0'); … … 105 105 shouldBeAround('d[3]', '76'); 106 106 107 d = ctx.getImageData(205, 49 9, 1, 1).data;107 d = ctx.getImageData(205, 498, 1, 1).data; 108 108 shouldBe('d[0]', '255'); 109 109 shouldBe('d[1]', '0'); -
trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-fillRect-shadow.js
r72784 r74040 59 59 shouldBe('d[3]', '255'); 60 60 61 d = ctx.getImageData(29 9, 295, 1, 1).data;61 d = ctx.getImageData(298, 298, 1, 1).data; 62 62 shouldBe('d[0]', '255'); 63 63 shouldBe('d[1]', '0'); … … 65 65 shouldBe('d[3]', '255'); 66 66 67 d = ctx.getImageData(20 0, 299, 1, 1).data;67 d = ctx.getImageData(201, 298, 1, 1).data; 68 68 shouldBe('d[0]', '255'); 69 69 shouldBe('d[1]', '0'); … … 78 78 shouldBeAround('d[3]', '76'); 79 79 80 d = ctx.getImageData(29 9, 405, 1, 1).data;80 d = ctx.getImageData(298, 405, 1, 1).data; 81 81 shouldBe('d[0]', '255'); 82 82 shouldBe('d[1]', '0'); … … 84 84 shouldBeAround('d[3]', '76'); 85 85 86 d = ctx.getImageData(205, 49 9, 1, 1).data;86 d = ctx.getImageData(205, 498, 1, 1).data; 87 87 shouldBe('d[0]', '255'); 88 88 shouldBe('d[1]', '0'); -
trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-strokePath-shadow.js
r72900 r74040 36 36 ctx.shadowOffsetY = 100; 37 37 ctx.strokeStyle = 'rgba(0, 0, 255, 1)'; 38 ctx.lineWidth = 5; 38 39 39 40 ctx.shadowColor = 'rgba(255, 0, 0, 1.0)'; … … 77 78 78 79 // Verify solid shadow. 79 d = ctx.getImageData(2 00, 205, 1, 1).data;80 d = ctx.getImageData(250, 200, 1, 1).data; 80 81 shouldBe('d[0]', '255'); 81 82 shouldBe('d[1]', '0'); … … 83 84 shouldBe('d[3]', '255'); 84 85 85 d = ctx.getImageData( 299, 295, 1, 1).data;86 d = ctx.getImageData(300, 290, 1, 1).data; 86 87 shouldBe('d[0]', '255'); 87 88 shouldBe('d[1]', '0'); … … 89 90 shouldBe('d[3]', '255'); 90 91 91 d = ctx.getImageData(20 1, 299, 1, 1).data;92 d = ctx.getImageData(200, 250, 1, 1).data; 92 93 shouldBe('d[0]', '255'); 93 94 shouldBe('d[1]', '0'); … … 96 97 97 98 // Verify solid alpha shadow. 98 d = ctx.getImageData(20 0, 405, 1, 1).data;99 d = ctx.getImageData(201, 405, 1, 1).data; 99 100 shouldBe('d[0]', '255'); 100 101 shouldBe('d[1]', '0'); … … 102 103 shouldBeAround('d[3]', '76'); 103 104 104 d = ctx.getImageData(2 99, 405, 1, 1).data;105 d = ctx.getImageData(201, 500, 1, 1).data; 105 106 shouldBe('d[0]', '255'); 106 107 shouldBe('d[1]', '0'); … … 108 109 shouldBeAround('d[3]', '76'); 109 110 110 d = ctx.getImageData( 205, 499, 1, 1).data;111 d = ctx.getImageData(300, 499, 1, 1).data; 111 112 shouldBe('d[0]', '255'); 112 113 shouldBe('d[1]', '0'); … … 115 116 116 117 // Verify blurry shadow. 117 d = ctx.getImageData( 394, 208, 1, 1).data;118 d = ctx.getImageData(404, 210, 1, 1).data; 118 119 shouldBe('d[0]', '255'); 119 120 shouldBe('d[1]', '0'); 120 121 shouldBe('d[2]', '0'); 121 shouldBeAround('d[3]', ' 20');122 shouldBeAround('d[3]', '149'); 122 123 123 d = ctx.getImageData(50 3, 301, 1, 1).data;124 d = ctx.getImageData(505, 250, 1, 1).data; 124 125 shouldBe('d[0]', '255'); 125 126 shouldBe('d[1]', '0'); 126 127 shouldBe('d[2]', '0'); 127 shouldBeAround('d[3]', ' 22');128 shouldBeAround('d[3]', '116'); 128 129 129 d = ctx.getImageData( 504, 250, 1, 1).data;130 d = ctx.getImageData(450, 205, 1, 1).data; 130 131 shouldBe('d[0]', '255'); 131 132 shouldBe('d[1]', '0'); 132 133 shouldBe('d[2]', '0'); 133 shouldBeAround('d[3]', ' 28');134 shouldBeAround('d[3]', '115'); 134 135 135 136 // Verify blurry alpha shadow. 136 d = ctx.getImageData( 405, 405, 1, 1).data;137 d = ctx.getImageData(505, 450, 1, 1).data; 137 138 shouldBe('d[0]', '255'); 138 139 shouldBe('d[1]', '0'); 139 140 shouldBe('d[2]', '0'); 140 shouldBeAround('d[3]', ' 22');141 shouldBeAround('d[3]', '70'); 141 142 142 d = ctx.getImageData( 415, 495, 1, 1).data;143 d = ctx.getImageData(505, 450, 1, 1).data; 143 144 shouldBe('d[0]', '255'); 144 145 shouldBe('d[1]', '0'); 145 146 shouldBe('d[2]', '0'); 146 shouldBeAround('d[3]', ' 15');147 shouldBeAround('d[3]', '70'); 147 148 148 d = ctx.getImageData(450, 504, 1, 1).data;149 d = ctx.getImageData(450, 405, 1, 1).data; 149 150 shouldBe('d[0]', '255'); 150 151 shouldBe('d[1]', '0'); 151 152 shouldBe('d[2]', '0'); 152 shouldBeAround('d[3]', ' 17');153 shouldBeAround('d[3]', '69'); 153 154 154 155 var successfullyParsed = true; -
trunk/LayoutTests/fast/canvas/script-tests/canvas-transforms-fillRect-shadow.js
r74039 r74040 1 description("Ensure correct behavior of canvas with fillRect+shadow after scaling. A blue and red checkered pattern should be displayed.");1 description("Ensure correct behavior of canvas with fillRect+shadow after translation+rotation+scaling. A blue and red checkered pattern should be displayed."); 2 2 3 3 function print(message, color) … … 28 28 var canvas = document.createElement('canvas'); 29 29 document.body.appendChild(canvas); 30 canvas.setAttribute('width', ' 1000');31 canvas.setAttribute('height', ' 1000');30 canvas.setAttribute('width', '600'); 31 canvas.setAttribute('height', '600'); 32 32 var ctx = canvas.getContext('2d'); 33 33 34 ctx. scale(2, 2);34 ctx.fillStyle = 'rgba(0, 0, 255, 1.0)'; 35 35 ctx.shadowOffsetX = 100; 36 36 ctx.shadowOffsetY = 100; 37 ctx.fillStyle = 'rgba(0, 0, 255, 1)'; 37 38 ctx.translate(-100, -100); 39 ctx.rotate(Math.PI/2); 40 ctx.scale(2, 2); 38 41 39 42 ctx.shadowColor = 'rgba(255, 0, 0, 1.0)'; 40 ctx.fillRect( 50,50, 50, 50);43 ctx.fillRect(100, -150, 50, 50); 41 44 42 ctx.shadowColor = 'rgba(255, 0, 0, 0. 3)';43 ctx.fillRect( 50,150, 50, 50);45 ctx.shadowColor = 'rgba(255, 0, 0, 0.5)'; 46 ctx.fillRect(200, -150, 50, 50); 44 47 48 ctx.shadowBlur = 5; 45 49 ctx.shadowColor = 'rgba(255, 0, 0, 1.0)'; 46 ctx.shadowBlur = 10; 47 ctx.fillRect(150, 50, 50, 50); 50 ctx.fillRect(100, -250, 50, 50); 48 51 49 ctx.shadowColor = 'rgba(255, 0, 0, 0. 3)';50 ctx.fillRect( 150, 150, 50, 50);52 ctx.shadowColor = 'rgba(255, 0, 0, 0.5)'; 53 ctx.fillRect(200, -250, 50, 50); 51 54 52 55 var d; // imageData.data … … 59 62 shouldBe('d[3]', '255'); 60 63 61 d = ctx.getImageData(29 9, 295, 1, 1).data;64 d = ctx.getImageData(298, 298, 1, 1).data; 62 65 shouldBe('d[0]', '255'); 63 66 shouldBe('d[1]', '0'); … … 65 68 shouldBe('d[3]', '255'); 66 69 67 d = ctx.getImageData(20 0, 299, 1, 1).data;70 d = ctx.getImageData(201, 298, 1, 1).data; 68 71 shouldBe('d[0]', '255'); 69 72 shouldBe('d[1]', '0'); … … 72 75 73 76 // Verify solid alpha shadow. 74 d = ctx.getImageData(20 0, 405, 1, 1).data;77 d = ctx.getImageData(201, 401, 1, 1).data; 75 78 shouldBe('d[0]', '255'); 76 79 shouldBe('d[1]', '0'); 77 80 shouldBe('d[2]', '0'); 78 shouldBeAround('d[3]', ' 76');81 shouldBeAround('d[3]', '127'); 79 82 80 d = ctx.getImageData(299, 4 05, 1, 1).data;83 d = ctx.getImageData(299, 450, 1, 1).data; 81 84 shouldBe('d[0]', '255'); 82 85 shouldBe('d[1]', '0'); 83 86 shouldBe('d[2]', '0'); 84 shouldBeAround('d[3]', ' 76');87 shouldBeAround('d[3]', '127'); 85 88 86 d = ctx.getImageData(205, 49 9, 1, 1).data;89 d = ctx.getImageData(205, 498, 1, 1).data; 87 90 shouldBe('d[0]', '255'); 88 91 shouldBe('d[1]', '0'); 89 92 shouldBe('d[2]', '0'); 90 shouldBeAround('d[3]', ' 76');93 shouldBeAround('d[3]', '127'); 91 94 92 95 // Verify blurry shadow. 93 d = ctx.getImageData(398, 205, 1, 1).data; 96 d = ctx.getImageData(399, 205, 1, 1).data; 97 shouldBe('d[0]', '255'); 98 shouldBe('d[1]', '0'); 99 shouldBe('d[2]', '0'); 100 shouldBeAround('d[3]', '106'); 101 102 d = ctx.getImageData(500, 205, 1, 1).data; 103 shouldBe('d[0]', '255'); 104 shouldBe('d[1]', '0'); 105 shouldBe('d[2]', '0'); 106 shouldBeAround('d[3]', '106'); 107 108 d = ctx.getImageData(499, 299, 1, 1).data; 94 109 shouldBe('d[0]', '255'); 95 110 shouldBe('d[1]', '0'); 96 111 shouldBe('d[2]', '0'); 97 112 shouldBeAround('d[3]', '83'); 98 99 d = ctx.getImageData(501, 205, 1, 1).data;100 shouldBe('d[0]', '255');101 shouldBe('d[1]', '0');102 shouldBe('d[2]', '0');103 shouldBeAround('d[3]', '83');104 105 d = ctx.getImageData(500, 300, 1, 1).data;106 shouldBe('d[0]', '255');107 shouldBe('d[1]', '0');108 shouldBe('d[2]', '0');109 shouldBeAround('d[3]', '53');110 113 111 114 // Verify blurry alpha shadow. … … 114 117 shouldBe('d[1]', '0'); 115 118 shouldBe('d[2]', '0'); 116 shouldBeAround('d[3]', ' 24');119 shouldBeAround('d[3]', '36'); 117 120 118 121 d = ctx.getImageData(405, 501, 1, 1).data; … … 120 123 shouldBe('d[1]', '0'); 121 124 shouldBe('d[2]', '0'); 122 shouldBeAround('d[3]', ' 24');125 shouldBeAround('d[3]', '36'); 123 126 124 127 d = ctx.getImageData(405, 501, 1, 1).data; … … 126 129 shouldBe('d[1]', '0'); 127 130 shouldBe('d[2]', '0'); 128 shouldBeAround('d[3]', ' 24');131 shouldBeAround('d[3]', '36'); 129 132 130 133 var successfullyParsed = true; -
trunk/WebCore/ChangeLog
r74038 r74040 1 2010-12-14 Helder Correia <helder@sencha.com> 2 3 Reviewed by Ariya Hidayat. 4 5 [Qt] Canvas shadow offset should not be affected by any transformation 6 https://bugs.webkit.org/show_bug.cgi?id=50422 7 8 On a canvas context, shadows are currently affected by all 9 transformations except scaling. According to the spec: 10 http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#shadows 11 12 "The shadowOffsetX and shadowOffsetY attributes specify the distance 13 that the shadow will be offset in the positive horizontal and positive 14 vertical distance respectively. Their values are in coordinate space 15 units. They are not affected by the current transformation matrix." 16 17 NOTE: this applies only to canvas, not to box shadows. 18 19 Test: fast/canvas/canvas-transforms-fillRect-shadow.html 20 21 * platform/graphics/ContextShadow.cpp: 22 (WebCore::ContextShadow::ContextShadow): 23 (WebCore::ContextShadow::calculateLayerBoundingRect): 24 * platform/graphics/ContextShadow.h: 25 (WebCore::ContextShadow::setShadowsIgnoreTransforms): 26 (WebCore::ContextShadow::shadowsIgnoreTransforms): 27 (WebCore::ContextShadow::offset): 28 * platform/graphics/qt/ContextShadowQt.cpp: 29 (WebCore::ContextShadow::beginShadowLayer): 30 (WebCore::ContextShadow::endShadowLayer): 31 * platform/graphics/qt/GraphicsContextQt.cpp: 32 (WebCore::mustUseContextShadow): 33 (WebCore::GraphicsContext::fillPath): 34 (WebCore::GraphicsContext::strokePath): 35 (WebCore::GraphicsContext::fillRect): 36 (WebCore::GraphicsContext::fillRoundedRect): 37 (WebCore::GraphicsContext::setPlatformShadow): 38 1 39 2010-12-14 Alexander Pavlov <apavlov@chromium.org> 2 40 -
trunk/WebCore/platform/graphics/ContextShadow.cpp
r69701 r74040 42 42 , m_blurDistance(0) 43 43 , m_layerContext(0) 44 , m_shadowsIgnoreTransforms(false) 44 45 { 45 46 } … … 50 51 , m_offset(offset) 51 52 , m_layerContext(0) 53 , m_shadowsIgnoreTransforms(false) 52 54 { 53 55 // See comments in http://webkit.org/b/40793, it seems sensible … … 150 152 } 151 153 154 #if PLATFORM(QT) 155 IntRect ContextShadow::calculateLayerBoundingRect(const PlatformContext p, const FloatRect& layerArea, const IntRect& clipRect) 156 { 157 // Calculate the destination of the blurred and/or transformed layer. 158 FloatRect layerFloatRect; 159 float inflation = 0; 160 161 const QTransform transform = p->transform(); 162 if (m_shadowsIgnoreTransforms && !transform.isIdentity()) { 163 QPolygonF transformedPolygon = transform.map(QPolygonF(layerArea)); 164 transformedPolygon.translate(offset()); 165 layerFloatRect = transform.inverted().map(transformedPolygon).boundingRect(); 166 } else { 167 layerFloatRect = layerArea; 168 layerFloatRect.move(m_offset); 169 } 170 171 // We expand the area by the blur radius to give extra space for the blur transition. 172 if (m_type == BlurShadow) { 173 layerFloatRect.inflate(m_blurDistance); 174 inflation += m_blurDistance; 175 } 176 177 if (!clipRect.contains(enclosingIntRect(layerFloatRect))) { 178 // No need to have the buffer larger than the clip. 179 layerFloatRect.intersect(clipRect); 180 181 // If we are totally outside the clip region, we aren't painting at all. 182 if (layerFloatRect.isEmpty()) 183 return IntRect(0, 0, 0, 0); 184 185 // We adjust again because the pixels at the borders are still 186 // potentially affected by the pixels outside the buffer. 187 if (m_type == BlurShadow) { 188 layerFloatRect.inflate(m_blurDistance); 189 inflation += m_blurDistance; 190 } 191 } 192 193 const int frameSize = inflation * 2; 194 m_sourceRect = IntRect(0, 0, layerArea.width() + frameSize, layerArea.height() + frameSize); 195 m_layerOrigin = FloatPoint(layerFloatRect.x(), layerFloatRect.y()); 196 return enclosingIntRect(layerFloatRect); 197 } 198 #endif 199 200 #if PLATFORM(CAIRO) 152 201 void ContextShadow::calculateLayerBoundingRect(const FloatRect& layerArea, const IntRect& clipRect) 153 202 { … … 174 223 } 175 224 } 225 #endif 176 226 177 227 } // namespace WebCore -
trunk/WebCore/platform/graphics/ContextShadow.h
r72987 r74040 107 107 void endShadowLayer(PlatformContext); 108 108 static void purgeScratchBuffer(); 109 void setShadowsIgnoreTransforms(bool enable) { m_shadowsIgnoreTransforms = enable; } 110 bool shadowsIgnoreTransforms() const { return m_shadowsIgnoreTransforms; } 109 111 #if PLATFORM(CAIRO) 110 112 void drawRectShadow(GraphicsContext* context, const IntRect& rect, const IntSize& topLeftRadius = IntSize(), const IntSize& topRightRadius = IntSize(), const IntSize& bottomLeftRadius = IntSize(), const IntSize& bottomRightRadius = IntSize()); 111 113 #endif 112 113 114 #if PLATFORM(QT) 114 QPointF offset() { return QPointF(m_offset.width(), m_offset.height()); }115 QPointF offset() const { return QPointF(m_offset.width(), m_offset.height()); } 115 116 #endif 116 117 117 118 118 119 private: 120 // Buffer to where the temporary shadow will be drawn to. 121 PlatformImage m_layerImage; 122 // Context used to paint the shadow to the layer image. 123 PlatformContext m_layerContext; 124 #if PLATFORM(QT) 125 // Sub-rect of m_layerImage that contains the shadow pixels. 126 FloatRect m_sourceRect; 127 // Top-left corner of the bounding rect where the shadow image needs to be drawn. 128 FloatPoint m_layerOrigin; 129 #endif 130 #if PLATFORM(CAIRO) 131 // Enclosing int rect where shadow needs to be drawn to using the layer context. 119 132 IntRect m_layerRect; 120 PlatformImage m_layerImage;121 PlatformContext m_layerContext;122 123 133 // Used for reference when canvas scale(x,y) was called. 124 134 FloatRect m_unscaledLayerRect; 135 #endif 136 bool m_shadowsIgnoreTransforms; 125 137 126 138 void blurLayerImage(unsigned char*, const IntSize& imageSize, int stride); 139 #if PLATFORM(CAIRO) 127 140 void calculateLayerBoundingRect(const FloatRect& layerArea, const IntRect& clipRect); 128 #if PLATFORM(CAIRO)129 141 void drawRectShadowWithoutTiling(PlatformContext context, const IntRect& shadowRect, const IntSize& topLeftRadius, const IntSize& topRightRadius, const IntSize& bottomLeftRadius, const IntSize& bottomRightRadius, float alpha); 142 #else 143 IntRect calculateLayerBoundingRect(const PlatformContext, const FloatRect& layerArea, const IntRect& clipRect); 130 144 #endif 131 145 }; -
trunk/WebCore/platform/graphics/qt/ContextShadowQt.cpp
r72784 r74040 115 115 clipRect = p->transform().inverted().mapRect(p->window()); 116 116 117 m_unscaledLayerRect = layerArea; 118 calculateLayerBoundingRect(layerArea, IntRect(clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height())); 117 // Set m_layerOrigin and m_sourceRect. 118 IntRect clip(clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height()); 119 IntRect layerRect = calculateLayerBoundingRect(p, layerArea, clip); 119 120 120 121 // Don't paint if we are totally outside the clip region. 121 if ( m_layerRect.isEmpty())122 if (layerRect.isEmpty()) 122 123 return 0; 123 124 124 125 ShadowBuffer* shadowBuffer = scratchShadowBuffer(); 125 QImage* shadowImage = shadowBuffer->scratchImage( m_layerRect.size());126 QImage* shadowImage = shadowBuffer->scratchImage(layerRect.size()); 126 127 m_layerImage = QImage(*shadowImage); 127 128 … … 129 130 m_layerContext->begin(&m_layerImage); 130 131 m_layerContext->setFont(p->font()); 131 m_layerContext->translate(m_offset.width(), m_offset.height());132 132 133 // The origin is now the top left corner of the scratch image. 134 m_layerContext->translate(-m_layerRect.x(), -m_layerRect.y()); 133 // Set the origin as the top left corner of the scratch image. 134 const int frameSize = (m_sourceRect.width() - layerArea.width()) / 2; 135 m_layerContext->translate(-layerArea.x() + frameSize, -layerArea.y() + frameSize); 135 136 136 137 return m_layerContext; … … 156 157 } 157 158 158 const QTransform transform = p->transform(); 159 if (transform.isScaling()) { 160 qreal x = m_unscaledLayerRect.x() + m_offset.width() / transform.m11() - m_blurDistance; 161 qreal y = m_unscaledLayerRect.y() + m_offset.height() / transform.m22() - m_blurDistance; 162 p->drawImage(QPointF(x, y), m_layerImage); 163 } else 164 p->drawImage(m_layerRect.topLeft(), m_layerImage); 159 p->drawImage(m_layerOrigin, m_layerImage, m_sourceRect); 165 160 166 161 scratchShadowBuffer()->schedulePurge(); -
trunk/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
r73729 r74040 54 54 55 55 #include <QBrush> 56 #include <QDebug>57 56 #include <QGradient> 58 57 #include <QPaintDevice> … … 176 175 } 177 176 177 static inline bool mustUseContextShadow(QPainter* painter, ContextShadow* shadow) 178 { 179 if (shadow->m_type == ContextShadow::BlurShadow) 180 // We can't avoid ContextShadow, since the shadow has blur. 181 return true; 182 if (!shadow->shadowsIgnoreTransforms()) 183 // We can avoid ContextShadow and optimize, since we're not drawing on a canvas and box 184 // shadows are affected by the transformation matrix. 185 return false; 186 if (painter->transform().isIdentity()) 187 // We can avoid ContextShadow, since there are no transformations to apply to the canvas. 188 return false; 189 // Otherwise, no chance avoiding ContextShadow. 190 return true; 191 } 192 178 193 class GraphicsContextPlatformPrivate : public Noncopyable { 179 194 public: … … 507 522 if (m_data->hasShadow()) { 508 523 ContextShadow* shadow = contextShadow(); 509 if (shadow->m_type != ContextShadow::BlurShadow 510 && !m_state.fillPattern && !m_state.fillGradient) 524 if (mustUseContextShadow(p, shadow) || m_state.fillPattern || m_state.fillGradient) 511 525 { 512 QPointF offset = shadow->offset();513 const QTransform& transform = p->transform();514 if (transform.isScaling()) {515 // If scaling is required, find the new coord for shadow origin,516 // so that the relative offset to its shape is kept.517 QPointF translatedOffset(offset.x() / transform.m11(),518 offset.y() / transform.m22());519 platformPath.translate(translatedOffset);520 p->fillPath(platformPath, QColor(shadow->m_color));521 platformPath.translate(-translatedOffset);522 } else {523 p->translate(offset);524 p->fillPath(platformPath, QColor(shadow->m_color));525 p->translate(-offset);526 }527 } else {528 526 QPainter* shadowPainter = shadow->beginShadowLayer(p, platformPath.controlPointRect()); 529 527 if (shadowPainter) { … … 532 530 shadow->endShadowLayer(p); 533 531 } 532 } else { 533 QPointF offset = shadow->offset(); 534 p->translate(offset); 535 p->fillPath(platformPath, QColor(shadow->m_color)); 536 p->translate(-offset); 534 537 } 535 536 538 } 537 539 if (m_state.fillPattern) { … … 558 560 if (m_data->hasShadow()) { 559 561 ContextShadow* shadow = contextShadow(); 560 561 if (shadow->m_type != ContextShadow::BlurShadow 562 && !m_state.strokePattern && !m_state.strokeGradient) 562 if (mustUseContextShadow(p, shadow) || m_state.strokePattern || m_state.strokeGradient) 563 563 { 564 QPen shadowPen(pen);565 shadowPen.setColor(m_data->shadow.m_color);566 QPointF offset = shadow->offset();567 const QTransform& transform = p->transform();568 if (transform.isScaling()) {569 // If scaling is required, find the new coord for shadow origin,570 // so that the relative offset to its shape is kept.571 QPointF translatedOffset(offset.x() / transform.m11(),572 offset.y() / transform.m22());573 platformPath.translate(translatedOffset);574 p->strokePath(platformPath, shadowPen);575 platformPath.translate(-translatedOffset);576 } else {577 p->translate(offset);578 p->strokePath(platformPath, shadowPen);579 p->translate(-offset);580 }581 } else {582 564 FloatRect boundingRect = platformPath.controlPointRect(); 583 565 boundingRect.inflate(pen.miterLimit() + pen.widthF()); … … 588 570 shadow->endShadowLayer(p); 589 571 } 572 } else { 573 QPen shadowPen(pen); 574 shadowPen.setColor(m_data->shadow.m_color); 575 QPointF offset = shadow->offset(); 576 p->translate(offset); 577 p->strokePath(platformPath, shadowPen); 578 p->translate(-offset); 590 579 } 591 580 } … … 707 696 } else { 708 697 if (m_data->hasShadow()) { 709 if ( shadow->m_type == ContextShadow::BlurShadow) {698 if (mustUseContextShadow(p, shadow)) { 710 699 QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect); 711 700 if (shadowPainter) { … … 715 704 } 716 705 } else { 717 // Solid rectangle fill with no blur shadow can be done faster718 // without using the shadow layer at all.706 // Solid rectangle fill with no blur shadow or transformations applied can be done 707 // faster without using the shadow layer at all. 719 708 QColor shadowColor = shadow->m_color; 720 709 shadowColor.setAlphaF(shadowColor.alphaF() * p->brush().color().alphaF()); 721 const QTransform& transform = p->transform(); 722 if (transform.isScaling()) { 723 p->fillRect(normalizedRect.translated(static_cast<qreal>(shadow->offset().x()) / transform.m11(), 724 static_cast<qreal>(shadow->offset().y() / transform.m22())), 725 shadowColor); 726 } else 727 p->fillRect(normalizedRect.translated(shadow->offset()), shadowColor); 710 p->fillRect(normalizedRect.translated(shadow->offset()), shadowColor); 728 711 } 729 712 } … … 745 728 if (m_data->hasShadow()) { 746 729 ContextShadow* shadow = contextShadow(); 747 748 if (shadow->m_type != ContextShadow::BlurShadow) { 749 // We do not need any layer for simple shadow. 750 p->fillRect(normalizedRect.translated(shadow->offset()), shadow->m_color); 751 } else { 730 if (mustUseContextShadow(p, shadow)) { 752 731 QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect); 753 732 if (shadowPainter) { … … 756 735 shadow->endShadowLayer(p); 757 736 } 758 } 737 } else 738 p->fillRect(normalizedRect.translated(shadow->offset()), shadow->m_color); 759 739 } 760 740 … … 772 752 if (m_data->hasShadow()) { 773 753 ContextShadow* shadow = contextShadow(); 774 775 if (shadow->m_type != ContextShadow::BlurShadow) { 776 // We do not need any layer for simple shadow. 777 p->translate(m_data->shadow.offset()); 778 p->fillPath(path.platformPath(), QColor(m_data->shadow.m_color)); 779 p->translate(-m_data->shadow.offset()); 780 } else { 754 if (mustUseContextShadow(p, shadow)) { 781 755 QPainter* shadowPainter = shadow->beginShadowLayer(p, rect); 782 756 if (shadowPainter) { … … 785 759 shadow->endShadowLayer(p); 786 760 } 761 } else { 762 p->translate(m_data->shadow.offset()); 763 p->fillPath(path.platformPath(), QColor(m_data->shadow.m_color)); 764 p->translate(-m_data->shadow.offset()); 787 765 } 788 766 } … … 972 950 m_state.shadowOffset = FloatSize(size.width(), -size.height()); 973 951 m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), -size.height())); 974 } else {952 } else 975 953 m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height())); 976 } 954 955 m_data->shadow.setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms); 977 956 } 978 957
Note: See TracChangeset
for help on using the changeset viewer.