diff --git a/Source/WebCore/PlatformGTK.cmake b/Source/WebCore/PlatformGTK.cmake index 51f4309ea40b..b4b6de2c4a8d 100644 --- a/Source/WebCore/PlatformGTK.cmake +++ b/Source/WebCore/PlatformGTK.cmake @@ -57,6 +57,7 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS platform/graphics/gbm/PlatformDisplayGBM.h platform/graphics/gtk/GdkCairoUtilities.h + platform/graphics/gtk/GdkSkiaUtilities.h platform/graphics/x11/PlatformDisplayX11.h platform/graphics/x11/XErrorTrapper.h diff --git a/Source/WebCore/SourcesGTK.txt b/Source/WebCore/SourcesGTK.txt index ccc9c5b34bb9..867352b02040 100644 --- a/Source/WebCore/SourcesGTK.txt +++ b/Source/WebCore/SourcesGTK.txt @@ -70,6 +70,7 @@ platform/graphics/gbm/PlatformDisplayGBM.cpp @no-unify platform/graphics/gtk/ColorGtk.cpp platform/graphics/gtk/GdkCairoUtilities.cpp +platform/graphics/gtk/GdkSkiaUtilities.cpp platform/graphics/gtk/ImageAdapterGtk.cpp platform/graphics/gtk/SystemFontDatabaseGTK.cpp diff --git a/Source/WebCore/platform/graphics/gtk/GdkSkiaUtilities.cpp b/Source/WebCore/platform/graphics/gtk/GdkSkiaUtilities.cpp new file mode 100644 index 000000000000..be392ab8fa6a --- /dev/null +++ b/Source/WebCore/platform/graphics/gtk/GdkSkiaUtilities.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2024 Igalia S.L. + * + * 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 "GdkSkiaUtilities.h" + +#if USE(SKIA) + +#if !USE(GTK4) +#include +#endif + +IGNORE_CLANG_WARNINGS_BEGIN("cast-align") +#include +IGNORE_CLANG_WARNINGS_END + +namespace WebCore { + +#if USE(GTK4) +GRefPtr skiaImageToGdkTexture(SkImage& image) +{ + SkPixmap pixmap; + if (!image.peekPixels(&pixmap)) + return { }; + + GRefPtr bytes = adoptGRef(g_bytes_new_with_free_func(pixmap.addr(), pixmap.computeByteSize(), [](gpointer data) { + static_cast(data)->unref(); + }, SkRef(&image))); + + return adoptGRef(gdk_memory_texture_new(pixmap.width(), pixmap.height(), GDK_MEMORY_DEFAULT, bytes.get(), pixmap.rowBytes())); +} + +#else + +RefPtr skiaImageToCairoSurface(SkImage& image) +{ + SkPixmap pixmap; + if (!image.peekPixels(&pixmap)) + return { }; + + RefPtr surface = adoptRef(cairo_image_surface_create_for_data(pixmap.writable_addr8(0, 0), CAIRO_FORMAT_ARGB32, pixmap.width(), pixmap.height(), pixmap.rowBytes())); + if (cairo_surface_status(surface.get()) != CAIRO_STATUS_SUCCESS) + return { }; + + static cairo_user_data_key_t surfaceDataKey; + cairo_surface_set_user_data(surface.get(), &surfaceDataKey, SkRef(&image), [](void* data) { + static_cast(data)->unref(); + }); + + return surface; +} +#endif + +} // namespace WebCore + +#endif // #if USE(SKIA) diff --git a/Source/WebCore/platform/graphics/gtk/GdkSkiaUtilities.h b/Source/WebCore/platform/graphics/gtk/GdkSkiaUtilities.h new file mode 100644 index 000000000000..0e0cf7857fa5 --- /dev/null +++ b/Source/WebCore/platform/graphics/gtk/GdkSkiaUtilities.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2024 Igalia S.L. + * + * 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(SKIA) + +#include +#include + +#if USE(GTK4) +#include +#else +#include +#endif + +namespace WebCore { + +#if USE(GTK4) +GRefPtr skiaImageToGdkTexture(SkImage&); +#else +RefPtr skiaImageToCairoSurface(SkImage&); +#endif + +} + +#endif // USE(SKIA) diff --git a/Source/WebKit/UIProcess/API/glib/WebKitFaviconDatabase.cpp b/Source/WebKit/UIProcess/API/glib/WebKitFaviconDatabase.cpp index 386a522e4063..58f8e0140547 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitFaviconDatabase.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitFaviconDatabase.cpp @@ -36,6 +36,7 @@ #if PLATFORM(GTK) #include +#include #include #endif @@ -187,21 +188,22 @@ void webkitFaviconDatabaseGetFaviconInternal(WebKitFaviconDatabase* database, co } GRefPtr task = adoptGRef(g_task_new(database, cancellable, callback, userData)); -#if USE(CAIRO) WebKitFaviconDatabasePrivate* priv = database->priv; priv->iconDatabase->loadIconForPageURL(String::fromUTF8(pageURI), isEphemeral ? IconDatabase::AllowDatabaseWrite::No : IconDatabase::AllowDatabaseWrite::Yes, - [task = WTFMove(task), pageURI = CString(pageURI)](RefPtr&& icon) { + [task = WTFMove(task), pageURI = CString(pageURI)](PlatformImagePtr&& icon) { if (!icon) { g_task_return_new_error(task.get(), WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN, _("Unknown favicon for page %s"), pageURI.data()); return; } +#if USE(CAIRO) g_task_return_pointer(task.get(), icon.leakRef(), reinterpret_cast(cairo_surface_destroy)); - }); #elif USE(SKIA) - notImplemented(); - g_task_return_new_error(task.get(), WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN, _("Unknown favicon for page %s"), pageURI); + g_task_return_pointer(task.get(), SkRef(icon.get()), [](gpointer data) { + static_cast(data)->unref(); + }); #endif + }); } /** @@ -254,18 +256,25 @@ cairo_surface_t* webkit_favicon_database_get_favicon_finish(WebKitFaviconDatabas #if USE(CAIRO) auto image = adoptRef(static_cast(g_task_propagate_pointer(G_TASK(result), error))); auto texture = image ? cairoSurfaceToGdkTexture(image.get()) : nullptr; - if (texture) - return texture.leakRef(); #elif USE(SKIA) - notImplemented(); + auto* image = static_cast(g_task_propagate_pointer(G_TASK(result), error)); + auto texture = image ? skiaImageToGdkTexture(*image) : nullptr; #endif + + if (texture) + return texture.leakRef(); // FIXME: Add a new WEBKIT_FAVICON_DATABASE_ERROR if (error && !*error) g_set_error_literal(error, WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN, _("Failed to create texture")); return nullptr; +#else +#if USE(SKIA) + auto* image = static_cast(g_task_propagate_pointer(G_TASK(result), error)); + return image ? skiaImageToCairoSurface(*image).leakRef() : nullptr; #else return static_cast(g_task_propagate_pointer(G_TASK(result), error)); #endif +#endif } #endif