Diff
Modified: trunk/Source/WebCore/ChangeLog (254899 => 254900)
--- trunk/Source/WebCore/ChangeLog 2020-01-22 03:11:39 UTC (rev 254899)
+++ trunk/Source/WebCore/ChangeLog 2020-01-22 07:00:16 UTC (rev 254900)
@@ -1,3 +1,45 @@
+2020-01-21 Said Abou-Hallawa <[email protected]>
+
+ Move ImageBuffer utilities function to separate files
+ https://bugs.webkit.org/show_bug.cgi?id=206519
+
+ Reviewed by Tim Horton.
+
+ These utilities function are merely related to the ImageData.
+
+ * SourcesGTK.txt:
+ * html/HTMLCanvasElement.cpp:
+ * platform/SourcesCairo.txt:
+ * platform/graphics/ImageBuffer.h:
+ * platform/graphics/cairo/ImageBufferCairo.cpp:
+ (WebCore::ImageBuffer::toData const):
+ (WebCore::writeFunction): Deleted.
+ (WebCore::encodeImage): Deleted.
+ * platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp: Added.
+ (WebCore::writeFunction):
+ (WebCore::encodeImage):
+ (WebCore::data):
+ * platform/graphics/cairo/ImageBufferUtilitiesCairo.h: Added.
+ * platform/graphics/cg/ImageBufferCG.cpp:
+ (WebCore::jpegUTI): Deleted.
+ (WebCore::utiFromImageBufferMIMEType): Deleted.
+ (WebCore::encodeImage): Deleted.
+ (WebCore::dataURL): Deleted.
+ (WebCore::dataVector): Deleted.
+ (WebCore::cfData): Deleted.
+ (WebCore::data): Deleted.
+ * platform/graphics/cg/ImageBufferDataCG.h:
+ * platform/graphics/cg/ImageBufferUtilitiesCG.cpp:
+ (WebCore::jpegUTI):
+ (WebCore::utiFromImageBufferMIMEType):
+ (WebCore::encodeImage):
+ (WebCore::cfData):
+ (WebCore::dataURL):
+ (WebCore::dataVector):
+ (WebCore::data):
+ * platform/graphics/cg/ImageBufferUtilitiesCG.h:
+ * platform/graphics/gtk/ImageBufferGtk.cpp: Removed.
+
2020-01-21 Fujii Hironori <[email protected]>
A partially selected RTL text is placed at a wrong vertical position if it has a vertical initial advance
Modified: trunk/Source/WebCore/SourcesGTK.txt (254899 => 254900)
--- trunk/Source/WebCore/SourcesGTK.txt 2020-01-22 03:11:39 UTC (rev 254899)
+++ trunk/Source/WebCore/SourcesGTK.txt 2020-01-22 07:00:16 UTC (rev 254900)
@@ -84,7 +84,6 @@
platform/graphics/gtk/DisplayRefreshMonitorGtk.cpp
platform/graphics/gtk/GdkCairoUtilities.cpp
platform/graphics/gtk/IconGtk.cpp
-platform/graphics/gtk/ImageBufferGtk.cpp
platform/graphics/gtk/ImageGtk.cpp
platform/graphics/gstreamer/ImageGStreamerCairo.cpp
Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (254899 => 254900)
--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp 2020-01-22 03:11:39 UTC (rev 254899)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp 2020-01-22 07:00:16 UTC (rev 254900)
@@ -83,6 +83,10 @@
#include <pal/cf/CoreMediaSoftLink.h>
#endif
+#if USE(CG)
+#include "ImageBufferUtilitiesCG.h"
+#endif
+
namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLCanvasElement);
Modified: trunk/Source/WebCore/platform/SourcesCairo.txt (254899 => 254900)
--- trunk/Source/WebCore/platform/SourcesCairo.txt 2020-01-22 03:11:39 UTC (rev 254899)
+++ trunk/Source/WebCore/platform/SourcesCairo.txt 2020-01-22 07:00:16 UTC (rev 254900)
@@ -31,6 +31,7 @@
platform/graphics/cairo/GraphicsContextCairo.cpp
platform/graphics/cairo/GraphicsContextImplCairo.cpp
platform/graphics/cairo/ImageBufferCairo.cpp
+platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp
platform/graphics/cairo/IntRectCairo.cpp
platform/graphics/cairo/NativeImageCairo.cpp
platform/graphics/cairo/PathCairo.cpp
Modified: trunk/Source/WebCore/platform/graphics/ImageBuffer.h (254899 => 254900)
--- trunk/Source/WebCore/platform/graphics/ImageBuffer.h 2020-01-22 03:11:39 UTC (rev 254899)
+++ trunk/Source/WebCore/platform/graphics/ImageBuffer.h 2020-01-22 07:00:16 UTC (rev 254900)
@@ -190,9 +190,4 @@
#endif
};
-#if USE(CG)
-String dataURL(const ImageData&, const String& mimeType, Optional<double> quality);
-Vector<uint8_t> data(const ImageData&, const String& mimeType, Optional<double> quality);
-#endif
-
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp (254899 => 254900)
--- trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp 2020-01-22 03:11:39 UTC (rev 254899)
+++ trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp 2020-01-22 07:00:16 UTC (rev 254900)
@@ -37,6 +37,7 @@
#include "Color.h"
#include "GraphicsContext.h"
#include "GraphicsContextImplCairo.h"
+#include "ImageBufferUtilitiesCairo.h"
#include "MIMETypeRegistry.h"
#include "NotImplemented.h"
#include "Pattern.h"
@@ -76,7 +77,6 @@
#endif
#endif
-
namespace WebCore {
ImageBufferData::ImageBufferData(const IntSize& size, RenderingMode renderingMode)
@@ -654,21 +654,6 @@
}
}
-#if !PLATFORM(GTK)
-static cairo_status_t writeFunction(void* output, const unsigned char* data, unsigned int length)
-{
- if (!reinterpret_cast<Vector<uint8_t>*>(output)->tryAppend(data, length))
- return CAIRO_STATUS_WRITE_ERROR;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static bool encodeImage(cairo_surface_t* image, const String& mimeType, Vector<uint8_t>* output)
-{
- ASSERT_UNUSED(mimeType, mimeType == "image/png"); // Only PNG output is supported for now.
-
- return cairo_surface_write_to_png_stream(image, writeFunction, output) == CAIRO_STATUS_SUCCESS;
-}
-
String ImageBuffer::toDataURL(const String& mimeType, Optional<double> quality, PreserveResolution) const
{
Vector<uint8_t> encodedImage = toData(mimeType, quality);
@@ -681,21 +666,13 @@
return "data:" + mimeType + ";base64," + base64Data;
}
-Vector<uint8_t> ImageBuffer::toData(const String& mimeType, Optional<double>) const
+Vector<uint8_t> ImageBuffer::toData(const String& mimeType, Optional<double> quality) const
{
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
-
cairo_surface_t* image = cairo_get_target(context().platformContext()->cr());
-
- Vector<uint8_t> encodedImage;
- if (!image || !encodeImage(image, mimeType, &encodedImage))
- return { };
-
- return encodedImage;
+ return data(image, mimeType, quality);
}
-#endif
-
#if ENABLE(ACCELERATED_2D_CANVAS) && !USE(COORDINATED_GRAPHICS)
void ImageBufferData::paintToTextureMapper(TextureMapper& textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity)
{
Copied: trunk/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp (from rev 254899, trunk/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp) (0 => 254900)
--- trunk/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp (rev 0)
+++ trunk/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp 2020-01-22 07:00:16 UTC (rev 254900)
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <[email protected]>
+ * Copyright (C) 2007 Holger Hans Peter Freyther <[email protected]>
+ * Copyright (C) 2008, 2009 Dirk Schulze <[email protected]>
+ * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
+ * Copyright (C) 2010 Igalia S.L.
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ImageBufferUtilitiesCairo.h"
+
+#if USE(CAIRO)
+
+#include "CairoUtilities.h"
+#include "MIMETypeRegistry.h"
+#include <cairo.h>
+#include <wtf/text/Base64.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+#if PLATFORM(GTK)
+#include "GRefPtrGtk.h"
+#include "GdkCairoUtilities.h"
+#include <gtk/gtk.h>
+#include <wtf/glib/GUniquePtr.h>
+#endif
+
+namespace WebCore {
+
+#if !PLATFORM(GTK)
+static cairo_status_t writeFunction(void* output, const unsigned char* data, unsigned length)
+{
+ if (!reinterpret_cast<Vector<uint8_t>*>(output)->tryAppend(data, length))
+ return CAIRO_STATUS_WRITE_ERROR;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static bool encodeImage(cairo_surface_t* image, const String& mimeType, Vector<uint8_t>* output)
+{
+ ASSERT_UNUSED(mimeType, mimeType == "image/png"); // Only PNG output is supported for now.
+
+ return cairo_surface_write_to_png_stream(image, writeFunction, output) == CAIRO_STATUS_SUCCESS;
+}
+
+Vector<uint8_t> data(cairo_surface_t* image, const String& mimeType, Optional<double>)
+{
+ Vector<uint8_t> encodedImage;
+ if (!image || !encodeImage(image, mimeType, &encodedImage))
+ return { };
+ return encodedImage;
+}
+#else
+static bool encodeImage(cairo_surface_t* surface, const String& mimeType, Optional<double> quality, GUniqueOutPtr<gchar>& buffer, gsize& bufferSize)
+{
+ // List of supported image encoding types comes from the GdkPixbuf documentation.
+ // http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-File-saving.html#gdk-pixbuf-save-to-bufferv
+
+ String type = mimeType.substring(sizeof "image");
+ if (type != "jpeg" && type != "png" && type != "tiff" && type != "ico" && type != "bmp")
+ return false;
+
+ GRefPtr<GdkPixbuf> pixbuf;
+ if (type == "jpeg") {
+ // JPEG doesn't support alpha channel. The <canvas> spec states that toDataURL() must encode a Porter-Duff
+ // composite source-over black for image types that do not support alpha.
+ RefPtr<cairo_surface_t> newSurface;
+ if (cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE) {
+ newSurface = adoptRef(cairo_image_surface_create_for_data(cairo_image_surface_get_data(surface),
+ CAIRO_FORMAT_RGB24,
+ cairo_image_surface_get_width(surface),
+ cairo_image_surface_get_height(surface),
+ cairo_image_surface_get_stride(surface)));
+ } else {
+ IntSize size = cairoSurfaceSize(surface);
+ newSurface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_RGB24, size.width(), size.height()));
+ RefPtr<cairo_t> cr = adoptRef(cairo_create(newSurface.get()));
+ cairo_set_source_surface(cr.get(), surface, 0, 0);
+ cairo_paint(cr.get());
+ }
+ pixbuf = adoptGRef(cairoSurfaceToGdkPixbuf(newSurface.get()));
+ } else
+ pixbuf = adoptGRef(cairoSurfaceToGdkPixbuf(surface));
+ if (!pixbuf)
+ return false;
+
+ GUniqueOutPtr<GError> error;
+ if (type == "jpeg" && quality && *quality >= 0.0 && *quality <= 1.0) {
+ String qualityString = String::number(static_cast<int>(*quality * 100.0 + 0.5));
+ gdk_pixbuf_save_to_buffer(pixbuf.get(), &buffer.outPtr(), &bufferSize, type.utf8().data(), &error.outPtr(), "quality", qualityString.utf8().data(), NULL);
+ } else
+ gdk_pixbuf_save_to_buffer(pixbuf.get(), &buffer.outPtr(), &bufferSize, type.utf8().data(), &error.outPtr(), NULL);
+
+ return !error;
+}
+
+Vector<uint8_t> data(cairo_surface_t* image, const String& mimeType, Optional<double> quality)
+{
+ GUniqueOutPtr<gchar> buffer;
+ gsize bufferSize;
+ if (!encodeImage(image, mimeType, quality, buffer, bufferSize))
+ return { };
+
+ Vector<uint8_t> imageData;
+ imageData.append(buffer.get(), bufferSize);
+ return imageData;
+}
+#endif // !PLATFORM(GTK)
+
+} // namespace WebCore
+
+#endif // USE(CAIRO)
Added: trunk/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.h (0 => 254900)
--- trunk/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.h (rev 0)
+++ trunk/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.h 2020-01-22 07:00:16 UTC (rev 254900)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <[email protected]>
+ * Copyright (C) 2007 Holger Hans Peter Freyther <[email protected]>
+ * Copyright (C) 2008, 2009 Dirk Schulze <[email protected]>
+ * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if USE(CAIRO)
+
+#include <cairo.h>
+#include <wtf/Optional.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+Vector<uint8_t> data(cairo_surface_t*, const String& mimeType, Optional<double> quality);
+
+} // namespace WebCore
+
+#endif // USE(CAIRO)
Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp (254899 => 254900)
--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp 2020-01-22 03:11:39 UTC (rev 254899)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp 2020-01-22 07:00:16 UTC (rev 254900)
@@ -445,79 +445,6 @@
context().fillRect(FloatRect(1, 1, 0, 0));
}
-static inline CFStringRef jpegUTI()
-{
-#if PLATFORM(IOS_FAMILY) || PLATFORM(WIN)
- static const CFStringRef kUTTypeJPEG = CFSTR("public.jpeg");
-#endif
- return kUTTypeJPEG;
-}
-
-static RetainPtr<CFStringRef> utiFromImageBufferMIMEType(const String& mimeType)
-{
- // FIXME: Why doesn't iOS use the CoreServices version?
-#if PLATFORM(MAC)
- return UTIFromMIMEType(mimeType).createCFString();
-#else
- ASSERT(isMainThread()); // It is unclear if CFSTR is threadsafe.
-
- // 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 kUTTypeGIF = CFSTR("com.compuserve.gif");
-
- if (equalLettersIgnoringASCIICase(mimeType, "image/png"))
- return kUTTypePNG;
- if (equalLettersIgnoringASCIICase(mimeType, "image/jpeg"))
- return jpegUTI();
- if (equalLettersIgnoringASCIICase(mimeType, "image/gif"))
- return kUTTypeGIF;
-
- ASSERT_NOT_REACHED();
- return kUTTypePNG;
-#endif
-}
-
-static bool encodeImage(CGImageRef image, CFStringRef uti, Optional<double> quality, CFMutableDataRef data)
-{
- if (!image || !uti || !data)
- return false;
-
- auto destination = adoptCF(CGImageDestinationCreateWithData(data, uti, 1, 0));
- if (!destination)
- return false;
-
- RetainPtr<CFDictionaryRef> imageProperties;
- if (CFEqual(uti, jpegUTI()) && quality && *quality >= 0.0 && *quality <= 1.0) {
- // Apply the compression quality to the JPEG image destination.
- auto compressionQuality = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &*quality));
- const void* key = kCGImageDestinationLossyCompressionQuality;
- const void* value = compressionQuality.get();
- imageProperties = adoptCF(CFDictionaryCreate(0, &key, &value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
- }
-
- // Setting kCGImageDestinationBackgroundColor to black for JPEG images in imageProperties would save some math
- // in the calling functions, but it doesn't seem to work.
-
- CGImageDestinationAddImage(destination.get(), image, imageProperties.get());
- return CGImageDestinationFinalize(destination.get());
-}
-
-static String dataURL(CFDataRef data, const String& mimeType)
-{
- Vector<char> base64Data;
- base64Encode(CFDataGetBytePtr(data), CFDataGetLength(data), base64Data);
-
- return "data:" + mimeType + ";base64," + base64Data;
-}
-
-static Vector<uint8_t> dataVector(CFDataRef cfData)
-{
- Vector<uint8_t> data;
- data.append(CFDataGetBytePtr(cfData), CFDataGetLength(cfData));
- return data;
-}
-
String ImageBuffer::toDataURL(const String& mimeType, Optional<double> quality, PreserveResolution preserveResolution) const
{
if (auto data = "" quality, preserveResolution))
@@ -578,70 +505,6 @@
return WTFMove(cfData);
}
-static RetainPtr<CFDataRef> cfData(const ImageData& source, const String& mimeType, Optional<double> quality)
-{
- ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
-
- auto uti = utiFromImageBufferMIMEType(mimeType);
- ASSERT(uti);
-
- CGImageAlphaInfo dataAlphaInfo = kCGImageAlphaLast;
- unsigned char* data = ""
- Vector<uint8_t> premultipliedData;
-
- if (CFEqual(uti.get(), jpegUTI())) {
- // JPEGs don't have an alpha channel, so we have to manually composite on top of black.
- size_t size = 4 * source.width() * source.height();
- if (!premultipliedData.tryReserveCapacity(size))
- return nullptr;
-
- premultipliedData.grow(size);
- unsigned char *buffer = premultipliedData.data();
- for (size_t i = 0; i < size; i += 4) {
- unsigned alpha = data[i + 3];
- if (alpha != 255) {
- buffer[i + 0] = data[i + 0] * alpha / 255;
- buffer[i + 1] = data[i + 1] * alpha / 255;
- buffer[i + 2] = data[i + 2] * alpha / 255;
- } else {
- buffer[i + 0] = data[i + 0];
- buffer[i + 1] = data[i + 1];
- buffer[i + 2] = data[i + 2];
- }
- }
-
- dataAlphaInfo = kCGImageAlphaNoneSkipLast; // Ignore the alpha channel.
- data = ""
- }
-
- verifyImageBufferIsBigEnough(data, 4 * source.width() * source.height());
- auto dataProvider = adoptCF(CGDataProviderCreateWithData(0, data, 4 * source.width() * source.height(), 0));
- if (!dataProvider)
- return nullptr;
-
- auto image = adoptCF(CGImageCreate(source.width(), source.height(), 8, 32, 4 * source.width(), sRGBColorSpaceRef(), kCGBitmapByteOrderDefault | dataAlphaInfo, dataProvider.get(), 0, false, kCGRenderingIntentDefault));
-
- auto cfData = adoptCF(CFDataCreateMutable(kCFAllocatorDefault, 0));
- if (!encodeImage(image.get(), uti.get(), quality, cfData.get()))
- return nullptr;
-
- return WTFMove(cfData);
-}
-
-String dataURL(const ImageData& source, const String& mimeType, Optional<double> quality)
-{
- if (auto data = "" mimeType, quality))
- return dataURL(data.get(), mimeType);
- return "data:,"_s;
-}
-
-Vector<uint8_t> data(const ImageData& source, const String& mimeType, Optional<double> quality)
-{
- if (auto data = "" mimeType, quality))
- return dataVector(data.get());
- return { };
-}
-
Vector<uint8_t> ImageBuffer::toBGRAData() const
{
if (context().isAcceleratedContext())
Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.cpp (254899 => 254900)
--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.cpp 2020-01-22 03:11:39 UTC (rev 254899)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.cpp 2020-01-22 07:00:16 UTC (rev 254900)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2018-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,8 +26,19 @@
#include "config.h"
#include "ImageBufferUtilitiesCG.h"
+#if USE(CG)
+
+#include "GraphicsContextCG.h"
+#include "ImageData.h"
+#include "MIMETypeRegistry.h"
+#include <ImageIO/ImageIO.h>
#include <wtf/CheckedArithmetic.h>
+#include <wtf/text/Base64.h>
+#if PLATFORM(COCOA)
+#include "UTIUtilities.h"
+#endif
+
namespace WebCore {
uint8_t verifyImageBufferIsBigEnough(const void* buffer, size_t bufferSize)
@@ -41,4 +52,143 @@
return *(uint8_t*)lastByte;
}
+CFStringRef jpegUTI()
+{
+#if PLATFORM(IOS_FAMILY) || PLATFORM(WIN)
+ static const CFStringRef kUTTypeJPEG = CFSTR("public.jpeg");
+#endif
+ return kUTTypeJPEG;
}
+
+RetainPtr<CFStringRef> utiFromImageBufferMIMEType(const String& mimeType)
+{
+ // FIXME: Why doesn't iOS use the CoreServices version?
+#if PLATFORM(MAC)
+ return UTIFromMIMEType(mimeType).createCFString();
+#else
+ ASSERT(isMainThread()); // It is unclear if CFSTR is threadsafe.
+
+ // 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 kUTTypeGIF = CFSTR("com.compuserve.gif");
+
+ if (equalLettersIgnoringASCIICase(mimeType, "image/png"))
+ return kUTTypePNG;
+ if (equalLettersIgnoringASCIICase(mimeType, "image/jpeg"))
+ return jpegUTI();
+ if (equalLettersIgnoringASCIICase(mimeType, "image/gif"))
+ return kUTTypeGIF;
+
+ ASSERT_NOT_REACHED();
+ return kUTTypePNG;
+#endif
+}
+
+bool encodeImage(CGImageRef image, CFStringRef uti, Optional<double> quality, CFMutableDataRef data)
+{
+ if (!image || !uti || !data)
+ return false;
+
+ auto destination = adoptCF(CGImageDestinationCreateWithData(data, uti, 1, 0));
+ if (!destination)
+ return false;
+
+ RetainPtr<CFDictionaryRef> imageProperties;
+ if (CFEqual(uti, jpegUTI()) && quality && *quality >= 0.0 && *quality <= 1.0) {
+ // Apply the compression quality to the JPEG image destination.
+ auto compressionQuality = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &*quality));
+ const void* key = kCGImageDestinationLossyCompressionQuality;
+ const void* value = compressionQuality.get();
+ imageProperties = adoptCF(CFDictionaryCreate(0, &key, &value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ }
+
+ // Setting kCGImageDestinationBackgroundColor to black for JPEG images in imageProperties would save some math
+ // in the calling functions, but it doesn't seem to work.
+
+ CGImageDestinationAddImage(destination.get(), image, imageProperties.get());
+ return CGImageDestinationFinalize(destination.get());
+}
+
+static RetainPtr<CFDataRef> cfData(const ImageData& source, const String& mimeType, Optional<double> quality)
+{
+ ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
+
+ auto uti = utiFromImageBufferMIMEType(mimeType);
+ ASSERT(uti);
+
+ CGImageAlphaInfo dataAlphaInfo = kCGImageAlphaLast;
+ unsigned char* data = ""
+ Vector<uint8_t> premultipliedData;
+
+ if (CFEqual(uti.get(), jpegUTI())) {
+ // JPEGs don't have an alpha channel, so we have to manually composite on top of black.
+ size_t size = 4 * source.width() * source.height();
+ if (!premultipliedData.tryReserveCapacity(size))
+ return nullptr;
+
+ premultipliedData.grow(size);
+ unsigned char* buffer = premultipliedData.data();
+ for (size_t i = 0; i < size; i += 4) {
+ unsigned alpha = data[i + 3];
+ if (alpha != 255) {
+ buffer[i + 0] = data[i + 0] * alpha / 255;
+ buffer[i + 1] = data[i + 1] * alpha / 255;
+ buffer[i + 2] = data[i + 2] * alpha / 255;
+ } else {
+ buffer[i + 0] = data[i + 0];
+ buffer[i + 1] = data[i + 1];
+ buffer[i + 2] = data[i + 2];
+ }
+ }
+
+ dataAlphaInfo = kCGImageAlphaNoneSkipLast; // Ignore the alpha channel.
+ data = ""
+ }
+
+ verifyImageBufferIsBigEnough(data, 4 * source.width() * source.height());
+ auto dataProvider = adoptCF(CGDataProviderCreateWithData(0, data, 4 * source.width() * source.height(), 0));
+ if (!dataProvider)
+ return nullptr;
+
+ auto image = adoptCF(CGImageCreate(source.width(), source.height(), 8, 32, 4 * source.width(), sRGBColorSpaceRef(), kCGBitmapByteOrderDefault | dataAlphaInfo, dataProvider.get(), 0, false, kCGRenderingIntentDefault));
+
+ auto cfData = adoptCF(CFDataCreateMutable(kCFAllocatorDefault, 0));
+ if (!encodeImage(image.get(), uti.get(), quality, cfData.get()))
+ return nullptr;
+
+ return WTFMove(cfData);
+}
+
+String dataURL(CFDataRef data, const String& mimeType)
+{
+ Vector<char> base64Data;
+ base64Encode(CFDataGetBytePtr(data), CFDataGetLength(data), base64Data);
+
+ return "data:" + mimeType + ";base64," + base64Data;
+}
+
+String dataURL(const ImageData& source, const String& mimeType, Optional<double> quality)
+{
+ if (auto data = "" mimeType, quality))
+ return dataURL(data.get(), mimeType);
+ return "data:,"_s;
+}
+
+Vector<uint8_t> dataVector(CFDataRef cfData)
+{
+ Vector<uint8_t> data;
+ data.append(CFDataGetBytePtr(cfData), CFDataGetLength(cfData));
+ return data;
+}
+
+Vector<uint8_t> data(const ImageData& source, const String& mimeType, Optional<double> quality)
+{
+ if (auto data = "" mimeType, quality))
+ return dataVector(data.get());
+ return { };
+}
+
+} // namespace WebCore
+
+#endif // USE(CG)
Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h (254899 => 254900)
--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h 2020-01-22 03:11:39 UTC (rev 254899)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h 2020-01-22 07:00:16 UTC (rev 254900)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2018-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,8 +25,31 @@
#pragma once
+#if USE(CG)
+
+#include <wtf/Forward.h>
+#include <wtf/Optional.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
namespace WebCore {
+class ImageData;
+
WEBCORE_EXPORT uint8_t verifyImageBufferIsBigEnough(const void* buffer, size_t bufferSize);
-}
+CFStringRef jpegUTI();
+RetainPtr<CFStringRef> utiFromImageBufferMIMEType(const String&);
+
+bool encodeImage(CGImageRef, CFStringRef uti, Optional<double> quality, CFMutableDataRef);
+
+String dataURL(CFDataRef, const String& mimeType);
+String dataURL(const ImageData&, const String& mimeType, Optional<double> quality);
+
+Vector<uint8_t> dataVector(CFDataRef);
+Vector<uint8_t> data(const ImageData&, const String& mimeType, Optional<double> quality);
+
+} // namespace WebCore
+
+#endif // USE(CG)
Deleted: trunk/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp (254899 => 254900)
--- trunk/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp 2020-01-22 03:11:39 UTC (rev 254899)
+++ trunk/Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp 2020-01-22 07:00:16 UTC (rev 254900)
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-#include "ImageBuffer.h"
-
-#include "CairoUtilities.h"
-#include "GRefPtrGtk.h"
-#include "GdkCairoUtilities.h"
-#include "MIMETypeRegistry.h"
-#include <cairo.h>
-#include <gtk/gtk.h>
-#include <wtf/glib/GUniquePtr.h>
-#include <wtf/text/Base64.h>
-#include <wtf/text/CString.h>
-#include <wtf/text/WTFString.h>
-
-namespace WebCore {
-
-static bool encodeImage(cairo_surface_t* surface, const String& mimeType, Optional<double> quality, GUniqueOutPtr<gchar>& buffer, gsize& bufferSize)
-{
- // List of supported image encoding types comes from the GdkPixbuf documentation.
- // http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-File-saving.html#gdk-pixbuf-save-to-bufferv
-
- String type = mimeType.substring(sizeof "image");
- if (type != "jpeg" && type != "png" && type != "tiff" && type != "ico" && type != "bmp")
- return false;
-
- GRefPtr<GdkPixbuf> pixbuf;
- if (type == "jpeg") {
- // JPEG doesn't support alpha channel. The <canvas> spec states that toDataURL() must encode a Porter-Duff
- // composite source-over black for image types that do not support alpha.
- RefPtr<cairo_surface_t> newSurface;
- if (cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE) {
- newSurface = adoptRef(cairo_image_surface_create_for_data(cairo_image_surface_get_data(surface),
- CAIRO_FORMAT_RGB24,
- cairo_image_surface_get_width(surface),
- cairo_image_surface_get_height(surface),
- cairo_image_surface_get_stride(surface)));
- } else {
- IntSize size = cairoSurfaceSize(surface);
- newSurface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_RGB24, size.width(), size.height()));
- RefPtr<cairo_t> cr = adoptRef(cairo_create(newSurface.get()));
- cairo_set_source_surface(cr.get(), surface, 0, 0);
- cairo_paint(cr.get());
- }
- pixbuf = adoptGRef(cairoSurfaceToGdkPixbuf(newSurface.get()));
- } else
- pixbuf = adoptGRef(cairoSurfaceToGdkPixbuf(surface));
- if (!pixbuf)
- return false;
-
- GUniqueOutPtr<GError> error;
- if (type == "jpeg" && quality && *quality >= 0.0 && *quality <= 1.0) {
- String qualityString = String::number(static_cast<int>(*quality * 100.0 + 0.5));
- gdk_pixbuf_save_to_buffer(pixbuf.get(), &buffer.outPtr(), &bufferSize, type.utf8().data(), &error.outPtr(), "quality", qualityString.utf8().data(), NULL);
- } else
- gdk_pixbuf_save_to_buffer(pixbuf.get(), &buffer.outPtr(), &bufferSize, type.utf8().data(), &error.outPtr(), NULL);
-
- return !error;
-}
-
-String ImageBuffer::toDataURL(const String& mimeType, Optional<double> quality, PreserveResolution) const
-{
- Vector<uint8_t> imageData = toData(mimeType, quality);
- if (imageData.isEmpty())
- return "data:,";
-
- Vector<char> base64Data;
- base64Encode(imageData.data(), imageData.size(), base64Data);
-
- return "data:" + mimeType + ";base64," + base64Data;
-}
-
-Vector<uint8_t> ImageBuffer::toData(const String& mimeType, Optional<double> quality) const
-{
- ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
-
- GUniqueOutPtr<gchar> buffer;
- gsize bufferSize;
- if (!encodeImage(m_data.m_surface.get(), mimeType, quality, buffer, bufferSize))
- return { };
-
- Vector<uint8_t> imageData;
- imageData.append(buffer.get(), bufferSize);
- return imageData;
-}
-
-}