Commit 01c309b8 authored by eric@webkit.org's avatar eric@webkit.org

2010-06-04 Matthew Delaney <mdelaney@apple.com>

        Reviewed by Darin Adler.

        CG implementation needed for compression quality in canvas.toDataURL
        https://bugs.webkit.org/show_bug.cgi?id=38492

        * platform/mac/Skipped:
2010-06-04  Matthew Delaney  <mdelaney@apple.com>

        Reviewed by Darin Adler.

        CG implementation needed for compression quality in canvas.toDataURL
        https://bugs.webkit.org/show_bug.cgi?id=38492

        Took toDataURL.jpeg.quality.basic.html test off of Skipped list. Passes.

        Went the route of avoiding in-band signaling to flag the use of a quality
        parameter or not. So, instead of simply passing the quality down as a
        double, instead I pass a reference to the quality parameter from where
        it comes in just after the JS bindings. Thus, no need for any global
        constants to signify when the quality is not specified. Updated the other
        platforms to support this (qt was on the only one currently with any
        implementation).

        * bindings/js/JSHTMLCanvasElementCustom.cpp: Moved range check logic for quality parameter down lower. Updated
        call to toDataURL to use double* instead of just passing the quality directly.
        (WebCore::JSHTMLCanvasElement::toDataURL):
        * bindings/v8/custom/V8HTMLCanvasElementCustom.cpp: Updated toDataURL call to pass double*
        (WebCore::V8HTMLCanvasElement::toDataURLCallback):
        * dom/CanvasSurface.cpp: Updated method prototype.
        (WebCore::CanvasSurface::toDataURL):
        * dom/CanvasSurface.h: Updated method prototype.
        (WebCore::CanvasSurface::toDataURL):
        * platform/graphics/ImageBuffer.h: Updated method signature to use double* for quality param.
        * platform/graphics/cairo/ImageBufferCairo.cpp: Updated prototype for consistency.
        (WebCore::ImageBuffer::toDataURL):
        * platform/graphics/cg/ImageBufferCG.cpp: Implemented support for quality parametejr when jpeg MIME type used.
        (WebCore::jpegUTI):
        (WebCore::utiFromMIMEType):
        (WebCore::ImageBuffer::toDataURL):
        * platform/graphics/haiku/ImageBufferHaiku.cpp: Updated prototype for consistency.
        (WebCore::ImageBuffer::toDataURL):
        * platform/graphics/qt/ImageBufferQt.cpp: Updated prototype for consistency.
        (WebCore::ImageBuffer::toDataURL):
        * platform/graphics/skia/ImageBufferSkia.cpp: Updated prototype for consistency.
        (WebCore::ImageBuffer::toDataURL):
        * platform/graphics/wince/ImageBufferWince.cpp: Updated prototype for consistency.
        (WebCore::ImageBuffer::toDataURL):
        * platform/graphics/wx/ImageBufferWx.cpp: Updated prototype for consistency.
        (WebCore::ImageBuffer::toDataURL):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@60675 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent e195240d
2010-06-04 Matthew Delaney <mdelaney@apple.com>
Reviewed by Darin Adler.
CG implementation needed for compression quality in canvas.toDataURL
https://bugs.webkit.org/show_bug.cgi?id=38492
* platform/mac/Skipped:
2010-06-04 Steve Block <steveblock@google.com>
Unreviewed. Test expectation fix.
......
......@@ -289,7 +289,6 @@ canvas/philip/tests/security.reset.html
canvas/philip/tests/size.attributes.parse.minus.html
canvas/philip/tests/size.attributes.setAttribute.minus.html
canvas/philip/tests/toDataURL.jpeg.alpha.html
canvas/philip/tests/toDataURL.jpeg.quality.basic.html
canvas/philip/tests/type.prototype.html
# IndexedDB is not yet enabled.
......
2010-06-04 Matthew Delaney <mdelaney@apple.com>
Reviewed by Darin Adler.
CG implementation needed for compression quality in canvas.toDataURL
https://bugs.webkit.org/show_bug.cgi?id=38492
Took toDataURL.jpeg.quality.basic.html test off of Skipped list. Passes.
Went the route of avoiding in-band signaling to flag the use of a quality
parameter or not. So, instead of simply passing the quality down as a
double, instead I pass a reference to the quality parameter from where
it comes in just after the JS bindings. Thus, no need for any global
constants to signify when the quality is not specified. Updated the other
platforms to support this (qt was on the only one currently with any
implementation).
* bindings/js/JSHTMLCanvasElementCustom.cpp: Moved range check logic for quality parameter down lower. Updated
call to toDataURL to use double* instead of just passing the quality directly.
(WebCore::JSHTMLCanvasElement::toDataURL):
* bindings/v8/custom/V8HTMLCanvasElementCustom.cpp: Updated toDataURL call to pass double*
(WebCore::V8HTMLCanvasElement::toDataURLCallback):
* dom/CanvasSurface.cpp: Updated method prototype.
(WebCore::CanvasSurface::toDataURL):
* dom/CanvasSurface.h: Updated method prototype.
(WebCore::CanvasSurface::toDataURL):
* platform/graphics/ImageBuffer.h: Updated method signature to use double* for quality param.
* platform/graphics/cairo/ImageBufferCairo.cpp: Updated prototype for consistency.
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/cg/ImageBufferCG.cpp: Implemented support for quality parametejr when jpeg MIME type used.
(WebCore::jpegUTI):
(WebCore::utiFromMIMEType):
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/haiku/ImageBufferHaiku.cpp: Updated prototype for consistency.
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/qt/ImageBufferQt.cpp: Updated prototype for consistency.
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/skia/ImageBufferSkia.cpp: Updated prototype for consistency.
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/wince/ImageBufferWince.cpp: Updated prototype for consistency.
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/wx/ImageBufferWx.cpp: Updated prototype for consistency.
(WebCore::ImageBuffer::toDataURL):
2010-06-04 Alejandro G. Castro <alex@igalia.com>
Reviewed by Xan Lopez.
......
......@@ -88,17 +88,21 @@ JSValue JSHTMLCanvasElement::getContext(ExecState* exec)
JSValue JSHTMLCanvasElement::toDataURL(ExecState* exec)
{
const String& type = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0));
double quality = 1.0;
HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(impl());
ExceptionCode ec = 0;
JSC::JSValue result;
double quality;
double* qualityPtr = 0;
if (exec->argumentCount() > 1) {
JSValue v = exec->argument(1);
if (v.isNumber())
if (v.isNumber()) {
quality = v.toNumber(exec);
if (!(0.0 <= quality && quality <= 1.0))
quality = 1.0;
qualityPtr = &quality;
}
}
HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(impl());
ExceptionCode ec = 0;
JSC::JSValue result = jsString(exec, canvas->toDataURL(type, quality, ec));
result = jsString(exec, canvas->toDataURL(type, qualityPtr, ec));
setDOMException(exec, ec);
return result;
}
......
......@@ -105,7 +105,7 @@ v8::Handle<v8::Value> V8HTMLCanvasElement::toDataURLCallback(const v8::Arguments
HTMLCanvasElement* canvas = V8HTMLCanvasElement::toNative(holder);
String type = toWebCoreString(args[0]);
ExceptionCode ec = 0;
String result = canvas->toDataURL(type, quality, ec);
String result = canvas->toDataURL(type, &quality, ec);
V8Proxy::setDOMException(ec);
return v8StringOrUndefined(result);
}
......
......@@ -65,7 +65,7 @@ void CanvasSurface::setSurfaceSize(const IntSize& size)
m_imageBuffer.clear();
}
String CanvasSurface::toDataURL(const String& mimeType, double quality, ExceptionCode& ec)
String CanvasSurface::toDataURL(const String& mimeType, const double* quality, ExceptionCode& ec)
{
if (!m_originClean) {
ec = SECURITY_ERR;
......
......@@ -59,9 +59,8 @@ public:
int width() const { return m_size.width(); }
int height() const { return m_size.height(); }
String toDataURL(const String& mimeType, double quality, ExceptionCode&);
String toDataURL(const String& mimeType, ExceptionCode& ec) { return toDataURL(mimeType, 1.0, ec); }
String toDataURL(const String& mimeType, const double* quality, ExceptionCode&);
String toDataURL(const String& mimeType, ExceptionCode& ec) { return toDataURL(mimeType, 0, ec); }
const IntSize& size() const { return m_size; }
......
......@@ -43,7 +43,7 @@ namespace WebCore {
class IntPoint;
class IntRect;
class String;
enum ImageColorSpace {
Unknown,
DeviceRGB, // like sRGB
......@@ -82,8 +82,8 @@ namespace WebCore {
void putUnmultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint);
void putPremultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint);
String toDataURL(const String& mimeType, double quality = 1.0) const;
String toDataURL(const String& mimeType, const double* quality = 0) const;
#if !PLATFORM(CG)
AffineTransform baseTransform() const { return AffineTransform(); }
void transformColorSpace(ImageColorSpace srcColorSpace, ImageColorSpace dstColorSpace);
......
......@@ -284,7 +284,7 @@ static cairo_status_t writeFunction(void* closure, const unsigned char* data, un
return CAIRO_STATUS_SUCCESS;
}
String ImageBuffer::toDataURL(const String& mimeType, double) const
String ImageBuffer::toDataURL(const String& mimeType, const double*) const
{
cairo_surface_t* image = cairo_get_target(context()->platformContext());
if (!image)
......
......@@ -250,6 +250,14 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size);
}
static inline CFStringRef jpegUTI()
{
#if PLATFORM(WIN)
static const CFStringRef kUTTypeJPEG = CFSTR("public.jpeg");
#endif
return kUTTypeJPEG;
}
static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType)
{
#if PLATFORM(MAC)
......@@ -261,13 +269,12 @@ static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType)
// FIXME: Add Windows support for all the supported UTIs when a way to convert from MIMEType to UTI reliably is found.
// For now, only support PNG, JPEG, and GIF. See <rdar://problem/6095286>.
static const CFStringRef kUTTypePNG = CFSTR("public.png");
static const CFStringRef kUTTypeJPEG = CFSTR("public.jpeg");
static const CFStringRef kUTTypeGIF = CFSTR("com.compuserve.gif");
if (equalIgnoringCase(mimeType, "image/png"))
return kUTTypePNG;
if (equalIgnoringCase(mimeType, "image/jpeg"))
return kUTTypeJPEG;
return jpegUTI();
if (equalIgnoringCase(mimeType, "image/gif"))
return kUTTypeGIF;
......@@ -276,7 +283,7 @@ static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType)
#endif
}
String ImageBuffer::toDataURL(const String& mimeType, double) const
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
{
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
......@@ -288,11 +295,23 @@ String ImageBuffer::toDataURL(const String& mimeType, double) const
if (!data)
return "data:,";
RetainPtr<CGImageDestinationRef> destination(AdoptCF, CGImageDestinationCreateWithData(data.get(), utiFromMIMEType(mimeType).get(), 1, 0));
RetainPtr<CFStringRef> uti = utiFromMIMEType(mimeType);
ASSERT(uti);
RetainPtr<CGImageDestinationRef> destination(AdoptCF, CGImageDestinationCreateWithData(data.get(), uti.get(), 1, 0));
if (!destination)
return "data:,";
CGImageDestinationAddImage(destination.get(), image.get(), 0);
RetainPtr<CFDictionaryRef> imageProperties = 0;
if (CFEqual(uti.get(), jpegUTI()) && quality && *quality >= 0.0 && *quality <= 1.0) {
// Apply the compression quality to the image destination.
RetainPtr<CFNumberRef> compressionQuality(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, quality));
const void* key = kCGImageDestinationLossyCompressionQuality;
const void* value = compressionQuality.get();
imageProperties.adoptCF(CFDictionaryCreate(0, &key, &value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
}
CGImageDestinationAddImage(destination.get(), image.get(), imageProperties.get());
CGImageDestinationFinalize(destination.get());
Vector<char> out;
......
......@@ -310,7 +310,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
putImageData(source, sourceRect, destPoint, m_data, m_size, true);
}
String ImageBuffer::toDataURL(const String& mimeType, double) const
String ImageBuffer::toDataURL(const String& mimeType, const double*) const
{
if (!MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType))
return "data:,";
......
......@@ -276,10 +276,9 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
// 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
// mimetypes and then remove the image/ to get the Qt format.
String ImageBuffer::toDataURL(const String& mimeType, double quality) const
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
{
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
ASSERT(0.0 <= quality && quality <= 1.0);
if (!mimeType.startsWith("image/"))
return "data:,";
......@@ -289,9 +288,16 @@ String ImageBuffer::toDataURL(const String& mimeType, double quality) const
QBuffer buffer(&data);
buffer.open(QBuffer::WriteOnly);
if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data(), quality * 100 + 0.5)) {
buffer.close();
return "data:,";
if (quality && *quality >= 0.0 && *quality <= 1.0) {
if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data(), *quality * 100 + 0.5)) {
buffer.close();
return "data:,";
}
} else {
if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data(), 100)) {
buffer.close();
return "data:,";
}
}
buffer.close();
......
......@@ -261,7 +261,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
putImageData<Premultiplied>(source, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size);
}
String ImageBuffer::toDataURL(const String&, double) const
String ImageBuffer::toDataURL(const String&, const double*) const
{
// Encode the image into a vector.
Vector<unsigned char> pngEncodedData;
......
......@@ -216,7 +216,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
putImageData<true>(source, sourceRect, destPoint, m_data.m_bitmap.get());
}
String ImageBuffer::toDataURL(const String& mimeType, double) const
String ImageBuffer::toDataURL(const String& mimeType, const double*) const
{
if (!m_data.m_bitmap->bytes())
return "data:,";
......
......@@ -76,7 +76,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
notImplemented();
}
String ImageBuffer::toDataURL(const String&, double) const
String ImageBuffer::toDataURL(const String&, const double*) const
{
notImplemented();
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