diff options
Diffstat (limited to 'pango')
-rw-r--r-- | pango/Makefile.am | 21 | ||||
-rw-r--r-- | pango/modules.h | 1 | ||||
-rw-r--r-- | pango/pangocairo-coretext.h | 55 | ||||
-rw-r--r-- | pango/pangocairo-coretextfont.c | 279 | ||||
-rw-r--r-- | pango/pangocairo-coretextfont.h | 37 | ||||
-rw-r--r-- | pango/pangocairo-coretextfontmap.c | 107 | ||||
-rw-r--r-- | pango/pangocairo-fontmap.c | 14 | ||||
-rw-r--r-- | pango/pangocoretext-fontmap.c | 952 | ||||
-rw-r--r-- | pango/pangocoretext-private.h | 101 | ||||
-rw-r--r-- | pango/pangocoretext.c | 205 | ||||
-rw-r--r-- | pango/pangocoretext.h | 80 |
11 files changed, 1851 insertions, 1 deletions
diff --git a/pango/Makefile.am b/pango/Makefile.am index 176d70ac..df1596d2 100644 --- a/pango/Makefile.am +++ b/pango/Makefile.am @@ -386,6 +386,26 @@ libpangocairo_1_0_la_SOURCES += \ endif if HAVE_CAIRO_ATSUI +if HAVE_CORE_TEXT +libpangocairo_1_0_la_SOURCES += \ + modules.h \ + module-defs-coretext.c \ + pangocoretext.h \ + pangocoretext.c \ + pangocoretext-private.h \ + pangocoretext-fontmap.c \ + pangocairo-coretext.h \ + pangocairo-coretextfont.c \ + pangocairo-coretextfont.h \ + pangocairo-coretextfontmap.c +pangoinclude_HEADERS += pangocoretext.h + +libpangocairo_1_0_la_LDFLAGS += -framework CoreFoundation -framework ApplicationServices +libpangocairo_1_0_la_LIBADD += $(INCLUDED_CORE_TEXT_MODULES) +# We don't have an CoreText GIR right now, so this is just hypothetical +PANGOCAIRO_FONT_BACKEND_GI_MODULE = PangoCoreText-1.0 + +else libpangocairo_1_0_la_SOURCES += \ modules.h \ module-defs-atsui.c \ @@ -405,6 +425,7 @@ libpangocairo_1_0_la_LIBADD += $(INCLUDED_ATSUI_MODULES) # We don't have an ATSUI GIR right now, so this is just hypothetical PANGOCAIRO_FONT_BACKEND_GI_MODULE = PangoATSUI-1.0 endif +endif pangocairo_introspection_files = \ $(libpangocairo_1_0_la_SOURCES) \ diff --git a/pango/modules.h b/pango/modules.h index ca22701b..7eac8fb6 100644 --- a/pango/modules.h +++ b/pango/modules.h @@ -30,5 +30,6 @@ extern PangoIncludedModule _pango_included_x_modules[]; extern PangoIncludedModule _pango_included_fc_modules[]; extern PangoIncludedModule _pango_included_win32_modules[]; extern PangoIncludedModule _pango_included_atsui_modules[]; +extern PangoIncludedModule _pango_included_core_text_modules[]; #endif /* __MODULES_H__ */ diff --git a/pango/pangocairo-coretext.h b/pango/pangocairo-coretext.h new file mode 100644 index 00000000..420e1c9e --- /dev/null +++ b/pango/pangocairo-coretext.h @@ -0,0 +1,55 @@ +/* Pango + * pangocairo-coretext.h: + * + * Copyright (C) 2005 Imendio AB + * Copyright (C) 2010 Kristian Rietveld <kris@gtk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __PANGOCAIRO_CORETEXT_H__ +#define __PANGOCAIRO_CORETEXT_H__ + +#include "pangocoretext-private.h" +#include <pango/pangocairo.h> +#include <cairo-quartz.h> + +G_BEGIN_DECLS + +#define PANGO_TYPE_CAIRO_CORE_TEXT_FONT_MAP (pango_cairo_core_text_font_map_get_type ()) +#define PANGO_CAIRO_CORE_TEXT_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_CORE_TEXT_FONT_MAP, PangoCairoCoreTextFontMap)) +#define PANGO_IS_CAIRO_CORE_TEXT_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CAIRO_CORE_TEXT_FONT_MAP)) + +typedef struct _PangoCairoCoreTextFontMap PangoCairoCoreTextFontMap; + +struct _PangoCairoCoreTextFontMap +{ + PangoCoreTextFontMap parent_instance; + + gdouble dpi; +}; + +GType pango_cairo_core_text_font_map_get_type (void) G_GNUC_CONST; + +PangoCoreTextFont * +_pango_cairo_core_text_font_new (PangoCairoCoreTextFontMap *cafontmap, + PangoContext *context, + PangoCoreTextFace *face, + const PangoFontDescription *desc); + +G_END_DECLS + +#endif /* __PANGOCAIRO_CORETEXT_H__ */ diff --git a/pango/pangocairo-coretextfont.c b/pango/pangocairo-coretextfont.c new file mode 100644 index 00000000..81747ac3 --- /dev/null +++ b/pango/pangocairo-coretextfont.c @@ -0,0 +1,279 @@ +/* Pango + * pangocairo-coretextfont.c + * + * Copyright (C) 2000-2005 Red Hat Software + * Copyright (C) 2005-2007 Imendio AB + * Copyright (C) 2010 Kristian Rietveld <kris@gtk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include <Carbon/Carbon.h> + +#include "pango-impl-utils.h" +#include "pangocoretext-private.h" +#include "pangocairo.h" +#include "pangocairo-private.h" +#include "pangocairo-coretext.h" +#include "pangocairo-coretextfont.h" + +struct _PangoCairoCoreTextFont +{ + PangoCoreTextFont font; + PangoCairoFontPrivate cf_priv; + + double size; + int absolute_size; +}; + +struct _PangoCairoCoreTextFontClass +{ + PangoCoreTextFontClass parent_class; +}; + + + +static cairo_font_face_t *pango_cairo_core_text_font_create_font_face (PangoCairoFont *font); +static PangoFontMetrics *pango_cairo_core_text_font_create_metrics_for_context (PangoCairoFont *font, + PangoContext *context); + +static void +cairo_font_iface_init (PangoCairoFontIface *iface) +{ + iface->create_font_face = pango_cairo_core_text_font_create_font_face; + iface->create_metrics_for_context = pango_cairo_core_text_font_create_metrics_for_context; + iface->cf_priv_offset = G_STRUCT_OFFSET (PangoCairoCoreTextFont, cf_priv); +} + +G_DEFINE_TYPE_WITH_CODE (PangoCairoCoreTextFont, pango_cairo_core_text_font, PANGO_TYPE_CORE_TEXT_FONT, + { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT, cairo_font_iface_init) }); + +/* we want get_glyph_extents extremely fast, so we use a small wrapper here + * to avoid having to lookup the interface data like we do for get_metrics + * in _pango_cairo_font_get_metrics(). */ +static void +pango_cairo_core_text_font_get_glyph_extents (PangoFont *font, + PangoGlyph glyph, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + PangoCairoCoreTextFont *cafont = (PangoCairoCoreTextFont *) (font); + + _pango_cairo_font_private_get_glyph_extents (&cafont->cf_priv, + glyph, + ink_rect, + logical_rect); +} + +static cairo_font_face_t * +pango_cairo_core_text_font_create_font_face (PangoCairoFont *font) +{ + PangoCoreTextFont *ctfont = (PangoCoreTextFont *) (font); + CTFontRef font_id; + CGFontRef cgfont; + cairo_font_face_t *cairo_face; + + font_id = pango_core_text_font_get_ctfont (ctfont); + cgfont = CTFontCopyGraphicsFont (font_id, NULL); + + cairo_face = cairo_quartz_font_face_create_for_cgfont (cgfont); + + CFRelease (cgfont); + + return cairo_face; +} + +static int +max_glyph_width (PangoLayout *layout) +{ + int max_width = 0; + GSList *l, *r; + + for (l = pango_layout_get_lines_readonly (layout); l; l = l->next) + { + PangoLayoutLine *line = l->data; + + for (r = line->runs; r; r = r->next) + { + PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs; + int i; + + for (i = 0; i < glyphs->num_glyphs; i++) + if (glyphs->glyphs[i].geometry.width > max_width) + max_width = glyphs->glyphs[i].geometry.width; + } + } + + return max_width; +} + +static PangoFontMetrics * +pango_cairo_core_text_font_create_metrics_for_context (PangoCairoFont *font, + PangoContext *context) +{ + PangoCoreTextFont *cfont = (PangoCoreTextFont *) font; + PangoFontMetrics *metrics; + PangoFontDescription *font_desc; + PangoLayout *layout; + PangoRectangle extents; + PangoLanguage *language = pango_context_get_language (context); + const char *sample_str = pango_language_get_sample_string (language); + CTFontRef ctfont; + + metrics = pango_font_metrics_new (); + + ctfont = pango_core_text_font_get_ctfont (cfont); + + metrics->ascent = CTFontGetAscent (ctfont) * PANGO_SCALE; + metrics->descent = CTFontGetDescent (ctfont) * PANGO_SCALE; + + metrics->underline_position = CTFontGetUnderlinePosition (ctfont) * PANGO_SCALE; + metrics->underline_thickness = CTFontGetUnderlineThickness (ctfont) * PANGO_SCALE; + + metrics->strikethrough_position = metrics->ascent / 3; + metrics->strikethrough_thickness = CTFontGetUnderlineThickness (ctfont) * PANGO_SCALE; + + layout = pango_layout_new (context); + font_desc = pango_font_describe_with_absolute_size ((PangoFont *) font); + pango_layout_set_font_description (layout, font_desc); + pango_layout_set_text (layout, sample_str, -1); + pango_layout_get_extents (layout, NULL, &extents); + + metrics->approximate_char_width = extents.width / pango_utf8_strwidth (sample_str); + + pango_layout_set_text (layout, "0123456789", -1); + metrics->approximate_digit_width = max_glyph_width (layout); + + pango_font_description_free (font_desc); + g_object_unref (layout); + + return metrics; +} + +static PangoFontDescription * +pango_cairo_core_text_font_describe_absolute (PangoFont *font) +{ + PangoFontDescription *desc; + PangoCairoCoreTextFont *cafont = (PangoCairoCoreTextFont *) font; + + desc = pango_font_describe (font); + pango_font_description_set_absolute_size (desc, cafont->absolute_size); + + return desc; +} + +static void +pango_cairo_core_text_font_finalize (GObject *object) +{ + PangoCairoCoreTextFont *cafont = (PangoCairoCoreTextFont *) object; + + _pango_cairo_font_private_finalize (&cafont->cf_priv); + + G_OBJECT_CLASS (pango_cairo_core_text_font_parent_class)->finalize (object); +} + +static void +pango_cairo_core_text_font_class_init (PangoCairoCoreTextFontClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + PangoFontClass *font_class = PANGO_FONT_CLASS (class); + + object_class->finalize = pango_cairo_core_text_font_finalize; + + font_class->get_glyph_extents = pango_cairo_core_text_font_get_glyph_extents; + font_class->get_metrics = _pango_cairo_font_get_metrics; + font_class->describe_absolute = pango_cairo_core_text_font_describe_absolute; +} + +static void +pango_cairo_core_text_font_init (PangoCairoCoreTextFont *cafont G_GNUC_UNUSED) +{ +} + +PangoCoreTextFont * +_pango_cairo_core_text_font_new (PangoCairoCoreTextFontMap *cafontmap, + PangoContext *context, + PangoCoreTextFace *face, + const PangoFontDescription *desc) +{ + const char *postscript_name; + PangoCairoCoreTextFont *cafont; + PangoCoreTextFont *cfont; + CFStringRef cfstr; + CTFontRef font_ref; + CGFontRef font_id; + double size; + double dpi; + cairo_matrix_t font_matrix; + + postscript_name = _pango_core_text_face_get_postscript_name (face); + + /* Calculate size in points */ + size = (double) pango_font_description_get_size (desc) / PANGO_SCALE; + + if (context) + { + dpi = pango_cairo_context_get_resolution (context); + + if (dpi <= 0) + dpi = cafontmap->dpi; + } + else + dpi = cafontmap->dpi; + + if (pango_font_description_get_size_is_absolute (desc)) + size *= dpi / 72.; + + + cfstr = CFStringCreateWithCString (NULL, postscript_name, + kCFStringEncodingUTF8); + font_ref = CTFontCreateWithName (cfstr, size, NULL); + CFRelease (cfstr); + + /* FIXME: Do we need the synthetic italic handling here? */ + font_id = CTFontCopyGraphicsFont (font_ref, NULL); + if (!font_id) + return NULL; + + cafont = g_object_new (PANGO_TYPE_CAIRO_CORE_TEXT_FONT, NULL); + cfont = PANGO_CORE_TEXT_FONT (cafont); + + _pango_core_text_font_set_font_description (cfont, desc); + _pango_core_text_font_set_face (cfont, face); + + _pango_core_text_font_set_ctfont (cfont, font_ref); + + if (pango_font_description_get_size_is_absolute (desc)) + cafont->absolute_size = pango_font_description_get_size (desc); + else + cafont->absolute_size = pango_font_description_get_size (desc) * (dpi / 72.); + + cafont->size = size; + + cairo_matrix_init_identity (&font_matrix); + cairo_matrix_scale (&font_matrix, size, size); + + _pango_cairo_font_private_initialize (&cafont->cf_priv, + (PangoCairoFont *) cafont, + pango_font_description_get_gravity (desc), + _pango_cairo_context_get_merged_font_options (context), + pango_context_get_matrix (context), + &font_matrix); + + return cfont; +} diff --git a/pango/pangocairo-coretextfont.h b/pango/pangocairo-coretextfont.h new file mode 100644 index 00000000..752dfdd7 --- /dev/null +++ b/pango/pangocairo-coretextfont.h @@ -0,0 +1,37 @@ +/* Pango + * pangocairo-coretextfont.c + * + * Copyright (C) 2005 Imendio AB + * Copyright (C) 2010 Kristian Rietveld <kris@gtk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __PANGOCAIRO_CORETEXTFONT_H__ +#define __PANGOCAIRO_CORETEXTFONT_H__ + +#define PANGO_TYPE_CAIRO_CORE_TEXT_FONT (pango_cairo_core_text_font_get_type ()) +#define PANGO_CAIRO_CORE_TEXT_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_CORE_TEXT_FONT, PangoCairoCoreTextFont)) +#define PANGO_CAIRO_CORE_TEXT_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_CORE_TEXT_FONT, PangoCairoCoreTextFontClass)) +#define PANGO_IS_CAIRO_CORE_TEXT_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CAIRO_CORE_TEXT_FONT)) +#define PANGO_CAIRO_CORE_TEXT_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CAIRO_CORE_TEXT_FONT, PangoCairoCoreTextFontClass)) + +typedef struct _PangoCairoCoreTextFont PangoCairoCoreTextFont; +typedef struct _PangoCairoCoreTextFontClass PangoCairoCoreTextFontClass; + +GType pango_cairo_core_text_font_get_type (void) G_GNUC_CONST; + +#endif /* __PANGOCAIRO_CORETEXTFONT_H__ */ diff --git a/pango/pangocairo-coretextfontmap.c b/pango/pangocairo-coretextfontmap.c new file mode 100644 index 00000000..e05a1d40 --- /dev/null +++ b/pango/pangocairo-coretextfontmap.c @@ -0,0 +1,107 @@ +/* Pango + * pangocairo-coretextfontmap.c + * + * Copyright (C) 2005 Imendio AB + * Copyright (C) 2010 Kristian Rietveld <kris@gtk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "pangocoretext-private.h" +#include "pangocairo.h" +#include "pangocairo-private.h" +#include "pangocairo-coretext.h" + +typedef struct _PangoCairoCoreTextFontMapClass PangoCairoCoreTextFontMapClass; + +struct _PangoCairoCoreTextFontMapClass +{ + PangoCoreTextFontMapClass parent_class; +}; + +static void +pango_cairo_core_text_font_map_set_resolution (PangoCairoFontMap *cfontmap, + double dpi) +{ + PangoCairoCoreTextFontMap *cafontmap = PANGO_CAIRO_CORE_TEXT_FONT_MAP (cfontmap); + + cafontmap->dpi = dpi; +} + +static double +pango_cairo_core_text_font_map_get_resolution (PangoCairoFontMap *cfontmap) +{ + PangoCairoCoreTextFontMap *cafontmap = PANGO_CAIRO_CORE_TEXT_FONT_MAP (cfontmap); + + return cafontmap->dpi; +} + +static cairo_font_type_t +pango_cairo_core_text_font_map_get_font_type (PangoCairoFontMap *cfontmap) +{ + /* This is a bit misleading, but Cairo takes a CoreGraphics font + * for rendering and does not use ATSUI. + */ + return CAIRO_FONT_TYPE_ATSUI; +} + +static void +cairo_font_map_iface_init (PangoCairoFontMapIface *iface) +{ + iface->set_resolution = pango_cairo_core_text_font_map_set_resolution; + iface->get_resolution = pango_cairo_core_text_font_map_get_resolution; + iface->get_font_type = pango_cairo_core_text_font_map_get_font_type; +} + +G_DEFINE_TYPE_WITH_CODE (PangoCairoCoreTextFontMap, pango_cairo_core_text_font_map, PANGO_TYPE_CORE_TEXT_FONT_MAP, + { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT_MAP, cairo_font_map_iface_init) }); + + +static PangoCoreTextFont * +pango_cairo_core_text_font_map_create_font (PangoCoreTextFontMap *fontmap, + PangoContext *context, + PangoCoreTextFace *face, + const PangoFontDescription *desc) + +{ + return _pango_cairo_core_text_font_new (PANGO_CAIRO_CORE_TEXT_FONT_MAP (fontmap), + context, face, desc); +} + +static void +pango_cairo_core_text_font_map_finalize (GObject *object) +{ + G_OBJECT_CLASS (pango_cairo_core_text_font_map_parent_class)->finalize (object); +} + +static void +pango_cairo_core_text_font_map_class_init (PangoCairoCoreTextFontMapClass *class) +{ + PangoCoreTextFontMapClass *ctfontmapclass = (PangoCoreTextFontMapClass *)class; + GObjectClass *object_class = (GObjectClass *)class; + + object_class->finalize = pango_cairo_core_text_font_map_finalize; + + ctfontmapclass->create_font = pango_cairo_core_text_font_map_create_font; +} + +static void +pango_cairo_core_text_font_map_init (PangoCairoCoreTextFontMap *cafontmap) +{ + cafontmap->dpi = 72.; +} diff --git a/pango/pangocairo-fontmap.c b/pango/pangocairo-fontmap.c index ae917d06..94042642 100644 --- a/pango/pangocairo-fontmap.c +++ b/pango/pangocairo-fontmap.c @@ -26,7 +26,11 @@ #include "pango-impl-utils.h" #if defined (HAVE_CAIRO_ATSUI) -# include "pangocairo-atsui.h" +# if defined (HAVE_CORE_TEXT) +# include "pangocairo-coretext.h" +# else +# include "pangocairo-atsui.h" +# endif #endif #if defined (HAVE_CAIRO_WIN32) # include "pangocairo-win32.h" @@ -92,7 +96,11 @@ pango_cairo_font_map_new (void) g_type_init (); #if defined(HAVE_CAIRO_ATSUI) +#if defined(HAVE_CORE_TEXT) + return g_object_new (PANGO_TYPE_CAIRO_CORE_TEXT_FONT_MAP, NULL); +#else return g_object_new (PANGO_TYPE_CAIRO_ATSUI_FONT_MAP, NULL); +#endif #elif defined(HAVE_CAIRO_WIN32) return g_object_new (PANGO_TYPE_CAIRO_WIN32_FONT_MAP, NULL); #elif defined(HAVE_CAIRO_FREETYPE) @@ -131,8 +139,12 @@ pango_cairo_font_map_new_for_font_type (cairo_font_type_t fonttype) { #if defined(HAVE_CAIRO_ATSUI) case CAIRO_FONT_TYPE_QUARTZ: +#if defined(HAVE_CORE_TEXT) + return g_object_new (PANGO_TYPE_CAIRO_CORE_TEXT_FONT_MAP, NULL); +#else return g_object_new (PANGO_TYPE_CAIRO_ATSUI_FONT_MAP, NULL); #endif +#endif #if defined(HAVE_CAIRO_WIN32) case CAIRO_FONT_TYPE_WIN32: return g_object_new (PANGO_TYPE_CAIRO_WIN32_FONT_MAP, NULL); diff --git a/pango/pangocoretext-fontmap.c b/pango/pangocoretext-fontmap.c new file mode 100644 index 00000000..b8cf671f --- /dev/null +++ b/pango/pangocoretext-fontmap.c @@ -0,0 +1,952 @@ +/* Pango + * pangocoretext-fontmap.c + * + * Copyright (C) 2000-2003 Red Hat, Inc. + * Copyright (C) 2005-2007 Imendio AB + * Copyright (C) 2010 Kristian Rietveld <kris@gtk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "pango-fontmap.h" +#include "pangocoretext-private.h" +#include "pango-impl-utils.h" +#include "modules.h" + +#include <Carbon/Carbon.h> + +typedef struct _FontHashKey FontHashKey; + +struct _PangoCoreTextFamily +{ + PangoFontFamily parent_instance; + + char *family_name; + + guint is_monospace : 1; + + PangoFontFace **faces; + gint n_faces; +}; + +#define PANGO_TYPE_CORE_TEXT_FAMILY (pango_core_text_family_get_type ()) +#define PANGO_CORE_TEXT_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CORE_TEXT_FAMILY, PangoCoreTextFamily)) +#define PANGO_IS_CORE_TEXT_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CORE_TEXT_FAMILY)) + +#define PANGO_TYPE_CORE_TEXT_FACE (pango_core_text_face_get_type ()) +#define PANGO_CORE_TEXT_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CORE_TEXT_FACE, PangoCoreTextFace)) +#define PANGO_IS_CORE_TEXT_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CORE_TEXT_FACE)) + +struct _PangoCoreTextFace +{ + PangoFontFace parent_instance; + + PangoCoreTextFamily *family; + + PangoCoverage *coverage; + + char *postscript_name; + char *style_name; + + float weight; + int traits; +}; + +static GType pango_core_text_family_get_type (void); +static GType pango_core_text_face_get_type (void); + +static gpointer pango_core_text_family_parent_class; +static gpointer pango_core_text_face_parent_class; + +static const char * +get_real_family (const char *family_name) +{ + switch (family_name[0]) + { + case 'm': + case 'M': + if (g_ascii_strcasecmp (family_name, "monospace") == 0) + return "Courier"; + break; + case 's': + case 'S': + if (g_ascii_strcasecmp (family_name, "sans") == 0) + return "Helvetica"; + else if (g_ascii_strcasecmp (family_name, "serif") == 0) + return "Times"; + break; + } + + return family_name; +} + +static gchar * +gchar_from_cf_string (CFStringRef str) +{ + CFIndex len; + gchar *buffer; + + /* GetLength returns the number of UTF-16 pairs, so this number + * times 2 should definitely gives us enough space for UTF8. + * We add one for the terminating zero. + */ + len = CFStringGetLength (str) * 2 + 1; + buffer = g_new0 (char, len); + CFStringGetCString (str, buffer, len, kCFStringEncodingUTF8); + + return buffer; +} + +static PangoCoverage * +pango_coverage_from_cf_charset (CFCharacterSetRef charset) +{ + CFIndex i, length; + CFDataRef bitmap; + const UInt8 *ptr; + PangoCoverage *coverage; + + coverage = pango_coverage_new (); + + bitmap = CFCharacterSetCreateBitmapRepresentation (kCFAllocatorDefault, + charset); + + /* We only handle the BMP plane */ + length = MIN (CFDataGetLength (bitmap), 8192); + ptr = CFDataGetBytePtr (bitmap); + + /* FIXME: can and should this be done more efficiently? */ + for (i = 0; i < length; i++) + { + int j; + + for (j = 0; j < 8; j++) + pango_coverage_set (coverage, i * 8 + j, + ((ptr[i] & (1 << j)) == (1 << j)) ? + PANGO_COVERAGE_EXACT : PANGO_COVERAGE_NONE); + } + + CFRelease (bitmap); + + return coverage; +} + +static void +pango_core_text_family_list_faces (PangoFontFamily *family, + PangoFontFace ***faces, + int *n_faces) +{ + PangoCoreTextFamily *ctfamily = PANGO_CORE_TEXT_FAMILY (family); + + if (ctfamily->n_faces < 0) + { + GList *l; + GList *faces = NULL; + const char *real_family = get_real_family (ctfamily->family_name); + CTFontCollectionRef collection; + CFArrayRef ctfaces; + CFArrayRef font_descriptors; + CFDictionaryRef attributes; + CFIndex i, count; + + CFTypeRef keys[] = { + (CFTypeRef) kCTFontFamilyNameAttribute + }; + + CFStringRef values[] = { + CFStringCreateWithCString (kCFAllocatorDefault, + real_family, + kCFStringEncodingUTF8) + }; + + CTFontDescriptorRef descriptors[1]; + + attributes = CFDictionaryCreate (kCFAllocatorDefault, + (const void **)keys, + (const void **)values, + 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + descriptors[0] = CTFontDescriptorCreateWithAttributes (attributes); + font_descriptors = CFArrayCreate (kCFAllocatorDefault, + (const void **)descriptors, + 1, + &kCFTypeArrayCallBacks); + collection = CTFontCollectionCreateWithFontDescriptors (font_descriptors, + NULL); + + ctfaces = CTFontCollectionCreateMatchingFontDescriptors (collection); + + /* FIXME: do we need the code for the synthetic italic faces? */ + count = CFArrayGetCount (ctfaces); + for (i = 0; i < count; i++) + { + int font_traits; + char *buffer; + CFStringRef str; + CFNumberRef number; + CGFloat value; + CFDictionaryRef dict; + CFCharacterSetRef charset; + CTFontDescriptorRef desc = CFArrayGetValueAtIndex (ctfaces, i); + PangoCoreTextFace *face = g_object_new (PANGO_TYPE_CORE_TEXT_FACE, + NULL); + + face->family = ctfamily; + + /* Get font name */ + str = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute); + buffer = gchar_from_cf_string (str); + + /* We strdup again to save space. */ + face->postscript_name = g_strdup (buffer); + + CFRelease (str); + g_free (buffer); + + /* Get style name */ + str = CTFontDescriptorCopyAttribute (desc, kCTFontStyleNameAttribute); + buffer = gchar_from_cf_string (str); + + face->style_name = g_strdup (buffer); + + CFRelease (str); + g_free (buffer); + + /* Get font traits, symbolic traits */ + dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute); + number = (CFNumberRef)CFDictionaryGetValue (dict, + kCTFontWeightTrait); + if (CFNumberGetValue (number, kCFNumberCGFloatType, &value)) + /* Map value from range [-1.0, 1.0] to range [1, 14] */ + face->weight = (value + 1.0f) * 6.5f + 1; + else + face->weight = PANGO_WEIGHT_NORMAL; + + number = (CFNumberRef)CFDictionaryGetValue (dict, + kCTFontSymbolicTrait); + if (CFNumberGetValue (number, kCFNumberIntType, &font_traits)) + { + face->traits = font_traits; + } + CFRelease (dict); + + /* Get font coverage */ + charset = CTFontDescriptorCopyAttribute (desc, + kCTFontCharacterSetAttribute); + face->coverage = pango_coverage_from_cf_charset (charset); + CFRelease (charset); + + faces = g_list_prepend (faces, face); + } + + CFRelease (font_descriptors); + CFRelease (attributes); + CFRelease (ctfaces); + + ctfamily->n_faces = g_list_length (faces); + ctfamily->faces = g_new (PangoFontFace *, ctfamily->n_faces); + + for (l = faces, i = 0; l; l = l->next, i++) + ctfamily->faces[i] = l->data; + + g_list_free (faces); + } + + if (n_faces) + *n_faces = ctfamily->n_faces; + + if (faces) + *faces = g_memdup (ctfamily->faces, ctfamily->n_faces * sizeof (PangoFontFace *)); +} + +static const char * +pango_core_text_family_get_name (PangoFontFamily *family) +{ + PangoCoreTextFamily *ctfamily = PANGO_CORE_TEXT_FAMILY (family); + + return ctfamily->family_name; +} + +static gboolean +pango_core_text_family_is_monospace (PangoFontFamily *family) +{ + PangoCoreTextFamily *ctfamily = PANGO_CORE_TEXT_FAMILY (family); + + return ctfamily->is_monospace; +} + +static void +pango_core_text_family_finalize (GObject *object) +{ + PangoCoreTextFamily *family = PANGO_CORE_TEXT_FAMILY (object); + int i; + + g_free (family->family_name); + + if (family->n_faces != -1) + { + for (i = 0; i < family->n_faces; i++) + g_object_unref (family->faces[i]); + + g_free (family->faces); + } + + G_OBJECT_CLASS (pango_core_text_family_parent_class)->finalize (object); +} + +static void +pango_core_text_family_class_init (PangoFontFamilyClass *class) +{ + GObjectClass *object_class = (GObjectClass *)class; + int i; + + pango_core_text_family_parent_class = g_type_class_peek_parent (class); + + object_class->finalize = pango_core_text_family_finalize; + + class->list_faces = pango_core_text_family_list_faces; + class->get_name = pango_core_text_family_get_name; + class->is_monospace = pango_core_text_family_is_monospace; + + for (i = 0; _pango_included_core_text_modules[i].list; i++) + pango_module_register (&_pango_included_core_text_modules[i]); +} + +static void +pango_core_text_family_init (PangoCoreTextFamily *family) +{ + family->n_faces = -1; +} + +static GType +pango_core_text_family_get_type (void) +{ + static GType object_type = 0; + + if (G_UNLIKELY (!object_type)) + { + const GTypeInfo object_info = + { + sizeof (PangoFontFamilyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pango_core_text_family_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PangoCoreTextFamily), + 0, /* n_preallocs */ + (GInstanceInitFunc) pango_core_text_family_init, + }; + + object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY, + I_("PangoCoreTextFamily"), + &object_info, 0); + } + + return object_type; +} + +static PangoFontDescription * +pango_core_text_face_describe (PangoFontFace *face) +{ + PangoCoreTextFace *ctface = PANGO_CORE_TEXT_FACE (face); + PangoFontDescription *description; + PangoWeight pango_weight; + PangoStyle pango_style; + PangoVariant pango_variant; + int weight; + + description = pango_font_description_new (); + + pango_font_description_set_family (description, ctface->family->family_name); + + weight = ctface->weight; + + switch (weight) + { + case 1: + case 2: + pango_weight = PANGO_WEIGHT_ULTRALIGHT; + break; + + case 3: + case 4: + pango_weight = PANGO_WEIGHT_LIGHT; + break; + + case 5: + case 6: + pango_weight = PANGO_WEIGHT_NORMAL; + break; + + case 7: + case 8: + pango_weight = PANGO_WEIGHT_SEMIBOLD; + break; + + case 9: + case 10: + pango_weight = PANGO_WEIGHT_BOLD; + break; + + case 11: + case 12: + pango_weight = PANGO_WEIGHT_ULTRABOLD; + break; + + case 13: + case 14: + pango_weight = PANGO_WEIGHT_HEAVY; + break; + + default: + g_assert_not_reached (); + }; + + if (ctface->traits & kCTFontItalicTrait) + pango_style = PANGO_STYLE_ITALIC; + else + pango_style = PANGO_STYLE_NORMAL; + + /* FIXME: How can this be figured using CoreText? */ +#if 0 + if (ctface->traits & NSSmallCapsFontMask) + pango_variant = PANGO_VARIANT_SMALL_CAPS; + else +#endif + pango_variant = PANGO_VARIANT_NORMAL; + + pango_font_description_set_weight (description, pango_weight); + pango_font_description_set_style (description, pango_style); + pango_font_description_set_variant (description, pango_variant); + + return description; +} + +static const char * +pango_core_text_face_get_face_name (PangoFontFace *face) +{ + PangoCoreTextFace *ctface = PANGO_CORE_TEXT_FACE (face); + + return ctface->style_name; +} + +static void +pango_core_text_face_list_sizes (PangoFontFace *face, + int **sizes, + int *n_sizes) +{ + *n_sizes = 0; + *sizes = NULL; +} + +static void +pango_core_text_face_finalize (GObject *object) +{ + PangoCoreTextFace *ctface = PANGO_CORE_TEXT_FACE (object); + + if (ctface->coverage) + pango_coverage_unref (ctface->coverage); + + g_free (ctface->postscript_name); + g_free (ctface->style_name); + + G_OBJECT_CLASS (pango_core_text_face_parent_class)->finalize (object); +} + +static void +pango_core_text_face_class_init (PangoFontFaceClass *class) +{ + GObjectClass *object_class = (GObjectClass *)class; + + pango_core_text_face_parent_class = g_type_class_peek_parent (class); + + object_class->finalize = pango_core_text_face_finalize; + + class->describe = pango_core_text_face_describe; + class->get_face_name = pango_core_text_face_get_face_name; + class->list_sizes = pango_core_text_face_list_sizes; +} + +GType +pango_core_text_face_get_type (void) +{ + static GType object_type = 0; + + if (G_UNLIKELY (!object_type)) + { + const GTypeInfo object_info = + { + sizeof (PangoFontFaceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pango_core_text_face_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PangoCoreTextFace), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (PANGO_TYPE_FONT_FACE, + I_("PangoCoreTextFace"), + &object_info, 0); + } + + return object_type; +} + +const char * +_pango_core_text_face_get_postscript_name (PangoCoreTextFace *face) +{ + return face->postscript_name; +} + +PangoCoverage * +_pango_core_text_face_get_coverage (PangoCoreTextFace *face, + PangoLanguage *language) +{ + return face->coverage; +} + +static void pango_core_text_font_map_class_init (PangoCoreTextFontMapClass *class); +static void pango_core_text_font_map_init (PangoCoreTextFontMap *ctfontmap); + +static guint font_hash_key_hash (const FontHashKey *key); +static gboolean font_hash_key_equal (const FontHashKey *key_a, + const FontHashKey *key_b); +static void font_hash_key_free (FontHashKey *key); + +G_DEFINE_TYPE (PangoCoreTextFontMap, pango_core_text_font_map, PANGO_TYPE_FONT_MAP); + +static void +pango_core_text_font_map_finalize (GObject *object) +{ + PangoCoreTextFontMap *fontmap = PANGO_CORE_TEXT_FONT_MAP (object); + + g_hash_table_destroy (fontmap->font_hash); + g_hash_table_destroy (fontmap->families); + + G_OBJECT_CLASS (pango_core_text_font_map_parent_class)->finalize (object); +} + +struct _FontHashKey { + PangoCoreTextFontMap *fontmap; + PangoMatrix matrix; + PangoFontDescription *desc; + char *postscript_name; + gpointer context_key; +}; + +/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/) + * + * Not necessarily better than a lot of other hashes, but should be OK, and + * well tested with binary data. + */ + +#define FNV_32_PRIME ((guint32)0x01000193) +#define FNV1_32_INIT ((guint32)0x811c9dc5) + +static guint32 +hash_bytes_fnv (unsigned char *buffer, + int len, + guint32 hval) +{ + while (len--) + { + hval *= FNV_32_PRIME; + hval ^= *buffer++; + } + + return hval; +} + +static gboolean +font_hash_key_equal (const FontHashKey *key_a, + const FontHashKey *key_b) +{ + if (key_a->matrix.xx == key_b->matrix.xx && + key_a->matrix.xy == key_b->matrix.xy && + key_a->matrix.yx == key_b->matrix.yx && + key_a->matrix.yy == key_b->matrix.yy && + pango_font_description_equal (key_a->desc, key_b->desc) && + strcmp (key_a->postscript_name, key_b->postscript_name) == 0) + { + if (key_a->context_key) + return PANGO_CORE_TEXT_FONT_MAP_GET_CLASS (key_a->fontmap)->context_key_equal (key_a->fontmap, + key_a->context_key, + key_b->context_key); + else + return TRUE; + } + else + return FALSE; +} + +static guint +font_hash_key_hash (const FontHashKey *key) +{ + guint32 hash = FNV1_32_INIT; + + /* We do a bytewise hash on the context matrix */ + hash = hash_bytes_fnv ((unsigned char *)(&key->matrix), + sizeof(double) * 4, + hash); + + if (key->context_key) + hash ^= PANGO_CORE_TEXT_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap, + key->context_key); + + hash ^= g_str_hash (key->postscript_name); + + return (hash ^ pango_font_description_hash (key->desc)); +} + +static void +font_hash_key_free (FontHashKey *key) +{ + if (key->context_key) + PANGO_CORE_TEXT_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap, + key->context_key); + + g_slice_free (FontHashKey, key); +} + +static FontHashKey * +font_hash_key_copy (FontHashKey *old) +{ + FontHashKey *key = g_slice_new (FontHashKey); + + key->fontmap = old->fontmap; + key->matrix = old->matrix; + key->desc = pango_font_description_copy (old->desc); + key->postscript_name = g_strdup (old->postscript_name); + if (old->context_key) + key->context_key = PANGO_CORE_TEXT_FONT_MAP_GET_CLASS (key->fontmap)->context_key_copy (key->fontmap, old->context_key); + else + key->context_key = NULL; + + return key; +} + + +static void +get_context_matrix (PangoContext *context, + PangoMatrix *matrix) +{ + const PangoMatrix *set_matrix; + static const PangoMatrix identity = PANGO_MATRIX_INIT; + + if (context) + set_matrix = pango_context_get_matrix (context); + else + set_matrix = NULL; + + if (set_matrix) + *matrix = *set_matrix; + else + *matrix = identity; +} + +static void +font_hash_key_for_context (PangoCoreTextFontMap *fcfontmap, + PangoContext *context, + FontHashKey *key) +{ + key->fontmap = fcfontmap; + get_context_matrix (context, &key->matrix); + + if (PANGO_CORE_TEXT_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get) + key->context_key = (gpointer)PANGO_CORE_TEXT_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get (fcfontmap, context); + else + key->context_key = NULL; +} + +static void +pango_core_text_font_map_add (PangoCoreTextFontMap *ctfontmap, + PangoContext *context, + PangoCoreTextFont *ctfont) +{ + FontHashKey key; + FontHashKey *key_copy; + PangoCoreTextFace *face; + + _pango_core_text_font_set_font_map (ctfont, ctfontmap); + + font_hash_key_for_context (ctfontmap, context, &key); + face = _pango_core_text_font_get_face (ctfont); + key.postscript_name = (char *)_pango_core_text_face_get_postscript_name (face); + key.desc = _pango_core_text_font_get_font_description (ctfont); + + key_copy = font_hash_key_copy (&key); + _pango_core_text_font_set_context_key (ctfont, key_copy->context_key); + g_hash_table_insert (ctfontmap->font_hash, key_copy, g_object_ref (ctfont)); +} + +static PangoCoreTextFont * +pango_core_text_font_map_lookup (PangoCoreTextFontMap *ctfontmap, + PangoContext *context, + PangoFontDescription *desc, + PangoCoreTextFace *face) +{ + FontHashKey key; + + font_hash_key_for_context (ctfontmap, context, &key); + key.postscript_name = (char *)_pango_core_text_face_get_postscript_name (face); + key.desc = desc; + + return g_hash_table_lookup (ctfontmap->font_hash, &key); +} + +static gboolean +find_best_match (PangoCoreTextFamily *font_family, + const PangoFontDescription *description, + PangoFontDescription **best_description, + PangoCoreTextFace **best_face) +{ + PangoFontDescription *new_desc; + int i; + + *best_description = NULL; + *best_face = NULL; + + for (i = 0; i < font_family->n_faces; i++) + { + new_desc = pango_font_face_describe (font_family->faces[i]); + + if (pango_font_description_better_match (description, *best_description, new_desc)) + { + pango_font_description_free (*best_description); + *best_description = new_desc; + *best_face = (PangoCoreTextFace *)font_family->faces[i]; + } + else + pango_font_description_free (new_desc); + } + + if (*best_description) + return TRUE; + + return FALSE; +} + +static PangoFont * +pango_core_text_font_map_load_font (PangoFontMap *fontmap, + PangoContext *context, + const PangoFontDescription *description) +{ + PangoCoreTextFontMap *ctfontmap = (PangoCoreTextFontMap *)fontmap; + PangoCoreTextFamily *font_family; + const gchar *family; + gchar *name; + gint size; + + size = pango_font_description_get_size (description); + if (size < 0) + return NULL; + + family = pango_font_description_get_family (description); + family = family ? family : ""; + name = g_utf8_casefold (family, -1); + font_family = g_hash_table_lookup (ctfontmap->families, name); + g_free (name); + + if (font_family) + { + PangoFontDescription *best_description; + PangoCoreTextFace *best_face; + PangoCoreTextFont *best_font; + + /* Force a listing of the available faces */ + pango_font_family_list_faces ((PangoFontFamily *)font_family, NULL, NULL); + + if (!find_best_match (font_family, description, &best_description, &best_face)) + return NULL; + + pango_font_description_set_size (best_description, size); + + best_font = pango_core_text_font_map_lookup (ctfontmap, + context, + best_description, + best_face); + + if (best_font) + g_object_ref (best_font); + else + { + PangoCoreTextFontMapClass *klass; + + klass = PANGO_CORE_TEXT_FONT_MAP_GET_CLASS (ctfontmap); + best_font = klass->create_font (ctfontmap, context, + best_face, best_description); + + if (best_font) + pango_core_text_font_map_add (ctfontmap, context, best_font); + /* FIXME: Handle the else case here. */ + } + + pango_font_description_free (best_description); + + return (PangoFont *)best_font; + } + + return NULL; +} + +static void +list_families_foreach (gpointer key, + gpointer value, + gpointer user_data) +{ + GSList **list = user_data; + + *list = g_slist_prepend (*list, value); +} + +static void +pango_core_text_font_map_list_families (PangoFontMap *fontmap, + PangoFontFamily ***families, + int *n_families) +{ + GSList *family_list = NULL; + GSList *tmp_list; + PangoCoreTextFontMap *ctfontmap = (PangoCoreTextFontMap *)fontmap; + + if (!n_families) + return; + + g_hash_table_foreach (ctfontmap->families, + list_families_foreach, &family_list); + + *n_families = g_slist_length (family_list); + + if (families) + { + int i = 0; + + *families = g_new (PangoFontFamily *, *n_families); + + tmp_list = family_list; + while (tmp_list) + { + (*families)[i] = tmp_list->data; + i++; + tmp_list = tmp_list->next; + } + } + + g_slist_free (family_list); +} + +static void +pango_core_text_font_map_init (PangoCoreTextFontMap *ctfontmap) +{ + PangoCoreTextFamily *family; + CTFontCollectionRef collection; + CFArrayRef ctfaces; + CFIndex i, count; + + ctfontmap->families = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_object_unref); + + + ctfontmap->font_hash = g_hash_table_new_full ((GHashFunc)font_hash_key_hash, + (GEqualFunc)font_hash_key_equal, + (GDestroyNotify)font_hash_key_free, + NULL); + + collection = CTFontCollectionCreateFromAvailableFonts (0); + ctfaces = CTFontCollectionCreateMatchingFontDescriptors (collection); + count = CFArrayGetCount (ctfaces); + + for (i = 0; i < count; i++) + { + int font_traits; + char *buffer; + char *family_name; + CFStringRef str; + CFNumberRef number; + CFDictionaryRef dict; + CTFontDescriptorRef desc = CFArrayGetValueAtIndex (ctfaces, i); + + str = CTFontDescriptorCopyAttribute (desc, kCTFontFamilyNameAttribute); + buffer = gchar_from_cf_string (str); + + family_name = g_utf8_casefold (buffer, -1); + + CFRelease (str); + g_free (buffer); + + family = g_hash_table_lookup (ctfontmap->families, family_name); + if (!family) + { + family = g_object_new (PANGO_TYPE_CORE_TEXT_FAMILY, NULL); + g_hash_table_insert (ctfontmap->families, g_strdup (family_name), + family); + + family->family_name = family_name; + family_name = NULL; + } + + if (family_name) + g_free (family_name); + + /* We assume that all faces in the family are monospaced or none. */ + dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute); + number = (CFNumberRef)CFDictionaryGetValue (dict, + kCTFontSymbolicTrait); + + if (CFNumberGetValue (number, kCFNumberIntType, &font_traits)) + { + if (font_traits & kCTFontMonoSpaceTrait) + family->is_monospace = TRUE; + } + + CFRelease (dict); + } + + /* Insert aliases */ + family = g_object_new (PANGO_TYPE_CORE_TEXT_FAMILY, NULL); + family->family_name = g_strdup ("Sans"); + g_hash_table_insert (ctfontmap->families, + g_utf8_casefold (family->family_name, -1), family); + + family = g_object_new (PANGO_TYPE_CORE_TEXT_FAMILY, NULL); + family->family_name = g_strdup ("Serif"); + g_hash_table_insert (ctfontmap->families, + g_utf8_casefold (family->family_name, -1), family); + + family = g_object_new (PANGO_TYPE_CORE_TEXT_FAMILY, NULL); + family->family_name = g_strdup ("Monospace"); + family->is_monospace = TRUE; + g_hash_table_insert (ctfontmap->families, + g_utf8_casefold (family->family_name, -1), family); +} + +static void +pango_core_text_font_map_class_init (PangoCoreTextFontMapClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + PangoFontMapClass *fontmap_class = PANGO_FONT_MAP_CLASS (class); + + object_class->finalize = pango_core_text_font_map_finalize; + + fontmap_class->load_font = pango_core_text_font_map_load_font; + fontmap_class->list_families = pango_core_text_font_map_list_families; + fontmap_class->shape_engine_type = PANGO_RENDER_TYPE_CORE_TEXT; +} diff --git a/pango/pangocoretext-private.h b/pango/pangocoretext-private.h new file mode 100644 index 00000000..dd5cff84 --- /dev/null +++ b/pango/pangocoretext-private.h @@ -0,0 +1,101 @@ +/* Pango + * pangocoretext-private.h: + * + * Copyright (C) 2003 Red Hat Software + * Copyright (C) 2005-2007 Imendio AB + * Copyright (C) 2010 Kristian Rietveld <kris@gtk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __PANGOCORETEXT_PRIVATE_H__ +#define __PANGOCORETEXT_PRIVATE_H__ + +#include <pango/pango-fontmap.h> +#include <pango/pango-context.h> +#include "pangocoretext.h" + +G_BEGIN_DECLS + +#define PANGO_TYPE_CORE_TEXT_FONT_MAP (pango_core_text_font_map_get_type ()) +#define PANGO_CORE_TEXT_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CORE_TEXT_FONT_MAP, PangoCoreTextFontMap)) +#define PANGO_CORE_TEXT_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CORE_TEXT_FONT_MAP)) +#define PANGO_CORE_TEXT_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CORE_TEXT_FONT_MAP, PangoCoreTextFontMapClass)) +#define PANGO_IS_CORE_TEXT_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CORE_TEXT_FONT_MAP)) +#define PANGO_CORE_TEXT_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CORE_TEXT_FONT_MAP, PangoCoreTextFontMapClass)) + + +typedef struct _PangoCoreTextFamily PangoCoreTextFamily; +typedef struct _PangoCoreTextFace PangoCoreTextFace; + +typedef struct _PangoCoreTextFontMap PangoCoreTextFontMap; +typedef struct _PangoCoreTextFontMapClass PangoCoreTextFontMapClass; + +struct _PangoCoreTextFontMap +{ + PangoFontMap parent_instance; + + GHashTable *font_hash; + + GHashTable *families; +}; + +struct _PangoCoreTextFontMapClass +{ + PangoFontMapClass parent_class; + + gconstpointer (*context_key_get) (PangoCoreTextFontMap *ctfontmap, + PangoContext *context); + gpointer (*context_key_copy) (PangoCoreTextFontMap *ctfontmap, + gconstpointer key); + void (*context_key_free) (PangoCoreTextFontMap *ctfontmap, + gpointer key); + guint32 (*context_key_hash) (PangoCoreTextFontMap *ctfontmap, + gconstpointer key); + gboolean (*context_key_equal) (PangoCoreTextFontMap *ctfontmap, + gconstpointer key_a, + gconstpointer key_b); + + PangoCoreTextFont * (* create_font) (PangoCoreTextFontMap *fontmap, + PangoContext *context, + PangoCoreTextFace *face, + const PangoFontDescription *desc); +}; + + +GType pango_core_text_font_map_get_type (void) G_GNUC_CONST; + +const char * _pango_core_text_face_get_postscript_name (PangoCoreTextFace *face); +PangoCoverage * _pango_core_text_face_get_coverage (PangoCoreTextFace *face, + PangoLanguage *language); + +void _pango_core_text_font_set_font_description (PangoCoreTextFont *afont, + const PangoFontDescription *desc); +PangoFontDescription *_pango_core_text_font_get_font_description (PangoCoreTextFont *afont); +void _pango_core_text_font_set_font_map (PangoCoreTextFont *afont, + PangoCoreTextFontMap *fontmap); +void _pango_core_text_font_set_face (PangoCoreTextFont *afont, + PangoCoreTextFace *aface); +PangoCoreTextFace * _pango_core_text_font_get_face (PangoCoreTextFont *font); +gpointer _pango_core_text_font_get_context_key (PangoCoreTextFont *afont); +void _pango_core_text_font_set_context_key (PangoCoreTextFont *afont, + gpointer context_key); +void _pango_core_text_font_set_ctfont (PangoCoreTextFont *font, + CTFontRef font_ref); + +G_END_DECLS + +#endif /* __PANGOCORETEXT_PRIVATE_H__ */ diff --git a/pango/pangocoretext.c b/pango/pangocoretext.c new file mode 100644 index 00000000..4d3ebb9a --- /dev/null +++ b/pango/pangocoretext.c @@ -0,0 +1,205 @@ +/* Pango + * pangocoretext.c + * + * Copyright (C) 2005-2007 Imendio AB + * Copyright (C) 2010 Kristian Rietveld <kris@gtk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "pangocoretext.h" +#include "pangocoretext-private.h" + +G_DEFINE_TYPE (PangoCoreTextFont, pango_core_text_font, PANGO_TYPE_FONT); + +struct _PangoCoreTextFontPrivate +{ + PangoCoreTextFace *face; + PangoFontDescription *desc; + gpointer context_key; + + CTFontRef font_ref; + + PangoFontMap *fontmap; +}; + +static void +pango_core_text_font_finalize (GObject *object) +{ + PangoCoreTextFont *ctfont = (PangoCoreTextFont *)object; + PangoCoreTextFontPrivate *priv = ctfont->priv; + + pango_font_description_free (priv->desc); + + g_assert (priv->fontmap != NULL); + g_object_remove_weak_pointer (G_OBJECT (priv->fontmap), (gpointer *) (gpointer) &priv->fontmap); + priv->fontmap = NULL; + + G_OBJECT_CLASS (pango_core_text_font_parent_class)->finalize (object); +} + +static PangoFontDescription * +pango_core_text_font_describe (PangoFont *font) +{ + PangoCoreTextFont *ctfont = (PangoCoreTextFont *)font; + PangoCoreTextFontPrivate *priv = ctfont->priv; + + return pango_font_description_copy (priv->desc); +} + +static PangoCoverage * +pango_core_text_font_get_coverage (PangoFont *font, + PangoLanguage *language) +{ + PangoCoreTextFont *ctfont = (PangoCoreTextFont *)font; + PangoCoreTextFontPrivate *priv = ctfont->priv; + + return pango_coverage_ref (_pango_core_text_face_get_coverage (priv->face, + language)); +} + +static PangoEngineShape * +pango_core_text_font_find_shaper (PangoFont *font, + PangoLanguage *language, + guint32 ch) +{ + /* FIXME: Implement */ + return NULL; +} + +static PangoFontMap * +pango_core_text_font_get_font_map (PangoFont *font) +{ + PangoCoreTextFont *ctfont = (PangoCoreTextFont *)font; + + return ctfont->priv->fontmap; +} + +static void +pango_core_text_font_init (PangoCoreTextFont *ctfont) +{ + ctfont->priv = G_TYPE_INSTANCE_GET_PRIVATE (ctfont, + PANGO_TYPE_CORE_TEXT_FONT, + PangoCoreTextFontPrivate); +} + +static void +pango_core_text_font_class_init (PangoCoreTextFontClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + PangoFontClass *font_class = PANGO_FONT_CLASS (class); + + object_class->finalize = pango_core_text_font_finalize; + + font_class->describe = pango_core_text_font_describe; + font_class->get_coverage = pango_core_text_font_get_coverage; + font_class->find_shaper = pango_core_text_font_find_shaper; + font_class->get_font_map = pango_core_text_font_get_font_map; + + g_type_class_add_private (object_class, sizeof (PangoCoreTextFontPrivate)); +} + +/* FIXME: why are these defined like this? */ +void +_pango_core_text_font_set_font_description (PangoCoreTextFont *font, + const PangoFontDescription *desc) +{ + PangoCoreTextFontPrivate *priv = font->priv; + + priv->desc = pango_font_description_copy (desc); +} + +PangoFontDescription * +_pango_core_text_font_get_font_description (PangoCoreTextFont *font) +{ + PangoCoreTextFontPrivate *priv = font->priv; + + return priv->desc; +} + +void +_pango_core_text_font_set_font_map (PangoCoreTextFont *font, + PangoCoreTextFontMap *fontmap) +{ + PangoCoreTextFontPrivate *priv = font->priv; + + g_assert (priv->fontmap == NULL); + priv->fontmap = (PangoFontMap *) fontmap; + g_object_add_weak_pointer (G_OBJECT (priv->fontmap), (gpointer *) (gpointer) &priv->fontmap); +} + +void +_pango_core_text_font_set_face (PangoCoreTextFont *ctfont, + PangoCoreTextFace *ctface) +{ + PangoCoreTextFontPrivate *priv = ctfont->priv; + + priv->face = ctface; +} + +PangoCoreTextFace * +_pango_core_text_font_get_face (PangoCoreTextFont *font) +{ + PangoCoreTextFontPrivate *priv = font->priv; + + return priv->face; +} + +gpointer +_pango_core_text_font_get_context_key (PangoCoreTextFont *font) +{ + PangoCoreTextFontPrivate *priv = font->priv; + + return priv->context_key; +} + +void +_pango_core_text_font_set_context_key (PangoCoreTextFont *font, + gpointer context_key) +{ + PangoCoreTextFontPrivate *priv = font->priv; + + priv->context_key = context_key; +} + +void +_pango_core_text_font_set_ctfont (PangoCoreTextFont *font, + CTFontRef font_ref) +{ + PangoCoreTextFontPrivate *priv = font->priv; + + priv->font_ref = font_ref; +} + +/** + * pango_core_text_font_get_ctfont: + * @font: A #PangoCoreTextFont + * + * Returns the CTFontRef of a font. + * + * Return value: the CTFontRef associated to @font. + * + * Since: 1.24 + */ +CTFontRef +pango_core_text_font_get_ctfont (PangoCoreTextFont *font) +{ + PangoCoreTextFontPrivate *priv = font->priv; + + return priv->font_ref; +} diff --git a/pango/pangocoretext.h b/pango/pangocoretext.h new file mode 100644 index 00000000..22dd9cb0 --- /dev/null +++ b/pango/pangocoretext.h @@ -0,0 +1,80 @@ +/* Pango + * pangocoretext.h: + * + * Copyright (C) 2005 Imendio AB + * Copyright (C) 2010 Kristian Rietveld <kris@gtk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __PANGOCORETEXT_H__ +#define __PANGOCORETEXT_H__ + +#include <pango/pango-context.h> +#include <pango/pango-font.h> +#include <Carbon/Carbon.h> + +G_BEGIN_DECLS + +#define PANGO_TYPE_CORE_TEXT_FONT (pango_core_text_font_get_type ()) +#define PANGO_CORE_TEXT_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CORE_TEXT_FONT, PangoCoreTextFont)) +#define PANGO_IS_CORE_TEXT_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CORE_TEXT_FONT)) + +typedef struct _PangoCoreTextFont PangoCoreTextFont; +typedef struct _PangoCoreTextFontClass PangoCoreTextFontClass; + +#if defined(PANGO_ENABLE_ENGINE) || defined(PANGO_ENABLE_BACKEND) + +#define PANGO_RENDER_TYPE_CORE_TEXT "PangoRenderCoreText" + +#ifdef PANGO_ENABLE_BACKEND + +#define PANGO_CORE_TEXT_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CORE_TEXT_FONT, PangoCoreTextFontClass)) +#define PANGO_IS_CORE_TEXT_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CORE_TEXT_FONT)) +#define PANGO_CORE_TEXT_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CORE_TEXT_FONT, PangoCoreTextFontClass)) + +typedef struct _PangoCoreTextFontPrivate PangoCoreTextFontPrivate; + +struct _PangoCoreTextFont +{ + PangoFont parent_instance; + PangoCoreTextFontPrivate *priv; +}; + +struct _PangoCoreTextFontClass +{ + PangoFontClass parent_class; + + /*< private >*/ + + /* Padding for future expansion */ + void (*_pango_reserved1) (void); + void (*_pango_reserved2) (void); + void (*_pango_reserved3) (void); + void (*_pango_reserved4) (void); +}; + +#endif /* PANGO_ENABLE_BACKEND */ + +CTFontRef pango_core_text_font_get_ctfont (PangoCoreTextFont *font); + +#endif /* PANGO_ENABLE_ENGINE || PANGO_ENABLE_BACKEND */ + +GType pango_core_text_font_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __PANGOCORETEXT_H__ */ |