Commit bd0d8071 authored by weinig@apple.com's avatar weinig@apple.com

Fix canvas.toDataURL(type, quality, ...) to let it support quality parameter.

And implement it in Qt port. 
https://bugs.webkit.org/show_bug.cgi?id=37304

Patch by Leo Yang <leo.yang@torchmobile.com.cn> on 2010-05-31
Reviewed by George Staikos.

WebCore: 

Tests: platform/qt/fast/canvas/toDataURL-jpeg-alpha.html
       platform/qt/fast/canvas/toDataURL-jpeg-primarycolors.html
       platform/qt/fast/canvas/toDataURL-jpeg-quality-basic.html
       platform/qt/fast/canvas/toDataURL-jpeg-quality-notnumber.html
       platform/qt/fast/canvas/toDataURL-jpeg-quality-outsiderange.html

* bindings/js/JSHTMLCanvasElementCustom.cpp:
(WebCore::JSHTMLCanvasElement::toDataURL):
* bindings/v8/custom/V8HTMLCanvasElementCustom.cpp:
(WebCore::V8HTMLCanvasElement::toDataURLCallback):
* dom/CanvasSurface.cpp:
(WebCore::CanvasSurface::toDataURL):
* dom/CanvasSurface.h:
(WebCore::CanvasSurface::toDataURL):
* html/HTMLCanvasElement.idl:
* platform/graphics/ImageBuffer.h:
* platform/graphics/cairo/ImageBufferCairo.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/cg/ImageBufferCG.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/haiku/ImageBufferHaiku.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/qt/ImageBufferQt.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/skia/ImageBufferSkia.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/wince/ImageBufferWince.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/wx/ImageBufferWx.cpp:
(WebCore::ImageBuffer::toDataURL):

LayoutTests: 

* platform/qt/fast/canvas/toDataURL-jpeg-alpha-expected.txt: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-alpha.html: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-primarycolors-expected.txt: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-primarycolors.html: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-quality-basic-expected.txt: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-quality-basic.html: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-quality-notnumber-expected.txt: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-quality-notnumber.html: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-quality-outsiderange-expected.txt: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-quality-outsiderange.html: Added.
* platform/qt/fast/canvas/toDataURL-jpeg.js: Added.



git-svn-id: svn://svn.chromium.org/blink/trunk@60458 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 2fed2e50
2010-05-31 Leo Yang <leo.yang@torchmobile.com.cn>
Reviewed by George Staikos.
Fix canvas.toDataURL(type, quality, ...) to let it support quality parameter.
And implement it in Qt port.
https://bugs.webkit.org/show_bug.cgi?id=37304
* platform/qt/fast/canvas/toDataURL-jpeg-alpha-expected.txt: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-alpha.html: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-primarycolors-expected.txt: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-primarycolors.html: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-quality-basic-expected.txt: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-quality-basic.html: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-quality-notnumber-expected.txt: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-quality-notnumber.html: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-quality-outsiderange-expected.txt: Added.
* platform/qt/fast/canvas/toDataURL-jpeg-quality-outsiderange.html: Added.
* platform/qt/fast/canvas/toDataURL-jpeg.js: Added.
2010-05-31 Stephen White <senorblanco@chromium.org> 2010-05-31 Stephen White <senorblanco@chromium.org>
Reviewed by Dimitri Glazkov. Reviewed by Dimitri Glazkov.
......
To verify jpeg data URL should take alpha component into account if canvas color has alpha component
Test result: passed
<html>
<head>
<script src="toDataURL-jpeg.js"></script>
<script>
if (window.layoutTestController)
layoutTestController.dumpAsText();
window.notifyEndTest = function ()
{
if (window.layoutTestController)
layoutTestController.notifyDone();
};
function testToDataURL(canvas, ctx)
{
ctx.fillStyle = 'rgba(128, 255, 128, 0.5)';
ctx.fillRect(0, 0, 100, 50);
ctx.globalCompositeOperation = 'destination-over'; // should be ignored by toDataURL
var data = canvas.toDataURL('image/jpeg');
ctx.globalCompositeOperation = 'source-over';
if (!data.match(/^data:image\/jpeg[;,]/)) {
_assert(true, "true");
} else {
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
var img = new Image();
deferTest();
img.onload = wrapFunction(function ()
{
ctx.drawImage(img, 0, 0);
_assertPixelApprox(canvas, 50,25, 63,127,63,255, "50,25", "63,127,63,255", 8);
});
img.src = data;
if (window.layoutTestController)
layoutTestController.waitUntilDone();
}
}
_addTest(testToDataURL);
</script>
</head>
<body>
<p>To verify jpeg data URL should take alpha component into account if canvas color has alpha component</p>
<canvas id="c" width="100" height="50"></canvas>
<p id="d"></p>
</body>
</html>
To verify color compressing loss (when the quality is 1.0) is in a tolerable range
Test result: passed
<html>
<head>
<script src="toDataURL-jpeg.js"></script>
<script>
if (window.layoutTestController)
layoutTestController.dumpAsText();
window.notifyEndTest = function ()
{
if (window.layoutTestController)
layoutTestController.notifyDone();
};
function testToDataURL(canvas, ctx)
{
ctx.fillStyle = '#ff0';
ctx.fillRect(0, 0, 25, 40);
ctx.fillStyle = '#0ff';
ctx.fillRect(25, 0, 50, 40);
ctx.fillStyle = '#00f';
ctx.fillRect(75, 0, 25, 40);
ctx.fillStyle = '#fff';
ctx.fillRect(0, 40, 100, 10);
var data = canvas.toDataURL('image/jpeg'); // it is okay if this returns a PNG instead
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
var img = new Image();
deferTest();
img.onload = wrapFunction(function ()
{
ctx.drawImage(img, 0, 0);
_assertPixelApprox(canvas, 12,20, 255,255,0,255, "12,20", "255,255,0,255", 8);
_assertPixelApprox(canvas, 50,20, 0,255,255,255, "50,20", "0,255,255,255", 8);
_assertPixelApprox(canvas, 87,20, 0,0,255,255, "87,20", "0,0,255,255", 8);
_assertPixelApprox(canvas, 50,45, 255,255,255,255, "50,45", "255,255,255,255", 8);
});
img.src = data;
if (window.layoutTestController)
layoutTestController.waitUntilDone();
}
_addTest(testToDataURL);
</script>
</head>
<body>
<p>To verify color compressing loss (when the quality is 1.0) is in a tolerable range</p>
<canvas id="c" width="100" height="50"></canvas>
<p id="d"></p>
</body>
</html>
To verify basic jpeg compressing loss: 1) Low qulity URL's length should be shorter than high qulity URL's length, 2) Compress loss should be in a tolerable range
Test result: passed
<html>
<head>
<script src="toDataURL-jpeg.js"></script>
<script>
if (window.layoutTestController)
layoutTestController.dumpAsText();
window.notifyEndTest = function ()
{
if (window.layoutTestController)
layoutTestController.notifyDone();
};
function testToDataURL(canvas, ctx)
{
ctx.fillStyle = '#00f';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0ff';
ctx.fillRect(0, 3, 100, 1);
// Check for JPEG support first
var data = canvas.toDataURL('image/jpeg');
if (!data.match(/^data:image\/jpeg[;,]/)) {
_assert(true, "true");
} else {
var data_hi = canvas.toDataURL('image/jpeg', 0.99);
var data_lo = canvas.toDataURL('image/jpeg', 0.01);
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
deferTest();
var img_hi = new Image();
img_hi.onload = function ()
{
var img_lo = new Image();
img_lo.onload = wrapFunction(function ()
{
ctx.drawImage(img_hi, 0, 0, 50, 50, 0, 0, 50, 50);
ctx.drawImage(img_lo, 0, 0, 50, 50, 50, 0, 50, 50);
_assert(data_hi.length > data_lo.length, "data_hi.length > data_lo.length");
_assertPixelApprox(canvas, 25,25, 0,0,255,255, "25,25", "0,0,255,255", 12);
_assertPixelApprox(canvas, 75,25, 0,0,255,255, "75,25", "0,0,255,255", 12);
});
img_lo.src = data_lo;
};
img_hi.src = data_hi;
if (window.layoutTestController)
layoutTestController.waitUntilDone();
}
}
_addTest(testToDataURL);
</script>
</head>
<body>
<p>To verify basic jpeg compressing loss: 1) Low qulity URL's length should be shorter than high qulity URL's length, 2) Compress loss should be in a tolerable range</p>
<canvas id="c" width="100" height="50"></canvas>
<p id="d"></p>
</body>
</html>
If the quality parameter is not a number, it should be treated as 1.0
Test result: passed
<html>
<head>
<script src="toDataURL-jpeg.js"></script>
<script>
if (window.layoutTestController)
layoutTestController.dumpAsText();
window.notifyEndTest = function ()
{
if (window.layoutTestController)
layoutTestController.notifyDone();
};
function testToDataURL(canvas, ctx)
{
ctx.fillStyle = '#00f';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0ff';
ctx.fillRect(0, 3, 100, 1);
// Check for JPEG support first
var data = canvas.toDataURL('image/jpeg');
if (!data.match(/^data:image\/jpeg[;,]/)) {
_assert(true, "true");
} else {
_assertSame(canvas.toDataURL('image/jpeg', 'bogus'), data, "canvas.toDataURL('image/jpeg', 'bogus')", "data");
_assertSame(canvas.toDataURL('image/jpeg', {}), data, "canvas.toDataURL('image/jpeg', {})", "data");
_assertSame(canvas.toDataURL('image/jpeg', null), data, "canvas.toDataURL('image/jpeg', null)", "data");
_assertSame(canvas.toDataURL('image/jpeg', undefined), data, "canvas.toDataURL('image/jpeg', undefined)", "data");
_assertSame(canvas.toDataURL('image/jpeg', true), data, "canvas.toDataURL('image/jpeg', true)", "data");
_assertSame(canvas.toDataURL('image/jpeg', '0.01'), data, "canvas.toDataURL('image/jpeg', '0.01')", "data");
if (window.layoutTestController)
layoutTestController.waitUntilDone();
}
}
_addTest(testToDataURL);
</script>
</head>
<body>
<p>If the quality parameter is not a number, it should be treated as 1.0</p>
<canvas id="c" width="100" height="50"></canvas>
<p id="d"></p>
</body>
</html>
If the quality parameter is out of range, it should be treated as 1.0
Test result: passed
<html>
<head>
<script src="toDataURL-jpeg.js"></script>
<script>
if (window.layoutTestController)
layoutTestController.dumpAsText();
window.notifyEndTest = function ()
{
if (window.layoutTestController)
layoutTestController.notifyDone();
};
function testToDataURL(canvas, ctx)
{
ctx.fillStyle = '#00f';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0ff';
ctx.fillRect(0, 3, 100, 1);
// Check for JPEG support first
var data = canvas.toDataURL('image/jpeg');
if (!data.match(/^data:image\/jpeg[;,]/)) {
_assert(true, "true");
} else {
_assertSame(canvas.toDataURL('image/jpeg', 10), data, "canvas.toDataURL('image/jpeg', 10)", "data");
_assertSame(canvas.toDataURL('image/jpeg', -10), data, "canvas.toDataURL('image/jpeg', -10)", "data");
_assertSame(canvas.toDataURL('image/jpeg', 1.01), data, "canvas.toDataURL('image/jpeg', 1.01)", "data");
_assertSame(canvas.toDataURL('image/jpeg', -0.01), data, "canvas.toDataURL('image/jpeg', -0.01)", "data");
_assert(canvas.toDataURL('image/jpeg', 1).length >= canvas.toDataURL('image/jpeg', 0.9).length, "canvas.toDataURL('image/jpeg', 1).length >= canvas.toDataURL('image/jpeg', 0.9).length");
_assert(canvas.toDataURL('image/jpeg', 0).length <= canvas.toDataURL('image/jpeg', 0.1).length, "canvas.toDataURL('image/jpeg', 0).length <= canvas.toDataURL('image/jpeg', 0.1).length");
if (window.layoutTestController)
layoutTestController.waitUntilDone();
}
}
_addTest(testToDataURL);
</script>
</head>
<body>
<p>If the quality parameter is out of range, it should be treated as 1.0</p>
<canvas id="c" width="100" height="50"></canvas>
<p id="d"></p>
</body>
</html>
function _valToString(val)
{
if (val === undefined || val === null)
return '[' + typeof(val) + ']';
return val.toString() + '[' + typeof(val) + ']';
}
var _hex2dec_table = {
0:0, 1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8, 9:9,
a:10, b:11, c:12, d:13, e:14, f:15,
A:10, B:11, C:12, D:13, E:14, F:15
};
function _hex2dec(hex)
{
return _hex2dec_table[hex.charAt(0)]*16 + _hex2dec_table[hex.charAt(1)];
}
var _failed = false;
var _asserted = false;
function _warn(text)
{
document.getElementById('d').appendChild(document.createElement('li')).appendChild(document.createTextNode(text));
}
function _fail(text)
{
_warn(text);
_failed = true;
}
function _assert(cond, text)
{
_asserted = true;
if (! cond)
_fail('Failed assertion: ' + text);
}
function _assertSame(a, b, text_a, text_b)
{
_asserted = true;
if (a !== b)
_fail('Failed assertion ' + text_a + ' === ' + text_b +
' (got ' + _valToString(a) + ', expected ' + _valToString(b) + ')');
}
function _assertDifferent(a, b, text_a, text_b)
{
_asserted = true;
if (a === b)
_fail('Failed assertion ' + text_a + ' !== ' + text_b +
' (got ' + _valToString(a) + ', expected not ' + _valToString(b) + ')');
}
function _assertEqual(a, b, text_a, text_b)
{
_asserted = true;
if (a != b)
_fail('Failed assertion ' + text_a + ' == ' + text_b +
' (got ' + _valToString(a) + ', expected ' + _valToString(b) + ')');
}
function _assertMatch(a, b, text_a, text_b)
{
_asserted = true;
if (! a.match(b))
_fail('Failed assertion ' + text_a + ' matches ' + text_b +
' (got ' + _valToString(a) + ')');
}
var _manual_check = false;
function _requireManualCheck()
{
_manual_check = true;
}
function _crash()
{
_fail('Aborted due to predicted crash');
}
var _getImageDataCalibrated = false;
var _getImageDataIsPremul, _getImageDataIsBGRA;
function _getPixel(canvas, x,y)
{
var ctx = canvas.getContext('2d');
if (ctx && typeof(ctx.getImageData) != 'undefined')
{
try {
var imgdata = ctx.getImageData(x, y, 1, 1);
} catch (e) {
// probably a security exception caused by having drawn
// data: URLs onto the canvas
imgdata = null;
}
if (imgdata)
{
// Work around getImageData bugs, since we want the other tests to
// carry on working as well as possible
if (! _getImageDataCalibrated)
{
var c2 = document.createElement('canvas');
c2.width = c2.height = 1;
var ctx2 = c2.getContext('2d');
ctx2.fillStyle = 'rgba(0, 255, 255, 0.5)';
ctx2.fillRect(0, 0, 1, 1);
var data2 = ctx2.getImageData(0, 0, 1, 1).data;
// Firefox returns premultiplied alpha
if (data2[1] > 100 && data2[1] < 150)
_getImageDataIsPremul = true;
else
_getImageDataIsPremul = false;
// Opera Mini 4 Beta returns BGRA instead of RGBA
if (data2[0] > 250 && data2[2] < 5)
_getImageDataIsBGRA = true;
else
_getImageDataIsBGRA = false;
_getImageDataCalibrated = true;
}
// Undo the BGRA flipping
var rgba = (_getImageDataIsBGRA
? [ imgdata.data[2], imgdata.data[1], imgdata.data[0], imgdata.data[3] ]
: [ imgdata.data[0], imgdata.data[1], imgdata.data[2], imgdata.data[3] ]);
if (! _getImageDataIsPremul)
return rgba;
// Undo the premultiplying
if (rgba[3] == 0)
return [ 0, 0, 0, 0 ];
else
{
var a = rgba[3] / 255;
return [
Math.round(rgba[0]/a),
Math.round(rgba[1]/a),
Math.round(rgba[2]/a),
rgba[3]
];
}
}
}
try { ctx = canvas.getContext('opera-2dgame'); } catch (e) { /* Firefox throws */ }
if (ctx && typeof(ctx.getPixel) != 'undefined')
{
try {
var c = ctx.getPixel(x, y);
} catch (e) {
// probably a security exception caused by having drawn
// data: URLs onto the canvas
c = null;
}
if (c)
{
var matches = /^rgba\((\d+), (\d+), (\d+), ([\d\.]+)\)$/.exec(c);
if (matches)
return [ matches[1], matches[2], matches[3], Math.round(matches[4]*255) ];
matches = /^#(..)(..)(..)$/.exec(c);
if (matches)
return [ _hex2dec(matches[1]), _hex2dec(matches[2]), _hex2dec(matches[3]), 255 ];
}
}
//_warn("(Can't test pixel value)");
_manual_check = true;
return undefined;
}
function _assertPixel(canvas, x,y, r,g,b,a, pos, colour)
{
_asserted = true;
var c = _getPixel(canvas, x,y);
if (c && ! (c[0] == r && c[1] == g && c[2] == b && c[3] == a))
_fail('Failed assertion: got pixel [' + c + '] at ('+x+','+y+'), expected ['+r+','+g+','+b+','+a+']');
}
function _assertPixelApprox(canvas, x,y, r,g,b,a, pos, colour, tolerance)
{
_asserted = true;
var c = _getPixel(canvas, x,y);
if (c)
{
var diff = Math.max(Math.abs(c[0]-r), Math.abs(c[1]-g), Math.abs(c[2]-b), Math.abs(c[3]-a));
if (diff > tolerance)
_fail('Failed assertion: got pixel [' + c + '] at ('+x+','+y+'), expected ['+r+','+g+','+b+','+a+'] +/- '+tolerance);
}
}
function _addTest(test)
{
var deferred = false;
window.deferTest = function () { deferred = true; };
function endTest()
{
if (_failed) // test failed
{
document.documentElement.className += ' fail';
window._testStatus = ['fail', document.getElementById('d').innerHTML];
}
else if (_manual_check || !_asserted)
{ // test case explicitly asked for a manual check, or no automatic assertions were performed
document.getElementById('d').innerHTML += '<li>Cannot automatically verify result';
document.documentElement.className += ' needs_check';
window._testStatus = ['check', document.getElementById('d').innerHTML];
}
else // test succeeded
{
document.getElementById('d').innerHTML = 'Test result: passed';
document.documentElement.className += ' pass';
window._testStatus = ['pass', document.getElementById('d').innerHTML];
}
if (window.notifyEndTest)
notifyEndTest();
}
window.endTest = endTest;
window.wrapFunction = function (f)
{
return function()
{
try
{
f.apply(null, arguments);
}
catch (e)
{
_fail('Aborted with exception: ' + e.message);
}
endTest();
}
}
window.onload = function ()
{
try
{
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
test(canvas, ctx);
}
catch (e)
{
_fail('Aborted with exception: ' + e.message);
deferred = false; // cancel any deference
}
if (! deferred)
endTest();
};
}
2010-05-31 Leo Yang <leo.yang@torchmobile.com.cn>
Reviewed by George Staikos.
Fix canvas.toDataURL(type, quality, ...) to let it support quality parameter.
And implement it in Qt port.
https://bugs.webkit.org/show_bug.cgi?id=37304
Tests: platform/qt/fast/canvas/toDataURL-jpeg-alpha.html
platform/qt/fast/canvas/toDataURL-jpeg-primarycolors.html
platform/qt/fast/canvas/toDataURL-jpeg-quality-basic.html
platform/qt/fast/canvas/toDataURL-jpeg-quality-notnumber.html
platform/qt/fast/canvas/toDataURL-jpeg-quality-outsiderange.html
* bindings/js/JSHTMLCanvasElementCustom.cpp:
(WebCore::JSHTMLCanvasElement::toDataURL):
* bindings/v8/custom/V8HTMLCanvasElementCustom.cpp:
(WebCore::V8HTMLCanvasElement::toDataURLCallback):
* dom/CanvasSurface.cpp:
(WebCore::CanvasSurface::toDataURL):
* dom/CanvasSurface.h:
(WebCore::CanvasSurface::toDataURL):
* html/HTMLCanvasElement.idl:
* platform/graphics/ImageBuffer.h:
* platform/graphics/cairo/ImageBufferCairo.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/cg/ImageBufferCG.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/haiku/ImageBufferHaiku.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/qt/ImageBufferQt.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/skia/ImageBufferSkia.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/wince/ImageBufferWince.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/wx/ImageBufferWx.cpp:
(WebCore::ImageBuffer::toDataURL):
2010-05-31 Lucas De Marchi <lucas.demarchi@profusion.mobi> 2010-05-31 Lucas De Marchi <lucas.demarchi@profusion.mobi>
Reviewed by Kenneth Rohde Christiansen. Reviewed by Kenneth Rohde Christiansen.
......
/* /*
* Copyright (C) 2007 Apple Inc. All rights reserved. * Copyright (C) 2007 Apple Inc. All rights reserved.
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -84,4 +85,22 @@ JSValue JSHTMLCanvasElement::getContext(ExecState* exec) ...@@ -84,4 +85,22 @@ JSValue JSHTMLCanvasElement::getContext(ExecState* exec)
return toJS(exec, globalObject(), WTF::getPtr(context)); return toJS(exec, globalObject(), WTF::getPtr(context));
} }
JSValue JSHTMLCanvasElement::toDataURL(ExecState* exec)
{
const String& type = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0));
double quality = 1.0;
if (exec->argumentCount() > 1) {
JSValue v = exec->argument(1);
if (v.isNumber())
quality = v.toNumber(exec);
if (!(0.0 <= quality && quality <= 1.0))
quality = 1.0;
}
HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(impl());
ExceptionCode ec = 0;
JSC::JSValue result = jsString(exec, canvas->toDataURL(type, quality, ec));
setDOMException(exec, ec);
return result;
}
} // namespace WebCore } // namespace WebCore
/* /*
* Copyright (C) 2007-2009 Google Inc. All rights reserved. * Copyright (C) 2007-2009 Google Inc. All rights reserved.
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
...@@ -34,6 +35,7 @@ ...@@ -34,6 +35,7 @@
#include "CanvasContextAttributes.h" #include "CanvasContextAttributes.h"
#include "CanvasRenderingContext.h" #include "CanvasRenderingContext.h"
#include "HTMLCanvasElement.h" #include "HTMLCanvasElement.h"
#include "PlatformString.h"
#include "WebGLContextAttributes.h" #include "WebGLContextAttributes.h"
#include "V8Binding.h" #include "V8Binding.h"
#include "V8CanvasRenderingContext2D.h" #include "V8CanvasRenderingContext2D.h"
...@@ -42,6 +44,7 @@ ...@@ -42,6 +44,7 @@
#if ENABLE(3D_CANVAS) #if ENABLE(3D_CANVAS)
#include "V8WebGLRenderingContext.h" #include "V8WebGLRenderingContext.h"
#endif #endif
#include <wtf/MathExtras.h>
namespace WebCore { namespace WebCore {
...@@ -89,4 +92,22 @@ v8::Handle<v8::Value> V8HTMLCanvasElement::getContextCallback(const v8::Argument ...@@ -89,4 +92,22 @@ v8::Handle<v8::Value> V8HTMLCanvasElement::getContextCallback(const v8::Argument
return v8::Null(); return v8::Null();
} }
v8::Handle<v8::Value> V8HTMLCanvasElement::toDataURLCallback(const v8::Arguments& args)
{
double quality = 1.0;
if (args.Length() > 1) {
if (args[1]->IsNumber())
quality = args[1]->NumberValue();
if (!(0.0 <= quality && quality <= 1.0))
quality = 1.0;
}
v8::Handle<v8::Object> holder = args.Holder();
HTMLCanvasElement* canvas = V8HTMLCanvasElement::toNative(holder);
String type = toWebCoreString(args[0]);
ExceptionCode ec = 0;
String result = canvas->toDataURL(type, quality, ec);
V8Proxy::setDOMException(ec);
return v8StringOrUndefined(result);
}
} // namespace WebCore } // namespace WebCore
/* /*
* Copyright (C) 2010 Google Inc. All rights reserved. * Copyright (C) 2010 Google Inc. All rights reserved.
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -64,7 +65,7 @@ void CanvasSurface::setSurfaceSize(const IntSize& size) ...@@ -64,7 +65,7 @@ void CanvasSurface::setSurfaceSize(const IntSize& size)
m_imageBuffer.clear(); m_imageBuffer.clear();
} }
String CanvasSurface::toDataURL(const String& mimeType, ExceptionCode& ec) String CanvasSurface::toDataURL(const String& mimeType, double quality, ExceptionCode& ec)
{ {
if (!m_originClean) { if (!m_originClean) {
ec = SECURITY_ERR; ec = SECURITY_ERR;
...@@ -80,7 +81,7 @@ String CanvasSurface::toDataURL(const String& mimeType, ExceptionCode& ec) ...@@ -80,7 +81,7 @@ String CanvasSurface::toDataURL(const String& mimeType, ExceptionCode& ec)
if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(lowercaseMimeType)) if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(lowercaseMimeType))
return buffer()->toDataURL("image/png"); return buffer()->toDataURL("image/png");
return buffer()->toDataURL(lowercaseMimeType); return buffer()->toDataURL(lowercaseMimeType, quality);
} }
void CanvasSurface::willDraw(const FloatRect&) void CanvasSurface::willDraw(const FloatRect&)
......
/* /*
* Copyright (C) 2010 Google Inc. All rights reserved. * Copyright (C) 2010 Google Inc. All rights reserved.
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -28,6 +29,7 @@ ...@@ -28,6 +29,7 @@
#include "AffineTransform.h" #include "AffineTransform.h"
#include "IntSize.h" #include "IntSize.h"
#include "PlatformString.h"
#include <wtf/OwnPtr.h> #include <wtf/OwnPtr.h>
#include <wtf/Noncopyable.h> #include <wtf/Noncopyable.h>
...@@ -41,7 +43,6 @@ class FloatSize; ...@@ -41,7 +43,6 @@ class FloatSize;
class GraphicsContext; class GraphicsContext;
class ImageBuffer; class ImageBuffer;
class IntPoint; class IntPoint;
class String;
class CSSStyleSelector; class CSSStyleSelector;
class RenderBox; class RenderBox;
...@@ -58,7 +59,9 @@ public: ...@@ -58,7 +59,9 @@ public:
int width() const { return m_size.width(); } int width() const { return m_size.width(); }
int height() const { return m_size.height(); } int height() const { return m_size.height(); }
String toDataURL(const String& mimeType, ExceptionCode&); String toDataURL(const String& mimeType, double quality, ExceptionCode&);
String toDataURL(const String& mimeType, ExceptionCode& ec) { return toDataURL(mimeType, 1.0, ec); }
const IntSize& size() const { return m_size; } const IntSize& size() const { return m_size; }
......
/* /*
* Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -32,7 +33,7 @@ module html { ...@@ -32,7 +33,7 @@ module html {
attribute long width; attribute long width;
attribute long height; attribute long height;
DOMString toDataURL(in [ConvertUndefinedOrNullToNullString] DOMString type) [Custom] DOMString toDataURL(in [ConvertUndefinedOrNullToNullString] DOMString type)
raises(DOMException); raises(DOMException);
#if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C #if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C
......
/* /*
* Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -82,7 +83,7 @@ namespace WebCore { ...@@ -82,7 +83,7 @@ namespace WebCore {
void putUnmultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint); void putUnmultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint);
void putPremultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint); void putPremultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint);
String toDataURL(const String& mimeType) const; String toDataURL(const String& mimeType, double quality = 1.0) const;
#if !PLATFORM(CG) #if !PLATFORM(CG)
AffineTransform baseTransform() const { return AffineTransform(); } AffineTransform baseTransform() const { return AffineTransform(); }
void transformColorSpace(ImageColorSpace srcColorSpace, ImageColorSpace dstColorSpace); void transformColorSpace(ImageColorSpace srcColorSpace, ImageColorSpace dstColorSpace);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) 2007 Holger Hans Peter Freyther <zecke@selfish.org> * Copyright (C) 2007 Holger Hans Peter Freyther <zecke@selfish.org>
* Copyright (C) 2008, 2009 Dirk Schulze <krit@webkit.org> * Copyright (C) 2008, 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -283,7 +284,7 @@ static cairo_status_t writeFunction(void* closure, const unsigned char* data, un ...@@ -283,7 +284,7 @@ static cairo_status_t writeFunction(void* closure, const unsigned char* data, un
return CAIRO_STATUS_SUCCESS; return CAIRO_STATUS_SUCCESS;
} }
String ImageBuffer::toDataURL(const String& mimeType) const String ImageBuffer::toDataURL(const String& mimeType, double) const
{ {
cairo_surface_t* image = cairo_get_target(context()->platformContext()); cairo_surface_t* image = cairo_get_target(context()->platformContext());
if (!image) if (!image)
......
/* /*
* Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) 2008 Apple Inc. All rights reserved. * Copyright (C) 2008 Apple Inc. All rights reserved.
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -275,7 +276,7 @@ static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType) ...@@ -275,7 +276,7 @@ static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType)
#endif #endif
} }
String ImageBuffer::toDataURL(const String& mimeType) const String ImageBuffer::toDataURL(const String& mimeType, double) const
{ {
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
......
/* /*
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -309,7 +310,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so ...@@ -309,7 +310,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
putImageData(source, sourceRect, destPoint, m_data, m_size, true); putImageData(source, sourceRect, destPoint, m_data, m_size, true);
} }
String ImageBuffer::toDataURL(const String& mimeType) const String ImageBuffer::toDataURL(const String& mimeType, double) const
{ {
if (!MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)) if (!MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType))
return "data:,"; return "data:,";
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) 2008 Holger Hans Peter Freyther * Copyright (C) 2008 Holger Hans Peter Freyther
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org> * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -275,9 +276,10 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so ...@@ -275,9 +276,10 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
// We get a mimeType here but QImageWriter does not support mimetypes but // We get a mimeType here but QImageWriter does not support mimetypes but
// only formats (png, gif, jpeg..., xpm). So assume we get image/ as image // only formats (png, gif, jpeg..., xpm). So assume we get image/ as image
// mimetypes and then remove the image/ to get the Qt format. // mimetypes and then remove the image/ to get the Qt format.
String ImageBuffer::toDataURL(const String& mimeType) const String ImageBuffer::toDataURL(const String& mimeType, double quality) const
{ {
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
ASSERT(0.0 <= quality && quality <= 1.0);
if (!mimeType.startsWith("image/")) if (!mimeType.startsWith("image/"))
return "data:,"; return "data:,";
...@@ -287,8 +289,10 @@ String ImageBuffer::toDataURL(const String& mimeType) const ...@@ -287,8 +289,10 @@ String ImageBuffer::toDataURL(const String& mimeType) const
QBuffer buffer(&data); QBuffer buffer(&data);
buffer.open(QBuffer::WriteOnly); buffer.open(QBuffer::WriteOnly);
if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data())) if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data(), quality * 100 + 0.5)) {
buffer.close();
return "data:,"; return "data:,";
}
buffer.close(); buffer.close();
return String::format("data:%s;base64,%s", mimeType.utf8().data(), data.toBase64().data()); return String::format("data:%s;base64,%s", mimeType.utf8().data(), data.toBase64().data());
......
/* /*
* Copyright (c) 2008, Google Inc. All rights reserved. * Copyright (c) 2008, Google Inc. All rights reserved.
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org> * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
...@@ -260,7 +261,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so ...@@ -260,7 +261,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
putImageData<Premultiplied>(source, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size); putImageData<Premultiplied>(source, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size);
} }
String ImageBuffer::toDataURL(const String&) const String ImageBuffer::toDataURL(const String&, double) const
{ {
// Encode the image into a vector. // Encode the image into a vector.
Vector<unsigned char> pngEncodedData; Vector<unsigned char> pngEncodedData;
......
/* /*
* Copyright (C) 2009 Torch Mobile, Inc. All rights reserved. * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved.
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
...@@ -215,7 +216,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so ...@@ -215,7 +216,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
putImageData<true>(source, sourceRect, destPoint, m_data.m_bitmap.get()); putImageData<true>(source, sourceRect, destPoint, m_data.m_bitmap.get());
} }
String ImageBuffer::toDataURL(const String& mimeType) const String ImageBuffer::toDataURL(const String& mimeType, double) const
{ {
if (!m_data.m_bitmap->bytes()) if (!m_data.m_bitmap->bytes())
return "data:,"; return "data:,";
......
/* /*
* Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com> * Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com>
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -75,7 +76,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so ...@@ -75,7 +76,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
notImplemented(); notImplemented();
} }
String ImageBuffer::toDataURL(const String&) const String ImageBuffer::toDataURL(const String&, double) const
{ {
notImplemented(); notImplemented();
return String(); return String();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment