blob: c9ce6a0cf2f811610217c5a569dd68d6753fbaeb [file] [log] [blame]
/*
* Copyright (C) 2010 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 "GdkCairoUtilities.h"
#include "CairoUniquePtr.h"
#include "CairoUtilities.h"
#include "IntSize.h"
#include <cairo.h>
#include <gtk/gtk.h>
#include <mutex>
#include <wtf/NeverDestroyed.h>
#include <wtf/glib/GUniquePtr.h>
namespace WebCore {
class SystemFontOptions {
public:
static SystemFontOptions& singleton()
{
static LazyNeverDestroyed<SystemFontOptions> fontOptions;
static std::once_flag flag;
std::call_once(flag, [&] {
fontOptions.construct();
});
return fontOptions;
}
SystemFontOptions()
: m_settings(gtk_settings_get_default())
{
if (m_settings) {
auto fontOptionsChangedCallback = +[](GtkSettings*, GParamSpec*, SystemFontOptions* systemFontOptions) {
systemFontOptions->updateFontOptions();
};
g_signal_connect(m_settings, "notify::gtk-xft-antialias", G_CALLBACK(fontOptionsChangedCallback), this);
g_signal_connect(m_settings, "notify::gtk-xft-hinting", G_CALLBACK(fontOptionsChangedCallback), this);
g_signal_connect(m_settings, "notify::gtk-xft-hintstyle", G_CALLBACK(fontOptionsChangedCallback), this);
g_signal_connect(m_settings, "notify::gtk-xft-rgba", G_CALLBACK(fontOptionsChangedCallback), this);
updateFontOptions();
} else
m_fontOptions.reset(cairo_font_options_create());
}
const cairo_font_options_t* fontOptions() const
{
return m_fontOptions.get();
}
private:
void updateFontOptions()
{
m_fontOptions.reset(cairo_font_options_create());
gint antialias, hinting;
GUniqueOutPtr<char> hintStyleString;
GUniqueOutPtr<char> rgbaString;
g_object_get(m_settings, "gtk-xft-antialias", &antialias, "gtk-xft-hinting", &hinting, "gtk-xft-hintstyle",
&hintStyleString.outPtr(), "gtk-xft-rgba", &rgbaString.outPtr(), nullptr);
cairo_font_options_set_hint_metrics(m_fontOptions.get(), CAIRO_HINT_METRICS_ON);
cairo_hint_style_t hintStyle = CAIRO_HINT_STYLE_DEFAULT;
switch (hinting) {
case 0:
hintStyle = CAIRO_HINT_STYLE_NONE;
break;
case 1:
if (hintStyleString) {
if (!strcmp(hintStyleString.get(), "hintnone"))
hintStyle = CAIRO_HINT_STYLE_NONE;
else if (!strcmp(hintStyleString.get(), "hintslight"))
hintStyle = CAIRO_HINT_STYLE_SLIGHT;
else if (!strcmp(hintStyleString.get(), "hintmedium"))
hintStyle = CAIRO_HINT_STYLE_MEDIUM;
else if (!strcmp(hintStyleString.get(), "hintfull"))
hintStyle = CAIRO_HINT_STYLE_FULL;
}
break;
}
cairo_font_options_set_hint_style(m_fontOptions.get(), hintStyle);
cairo_subpixel_order_t subpixelOrder = CAIRO_SUBPIXEL_ORDER_DEFAULT;
if (rgbaString) {
if (!strcmp(rgbaString.get(), "rgb"))
subpixelOrder = CAIRO_SUBPIXEL_ORDER_RGB;
else if (!strcmp(rgbaString.get(), "bgr"))
subpixelOrder = CAIRO_SUBPIXEL_ORDER_BGR;
else if (!strcmp(rgbaString.get(), "vrgb"))
subpixelOrder = CAIRO_SUBPIXEL_ORDER_VRGB;
else if (!strcmp(rgbaString.get(), "vbgr"))
subpixelOrder = CAIRO_SUBPIXEL_ORDER_VBGR;
}
cairo_font_options_set_subpixel_order(m_fontOptions.get(), subpixelOrder);
cairo_antialias_t antialiasMode = CAIRO_ANTIALIAS_DEFAULT;
switch (antialias) {
case 0:
antialiasMode = CAIRO_ANTIALIAS_NONE;
break;
case 1:
if (subpixelOrder != CAIRO_SUBPIXEL_ORDER_DEFAULT)
antialiasMode = CAIRO_ANTIALIAS_SUBPIXEL;
else
antialiasMode = CAIRO_ANTIALIAS_GRAY;
break;
}
cairo_font_options_set_antialias(m_fontOptions.get(), antialiasMode);
}
GtkSettings* m_settings;
CairoUniquePtr<cairo_font_options_t> m_fontOptions;
};
const cairo_font_options_t* getDefaultCairoFontOptions()
{
return SystemFontOptions::singleton().fontOptions();
}
GdkPixbuf* cairoSurfaceToGdkPixbuf(cairo_surface_t* surface)
{
IntSize size = cairoSurfaceSize(surface);
return gdk_pixbuf_get_from_surface(surface, 0, 0, size.width(), size.height());
}
} // namespace WebCore