mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-15 05:00:09 +00:00
144cd2d91c
We can use a static font options object and allocate it only once.
189 lines
5.7 KiB
C
189 lines
5.7 KiB
C
#include "gskresources.h"
|
|
#include "gskprivate.h"
|
|
|
|
#include <cairo.h>
|
|
#include <pango/pangocairo.h>
|
|
#include <pango/pangoft2.h>
|
|
#include <math.h>
|
|
|
|
static gpointer
|
|
register_resources (gpointer data)
|
|
{
|
|
_gsk_register_resource ();
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
gsk_ensure_resources (void)
|
|
{
|
|
static GOnce register_resources_once = G_ONCE_INIT;
|
|
|
|
g_once (®ister_resources_once, register_resources, NULL);
|
|
}
|
|
|
|
/*< private >
|
|
* gsk_reload_font:
|
|
* @font: a `PangoFont`
|
|
* @scale: the scale to apply
|
|
* @hint_metris: hint metrics to use or `CAIRO_HINT_METRICS_DEFAILT` to keep the
|
|
* hint metrics of the font unchanged
|
|
* @hint_style: hint style to use or `CAIRO_HINT_STYLE_DEFAULT` to keep the
|
|
* hint style of @font unchanged
|
|
* @antialias: antialiasing to use, or `CAIRO_ANTIALIAS_DEFAULT` to keep the
|
|
* antialias option of @font unchanged
|
|
*
|
|
* Returns a font that is just like @font, but uses the
|
|
* given scale and hinting options for its glyphs and metrics.
|
|
*
|
|
* Returns: (transfer full): the modified `PangoFont`
|
|
*/
|
|
PangoFont *
|
|
gsk_reload_font (PangoFont *font,
|
|
float scale,
|
|
cairo_hint_metrics_t hint_metrics,
|
|
cairo_hint_style_t hint_style,
|
|
cairo_antialias_t antialias)
|
|
{
|
|
static cairo_font_options_t *options = NULL;
|
|
static PangoContext *context = NULL;
|
|
cairo_scaled_font_t *sf;
|
|
#if !PANGO_VERSION_CHECK (1, 52, 0)
|
|
PangoFontDescription *desc;
|
|
FcPattern *pattern;
|
|
double dpi;
|
|
int size;
|
|
#endif
|
|
|
|
/* These requests often come in sequentially so keep the result
|
|
* around and re-use it if everything matches.
|
|
*/
|
|
static PangoFont *last_font;
|
|
static float last_scale;
|
|
static cairo_hint_metrics_t last_hint_metrics;
|
|
static cairo_hint_style_t last_hint_style;
|
|
static cairo_antialias_t last_antialias;
|
|
static PangoFont *last_result;
|
|
|
|
if (last_result != NULL &&
|
|
last_font == font &&
|
|
last_scale == scale &&
|
|
last_hint_metrics == hint_metrics &&
|
|
last_hint_style == hint_style &&
|
|
last_antialias == antialias)
|
|
return g_object_ref (last_result);
|
|
|
|
last_scale = scale;
|
|
last_hint_metrics = hint_metrics;
|
|
last_hint_style = hint_style;
|
|
last_antialias = antialias;
|
|
|
|
g_set_object (&last_font, font);
|
|
g_clear_object (&last_result);
|
|
|
|
if (G_UNLIKELY (options == NULL))
|
|
options = cairo_font_options_create ();
|
|
|
|
sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
|
|
cairo_scaled_font_get_font_options (sf, options);
|
|
|
|
if (hint_metrics == CAIRO_HINT_METRICS_DEFAULT)
|
|
hint_metrics = cairo_font_options_get_hint_metrics (options);
|
|
|
|
if (hint_style == CAIRO_HINT_STYLE_DEFAULT)
|
|
hint_style = cairo_font_options_get_hint_style (options);
|
|
|
|
if (antialias == CAIRO_ANTIALIAS_DEFAULT)
|
|
antialias = cairo_font_options_get_antialias (options);
|
|
|
|
if (1.0 == scale &&
|
|
cairo_font_options_get_hint_metrics (options) == hint_metrics &&
|
|
cairo_font_options_get_hint_style (options) == hint_style &&
|
|
cairo_font_options_get_antialias (options) == antialias &&
|
|
cairo_font_options_get_subpixel_order (options) == CAIRO_SUBPIXEL_ORDER_DEFAULT)
|
|
{
|
|
last_result = g_object_ref (font);
|
|
return g_object_ref (font);
|
|
}
|
|
|
|
cairo_font_options_set_hint_metrics (options, hint_metrics);
|
|
cairo_font_options_set_hint_style (options, hint_style);
|
|
cairo_font_options_set_antialias (options, antialias);
|
|
cairo_font_options_set_subpixel_order (options, CAIRO_SUBPIXEL_ORDER_DEFAULT);
|
|
|
|
if (G_UNLIKELY (context == NULL))
|
|
context = pango_context_new ();
|
|
|
|
pango_cairo_context_set_font_options (context, options);
|
|
|
|
#if PANGO_VERSION_CHECK (1, 52, 0)
|
|
last_result = pango_font_map_reload_font (pango_font_get_font_map (font), font, scale, context, NULL);
|
|
#else
|
|
|
|
pattern = pango_fc_font_get_pattern (PANGO_FC_FONT (font));
|
|
if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) == FcResultMatch)
|
|
pango_cairo_context_set_resolution (context, dpi);
|
|
|
|
desc = pango_font_describe_with_absolute_size (font);
|
|
size = pango_font_description_get_size (desc);
|
|
pango_font_description_set_absolute_size (desc, size * scale);
|
|
last_result = pango_font_map_load_font (pango_font_get_font_map (font), context, desc);
|
|
pango_font_description_free (desc);
|
|
#endif
|
|
|
|
return g_object_ref (last_result);
|
|
}
|
|
|
|
/*< private >
|
|
* gsk_get_unhinted_glyph_string_extents:
|
|
* @glyphs: a `PangoGlyphString`
|
|
* @font: a `PangoFont`
|
|
* @ink_rect: (out): rectangle used to store the extents of the glyph string as drawn
|
|
*
|
|
* Compute the ink extents of a glyph string.
|
|
*
|
|
* This is like [method@Pango.GlyphString.extents], but it
|
|
* ignores hinting of the font.
|
|
*/
|
|
void
|
|
gsk_get_unhinted_glyph_string_extents (PangoGlyphString *glyphs,
|
|
PangoFont *font,
|
|
PangoRectangle *ink_rect)
|
|
{
|
|
PangoFont *unhinted;
|
|
|
|
unhinted = gsk_reload_font (font,
|
|
1.0,
|
|
CAIRO_HINT_METRICS_OFF,
|
|
CAIRO_HINT_STYLE_NONE,
|
|
CAIRO_ANTIALIAS_DEFAULT);
|
|
|
|
pango_glyph_string_extents (glyphs, unhinted, ink_rect, NULL);
|
|
|
|
g_object_unref (unhinted);
|
|
}
|
|
|
|
/*< private >
|
|
* gsk_font_get_hint_style:
|
|
* @font: a `PangoFont`
|
|
*
|
|
* Get the hint style from the cairo font options.
|
|
*
|
|
* Returns: the hint style
|
|
*/
|
|
cairo_hint_style_t
|
|
gsk_font_get_hint_style (PangoFont *font)
|
|
{
|
|
static cairo_font_options_t *options = NULL;
|
|
cairo_scaled_font_t *sf;
|
|
cairo_hint_style_t style;
|
|
|
|
if (G_UNLIKELY (options == NULL))
|
|
options = cairo_font_options_create ();
|
|
|
|
sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
|
|
cairo_scaled_font_get_font_options (sf, options);
|
|
style = cairo_font_options_get_hint_style (options);
|
|
|
|
return style;
|
|
}
|