--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderSVGRoot {svg} at (18,16) size 542x544
+ RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+ RenderSVGResourceLinearGradient {linearGradient} [id="gradient"] [gradientUnits=objectBoundingBox] [start=(0,0)] [end=(1,0)]
+ RenderSVGGradientStop {stop} [offset=0.00] [color=#0000FF]
+ RenderSVGGradientStop {stop} [offset=1.00] [color=#008000]
+ RenderSVGPath {circle} at (20,20) size 176x176 [transform={m=((4.00,0.00)(0.00,4.00)) t=(0.00,0.00)}] [fill={[type=LINEAR-GRADIENT] [id="gradient"]}] [cx=25.00] [cy=25.00] [r=20.00]
+ RenderSVGRect {rect} at (320,16) size 288x288 [transform={m=((32.00,0.00)(0.00,32.00)) t=(0.00,0.00)}] [fill={[type=LINEAR-GRADIENT] [id="gradient"]}] [x=10.00] [y=0.50] [width=5.00] [height=5.00]
+ RenderSVGPath {circle} at (18,318) size 180x180 [transform={m=((4.00,0.00)(0.00,4.00)) t=(0.00,0.00)}] [stroke={[type=LINEAR-GRADIENT] [id="gradient"]}] [fill={[type=SOLID] [color=#00000000]}] [cx=25.00] [cy=100.00] [r=20.00]
+ RenderSVGRect {rect} at (304,304) size 320x296 [transform={m=((32.00,0.00)(0.00,32.00)) t=(0.00,0.00)}] [stroke={[type=LINEAR-GRADIENT] [id="gradient"]}] [fill={[type=SOLID] [color=#00000000]}] [x=10.00] [y=10.00] [width=5.00] [height=5.00]
+2012-01-18 Tim Horton <timothy_horton@apple.com>
+
+ [CG] Rasterized scaling of transformed SVG shapes with gradient fill and -webkit-svg-shadow applied
+ https://bugs.webkit.org/show_bug.cgi?id=76482
+ <rdar://problem/10415483>
+
+ Reviewed by Simon Fraser.
+
+ Scale the CGLayer used when filling or stroking a shadowed path or rect with
+ a gradient in GraphicsContextCG. Previously, the CGLayer was created and rendered
+ into at the untransformed size of the shape, leading to pixelation when it was
+ then scaled up and drawn into the destination.
+
+ Add AffineTransform::mapSize() to map a size through a transformation.
+
+ Test: svg/custom/transform-with-shadow-and-gradient.svg
+
+ * platform/graphics/cg/GraphicsContextCG.cpp:
+ (WebCore::GraphicsContext::fillPath):
+ (WebCore::GraphicsContext::strokePath):
+ (WebCore::GraphicsContext::fillRect):
+ (WebCore::GraphicsContext::strokeRect):
+ * platform/graphics/transforms/AffineTransform.cpp:
+ (WebCore::AffineTransform::mapSize): Added.
+ * platform/graphics/transforms/AffineTransform.h:
+
2012-01-18 Dominic Mazzoni <dmazzoni@google.com>
Accessibility: Chromium needs methods to scroll an object into view or to a specific location.
if (m_state.fillGradient) {
if (hasShadow()) {
FloatRect rect = path.fastBoundingRect();
- CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(rect.width(), rect.height()), 0);
+ FloatSize layerSize = getCTM().mapSize(rect.size());
+
+ CGLayerRef layer = CGLayerCreateWithContext(context, layerSize, 0);
CGContextRef layerContext = CGLayerGetContext(layer);
+ CGContextScaleCTM(layerContext, layerSize.width() / rect.width(), layerSize.height() / rect.height());
CGContextTranslateCTM(layerContext, -rect.x(), -rect.y());
CGContextBeginPath(layerContext);
CGContextAddPath(layerContext, path.platformPath());
CGContextClip(layerContext);
m_state.fillGradient->paint(layerContext);
- CGContextDrawLayerAtPoint(context, CGPointMake(rect.x(), rect.y()), layer);
+ CGContextDrawLayerInRect(context, rect, layer);
CGLayerRelease(layer);
} else {
CGContextBeginPath(context);
FloatRect rect = path.fastBoundingRect();
float lineWidth = strokeThickness();
float doubleLineWidth = lineWidth * 2;
- float layerWidth = ceilf(rect.width() + doubleLineWidth);
- float layerHeight = ceilf(rect.height() + doubleLineWidth);
+ float adjustedWidth = ceilf(rect.width() + doubleLineWidth);
+ float adjustedHeight = ceilf(rect.height() + doubleLineWidth);
+
+ FloatSize layerSize = getCTM().mapSize(FloatSize(adjustedWidth, adjustedHeight));
- CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(layerWidth, layerHeight), 0);
+ CGLayerRef layer = CGLayerCreateWithContext(context, layerSize, 0);
CGContextRef layerContext = CGLayerGetContext(layer);
CGContextSetLineWidth(layerContext, lineWidth);
// the layer on the left and top sides.
float translationX = lineWidth - rect.x();
float translationY = lineWidth - rect.y();
+ CGContextScaleCTM(layerContext, layerSize.width() / adjustedWidth, layerSize.height() / adjustedHeight);
CGContextTranslateCTM(layerContext, translationX, translationY);
CGContextAddPath(layerContext, path.platformPath());
float destinationX = roundf(rect.x() - lineWidth);
float destinationY = roundf(rect.y() - lineWidth);
- CGContextDrawLayerAtPoint(context, CGPointMake(destinationX, destinationY), layer);
+ CGContextDrawLayerInRect(context, CGRectMake(destinationX, destinationY, adjustedWidth, adjustedHeight), layer);
CGLayerRelease(layer);
} else {
CGContextSaveGState(context);
if (m_state.fillGradient) {
CGContextSaveGState(context);
if (hasShadow()) {
- CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(rect.width(), rect.height()), 0);
+ FloatSize layerSize = getCTM().mapSize(rect.size());
+
+ CGLayerRef layer = CGLayerCreateWithContext(context, layerSize, 0);
CGContextRef layerContext = CGLayerGetContext(layer);
+ CGContextScaleCTM(layerContext, layerSize.width() / rect.width(), layerSize.height() / rect.height());
CGContextTranslateCTM(layerContext, -rect.x(), -rect.y());
CGContextAddRect(layerContext, rect);
CGContextClip(layerContext);
CGContextConcatCTM(layerContext, m_state.fillGradient->gradientSpaceTransform());
m_state.fillGradient->paint(layerContext);
- CGContextDrawLayerAtPoint(context, CGPointMake(rect.x(), rect.y()), layer);
+ CGContextDrawLayerInRect(context, rect, layer);
CGLayerRelease(layer);
} else {
CGContextClipToRect(context, rect);
if (m_state.strokeGradient) {
if (hasShadow()) {
const float doubleLineWidth = lineWidth * 2;
- const float layerWidth = ceilf(rect.width() + doubleLineWidth);
- const float layerHeight = ceilf(rect.height() + doubleLineWidth);
- CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(layerWidth, layerHeight), 0);
+ float adjustedWidth = ceilf(rect.width() + doubleLineWidth);
+ float adjustedHeight = ceilf(rect.height() + doubleLineWidth);
+ FloatSize layerSize = getCTM().mapSize(FloatSize(adjustedWidth, adjustedHeight));
+
+ CGLayerRef layer = CGLayerCreateWithContext(context, layerSize, 0);
CGContextRef layerContext = CGLayerGetContext(layer);
m_state.strokeThickness = lineWidth;
// the layer on the left and top sides.
const float translationX = lineWidth - rect.x();
const float translationY = lineWidth - rect.y();
+ CGContextScaleCTM(layerContext, layerSize.width() / adjustedWidth, layerSize.height() / adjustedHeight);
CGContextTranslateCTM(layerContext, translationX, translationY);
CGContextAddRect(layerContext, rect);
const float destinationX = roundf(rect.x() - lineWidth);
const float destinationY = roundf(rect.y() - lineWidth);
- CGContextDrawLayerAtPoint(context, CGPointMake(destinationX, destinationY), layer);
+ CGContextDrawLayerInRect(context, CGRectMake(destinationX, destinationY, adjustedWidth, adjustedHeight), layer);
CGLayerRelease(layer);
} else {
CGContextSaveGState(context);