Modified: trunk/LayoutTests/fast/canvas/webgl/premultiplyalpha-test-expected.txt (95999 => 96000)
--- trunk/LayoutTests/fast/canvas/webgl/premultiplyalpha-test-expected.txt 2011-09-26 22:00:06 UTC (rev 95999)
+++ trunk/LayoutTests/fast/canvas/webgl/premultiplyalpha-test-expected.txt 2011-09-26 22:07:33 UTC (rev 96000)
@@ -3,35 +3,57 @@
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-testing: premultipliedAlpha: true toDataURL: true
+testing: premultipliedAlpha: true imageFormat: image/png
PASS gl.getContextAttributes().premultipledAlpha is premultipledAlpha
+PASS gl.getContextAttributes().preserveDrawingBuffer is true
PASS getError was expected value: NO_ERROR : Should be no errors from setup.
PASS getError was expected value: NO_ERROR : Should be no errors from drawing.
PASS getError was expected value: NO_ERROR : Should be no errors from creating copy.
PASS getError was expected value: NO_ERROR : Should be no errors from 2nd drawing.
PASS should draw with 64,128,255,128
-testing: premultipliedAlpha: true toDataURL: false
+testing: premultipliedAlpha: true imageFormat: undefined
PASS gl.getContextAttributes().premultipledAlpha is premultipledAlpha
+PASS gl.getContextAttributes().preserveDrawingBuffer is true
PASS getError was expected value: NO_ERROR : Should be no errors from setup.
PASS getError was expected value: NO_ERROR : Should be no errors from drawing.
PASS getError was expected value: NO_ERROR : Should be no errors from creating copy.
PASS getError was expected value: NO_ERROR : Should be no errors from 2nd drawing.
PASS should draw with 64,128,255,128
-testing: premultipliedAlpha: false toDataURL: true
+testing: premultipliedAlpha: false imageFormat: image/png
PASS gl.getContextAttributes().premultipledAlpha is premultipledAlpha
+PASS gl.getContextAttributes().preserveDrawingBuffer is true
PASS getError was expected value: NO_ERROR : Should be no errors from setup.
PASS getError was expected value: NO_ERROR : Should be no errors from drawing.
PASS getError was expected value: NO_ERROR : Should be no errors from creating copy.
PASS getError was expected value: NO_ERROR : Should be no errors from 2nd drawing.
PASS should draw with 255,192,128,1
-testing: premultipliedAlpha: false toDataURL: false
+testing: premultipliedAlpha: false imageFormat: undefined
PASS gl.getContextAttributes().premultipledAlpha is premultipledAlpha
+PASS gl.getContextAttributes().preserveDrawingBuffer is true
PASS getError was expected value: NO_ERROR : Should be no errors from setup.
PASS getError was expected value: NO_ERROR : Should be no errors from drawing.
PASS getError was expected value: NO_ERROR : Should be no errors from creating copy.
PASS getError was expected value: NO_ERROR : Should be no errors from 2nd drawing.
PASS should draw with 255,192,128,1
+testing: premultipliedAlpha: false imageFormat: image/jpeg
+PASS gl.getContextAttributes().premultipledAlpha is premultipledAlpha
+PASS gl.getContextAttributes().preserveDrawingBuffer is true
+PASS getError was expected value: NO_ERROR : Should be no errors from setup.
+PASS getError was expected value: NO_ERROR : Should be no errors from drawing.
+PASS getError was expected value: NO_ERROR : Should be no errors from creating copy.
+PASS getError was expected value: NO_ERROR : Should be no errors from 2nd drawing.
+PASS should draw with 128,128,128,255
+
+testing: premultipliedAlpha: true imageFormat: image/jpeg
+PASS gl.getContextAttributes().premultipledAlpha is premultipledAlpha
+PASS gl.getContextAttributes().preserveDrawingBuffer is true
+PASS getError was expected value: NO_ERROR : Should be no errors from setup.
+PASS getError was expected value: NO_ERROR : Should be no errors from drawing.
+PASS getError was expected value: NO_ERROR : Should be no errors from creating copy.
+PASS getError was expected value: NO_ERROR : Should be no errors from 2nd drawing.
+PASS should draw with 128,128,128,255
+
Modified: trunk/LayoutTests/fast/canvas/webgl/premultiplyalpha-test.html (95999 => 96000)
--- trunk/LayoutTests/fast/canvas/webgl/premultiplyalpha-test.html 2011-09-26 22:00:06 UTC (rev 95999)
+++ trunk/LayoutTests/fast/canvas/webgl/premultiplyalpha-test.html 2011-09-26 22:07:33 UTC (rev 96000)
@@ -1,7 +1,7 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
+<!DOCTYPE html>
<html>
<head>
+<meta charset="utf-8">
<title>Test the WebGL premultipledAlpha context creation flag.</title>
<link rel="stylesheet" href=""
<script src=""
@@ -21,7 +21,7 @@
sentColor: [32, 64, 128, 128],
expectedColor: [64, 128, 255, 128],
errorRange: 2,
- useToDataURL: true,
+ imageFormat: "image/png"
},
// If premultipledAlpha is true then
// [texture] [canvas] [texture]
@@ -30,7 +30,6 @@
sentColor: [32, 64, 128, 128],
expectedColor: [64, 128, 255, 128],
errorRange: 2,
- useToDataURL: false,
},
// If premultipledAlpha is false then
// [texture] [canvas] [dataURL]
@@ -39,7 +38,7 @@
sentColor: [255, 192, 128, 1],
expectedColor: [255, 192, 128, 1],
errorRange: 0,
- useToDataURL: true,
+ imageFormat: "image/png"
},
// If premultipledAlpha is false then
// [texture] [canvas] [texture]
@@ -48,7 +47,24 @@
sentColor: [255, 192, 128, 1],
expectedColor: [255, 192, 128, 1],
errorRange: 0,
- useToDataURL: false,
+ },
+ // If premultipledAlpha is false then
+ // [texture] [canvas] [dataURL]
+ // 255, 255, 255, 128 -> 255, 255, 255, 128 -> 128, 128, 128, 255
+ { creationAttributes: {premultipliedAlpha: false},
+ sentColor: [255, 255, 255, 128],
+ expectedColor: [128, 128, 128, 255],
+ errorRange: 2,
+ imageFormat: "image/jpeg"
+ },
+ // If premultipledAlpha is true then
+ // [texture] [canvas] [dataURL]
+ // 128, 128, 128, 128 -> 255, 255, 255, 128 -> 128, 128, 128, 255
+ { creationAttributes: {},
+ sentColor: [128, 128, 128, 128],
+ expectedColor: [128, 128, 128, 255],
+ errorRange: 2,
+ imageFormat: "image/jpeg"
}
];
@@ -68,12 +84,15 @@
if (g_count < tests.length) {
var test = tests[g_count++];
canvas = document.createElement("canvas");
+ // Need to preserve drawing buffer to load it in a callback
+ test.creationAttributes.preserveDrawingBuffer = true;
gl = wtu.create3DContext(canvas, test.creationAttributes);
var premultipliedAlpha = test.creationAttributes.premultipliedAlpha != false;
debug("")
- debug("testing: premultipliedAlpha: " + premultipliedAlpha + " toDataURL: " + test.useToDataURL);
+ debug("testing: premultipliedAlpha: " + premultipliedAlpha + " imageFormat: " + test.imageFormat);
shouldBe('gl.getContextAttributes().premultipledAlpha', 'premultipledAlpha');
+ shouldBeTrue('gl.getContextAttributes().preserveDrawingBuffer');
var program = wtu.setupTexturedQuad(gl);
@@ -96,7 +115,7 @@
// gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, false);
gl.bindTexture(gl.TEXTURE_2D, pngTex);
- if (test.useToDataURL) {
+ if (test.imageFormat) {
// create texture from image
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this);
} else {
@@ -117,13 +136,20 @@
doNextTest();
}
- if (test.useToDataURL) {
+ if (test.imageFormat) {
// Load canvas into string using toDataURL
- var png = canvas.toDataURL();
- // Load string into the texture
- var input = document.createElement("img");
- input._onload_ = loadTexture;
- input.src = ""
+ var imageUrl = canvas.toDataURL(test.imageFormat);
+ if (test.imageFormat != "image/png" &&
+ (imageUrl.indexOf("data:image/png,") == 0 ||
+ imageUrl.indexOf("data:image/png;") == 0)) {
+ debug("Image format " + test.imageFormat + " not supported; skipping");
+ setTimeout(doNextTest, 0);
+ } else {
+ // Load string into the texture
+ var input = document.createElement("img");
+ input._onload_ = loadTexture;
+ input.src = ""
+ }
} else {
// Load canvas into the texture asynchronously (to prevent unbounded stack consumption)
setTimeout(loadTexture, 0);
@@ -138,9 +164,6 @@
</script>
-<script>
-</script>
-
</body>
</html>
Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp (95999 => 96000)
--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp 2011-09-26 22:00:06 UTC (rev 95999)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp 2011-09-26 22:07:33 UTC (rev 96000)
@@ -343,6 +343,9 @@
imageProperties.adoptCF(CFDictionaryCreate(0, &key, &value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
}
+ // Setting kCGImageDestinationBackgroundColor to black in imageProperties would allow saving some math in the
+ // calling functions, but it doesn't seem to work.
+
CGImageDestinationAddImage(destination.get(), image, imageProperties.get());
CGImageDestinationFinalize(destination.get());
@@ -355,9 +358,32 @@
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
{
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
+ RetainPtr<CGImageRef> image;
+ RetainPtr<CFStringRef> uti = utiFromMIMEType(mimeType);
+ ASSERT(uti);
- RetainPtr<CGImageRef> image(AdoptCF, copyNativeImage(CopyBackingStore));
+ if (CFEqual(uti.get(), jpegUTI())) {
+ // JPEGs don't have an alpha channel, so we have to manually composite on top of black.
+ RefPtr<ByteArray> arr = getPremultipliedImageData(IntRect(IntPoint(0, 0), m_size));
+ unsigned char *data = ""
+ for (int i = 0; i < width() * height(); i++)
+ data[i * 4 + 3] = 255; // The image is already premultiplied, so we just need to make it opaque.
+
+ RetainPtr<CGDataProviderRef> dataProvider;
+
+ dataProvider.adoptCF(CGDataProviderCreateWithData(0, data,
+ 4 * width() * height(), 0));
+
+ if (!dataProvider)
+ return "data:,";
+
+ image.adoptCF(CGImageCreate(width(), height(), 8, 32, 4 * width(),
+ CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault | kCGImageAlphaLast,
+ dataProvider.get(), 0, false, kCGRenderingIntentDefault));
+ } else
+ image.adoptCF(copyNativeImage(CopyBackingStore));
+
if (!image)
return "data:,";
@@ -370,8 +396,35 @@
RetainPtr<CGImageRef> image;
RetainPtr<CGDataProviderRef> dataProvider;
+
+ unsigned char* data = ""
+ RetainPtr<CFStringRef> uti = utiFromMIMEType(mimeType);
+ ASSERT(uti);
+ Vector<uint8_t> dataVector;
+ if (CFEqual(uti.get(), jpegUTI())) {
+ // JPEGs don't have an alpha channel, so we have to manually composite on top of black.
+ dataVector.resize(4 * source.width() * source.height());
+ unsigned char *out = dataVector.data();
+
+ for (int i = 0; i < source.width() * source.height(); i++) {
+ // Multiply color data by alpha, and set alpha to 255.
+ int alpha = data[4 * i + 3];
+ if (alpha != 255) {
+ out[4 * i + 0] = data[4 * i + 0] * alpha / 255;
+ out[4 * i + 1] = data[4 * i + 1] * alpha / 255;
+ out[4 * i + 2] = data[4 * i + 2] * alpha / 255;
+ } else {
+ out[4 * i + 0] = data[4 * i + 0];
+ out[4 * i + 1] = data[4 * i + 1];
+ out[4 * i + 2] = data[4 * i + 2];
+ }
+ out[4 * i + 3] = 255;
+ }
+
+ data = ""
+ }
- dataProvider.adoptCF(CGDataProviderCreateWithData(0, source.data()->data()->data(),
+ dataProvider.adoptCF(CGDataProviderCreateWithData(0, data,
4 * source.width() * source.height(), 0));
if (!dataProvider)