Changeset 74317 in webkit
- Timestamp:
- Dec 18, 2010 10:44:48 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 2 deleted
- 16 edited
- 1 copied
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r74315 r74317 1 2010-12-18 Helder Correia <helder@sencha.com> and Martin Robinson <mrobinson@igalia.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: See strokePath below. 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 * platform/gtk/Skipped: GTK port needs to implement this feature. 33 * platform/gtk/fast/canvas/canvas-scale-fillPath-shadow-expected.txt: Removed. 34 * platform/gtk/fast/canvas/canvas-scale-fillRect-shadow-expected.txt: Removed. 35 * platform/gtk/fast/canvas/canvas-scale-strokePath-shadow-expected.txt: Removed. 36 1 37 2010-12-18 Tony Gentilcore <tonyg@chromium.org> 2 38 -
trunk/LayoutTests/fast/canvas/canvas-scale-strokePath-shadow-expected.txt
r74187 r74317 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
r74316 r74317 1 Ensure correct behavior of canvas with fillRect+shadow after scaling. 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". … … 7 7 PASS d[1] is 0 8 8 PASS d[2] is 0 9 FAIL d[3] should be 255. Was 191. 9 PASS d[3] is 255 10 10 PASS d[0] is 255 11 11 PASS d[1] is 0 12 12 PASS d[2] is 0 13 FAIL d[3] should be 255. Was 191. 13 PASS d[3] is 255 14 14 PASS d[0] is 255 15 15 PASS d[1] is 0 16 16 PASS d[2] is 0 17 FAIL d[3] should be 255. Was 143. 17 PASS d[3] is 255 18 18 PASS d[0] is 255 19 19 PASS d[1] is 0 20 20 PASS d[2] is 0 21 FAIL d[3] is not around 76 (actual: 57) 21 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 FAIL d[3] is not around 76 (actual: 57) 25 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 FAIL d[3] is not around 76 (actual: 57) 29 PASS d[3] is around 127 30 PASS d[0] is 255 31 PASS d[1] is 0 32 PASS d[2] is 0 33 PASS d[3] is around 106 34 PASS d[0] is 255 35 PASS d[1] is 0 36 PASS d[2] is 0 37 PASS d[3] is around 106 30 38 PASS d[0] is 255 31 39 PASS d[1] is 0 … … 35 43 PASS d[1] is 0 36 44 PASS d[2] is 0 37 PASS d[3] is around 8345 PASS d[3] is around 36 38 46 PASS d[0] is 255 39 47 PASS d[1] is 0 40 48 PASS d[2] is 0 41 PASS d[3] is around 5349 PASS d[3] is around 36 42 50 PASS d[0] is 255 43 51 PASS d[1] is 0 44 52 PASS d[2] is 0 45 PASS d[3] is around 24 46 PASS d[0] is 255 47 PASS d[1] is 0 48 PASS d[2] is 0 49 PASS d[3] is around 24 50 PASS d[0] is 255 51 PASS d[1] is 0 52 PASS d[2] is 0 53 PASS d[3] is around 24 53 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
r74187 r74317 20 20 } 21 21 22 if (Math.abs(evalA - b) < 10)22 if (Math.abs(evalA - b) < 20) 23 23 print("PASS " + a + " is around " + b , "green") 24 24 else … … 36 36 ctx.shadowOffsetY = 100; 37 37 ctx.fillStyle = 'rgba(0, 0, 255, 1)'; 38 //ctx.lineWidth = 30;39 38 40 39 ctx.shadowColor = 'rgba(255, 0, 0, 1.0)'; … … 74 73 75 74 // Verify solid shadow. 76 d = ctx.getImageData(20 0, 205, 1, 1).data;75 d = ctx.getImageData(201, 205, 1, 1).data; 77 76 shouldBe('d[0]', '255'); 78 77 shouldBe('d[1]', '0'); … … 80 79 shouldBe('d[3]', '255'); 81 80 82 d = ctx.getImageData(29 9, 295, 1, 1).data;81 d = ctx.getImageData(298, 295, 1, 1).data; 83 82 shouldBe('d[0]', '255'); 84 83 shouldBe('d[1]', '0'); … … 86 85 shouldBe('d[3]', '255'); 87 86 88 d = ctx.getImageData(20 0, 299, 1, 1).data;87 d = ctx.getImageData(201, 298, 1, 1).data; 89 88 shouldBe('d[0]', '255'); 90 89 shouldBe('d[1]', '0'); … … 93 92 94 93 // Verify solid alpha shadow. 95 d = ctx.getImageData(20 0, 405, 1, 1).data;94 d = ctx.getImageData(201, 405, 1, 1).data; 96 95 shouldBe('d[0]', '255'); 97 96 shouldBe('d[1]', '0'); … … 99 98 shouldBeAround('d[3]', '76'); 100 99 101 d = ctx.getImageData(29 9, 405, 1, 1).data;100 d = ctx.getImageData(298, 405, 1, 1).data; 102 101 shouldBe('d[0]', '255'); 103 102 shouldBe('d[1]', '0'); … … 105 104 shouldBeAround('d[3]', '76'); 106 105 107 d = ctx.getImageData(205, 49 9, 1, 1).data;106 d = ctx.getImageData(205, 498, 1, 1).data; 108 107 shouldBe('d[0]', '255'); 109 108 shouldBe('d[1]', '0'); -
trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-fillRect-shadow.js
r74187 r74317 20 20 } 21 21 22 if (Math.abs(evalA - b) < 10)22 if (Math.abs(evalA - b) < 20) 23 23 print("PASS " + a + " is around " + b , "green") 24 24 else … … 53 53 54 54 // Verify solid shadow. 55 d = ctx.getImageData(20 0, 205, 1, 1).data;55 d = ctx.getImageData(201, 205, 1, 1).data; 56 56 shouldBe('d[0]', '255'); 57 57 shouldBe('d[1]', '0'); … … 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'); … … 72 72 73 73 // Verify solid alpha shadow. 74 d = ctx.getImageData(20 0, 405, 1, 1).data;74 d = ctx.getImageData(201, 405, 1, 1).data; 75 75 shouldBe('d[0]', '255'); 76 76 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
r74187 r74317 20 20 } 21 21 22 if (Math.abs(evalA - b) < 10)22 if (Math.abs(evalA - b) < 20) 23 23 print("PASS " + a + " is around " + b , "green") 24 24 else … … 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
r74316 r74317 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 53 56 54 57 // Verify solid shadow. 55 d = ctx.getImageData(20 0, 205, 1, 1).data;58 d = ctx.getImageData(201, 205, 1, 1).data; 56 59 shouldBe('d[0]', '255'); 57 60 shouldBe('d[1]', '0'); … … 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(29 9, 405, 1, 1).data;83 d = ctx.getImageData(298, 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/LayoutTests/platform/gtk/Skipped
r74263 r74317 1026 1026 fast/canvas/canvas-getImageData.html 1027 1027 fast/canvas/canvas-gradient-addStop-error.html 1028 fast/canvas/canvas-transforms-fillRect-shadow.html 1028 1029 fast/canvas/canvas-zoom.html 1029 1030 fast/css/css1_forward_compatible_parsing.html -
trunk/WebCore/ChangeLog
r74316 r74317 1 2010-12-18 Helder Correia <helder@sencha.com> and Martin Robinson <mrobinson@igalia.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-18 Ariya Hidayat <ariya@sencha.com> 2 40 -
trunk/WebCore/platform/graphics/ContextShadow.cpp
r74187 r74317 30 30 #include "ContextShadow.h" 31 31 32 #include "FloatQuad.h" 32 33 #include <wtf/MathExtras.h> 33 34 #include <wtf/Noncopyable.h> … … 42 43 , m_blurDistance(0) 43 44 , m_layerContext(0) 45 , m_shadowsIgnoreTransforms(false) 44 46 { 45 47 } … … 50 52 , m_offset(offset) 51 53 , m_layerContext(0) 54 , m_shadowsIgnoreTransforms(false) 52 55 { 53 56 // See comments in http://webkit.org/b/40793, it seems sensible … … 76 79 m_blurDistance = 0; 77 80 m_offset = FloatSize(); 81 } 82 83 bool ContextShadow::mustUseContextShadow(PlatformContext context) 84 { 85 // We can't avoid ContextShadow, since the shadow has blur. 86 if (m_type == ContextShadow::BlurShadow) 87 return true; 88 // We can avoid ContextShadow and optimize, since we're not drawing on a 89 // canvas and box shadows are affected by the transformation matrix. 90 if (!shadowsIgnoreTransforms()) 91 return false; 92 // We can avoid ContextShadow, since there are no transformations to apply to the canvas. 93 const TransformationMatrix transform(getTransformationMatrixFromContext(context)); 94 if (transform.isIdentity()) 95 return false; 96 // Otherwise, no chance avoiding ContextShadow. 97 return true; 78 98 } 79 99 … … 150 170 } 151 171 152 void ContextShadow::calculateLayerBoundingRect(const FloatRect& layerArea, const IntRect& clipRect) 153 { 154 // Calculate the destination of the blurred layer. 155 FloatRect destinationRect(layerArea); 156 destinationRect.move(m_offset); 157 m_layerRect = enclosingIntRect(destinationRect); 172 IntRect ContextShadow::calculateLayerBoundingRect(const PlatformContext context, const FloatRect& layerArea, const IntRect& clipRect) 173 { 174 // Calculate the destination of the blurred and/or transformed layer. 175 FloatRect layerFloatRect; 176 float inflation = 0; 177 178 const TransformationMatrix transform(getTransformationMatrixFromContext(context)); 179 if (m_shadowsIgnoreTransforms && !transform.isIdentity()) { 180 FloatQuad transformedPolygon = transform.mapQuad(FloatQuad(layerArea)); 181 transformedPolygon.move(m_offset); 182 layerFloatRect = transform.inverse().mapQuad(transformedPolygon).boundingBox(); 183 } else { 184 layerFloatRect = layerArea; 185 layerFloatRect.move(m_offset); 186 } 158 187 159 188 // We expand the area by the blur radius to give extra space for the blur transition. 160 m_layerRect.inflate(m_type == BlurShadow ? m_blurDistance : 0); 161 162 if (!clipRect.contains(m_layerRect)) { 189 if (m_type == BlurShadow) { 190 layerFloatRect.inflate(m_blurDistance); 191 inflation += m_blurDistance; 192 } 193 194 FloatRect unclippedLayerRect = layerFloatRect; 195 196 if (!clipRect.contains(enclosingIntRect(layerFloatRect))) { 163 197 // No need to have the buffer larger than the clip. 164 m_layerRect.intersect(clipRect);198 layerFloatRect.intersect(clipRect); 165 199 166 200 // If we are totally outside the clip region, we aren't painting at all. 167 if ( m_layerRect.isEmpty())168 return ;201 if (layerFloatRect.isEmpty()) 202 return IntRect(0, 0, 0, 0); 169 203 170 204 // We adjust again because the pixels at the borders are still 171 205 // potentially affected by the pixels outside the buffer. 172 if (m_type == BlurShadow) 173 m_layerRect.inflate(m_type == BlurShadow ? m_blurDistance : 0); 174 } 206 if (m_type == BlurShadow) { 207 layerFloatRect.inflate(m_blurDistance); 208 unclippedLayerRect.inflate(m_blurDistance); 209 inflation += m_blurDistance; 210 } 211 } 212 213 const int frameSize = inflation * 2; 214 m_sourceRect = IntRect(0, 0, layerArea.width() + frameSize, layerArea.height() + frameSize); 215 m_layerOrigin = FloatPoint(layerFloatRect.x(), layerFloatRect.y()); 216 217 const FloatPoint m_unclippedLayerOrigin = FloatPoint(unclippedLayerRect.x(), unclippedLayerRect.y()); 218 const FloatSize clippedOut = m_unclippedLayerOrigin - m_layerOrigin; 219 220 // Set the origin as the top left corner of the scratch image, or, in case there's a clipped 221 // out region, set the origin accordingly to the full bounding rect's top-left corner. 222 const float translationX = -layerArea.x() + inflation - fabsf(clippedOut.width()); 223 const float translationY = -layerArea.y() + inflation - fabsf(clippedOut.height()); 224 m_layerContextTranslation = FloatPoint(translationX, translationY); 225 226 return enclosingIntRect(layerFloatRect); 175 227 } 176 228 -
trunk/WebCore/platform/graphics/ContextShadow.h
r74187 r74317 80 80 ContextShadow(const Color&, float radius, const FloatSize& offset); 81 81 82 bool mustUseContextShadow(PlatformContext); 82 83 void clear(); 83 84 … … 107 108 void endShadowLayer(PlatformContext); 108 109 static void purgeScratchBuffer(); 110 static TransformationMatrix getTransformationMatrixFromContext(PlatformContext); 111 112 void setShadowsIgnoreTransforms(bool enable) { m_shadowsIgnoreTransforms = enable; } 113 bool shadowsIgnoreTransforms() const { return m_shadowsIgnoreTransforms; } 109 114 #if PLATFORM(CAIRO) 110 115 void drawRectShadow(GraphicsContext* context, const IntRect& rect, const IntSize& topLeftRadius = IntSize(), const IntSize& topRightRadius = IntSize(), const IntSize& bottomLeftRadius = IntSize(), const IntSize& bottomRightRadius = IntSize()); 111 116 #endif 112 113 117 #if PLATFORM(QT) 114 QPointF offset() { return QPointF(m_offset.width(), m_offset.height()); }118 QPointF offset() const { return QPointF(m_offset.width(), m_offset.height()); } 115 119 #endif 116 120 117 118 121 private: 119 IntRect m_layerRect;120 Platform Image m_layerImage;121 PlatformContext m_layerContext;122 123 // Used for reference when canvas scale(x,y) was called.124 FloatRect m_unscaledLayerRect;122 PlatformImage m_layerImage; // Buffer to where the temporary shadow will be drawn to. 123 PlatformContext m_layerContext; // Context used to paint the shadow to the layer image. 124 FloatRect m_sourceRect; // Sub-rect of m_layerImage that contains the shadow pixels. 125 FloatPoint m_layerOrigin; // Top-left corner of the (possibly clipped) bounding rect to draw the shadow to. 126 FloatPoint m_layerContextTranslation; // Translation to apply to m_layerContext for the shadow to be correctly clipped. 127 bool m_shadowsIgnoreTransforms; 125 128 126 129 void blurLayerImage(unsigned char*, const IntSize& imageSize, int stride); 127 void calculateLayerBoundingRect(const FloatRect& layerArea, const IntRect& clipRect); 130 IntRect calculateLayerBoundingRect(const PlatformContext, const FloatRect& layerArea, const IntRect& clipRect); 131 128 132 #if PLATFORM(CAIRO) 129 133 void drawRectShadowWithoutTiling(PlatformContext context, const IntRect& shadowRect, const IntSize& topLeftRadius, const IntSize& topRightRadius, const IntSize& bottomLeftRadius, const IntSize& bottomRightRadius, float alpha); -
trunk/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
r72987 r74317 83 83 } 84 84 85 TransformationMatrix ContextShadow::getTransformationMatrixFromContext(PlatformContext context) 86 { 87 cairo_matrix_t transform; 88 cairo_get_matrix(context, &transform); 89 return TransformationMatrix(transform.xx, transform.yx, transform.xy, 90 transform.yy, transform.x0, transform.y0); 91 } 92 85 93 PlatformContext ContextShadow::beginShadowLayer(PlatformContext context, const FloatRect& layerArea) 86 94 { 87 m_unscaledLayerRect = layerArea;88 89 95 double x1, x2, y1, y2; 90 96 cairo_clip_extents(context, &x1, &y1, &x2, &y2); 91 calculateLayerBoundingRect(layerArea, IntRect(x1, y1, x2 - x1, y2 - y1));97 IntRect layerRect = calculateLayerBoundingRect(context, layerArea, IntRect(x1, y1, x2 - x1, y2 - y1)); 92 98 93 99 // Don't paint if we are totally outside the clip region. 94 if ( m_layerRect.isEmpty())100 if (layerRect.isEmpty()) 95 101 return 0; 96 102 97 m_layerImage = getScratchBuffer( m_layerRect.size());103 m_layerImage = getScratchBuffer(layerRect.size()); 98 104 m_layerContext = cairo_create(m_layerImage); 99 105 … … 103 109 cairo_set_operator(m_layerContext, CAIRO_OPERATOR_OVER); 104 110 105 cairo_translate(m_layerContext, m_offset.width(), m_offset.height()); 106 cairo_translate(m_layerContext, -m_layerRect.x(), -m_layerRect.y()); 111 cairo_translate(m_layerContext, m_layerContextTranslation.x(), m_layerContextTranslation.y()); 107 112 return m_layerContext; 108 113 } … … 123 128 cairo_save(cr); 124 129 setSourceRGBAFromColor(cr, m_color); 125 126 cairo_matrix_t transform; 127 cairo_get_matrix(cr, &transform); 128 double x = m_layerRect.x(); 129 double y = m_layerRect.y(); 130 131 double xScale = sqrt(transform.xx * transform.xx + transform.yx * transform.yx); 132 double yScale = sqrt(transform.xy * transform.xy + transform.yy * transform.yy); 133 if (xScale != 1 || yScale != 1) { 134 x = m_unscaledLayerRect.x() + m_offset.width() / transform.xx - m_blurDistance; 135 y = m_unscaledLayerRect.y() + m_offset.height() / transform.yy - m_blurDistance; 136 } 137 cairo_mask_surface(cr, m_layerImage, x, y); 130 cairo_mask_surface(cr, m_layerImage, m_layerOrigin.x(), m_layerOrigin.y()); 138 131 cairo_restore(cr); 139 132 … … 236 229 double x1, x2, y1, y2; 237 230 cairo_clip_extents(cr, &x1, &y1, &x2, &y2); 238 calculateLayerBoundingRect( shadowRect, IntRect(x1, y1, x2 - x1, y2 - y1));239 240 if ((shadowTemplateSize.width() * shadowTemplateSize.height() > m_ layerRect.width() * m_layerRect.height())) {231 calculateLayerBoundingRect(cr, shadowRect, IntRect(x1, y1, x2 - x1, y2 - y1)); 232 233 if ((shadowTemplateSize.width() * shadowTemplateSize.height() > m_sourceRect.width() * m_sourceRect.height())) { 241 234 drawRectShadowWithoutTiling(cr, rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, context->getAlpha()); 242 235 return; -
trunk/WebCore/platform/graphics/cairo/FontCairo.cpp
r73284 r74317 73 73 return; 74 74 75 if ( shadow->m_type == ContextShadow::SolidShadow) {75 if (!shadow->mustUseContextShadow(context)) { 76 76 // Optimize non-blurry shadows, by just drawing text without the ContextShadow. 77 77 cairo_save(context); -
trunk/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
r73729 r74317 872 872 } else 873 873 m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height())); 874 875 m_data->shadow.setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms); 874 876 } 875 877 -
trunk/WebCore/platform/graphics/gtk/FontGtk.cpp
r74169 r74317 226 226 227 227 // Optimize non-blurry shadows, by just drawing text without the ContextShadow. 228 if ( shadow->m_type == ContextShadow::SolidShadow) {228 if (!shadow->mustUseContextShadow(context)) { 229 229 cairo_save(context); 230 230 cairo_translate(context, totalOffset.x(), totalOffset.y()); -
trunk/WebCore/platform/graphics/qt/ContextShadowQt.cpp
r74187 r74317 101 101 } 102 102 103 TransformationMatrix ContextShadow::getTransformationMatrixFromContext(PlatformContext context) 104 { 105 const QTransform& transform = context->transform(); 106 return TransformationMatrix(transform.m11(), transform.m12(), transform.m21(), 107 transform.m22(), transform.dx(), transform.dy()); 108 } 109 103 110 Q_GLOBAL_STATIC(ShadowBuffer, scratchShadowBuffer) 104 111 … … 115 122 clipRect = p->transform().inverted().mapRect(p->window()); 116 123 117 m_unscaledLayerRect = layerArea; 118 calculateLayerBoundingRect(layerArea, IntRect(clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height())); 124 // Set m_layerOrigin, m_layerContextTranslation, m_sourceRect. 125 IntRect clip(clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height()); 126 IntRect layerRect = calculateLayerBoundingRect(p, layerArea, clip); 119 127 120 128 // Don't paint if we are totally outside the clip region. 121 if ( m_layerRect.isEmpty())129 if (layerRect.isEmpty()) 122 130 return 0; 123 131 124 132 ShadowBuffer* shadowBuffer = scratchShadowBuffer(); 125 QImage* shadowImage = shadowBuffer->scratchImage( m_layerRect.size());133 QImage* shadowImage = shadowBuffer->scratchImage(layerRect.size()); 126 134 m_layerImage = QImage(*shadowImage); 127 135 … … 129 137 m_layerContext->begin(&m_layerImage); 130 138 m_layerContext->setFont(p->font()); 131 m_layerContext->translate(m_offset.width(), m_offset.height()); 132 133 // The origin is now the top left corner of the scratch image. 134 m_layerContext->translate(-m_layerRect.x(), -m_layerRect.y()); 135 139 m_layerContext->translate(m_layerContextTranslation); 136 140 return m_layerContext; 137 141 } … … 156 160 } 157 161 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); 162 p->drawImage(m_layerOrigin, m_layerImage, m_sourceRect); 165 163 166 164 scratchShadowBuffer()->schedulePurge(); -
trunk/WebCore/platform/graphics/qt/FontQt.cpp
r74169 r74317 147 147 if (ctxShadow->m_type != ContextShadow::NoShadow) { 148 148 ContextShadow* ctxShadow = ctx->contextShadow(); 149 if ( ctxShadow->m_type != ContextShadow::BlurShadow) {149 if (!ctxShadow->mustUseContextShadow(p)) { 150 150 p->save(); 151 151 p->setPen(ctxShadow->m_color); -
trunk/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
r74272 r74317 54 54 55 55 #include <QBrush> 56 #include <QDebug>57 56 #include <QGradient> 58 57 #include <QPaintDevice> … … 512 511 if (m_data->hasShadow()) { 513 512 ContextShadow* shadow = contextShadow(); 514 if (shadow->m_type != ContextShadow::BlurShadow 515 && !m_state.fillPattern && !m_state.fillGradient) 513 if (shadow->mustUseContextShadow(p) || m_state.fillPattern || m_state.fillGradient) 516 514 { 517 QPointF offset = shadow->offset();518 const QTransform& transform = p->transform();519 if (transform.isScaling()) {520 // If scaling is required, find the new coord for shadow origin,521 // so that the relative offset to its shape is kept.522 QPointF translatedOffset(offset.x() / transform.m11(),523 offset.y() / transform.m22());524 platformPath.translate(translatedOffset);525 p->fillPath(platformPath, QColor(shadow->m_color));526 platformPath.translate(-translatedOffset);527 } else {528 p->translate(offset);529 p->fillPath(platformPath, QColor(shadow->m_color));530 p->translate(-offset);531 }532 } else {533 515 QPainter* shadowPainter = shadow->beginShadowLayer(p, platformPath.controlPointRect()); 534 516 if (shadowPainter) { … … 537 519 shadow->endShadowLayer(p); 538 520 } 521 } else { 522 QPointF offset = shadow->offset(); 523 p->translate(offset); 524 p->fillPath(platformPath, QColor(shadow->m_color)); 525 p->translate(-offset); 539 526 } 540 541 527 } 542 528 if (m_state.fillPattern) { … … 563 549 if (m_data->hasShadow()) { 564 550 ContextShadow* shadow = contextShadow(); 565 566 if (shadow->m_type != ContextShadow::BlurShadow 567 && !m_state.strokePattern && !m_state.strokeGradient) 551 if (shadow->mustUseContextShadow(p) || m_state.strokePattern || m_state.strokeGradient) 568 552 { 569 QPen shadowPen(pen);570 shadowPen.setColor(m_data->shadow.m_color);571 QPointF offset = shadow->offset();572 const QTransform& transform = p->transform();573 if (transform.isScaling()) {574 // If scaling is required, find the new coord for shadow origin,575 // so that the relative offset to its shape is kept.576 QPointF translatedOffset(offset.x() / transform.m11(),577 offset.y() / transform.m22());578 platformPath.translate(translatedOffset);579 p->strokePath(platformPath, shadowPen);580 platformPath.translate(-translatedOffset);581 } else {582 p->translate(offset);583 p->strokePath(platformPath, shadowPen);584 p->translate(-offset);585 }586 } else {587 553 FloatRect boundingRect = platformPath.controlPointRect(); 588 554 boundingRect.inflate(pen.miterLimit() + pen.widthF()); … … 593 559 shadow->endShadowLayer(p); 594 560 } 561 } else { 562 QPen shadowPen(pen); 563 shadowPen.setColor(m_data->shadow.m_color); 564 QPointF offset = shadow->offset(); 565 p->translate(offset); 566 p->strokePath(platformPath, shadowPen); 567 p->translate(-offset); 595 568 } 596 569 } … … 712 685 } else { 713 686 if (m_data->hasShadow()) { 714 if (shadow->m _type == ContextShadow::BlurShadow) {687 if (shadow->mustUseContextShadow(p)) { 715 688 QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect); 716 689 if (shadowPainter) { … … 720 693 } 721 694 } else { 722 // Solid rectangle fill with no blur shadow can be done faster723 // without using the shadow layer at all.695 // Solid rectangle fill with no blur shadow or transformations applied can be done 696 // faster without using the shadow layer at all. 724 697 QColor shadowColor = shadow->m_color; 725 698 shadowColor.setAlphaF(shadowColor.alphaF() * p->brush().color().alphaF()); 726 const QTransform& transform = p->transform(); 727 if (transform.isScaling()) { 728 p->fillRect(normalizedRect.translated(static_cast<qreal>(shadow->offset().x()) / transform.m11(), 729 static_cast<qreal>(shadow->offset().y() / transform.m22())), 730 shadowColor); 731 } else 732 p->fillRect(normalizedRect.translated(shadow->offset()), shadowColor); 699 p->fillRect(normalizedRect.translated(shadow->offset()), shadowColor); 733 700 } 734 701 } … … 750 717 if (m_data->hasShadow()) { 751 718 ContextShadow* shadow = contextShadow(); 752 753 if (shadow->m_type != ContextShadow::BlurShadow) { 754 // We do not need any layer for simple shadow. 755 p->fillRect(normalizedRect.translated(shadow->offset()), shadow->m_color); 756 } else { 719 if (shadow->mustUseContextShadow(p)) { 757 720 QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect); 758 721 if (shadowPainter) { … … 761 724 shadow->endShadowLayer(p); 762 725 } 763 } 726 } else 727 p->fillRect(normalizedRect.translated(shadow->offset()), shadow->m_color); 764 728 } 765 729 … … 777 741 if (m_data->hasShadow()) { 778 742 ContextShadow* shadow = contextShadow(); 779 780 if (shadow->m_type != ContextShadow::BlurShadow) { 781 // We do not need any layer for simple shadow. 782 p->translate(m_data->shadow.offset()); 783 p->fillPath(path.platformPath(), QColor(m_data->shadow.m_color)); 784 p->translate(-m_data->shadow.offset()); 785 } else { 743 if (shadow->mustUseContextShadow(p)) { 786 744 QPainter* shadowPainter = shadow->beginShadowLayer(p, rect); 787 745 if (shadowPainter) { … … 790 748 shadow->endShadowLayer(p); 791 749 } 750 } else { 751 p->translate(m_data->shadow.offset()); 752 p->fillPath(path.platformPath(), QColor(m_data->shadow.m_color)); 753 p->translate(-m_data->shadow.offset()); 792 754 } 793 755 } … … 959 921 m_state.shadowOffset = FloatSize(size.width(), -size.height()); 960 922 m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), -size.height())); 961 } else {923 } else 962 924 m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height())); 963 } 925 926 m_data->shadow.setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms); 964 927 } 965 928
Note: See TracChangeset
for help on using the changeset viewer.