Changeset 74317 in webkit


Ignore:
Timestamp:
Dec 18, 2010 10:44:48 AM (13 years ago)
Author:
Martin Robinson
Message:

2010-12-18 Helder Correia <helder@sencha.com> and Martin Robinson <mrobinson@igalia.com>

Reviewed by Ariya Hidayat.

[Qt] Canvas shadow offset should not be affected by any transformation
https://bugs.webkit.org/show_bug.cgi?id=50422

On a canvas context, shadows are currently affected by all
transformations except scaling. According to the spec:
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#shadows

"The shadowOffsetX and shadowOffsetY attributes specify the distance
that the shadow will be offset in the positive horizontal and positive
vertical distance respectively. Their values are in coordinate space
units. They are not affected by the current transformation matrix."

NOTE: this applies only to canvas, not to box shadows.

Add new test to ensure that shadows are correctly transformed keeping
the relative offset to the shape.

  • fast/canvas/canvas-scale-strokePath-shadow-expected.txt: See strokePath below.
  • fast/canvas/canvas-transforms-fillRect-shadow-expected.txt: Added.
  • fast/canvas/canvas-transforms-fillRect-shadow.html: Added.
  • fast/canvas/script-tests/canvas-scale-fillPath-shadow.js:
  • fast/canvas/script-tests/canvas-scale-fillRect-shadow.js:
  • fast/canvas/script-tests/canvas-scale-strokePath-shadow.js: Now using a lineWidth > 1 to make it easier to test and more fair among all ports, since there can be different transformation smoothness or aliasing settings.
  • fast/canvas/script-tests/canvas-transforms-fillRect-shadow.js: Added.
  • platform/gtk/Skipped: GTK port needs to implement this feature.
  • platform/gtk/fast/canvas/canvas-scale-fillPath-shadow-expected.txt: Removed.
  • platform/gtk/fast/canvas/canvas-scale-fillRect-shadow-expected.txt: Removed.
  • platform/gtk/fast/canvas/canvas-scale-strokePath-shadow-expected.txt: Removed.

2010-12-18 Helder Correia <helder@sencha.com> and Martin Robinson <mrobinson@igalia.com>

Reviewed by Ariya Hidayat.

[Qt] Canvas shadow offset should not be affected by any transformation
https://bugs.webkit.org/show_bug.cgi?id=50422

On a canvas context, shadows are currently affected by all
transformations except scaling. According to the spec:
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#shadows

"The shadowOffsetX and shadowOffsetY attributes specify the distance
that the shadow will be offset in the positive horizontal and positive
vertical distance respectively. Their values are in coordinate space
units. They are not affected by the current transformation matrix."

NOTE: this applies only to canvas, not to box shadows.

Test: fast/canvas/canvas-transforms-fillRect-shadow.html

  • platform/graphics/ContextShadow.cpp: (WebCore::ContextShadow::ContextShadow): (WebCore::ContextShadow::calculateLayerBoundingRect):
  • platform/graphics/ContextShadow.h: (WebCore::ContextShadow::setShadowsIgnoreTransforms): (WebCore::ContextShadow::shadowsIgnoreTransforms): (WebCore::ContextShadow::offset):
  • platform/graphics/qt/ContextShadowQt.cpp: (WebCore::ContextShadow::beginShadowLayer): (WebCore::ContextShadow::endShadowLayer):
  • platform/graphics/qt/GraphicsContextQt.cpp: (WebCore::mustUseContextShadow): (WebCore::GraphicsContext::fillPath): (WebCore::GraphicsContext::strokePath): (WebCore::GraphicsContext::fillRect): (WebCore::GraphicsContext::fillRoundedRect): (WebCore::GraphicsContext::setPlatformShadow):
Location:
trunk
Files:
1 added
2 deleted
16 edited
1 copied
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r74315 r74317  
     12010-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
    1372010-12-18  Tony Gentilcore  <tonyg@chromium.org>
    238
  • trunk/LayoutTests/fast/canvas/canvas-scale-strokePath-shadow-expected.txt

    r74187 r74317  
    3131PASS d[1] is 0
    3232PASS d[2] is 0
    33 PASS d[3] is around 20
     33PASS d[3] is around 149
    3434PASS d[0] is 255
    3535PASS d[1] is 0
    3636PASS d[2] is 0
    37 PASS d[3] is around 22
     37PASS d[3] is around 116
    3838PASS d[0] is 255
    3939PASS d[1] is 0
    4040PASS d[2] is 0
    41 PASS d[3] is around 28
     41PASS d[3] is around 115
    4242PASS d[0] is 255
    4343PASS d[1] is 0
    4444PASS d[2] is 0
    45 PASS d[3] is around 22
     45PASS d[3] is around 70
    4646PASS d[0] is 255
    4747PASS d[1] is 0
    4848PASS d[2] is 0
    49 PASS d[3] is around 15
     49PASS d[3] is around 70
    5050PASS d[0] is 255
    5151PASS d[1] is 0
    5252PASS d[2] is 0
    53 PASS d[3] is around 17
     53PASS d[3] is around 69
    5454PASS successfullyParsed is true
    5555
  • 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.
     1Ensure correct behavior of canvas with fillRect+shadow after translation+rotation+scaling. A blue and red checkered pattern should be displayed.
    22
    33On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
     
    77PASS d[1] is 0
    88PASS d[2] is 0
    9 FAIL d[3] should be 255. Was 191.
     9PASS d[3] is 255
    1010PASS d[0] is 255
    1111PASS d[1] is 0
    1212PASS d[2] is 0
    13 FAIL d[3] should be 255. Was 191.
     13PASS d[3] is 255
    1414PASS d[0] is 255
    1515PASS d[1] is 0
    1616PASS d[2] is 0
    17 FAIL d[3] should be 255. Was 143.
     17PASS d[3] is 255
    1818PASS d[0] is 255
    1919PASS d[1] is 0
    2020PASS d[2] is 0
    21 FAIL d[3] is not around 76 (actual: 57)
     21PASS d[3] is around 127
    2222PASS d[0] is 255
    2323PASS d[1] is 0
    2424PASS d[2] is 0
    25 FAIL d[3] is not around 76 (actual: 57)
     25PASS d[3] is around 127
    2626PASS d[0] is 255
    2727PASS d[1] is 0
    2828PASS d[2] is 0
    29 FAIL d[3] is not around 76 (actual: 57)
     29PASS d[3] is around 127
     30PASS d[0] is 255
     31PASS d[1] is 0
     32PASS d[2] is 0
     33PASS d[3] is around 106
     34PASS d[0] is 255
     35PASS d[1] is 0
     36PASS d[2] is 0
     37PASS d[3] is around 106
    3038PASS d[0] is 255
    3139PASS d[1] is 0
     
    3543PASS d[1] is 0
    3644PASS d[2] is 0
    37 PASS d[3] is around 83
     45PASS d[3] is around 36
    3846PASS d[0] is 255
    3947PASS d[1] is 0
    4048PASS d[2] is 0
    41 PASS d[3] is around 53
     49PASS d[3] is around 36
    4250PASS d[0] is 255
    4351PASS d[1] is 0
    4452PASS 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
     53PASS d[3] is around 36
    5454PASS successfullyParsed is true
    5555
  • trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-fillPath-shadow.js

    r74187 r74317  
    2020    }
    2121
    22     if (Math.abs(evalA - b) < 10)
     22    if (Math.abs(evalA - b) < 20)
    2323        print("PASS " + a + " is around " + b , "green")
    2424    else
     
    3636ctx.shadowOffsetY = 100;
    3737ctx.fillStyle = 'rgba(0, 0, 255, 1)';
    38 //ctx.lineWidth = 30;
    3938
    4039ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
     
    7473
    7574// Verify solid shadow.
    76 d = ctx.getImageData(200, 205, 1, 1).data;
     75d = ctx.getImageData(201, 205, 1, 1).data;
    7776shouldBe('d[0]', '255');
    7877shouldBe('d[1]', '0');
     
    8079shouldBe('d[3]', '255');
    8180
    82 d = ctx.getImageData(299, 295, 1, 1).data;
     81d = ctx.getImageData(298, 295, 1, 1).data;
    8382shouldBe('d[0]', '255');
    8483shouldBe('d[1]', '0');
     
    8685shouldBe('d[3]', '255');
    8786
    88 d = ctx.getImageData(200, 299, 1, 1).data;
     87d = ctx.getImageData(201, 298, 1, 1).data;
    8988shouldBe('d[0]', '255');
    9089shouldBe('d[1]', '0');
     
    9392
    9493// Verify solid alpha shadow.
    95 d = ctx.getImageData(200, 405, 1, 1).data;
     94d = ctx.getImageData(201, 405, 1, 1).data;
    9695shouldBe('d[0]', '255');
    9796shouldBe('d[1]', '0');
     
    9998shouldBeAround('d[3]', '76');
    10099
    101 d = ctx.getImageData(299, 405, 1, 1).data;
     100d = ctx.getImageData(298, 405, 1, 1).data;
    102101shouldBe('d[0]', '255');
    103102shouldBe('d[1]', '0');
     
    105104shouldBeAround('d[3]', '76');
    106105
    107 d = ctx.getImageData(205, 499, 1, 1).data;
     106d = ctx.getImageData(205, 498, 1, 1).data;
    108107shouldBe('d[0]', '255');
    109108shouldBe('d[1]', '0');
  • trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-fillRect-shadow.js

    r74187 r74317  
    2020    }
    2121
    22     if (Math.abs(evalA - b) < 10)
     22    if (Math.abs(evalA - b) < 20)
    2323        print("PASS " + a + " is around " + b , "green")
    2424    else
     
    5353
    5454// Verify solid shadow.
    55 d = ctx.getImageData(200, 205, 1, 1).data;
     55d = ctx.getImageData(201, 205, 1, 1).data;
    5656shouldBe('d[0]', '255');
    5757shouldBe('d[1]', '0');
     
    5959shouldBe('d[3]', '255');
    6060
    61 d = ctx.getImageData(299, 295, 1, 1).data;
     61d = ctx.getImageData(298, 298, 1, 1).data;
    6262shouldBe('d[0]', '255');
    6363shouldBe('d[1]', '0');
     
    6565shouldBe('d[3]', '255');
    6666
    67 d = ctx.getImageData(200, 299, 1, 1).data;
     67d = ctx.getImageData(201, 298, 1, 1).data;
    6868shouldBe('d[0]', '255');
    6969shouldBe('d[1]', '0');
     
    7272
    7373// Verify solid alpha shadow.
    74 d = ctx.getImageData(200, 405, 1, 1).data;
     74d = ctx.getImageData(201, 405, 1, 1).data;
    7575shouldBe('d[0]', '255');
    7676shouldBe('d[1]', '0');
     
    7878shouldBeAround('d[3]', '76');
    7979
    80 d = ctx.getImageData(299, 405, 1, 1).data;
     80d = ctx.getImageData(298, 405, 1, 1).data;
    8181shouldBe('d[0]', '255');
    8282shouldBe('d[1]', '0');
     
    8484shouldBeAround('d[3]', '76');
    8585
    86 d = ctx.getImageData(205, 499, 1, 1).data;
     86d = ctx.getImageData(205, 498, 1, 1).data;
    8787shouldBe('d[0]', '255');
    8888shouldBe('d[1]', '0');
  • trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-strokePath-shadow.js

    r74187 r74317  
    2020    }
    2121
    22     if (Math.abs(evalA - b) < 10)
     22    if (Math.abs(evalA - b) < 20)
    2323        print("PASS " + a + " is around " + b , "green")
    2424    else
     
    3636ctx.shadowOffsetY = 100;
    3737ctx.strokeStyle = 'rgba(0, 0, 255, 1)';
     38ctx.lineWidth = 5;
    3839
    3940ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
     
    7778
    7879// Verify solid shadow.
    79 d = ctx.getImageData(200, 205, 1, 1).data;
     80d = ctx.getImageData(250, 200, 1, 1).data;
    8081shouldBe('d[0]', '255');
    8182shouldBe('d[1]', '0');
     
    8384shouldBe('d[3]', '255');
    8485
    85 d = ctx.getImageData(299, 295, 1, 1).data;
     86d = ctx.getImageData(300, 290, 1, 1).data;
    8687shouldBe('d[0]', '255');
    8788shouldBe('d[1]', '0');
     
    8990shouldBe('d[3]', '255');
    9091
    91 d = ctx.getImageData(201, 299, 1, 1).data;
     92d = ctx.getImageData(200, 250, 1, 1).data;
    9293shouldBe('d[0]', '255');
    9394shouldBe('d[1]', '0');
     
    9697
    9798// Verify solid alpha shadow.
    98 d = ctx.getImageData(200, 405, 1, 1).data;
     99d = ctx.getImageData(201, 405, 1, 1).data;
    99100shouldBe('d[0]', '255');
    100101shouldBe('d[1]', '0');
     
    102103shouldBeAround('d[3]', '76');
    103104
    104 d = ctx.getImageData(299, 405, 1, 1).data;
     105d = ctx.getImageData(201, 500, 1, 1).data;
    105106shouldBe('d[0]', '255');
    106107shouldBe('d[1]', '0');
     
    108109shouldBeAround('d[3]', '76');
    109110
    110 d = ctx.getImageData(205, 499, 1, 1).data;
     111d = ctx.getImageData(300, 499, 1, 1).data;
    111112shouldBe('d[0]', '255');
    112113shouldBe('d[1]', '0');
     
    115116
    116117// Verify blurry shadow.
    117 d = ctx.getImageData(394, 208, 1, 1).data;
     118d = ctx.getImageData(404, 210, 1, 1).data;
    118119shouldBe('d[0]', '255');
    119120shouldBe('d[1]', '0');
    120121shouldBe('d[2]', '0');
    121 shouldBeAround('d[3]', '20');
     122shouldBeAround('d[3]', '149');
    122123
    123 d = ctx.getImageData(503, 301, 1, 1).data;
     124d = ctx.getImageData(505, 250, 1, 1).data;
    124125shouldBe('d[0]', '255');
    125126shouldBe('d[1]', '0');
    126127shouldBe('d[2]', '0');
    127 shouldBeAround('d[3]', '22');
     128shouldBeAround('d[3]', '116');
    128129
    129 d = ctx.getImageData(504, 250, 1, 1).data;
     130d = ctx.getImageData(450, 205, 1, 1).data;
    130131shouldBe('d[0]', '255');
    131132shouldBe('d[1]', '0');
    132133shouldBe('d[2]', '0');
    133 shouldBeAround('d[3]', '28');
     134shouldBeAround('d[3]', '115');
    134135
    135136// Verify blurry alpha shadow.
    136 d = ctx.getImageData(405, 405, 1, 1).data;
     137d = ctx.getImageData(505, 450, 1, 1).data;
    137138shouldBe('d[0]', '255');
    138139shouldBe('d[1]', '0');
    139140shouldBe('d[2]', '0');
    140 shouldBeAround('d[3]', '22');
     141shouldBeAround('d[3]', '70');
    141142
    142 d = ctx.getImageData(415, 495, 1, 1).data;
     143d = ctx.getImageData(505, 450, 1, 1).data;
    143144shouldBe('d[0]', '255');
    144145shouldBe('d[1]', '0');
    145146shouldBe('d[2]', '0');
    146 shouldBeAround('d[3]', '15');
     147shouldBeAround('d[3]', '70');
    147148
    148 d = ctx.getImageData(450, 504, 1, 1).data;
     149d = ctx.getImageData(450, 405, 1, 1).data;
    149150shouldBe('d[0]', '255');
    150151shouldBe('d[1]', '0');
    151152shouldBe('d[2]', '0');
    152 shouldBeAround('d[3]', '17');
     153shouldBeAround('d[3]', '69');
    153154
    154155var 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.");
     1description("Ensure correct behavior of canvas with fillRect+shadow after translation+rotation+scaling. A blue and red checkered pattern should be displayed.");
    22
    33function print(message, color)
     
    2828var canvas = document.createElement('canvas');
    2929document.body.appendChild(canvas);
    30 canvas.setAttribute('width', '1000');
    31 canvas.setAttribute('height', '1000');
     30canvas.setAttribute('width', '600');
     31canvas.setAttribute('height', '600');
    3232var ctx = canvas.getContext('2d');
    3333
    34 ctx.scale(2, 2);
     34ctx.fillStyle = 'rgba(0, 0, 255, 1.0)';
    3535ctx.shadowOffsetX = 100;
    3636ctx.shadowOffsetY = 100;
    37 ctx.fillStyle = 'rgba(0, 0, 255, 1)';
     37
     38ctx.translate(-100, -100);
     39ctx.rotate(Math.PI/2);
     40ctx.scale(2, 2);
    3841
    3942ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
    40 ctx.fillRect(50, 50, 50, 50);
     43ctx.fillRect(100, -150, 50, 50);
    4144
    42 ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
    43 ctx.fillRect(50, 150, 50, 50);
     45ctx.shadowColor = 'rgba(255, 0, 0, 0.5)';
     46ctx.fillRect(200, -150, 50, 50);
    4447
     48ctx.shadowBlur = 5;
    4549ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
    46 ctx.shadowBlur = 10;
    47 ctx.fillRect(150, 50, 50, 50);
     50ctx.fillRect(100, -250, 50, 50);
    4851
    49 ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
    50 ctx.fillRect(150, 150, 50, 50);
     52ctx.shadowColor = 'rgba(255, 0, 0, 0.5)';
     53ctx.fillRect(200, -250, 50, 50);
    5154
    5255var d; // imageData.data
    5356
    5457// Verify solid shadow.
    55 d = ctx.getImageData(200, 205, 1, 1).data;
     58d = ctx.getImageData(201, 205, 1, 1).data;
    5659shouldBe('d[0]', '255');
    5760shouldBe('d[1]', '0');
     
    5962shouldBe('d[3]', '255');
    6063
    61 d = ctx.getImageData(299, 295, 1, 1).data;
     64d = ctx.getImageData(298, 298, 1, 1).data;
    6265shouldBe('d[0]', '255');
    6366shouldBe('d[1]', '0');
     
    6568shouldBe('d[3]', '255');
    6669
    67 d = ctx.getImageData(200, 299, 1, 1).data;
     70d = ctx.getImageData(201, 298, 1, 1).data;
    6871shouldBe('d[0]', '255');
    6972shouldBe('d[1]', '0');
     
    7275
    7376// Verify solid alpha shadow.
    74 d = ctx.getImageData(200, 405, 1, 1).data;
     77d = ctx.getImageData(201, 401, 1, 1).data;
    7578shouldBe('d[0]', '255');
    7679shouldBe('d[1]', '0');
    7780shouldBe('d[2]', '0');
    78 shouldBeAround('d[3]', '76');
     81shouldBeAround('d[3]', '127');
    7982
    80 d = ctx.getImageData(299, 405, 1, 1).data;
     83d = ctx.getImageData(298, 450, 1, 1).data;
    8184shouldBe('d[0]', '255');
    8285shouldBe('d[1]', '0');
    8386shouldBe('d[2]', '0');
    84 shouldBeAround('d[3]', '76');
     87shouldBeAround('d[3]', '127');
    8588
    86 d = ctx.getImageData(205, 499, 1, 1).data;
     89d = ctx.getImageData(205, 498, 1, 1).data;
    8790shouldBe('d[0]', '255');
    8891shouldBe('d[1]', '0');
    8992shouldBe('d[2]', '0');
    90 shouldBeAround('d[3]', '76');
     93shouldBeAround('d[3]', '127');
    9194
    9295// Verify blurry shadow.
    93 d = ctx.getImageData(398, 205, 1, 1).data;
     96d = ctx.getImageData(399, 205, 1, 1).data;
     97shouldBe('d[0]', '255');
     98shouldBe('d[1]', '0');
     99shouldBe('d[2]', '0');
     100shouldBeAround('d[3]', '106');
     101
     102d = ctx.getImageData(500, 205, 1, 1).data;
     103shouldBe('d[0]', '255');
     104shouldBe('d[1]', '0');
     105shouldBe('d[2]', '0');
     106shouldBeAround('d[3]', '106');
     107
     108d = ctx.getImageData(499, 299, 1, 1).data;
    94109shouldBe('d[0]', '255');
    95110shouldBe('d[1]', '0');
    96111shouldBe('d[2]', '0');
    97112shouldBeAround('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');
    110113
    111114// Verify blurry alpha shadow.
     
    114117shouldBe('d[1]', '0');
    115118shouldBe('d[2]', '0');
    116 shouldBeAround('d[3]', '24');
     119shouldBeAround('d[3]', '36');
    117120
    118121d = ctx.getImageData(405, 501, 1, 1).data;
     
    120123shouldBe('d[1]', '0');
    121124shouldBe('d[2]', '0');
    122 shouldBeAround('d[3]', '24');
     125shouldBeAround('d[3]', '36');
    123126
    124127d = ctx.getImageData(405, 501, 1, 1).data;
     
    126129shouldBe('d[1]', '0');
    127130shouldBe('d[2]', '0');
    128 shouldBeAround('d[3]', '24');
     131shouldBeAround('d[3]', '36');
    129132
    130133var successfullyParsed = true;
  • trunk/LayoutTests/platform/gtk/Skipped

    r74263 r74317  
    10261026fast/canvas/canvas-getImageData.html
    10271027fast/canvas/canvas-gradient-addStop-error.html
     1028fast/canvas/canvas-transforms-fillRect-shadow.html
    10281029fast/canvas/canvas-zoom.html
    10291030fast/css/css1_forward_compatible_parsing.html
  • trunk/WebCore/ChangeLog

    r74316 r74317  
     12010-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
    1392010-12-18  Ariya Hidayat  <ariya@sencha.com>
    240
  • trunk/WebCore/platform/graphics/ContextShadow.cpp

    r74187 r74317  
    3030#include "ContextShadow.h"
    3131
     32#include "FloatQuad.h"
    3233#include <wtf/MathExtras.h>
    3334#include <wtf/Noncopyable.h>
     
    4243    , m_blurDistance(0)
    4344    , m_layerContext(0)
     45    , m_shadowsIgnoreTransforms(false)
    4446{
    4547}
     
    5052    , m_offset(offset)
    5153    , m_layerContext(0)
     54    , m_shadowsIgnoreTransforms(false)
    5255{
    5356    // See comments in http://webkit.org/b/40793, it seems sensible
     
    7679    m_blurDistance = 0;
    7780    m_offset = FloatSize();
     81}
     82
     83bool 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;
    7898}
    7999
     
    150170}
    151171
    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);
     172IntRect 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    }
    158187
    159188    // 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))) {
    163197        // No need to have the buffer larger than the clip.
    164         m_layerRect.intersect(clipRect);
     198        layerFloatRect.intersect(clipRect);
    165199
    166200        // 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);
    169203
    170204        // We adjust again because the pixels at the borders are still
    171205        // 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);
    175227}
    176228
  • trunk/WebCore/platform/graphics/ContextShadow.h

    r74187 r74317  
    8080    ContextShadow(const Color&, float radius, const FloatSize& offset);
    8181
     82    bool mustUseContextShadow(PlatformContext);
    8283    void clear();
    8384
     
    107108    void endShadowLayer(PlatformContext);
    108109    static void purgeScratchBuffer();
     110    static TransformationMatrix getTransformationMatrixFromContext(PlatformContext);
     111
     112    void setShadowsIgnoreTransforms(bool enable) { m_shadowsIgnoreTransforms = enable; }
     113    bool shadowsIgnoreTransforms() const { return m_shadowsIgnoreTransforms; }
    109114#if PLATFORM(CAIRO)
    110115    void drawRectShadow(GraphicsContext* context, const IntRect& rect, const IntSize& topLeftRadius = IntSize(), const IntSize& topRightRadius = IntSize(), const IntSize& bottomLeftRadius = IntSize(), const IntSize& bottomRightRadius = IntSize());
    111116#endif
    112 
    113117#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()); }
    115119#endif
    116120
    117 
    118121private:
    119     IntRect m_layerRect;
    120     PlatformImage 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;
    125128
    126129    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
    128132#if PLATFORM(CAIRO)
    129133    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  
    8383}
    8484
     85TransformationMatrix 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
    8593PlatformContext ContextShadow::beginShadowLayer(PlatformContext context, const FloatRect& layerArea)
    8694{
    87     m_unscaledLayerRect = layerArea;
    88 
    8995    double x1, x2, y1, y2;
    9096    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));
    9298
    9399    // Don't paint if we are totally outside the clip region.
    94     if (m_layerRect.isEmpty())
     100    if (layerRect.isEmpty())
    95101        return 0;
    96102
    97     m_layerImage = getScratchBuffer(m_layerRect.size());
     103    m_layerImage = getScratchBuffer(layerRect.size());
    98104    m_layerContext = cairo_create(m_layerImage);
    99105
     
    103109    cairo_set_operator(m_layerContext, CAIRO_OPERATOR_OVER);
    104110
    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());
    107112    return m_layerContext;
    108113}
     
    123128    cairo_save(cr);
    124129    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());
    138131    cairo_restore(cr);
    139132
     
    236229    double x1, x2, y1, y2;
    237230    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())) {
    241234        drawRectShadowWithoutTiling(cr, rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, context->getAlpha());
    242235        return;
  • trunk/WebCore/platform/graphics/cairo/FontCairo.cpp

    r73284 r74317  
    7373        return;
    7474
    75     if (shadow->m_type == ContextShadow::SolidShadow) {
     75    if (!shadow->mustUseContextShadow(context)) {
    7676        // Optimize non-blurry shadows, by just drawing text without the ContextShadow.
    7777        cairo_save(context);
  • trunk/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp

    r73729 r74317  
    872872    } else
    873873        m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height()));
     874
     875    m_data->shadow.setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms);
    874876}
    875877
  • trunk/WebCore/platform/graphics/gtk/FontGtk.cpp

    r74169 r74317  
    226226
    227227    // Optimize non-blurry shadows, by just drawing text without the ContextShadow.
    228     if (shadow->m_type == ContextShadow::SolidShadow) {
     228    if (!shadow->mustUseContextShadow(context)) {
    229229        cairo_save(context);
    230230        cairo_translate(context, totalOffset.x(), totalOffset.y());
  • trunk/WebCore/platform/graphics/qt/ContextShadowQt.cpp

    r74187 r74317  
    101101}
    102102
     103TransformationMatrix 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
    103110Q_GLOBAL_STATIC(ShadowBuffer, scratchShadowBuffer)
    104111
     
    115122        clipRect = p->transform().inverted().mapRect(p->window());
    116123
    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);
    119127
    120128    // Don't paint if we are totally outside the clip region.
    121     if (m_layerRect.isEmpty())
     129    if (layerRect.isEmpty())
    122130        return 0;
    123131
    124132    ShadowBuffer* shadowBuffer = scratchShadowBuffer();
    125     QImage* shadowImage = shadowBuffer->scratchImage(m_layerRect.size());
     133    QImage* shadowImage = shadowBuffer->scratchImage(layerRect.size());
    126134    m_layerImage = QImage(*shadowImage);
    127135
     
    129137    m_layerContext->begin(&m_layerImage);
    130138    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);
    136140    return m_layerContext;
    137141}
     
    156160    }
    157161
    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);
    165163
    166164    scratchShadowBuffer()->schedulePurge();
  • trunk/WebCore/platform/graphics/qt/FontQt.cpp

    r74169 r74317  
    147147            if (ctxShadow->m_type != ContextShadow::NoShadow) {
    148148                ContextShadow* ctxShadow = ctx->contextShadow();
    149                 if (ctxShadow->m_type != ContextShadow::BlurShadow) {
     149                if (!ctxShadow->mustUseContextShadow(p)) {
    150150                    p->save();
    151151                    p->setPen(ctxShadow->m_color);
  • trunk/WebCore/platform/graphics/qt/GraphicsContextQt.cpp

    r74272 r74317  
    5454
    5555#include <QBrush>
    56 #include <QDebug>
    5756#include <QGradient>
    5857#include <QPaintDevice>
     
    512511    if (m_data->hasShadow()) {
    513512        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)
    516514        {
    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 {
    533515            QPainter* shadowPainter = shadow->beginShadowLayer(p, platformPath.controlPointRect());
    534516            if (shadowPainter) {
     
    537519                shadow->endShadowLayer(p);
    538520            }
     521        } else {
     522            QPointF offset = shadow->offset();
     523            p->translate(offset);
     524            p->fillPath(platformPath, QColor(shadow->m_color));
     525            p->translate(-offset);
    539526        }
    540 
    541527    }
    542528    if (m_state.fillPattern) {
     
    563549    if (m_data->hasShadow()) {
    564550        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)
    568552        {
    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 {
    587553            FloatRect boundingRect = platformPath.controlPointRect();
    588554            boundingRect.inflate(pen.miterLimit() + pen.widthF());
     
    593559                shadow->endShadowLayer(p);
    594560            }
     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);
    595568        }
    596569    }
     
    712685    } else {
    713686        if (m_data->hasShadow()) {
    714             if (shadow->m_type == ContextShadow::BlurShadow) {
     687            if (shadow->mustUseContextShadow(p)) {
    715688                QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect);
    716689                if (shadowPainter) {
     
    720693                }
    721694            } else {
    722                 // Solid rectangle fill with no blur shadow can be done faster
    723                 // 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.
    724697                QColor shadowColor = shadow->m_color;
    725698                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);
    733700            }
    734701        }
     
    750717    if (m_data->hasShadow()) {
    751718        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)) {
    757720            QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect);
    758721            if (shadowPainter) {
     
    761724                shadow->endShadowLayer(p);
    762725            }
    763         }
     726        } else
     727            p->fillRect(normalizedRect.translated(shadow->offset()), shadow->m_color);
    764728    }
    765729
     
    777741    if (m_data->hasShadow()) {
    778742        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)) {
    786744            QPainter* shadowPainter = shadow->beginShadowLayer(p, rect);
    787745            if (shadowPainter) {
     
    790748                shadow->endShadowLayer(p);
    791749            }
     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());
    792754        }
    793755    }
     
    959921        m_state.shadowOffset = FloatSize(size.width(), -size.height());
    960922        m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), -size.height()));
    961     } else {
     923    } else
    962924        m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height()));
    963     }
     925
     926    m_data->shadow.setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms);
    964927}
    965928
Note: See TracChangeset for help on using the changeset viewer.