Bug 564388 - Make the 'quality' parameter to ToDataURL work for image/jpeg. Also fixes bug 401795 (handle excess arguments to ToDataURL by ignoring them). r=bz,roc

This commit is contained in:
Brian O'Keefe 2011-05-26 09:28:26 +02:00
parent 7d859d6db2
commit 02a4c1c6d9
8 changed files with 97 additions and 41 deletions

View File

@ -123,7 +123,7 @@ var stringBundle;
// and targets
let io = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
let source = io.newURI(canvas.toDataURL("image/png", ""), "UTF8", null);
let source = io.newURI(canvas.toDataURL("image/png"), "UTF8", null);
let target = io.newFileURI(file);
// prepare to save the canvas data

View File

@ -1558,6 +1558,6 @@ TabCanvas.prototype = {
// ----------
// Function: toImageData
toImageData: function TabCanvas_toImageData() {
return this.canvas.toDataURL("image/png", "");
return this.canvas.toDataURL("image/png");
}
};

View File

@ -80,6 +80,7 @@ _TEST_FILES_0 = \
test_2d.composite.uncovered.image.source-in.html \
test_2d.composite.uncovered.image.source-out.html \
test_toDataURL_lowercase_ascii.html \
test_toDataURL_parameters.html \
test_mozGetAsFile.html \
test_canvas_strokeStyle_getter.html \
test_bug613794.html \

View File

@ -19537,21 +19537,23 @@ var canvas = document.getElementById('c614');
var ctx = canvas.getContext('2d');
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var _threw = false;
try {
var data = canvas.toDataURL('image/png', 'quality=100');
ok(false, "Should have thrown an exception for invalid args to png encoder");
}
catch (e) {
is(e.result, Components.results.NS_ERROR_INVALID_ARG, "Exception was wrong for png encoder");
_threw = true;
}
ok(!_threw, "Should not throw an exception for invalid args to png encoder");
_threw = false;
try {
var data = canvas.toDataURL('image/jpeg', 'foobar=true');
ok(false, "Should have thrown an exception for invalid args to jpeg encoder");
}
catch (e) {
is(e.result, Components.results.NS_ERROR_INVALID_ARG, "Exception was wrong for jpeg encoder");
_threw = true;
}
ok(!_threw, "Should not throw an exception for invalid args to jpeg encoder");
}
</script>
@ -20761,7 +20763,7 @@ ok(/^data:image\/png[;,]/.test(data), "data =~ /^data:image\\/png[;,]/");
} catch (e) {
_thrown_outer = true;
}
todo(!_thrown_outer, 'should not throw exception');
ok(!_thrown_outer, 'should not throw exception');
}
@ -20788,7 +20790,7 @@ ok(/^data:image\/png[;,]/.test(data), "data =~ /^data:image\\/png[;,]/");
} catch (e) {
_thrown_outer = true;
}
todo(!_thrown_outer, 'should not throw exception');
ok(!_thrown_outer, 'should not throw exception');
}
@ -20816,7 +20818,7 @@ ok(/^data:image\/png[;,]/.test(data), "data =~ /^data:image\\/png[;,]/");
} catch (e) {
_thrown_outer = true;
}
todo(!_thrown_outer, 'should not throw exception');
ok(!_thrown_outer, 'should not throw exception');
}

View File

@ -0,0 +1,55 @@
<!DOCTYPE HTML>
<title>Canvas test: toDataURL parameters (Bug 564388)</title>
<script src="/MochiKit/MochiKit.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<body>
<p>
This test covers the JPEG quality parameter. If (when) the HTML5 spec changes the
allowed parameters for ToDataURL, new tests should go here.
</p>
<canvas id="c" width="100" height="100"><p class="fallback">FAIL (fallback content)</p></canvas>
<script>
var canvas = document.getElementById('c');
var ctx = canvas.getContext("2d");
ctx.strokeStyle = '#FF0000';
ctx.fillStyle = '#00FF00';
ctx.fillRect(0, 0, 100, 100);
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(90, 90);
ctx.stroke();
var pngData = canvas.toDataURL('image/png');
var pngQuality = canvas.toDataURL('image/png', 0.1);
is(pngQuality, pngData, "Quality is not supported for PNG images");
var data = canvas.toDataURL('image/jpeg');
if (data.match(/^data:image\/jpeg[;,]/)) {
// Test the JPEG quality parameter
var fullQuality = canvas.toDataURL('image/jpeg', 1.0);
var lowQuality = canvas.toDataURL('image/jpeg', 0.1);
isnot(lowQuality, fullQuality, "A low quality (0.1) should differ from high quality (1.0)");
var medQuality = canvas.toDataURL('image/jpeg', 0.5);
isnot(medQuality, fullQuality, "A medium quality (0.5) should differ from high (1.0)");
isnot(medQuality, lowQuality, "A medium quality (0.5) should differ from low (0.5)");
var tooHigh = canvas.toDataURL('image/jpeg', 2.0);
is(tooHigh, data, "Quality above 1.0 is treated as unspecified");
var tooLow = canvas.toDataURL('image/jpeg', -1.0);
is(tooLow, data, "Quality below 0.0 is treated as unspecified");
var lowQualityExtra = canvas.toDataURL('image/jpeg', 0.1, 'foo', 'bar', null);
is(lowQualityExtra, lowQuality, "Quality applies even if extra arguments are present");
var lowQualityUppercase = canvas.toDataURL('IMAGE/JPEG', 0.1);
is(lowQualityUppercase, lowQuality, "Quality applies to image/jpeg regardless of case");
var lowQualityString = canvas.toDataURL('image/jpeg', '0.1');
isnot(lowQualityString, lowQuality, "Quality must be a number (should not be a string)");
}
</script>

View File

@ -181,7 +181,7 @@ protected:
PRUint32& aSize,
bool& aFellBackToPNG);
nsresult ToDataURLImpl(const nsAString& aMimeType,
const nsAString& aEncoderOptions,
nsIVariant* aEncoderOptions,
nsAString& aDataURL);
nsresult MozGetAsFileImpl(const nsAString& aName,
const nsAString& aType,

View File

@ -47,6 +47,7 @@
#include "nsIXPConnect.h"
#include "jsapi.h"
#include "nsJSUtils.h"
#include "nsMathUtils.h"
#include "nsFrameManager.h"
#include "nsDisplayList.h"
@ -196,32 +197,17 @@ nsHTMLCanvasElement::ParseAttribute(PRInt32 aNamespaceID,
// nsHTMLCanvasElement::toDataURL
NS_IMETHODIMP
nsHTMLCanvasElement::ToDataURL(const nsAString& aType, const nsAString& aParams,
nsHTMLCanvasElement::ToDataURL(const nsAString& aType, nsIVariant* aParams,
PRUint8 optional_argc, nsAString& aDataURL)
{
// do a trust check if this is a write-only canvas
// or if we're trying to use the 2-arg form
if ((mWriteOnly || optional_argc >= 2) &&
!nsContentUtils::IsCallerTrustedForRead()) {
if (mWriteOnly && !nsContentUtils::IsCallerTrustedForRead()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
return ToDataURLImpl(aType, aParams, aDataURL);
}
// nsHTMLCanvasElement::toDataURLAs
//
// Native-callers only
NS_IMETHODIMP
nsHTMLCanvasElement::ToDataURLAs(const nsAString& aMimeType,
const nsAString& aEncoderOptions,
nsAString& aDataURL)
{
return ToDataURLImpl(aMimeType, aEncoderOptions, aDataURL);
}
nsresult
nsHTMLCanvasElement::ExtractData(const nsAString& aType,
const nsAString& aOptions,
@ -323,7 +309,7 @@ nsHTMLCanvasElement::ExtractData(const nsAString& aType,
nsresult
nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType,
const nsAString& aEncoderOptions,
nsIVariant* aEncoderOptions,
nsAString& aDataURL)
{
bool fallbackToPNG = false;
@ -337,11 +323,30 @@ nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType,
nsAutoString type;
nsContentUtils::ASCIIToLower(aMimeType, type);
nsAutoString params;
// Quality parameter is only valid for the image/jpeg MIME type
if (type.EqualsLiteral("image/jpeg")) {
PRUint16 vartype;
if (aEncoderOptions &&
NS_SUCCEEDED(aEncoderOptions->GetDataType(&vartype)) &&
vartype <= nsIDataType::VTYPE_DOUBLE) {
double quality;
// Quality must be between 0.0 and 1.0, inclusive
if (NS_SUCCEEDED(aEncoderOptions->GetAsDouble(&quality)) &&
quality >= 0.0 && quality <= 1.0) {
params.AppendLiteral("quality=");
params.AppendInt(NS_lround(quality * 100.0));
}
}
}
PRUint32 imgSize = 0;
char* imgData;
nsresult rv = ExtractData(type, aEncoderOptions, imgData,
imgSize, fallbackToPNG);
nsresult rv = ExtractData(type, params, imgData, imgSize, fallbackToPNG);
NS_ENSURE_SUCCESS(rv, rv);
// base 64, result will be NULL terminated

View File

@ -53,8 +53,9 @@
*/
interface nsIDOMFile;
interface nsIVariant;
[scriptable, uuid(2e98cd39-2269-493a-a3bb-abe85be2523c)]
[scriptable, uuid(010d8e6f-86ba-47ad-a04f-1a4d75f1caf8)]
interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement
{
attribute unsigned long width;
@ -68,18 +69,10 @@ interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement
// Valid calls are:
// toDataURL(); -- defaults to image/png
// toDataURL(type); -- uses given type
// toDataURL(type, params); -- only available to trusted callers
// toDataURL(type, params); -- uses given type, and any valid parameters
[optional_argc] DOMString toDataURL([optional] in DOMString type,
[optional] in DOMString params);
[optional] in nsIVariant params);
// This version lets you specify different image types and pass parameters
// to the encoder. For example toDataURLAs("image/png", "transparency=none")
// gives you a PNG with the alpha channel discarded. See the encoder for
// the options string that it supports. Separate multiple options with
// semicolons.
[noscript] DOMString toDataURLAs(in DOMString mimeType, in DOMString encoderOptions);
// Valid calls are
// mozGetAsFile(name); -- defaults to image/png
// mozGetAsFile(name, type); -- uses given type