Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Skia] Add support for favicons on GTK #25735

Merged
merged 1 commit into from Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Source/WebCore/PlatformGTK.cmake
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/SourcesGTK.txt
Expand Up @@ -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

Expand Down
78 changes: 78 additions & 0 deletions 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 <graphics/cairo/RefPtrCairo.h>
#endif

IGNORE_CLANG_WARNINGS_BEGIN("cast-align")
#include <skia/core/SkPixmap.h>
IGNORE_CLANG_WARNINGS_END

namespace WebCore {

#if USE(GTK4)
GRefPtr<GdkTexture> skiaImageToGdkTexture(SkImage& image)
{
SkPixmap pixmap;
if (!image.peekPixels(&pixmap))
return { };

GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new_with_free_func(pixmap.addr(), pixmap.computeByteSize(), [](gpointer data) {
static_cast<SkImage*>(data)->unref();
}, SkRef(&image)));

return adoptGRef(gdk_memory_texture_new(pixmap.width(), pixmap.height(), GDK_MEMORY_DEFAULT, bytes.get(), pixmap.rowBytes()));
}

#else

RefPtr<cairo_surface_t> skiaImageToCairoSurface(SkImage& image)
{
SkPixmap pixmap;
if (!image.peekPixels(&pixmap))
return { };

RefPtr<cairo_surface_t> 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<SkImage*>(data)->unref();
});

return surface;
}
#endif

} // namespace WebCore

#endif // #if USE(SKIA)
49 changes: 49 additions & 0 deletions 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 <skia/core/SkImage.h>
#include <wtf/glib/GRefPtr.h>

#if USE(GTK4)
#include <gdk/gdk.h>
#else
#include <cairo.h>
#endif

namespace WebCore {

#if USE(GTK4)
GRefPtr<GdkTexture> skiaImageToGdkTexture(SkImage&);
#else
RefPtr<cairo_surface_t> skiaImageToCairoSurface(SkImage&);
#endif

}

#endif // USE(SKIA)
25 changes: 17 additions & 8 deletions Source/WebKit/UIProcess/API/glib/WebKitFaviconDatabase.cpp
Expand Up @@ -36,6 +36,7 @@

#if PLATFORM(GTK)
#include <WebCore/GdkCairoUtilities.h>
#include <WebCore/GdkSkiaUtilities.h>
#include <WebCore/RefPtrCairo.h>
#endif

Expand Down Expand Up @@ -187,21 +188,22 @@ void webkitFaviconDatabaseGetFaviconInternal(WebKitFaviconDatabase* database, co
}

GRefPtr<GTask> 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<cairo_surface_t>&& 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<GDestroyNotify>(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<SkImage*>(data)->unref();
});
#endif
});
}

/**
Expand Down Expand Up @@ -254,18 +256,25 @@ cairo_surface_t* webkit_favicon_database_get_favicon_finish(WebKitFaviconDatabas
#if USE(CAIRO)
auto image = adoptRef(static_cast<cairo_surface_t*>(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<SkImage*>(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<SkImage*>(g_task_propagate_pointer(G_TASK(result), error));
return image ? skiaImageToCairoSurface(*image).leakRef() : nullptr;
#else
return static_cast<cairo_surface_t*>(g_task_propagate_pointer(G_TASK(result), error));
#endif
#endif
}
#endif

Expand Down