|
Packit |
0ec9dd |
/* Pango
|
|
Packit |
0ec9dd |
* pangocairofc-font.c: Cairo font handling, fontconfig backend
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* Copyright (C) 2000-2005 Red Hat Software
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* This library is free software; you can redistribute it and/or
|
|
Packit |
0ec9dd |
* modify it under the terms of the GNU Library General Public
|
|
Packit |
0ec9dd |
* License as published by the Free Software Foundation; either
|
|
Packit |
0ec9dd |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
0ec9dd |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
0ec9dd |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
0ec9dd |
* Library General Public License for more details.
|
|
Packit |
0ec9dd |
*
|
|
Packit |
0ec9dd |
* You should have received a copy of the GNU Library General Public
|
|
Packit |
0ec9dd |
* License along with this library; if not, write to the
|
|
Packit |
0ec9dd |
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
Packit |
0ec9dd |
* Boston, MA 02111-1307, USA.
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
#include "config.h"
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Freetype has undefined macros in its header */
|
|
Packit |
0ec9dd |
#pragma GCC diagnostic push
|
|
Packit |
0ec9dd |
#pragma GCC diagnostic ignored "-Wundef"
|
|
Packit |
0ec9dd |
#include <cairo-ft.h>
|
|
Packit |
0ec9dd |
#pragma GCC diagnostic pop
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
#include "pango-fontmap.h"
|
|
Packit |
0ec9dd |
#include "pangocairo-private.h"
|
|
Packit |
0ec9dd |
#include "pangocairo-fc.h"
|
|
Packit |
0ec9dd |
#include "pangofc-private.h"
|
|
Packit |
0ec9dd |
#include "pango-impl-utils.h"
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
#include <hb-ot.h>
|
|
Packit |
0ec9dd |
#include <freetype/ftmm.h>
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
#define PANGO_TYPE_CAIRO_FC_FONT (pango_cairo_fc_font_get_type ())
|
|
Packit |
0ec9dd |
#define PANGO_CAIRO_FC_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFont))
|
|
Packit |
0ec9dd |
#define PANGO_CAIRO_FC_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFontClass))
|
|
Packit |
0ec9dd |
#define PANGO_CAIRO_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CAIRO_FC_FONT))
|
|
Packit |
0ec9dd |
#define PANGO_CAIRO_FC_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFontClass))
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
typedef struct _PangoCairoFcFont PangoCairoFcFont;
|
|
Packit |
0ec9dd |
typedef struct _PangoCairoFcFontClass PangoCairoFcFontClass;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
struct _PangoCairoFcFont
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoFcFont font;
|
|
Packit |
0ec9dd |
PangoCairoFontPrivate cf_priv;
|
|
Packit |
0ec9dd |
};
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
struct _PangoCairoFcFontClass
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoFcFontClass parent_class;
|
|
Packit |
0ec9dd |
};
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
_PANGO_EXTERN
|
|
Packit |
0ec9dd |
GType pango_cairo_fc_font_get_type (void);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/********************************
|
|
Packit |
0ec9dd |
* Method implementations *
|
|
Packit |
0ec9dd |
********************************/
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static cairo_font_face_t *
|
|
Packit |
0ec9dd |
pango_cairo_fc_font_create_font_face (PangoCairoFont *cfont)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoFcFont *fcfont = (PangoFcFont *) (cfont);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return cairo_ft_font_face_create_for_pattern (fcfont->font_pattern);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static PangoFontMetrics *
|
|
Packit |
0ec9dd |
pango_cairo_fc_font_create_base_metrics_for_context (PangoCairoFont *cfont,
|
|
Packit |
0ec9dd |
PangoContext *context)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoFcFont *fcfont = (PangoFcFont *) (cfont);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return pango_fc_font_create_base_metrics_for_context (fcfont, context);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
cairo_font_iface_init (PangoCairoFontIface *iface)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
iface->create_font_face = pango_cairo_fc_font_create_font_face;
|
|
Packit |
0ec9dd |
iface->create_base_metrics_for_context = pango_cairo_fc_font_create_base_metrics_for_context;
|
|
Packit |
0ec9dd |
iface->cf_priv_offset = G_STRUCT_OFFSET (PangoCairoFcFont, cf_priv);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
G_DEFINE_TYPE_WITH_CODE (PangoCairoFcFont, pango_cairo_fc_font, PANGO_TYPE_FC_FONT,
|
|
Packit |
0ec9dd |
{ G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT, cairo_font_iface_init) })
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_cairo_fc_font_finalize (GObject *object)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoCairoFcFont *cffont = (PangoCairoFcFont *) object;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
_pango_cairo_font_private_finalize (&cffont->cf_priv);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
G_OBJECT_CLASS (pango_cairo_fc_font_parent_class)->finalize (object);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* we want get_glyph_extents extremely fast, so we use a small wrapper here
|
|
Packit |
0ec9dd |
* to avoid having to lookup the interface data like we do for get_metrics
|
|
Packit |
0ec9dd |
* in _pango_cairo_font_get_metrics(). */
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_cairo_fc_font_get_glyph_extents (PangoFont *font,
|
|
Packit |
0ec9dd |
PangoGlyph glyph,
|
|
Packit |
0ec9dd |
PangoRectangle *ink_rect,
|
|
Packit |
0ec9dd |
PangoRectangle *logical_rect)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
_pango_cairo_font_private_get_glyph_extents (&cffont->cf_priv,
|
|
Packit |
0ec9dd |
glyph,
|
|
Packit |
0ec9dd |
ink_rect,
|
|
Packit |
0ec9dd |
logical_rect);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static FT_Face
|
|
Packit |
0ec9dd |
pango_cairo_fc_font_lock_face (PangoFcFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
|
|
Packit |
0ec9dd |
cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&cffont->cf_priv);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (G_UNLIKELY (!scaled_font))
|
|
Packit |
0ec9dd |
return NULL;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return cairo_ft_scaled_font_lock_face (scaled_font);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_cairo_fc_font_unlock_face (PangoFcFont *font)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
|
|
Packit |
0ec9dd |
cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&cffont->cf_priv);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (G_UNLIKELY (!scaled_font))
|
|
Packit |
0ec9dd |
return;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
cairo_ft_scaled_font_unlock_face (scaled_font);
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_cairo_fc_font_class_init (PangoCairoFcFontClass *class)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
Packit |
0ec9dd |
PangoFontClass *font_class = PANGO_FONT_CLASS (class);
|
|
Packit |
0ec9dd |
PangoFcFontClass *fc_font_class = PANGO_FC_FONT_CLASS (class);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
object_class->finalize = pango_cairo_fc_font_finalize;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
font_class->get_glyph_extents = pango_cairo_fc_font_get_glyph_extents;
|
|
Packit |
0ec9dd |
font_class->get_metrics = _pango_cairo_font_get_metrics;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
fc_font_class->lock_face = pango_cairo_fc_font_lock_face;
|
|
Packit |
0ec9dd |
fc_font_class->unlock_face = pango_cairo_fc_font_unlock_face;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static void
|
|
Packit |
0ec9dd |
pango_cairo_fc_font_init (PangoCairoFcFont *cffont G_GNUC_UNUSED)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/********************
|
|
Packit |
0ec9dd |
* Private API *
|
|
Packit |
0ec9dd |
********************/
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static double
|
|
Packit |
0ec9dd |
get_font_size (const FcPattern *pattern)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
double size;
|
|
Packit |
0ec9dd |
double dpi;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
|
|
Packit |
0ec9dd |
return size;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Just in case FC_PIXEL_SIZE got unset between pango_fc_make_pattern()
|
|
Packit |
0ec9dd |
* and here. That would be very weird.
|
|
Packit |
0ec9dd |
*/
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) != FcResultMatch)
|
|
Packit |
0ec9dd |
dpi = 72;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (FcPatternGetDouble (pattern, FC_SIZE, 0, &size) == FcResultMatch)
|
|
Packit |
0ec9dd |
return size * dpi / 72.;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
/* Whatever */
|
|
Packit |
0ec9dd |
return 18.;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static gpointer
|
|
Packit |
0ec9dd |
get_gravity_class (void)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
static GEnumClass *class = NULL; /* MT-safe */
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (g_once_init_enter (&class))
|
|
Packit |
0ec9dd |
g_once_init_leave(&class, (gpointer)g_type_class_ref (PANGO_TYPE_GRAVITY));
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return class;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
static PangoGravity
|
|
Packit |
0ec9dd |
get_gravity (const FcPattern *pattern)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
char *s;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
if (FcPatternGetString (pattern, PANGO_FC_GRAVITY, 0, (FcChar8 **)(void *)&s) == FcResultMatch)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
GEnumValue *value = g_enum_get_value_by_nick (get_gravity_class (), s);
|
|
Packit |
0ec9dd |
return value->value;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return PANGO_GRAVITY_SOUTH;
|
|
Packit |
0ec9dd |
}
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
PangoFcFont *
|
|
Packit |
0ec9dd |
_pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap,
|
|
Packit |
0ec9dd |
PangoFcFontKey *key)
|
|
Packit |
0ec9dd |
{
|
|
Packit |
0ec9dd |
PangoCairoFcFont *cffont;
|
|
Packit |
0ec9dd |
const FcPattern *pattern = pango_fc_font_key_get_pattern (key);
|
|
Packit |
0ec9dd |
cairo_matrix_t font_matrix;
|
|
Packit |
0ec9dd |
FcMatrix fc_matrix, *fc_matrix_val;
|
|
Packit |
0ec9dd |
double size;
|
|
Packit |
0ec9dd |
int i;
|
|
Packit |
0ec9dd |
cairo_font_options_t *options;
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
g_return_val_if_fail (PANGO_IS_CAIRO_FC_FONT_MAP (cffontmap), NULL);
|
|
Packit |
0ec9dd |
g_return_val_if_fail (pattern != NULL, NULL);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
cffont = g_object_new (PANGO_TYPE_CAIRO_FC_FONT,
|
|
Packit |
0ec9dd |
"pattern", pattern,
|
|
Packit |
0ec9dd |
"fontmap", cffontmap,
|
|
Packit |
0ec9dd |
NULL);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
size = get_font_size (pattern) /
|
|
Packit |
0ec9dd |
pango_matrix_get_font_scale_factor (pango_fc_font_key_get_matrix (key));
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
FcMatrixInit (&fc_matrix);
|
|
Packit |
0ec9dd |
for (i = 0; FcPatternGetMatrix (pattern, FC_MATRIX, i, &fc_matrix_val) == FcResultMatch; i++)
|
|
Packit |
0ec9dd |
FcMatrixMultiply (&fc_matrix, &fc_matrix, fc_matrix_val);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
cairo_matrix_init (&font_matrix,
|
|
Packit |
0ec9dd |
fc_matrix.xx,
|
|
Packit |
0ec9dd |
- fc_matrix.yx,
|
|
Packit |
0ec9dd |
- fc_matrix.xy,
|
|
Packit |
0ec9dd |
fc_matrix.yy,
|
|
Packit |
0ec9dd |
0., 0.);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
cairo_matrix_scale (&font_matrix, size, size);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
options = pango_fc_font_key_get_context_key (key);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
_pango_cairo_font_private_initialize (&cffont->cf_priv,
|
|
Packit |
0ec9dd |
(PangoCairoFont *) cffont,
|
|
Packit |
0ec9dd |
get_gravity (pattern),
|
|
Packit |
0ec9dd |
options,
|
|
Packit |
0ec9dd |
pango_fc_font_key_get_matrix (key),
|
|
Packit |
0ec9dd |
&font_matrix);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
((PangoFcFont *)(cffont))->is_hinted = _pango_cairo_font_private_is_metrics_hinted (&cffont->cf_priv);
|
|
Packit |
0ec9dd |
|
|
Packit |
0ec9dd |
return (PangoFcFont *) cffont;
|
|
Packit |
0ec9dd |
}
|