[pango] Start implementation of CoreText backend



commit 87882adf1ccacfb49e8c119b1fcb6d13a0e4731f
Author: Kristian Rietveld <kris gtk org>
Date:   Fri Mar 5 21:46:38 2010 +0100

    Start implementation of CoreText backend
    
    On Mac OS X systems where CoreText is available (that is, 10.5 or
    higher), we will build the CoreText backend instead of the ATSUI
    backend.  In this case, the ATSUI backend will not be built and
    installed.  This change is necessary because since Mac OS 10.5
    ATSUI has been marked as deprecated.
    
    For older systems, we will have to continue to use the
    ATSUI backend.

 configure.in                       |   57 ++-
 modules/basic/Makefile.am          |   17 +
 modules/basic/basic-coretext.c     |  232 +++++++++
 pango/Makefile.am                  |   21 +
 pango/modules.h                    |    1 +
 pango/pangocairo-coretext.h        |   55 ++
 pango/pangocairo-coretextfont.c    |  279 +++++++++++
 pango/pangocairo-coretextfont.h    |   37 ++
 pango/pangocairo-coretextfontmap.c |  107 ++++
 pango/pangocairo-fontmap.c         |   14 +-
 pango/pangocoretext-fontmap.c      |  952 ++++++++++++++++++++++++++++++++++++
 pango/pangocoretext-private.h      |  101 ++++
 pango/pangocoretext.c              |  205 ++++++++
 pango/pangocoretext.h              |   80 +++
 14 files changed, 2155 insertions(+), 3 deletions(-)
---
diff --git a/configure.in b/configure.in
index 03c79a8..7d8cbeb 100644
--- a/configure.in
+++ b/configure.in
@@ -337,6 +337,25 @@ fi
 AC_CHECK_HEADER(Carbon/Carbon.h, [have_atsui=true], [have_atsui=false])
 
 #
+# Checks for CoreText
+#
+
+AC_MSG_CHECKING([for CoreText availability])
+pango_save_libs=$LIBS
+LIBS="$LIBS -framework ApplicationServices"
+AC_TRY_LINK([#include <Carbon/Carbon.h>], [CTGetCoreTextVersion ();],
+[have_core_text=yes], [have_core_text=no])
+LIBS=$pango_save_libs
+
+if test "$have_core_text" = "yes"; then
+  AC_DEFINE(HAVE_CORE_TEXT, 1, [Whether CoreText is available on the system])
+fi
+
+AC_MSG_RESULT([$have_core_text])
+
+AM_CONDITIONAL(HAVE_CORE_TEXT, test "$have_core_text" = "yes")
+
+#
 # Checks for Cairo
 #
 have_cairo=false
@@ -378,7 +397,7 @@ if $have_cairo ; then
     have_cairo=true
   fi
 
-  if $have_atsui; then
+  if test $have_atsui -o $have_core_text; then
     PKG_CHECK_EXISTS(cairo-quartz-font >= $cairo_required, have_cairo_atsui=true, :)
   fi
   if $have_cairo_atsui; then
@@ -487,7 +506,7 @@ GOBJECT_INTROSPECTION_CHECK([0.9.5])
 # Modules to build
 #
 arabic_modules="arabic-fc,arabic-lang"
-basic_modules="basic-fc,basic-win32,basic-x,basic-atsui"
+basic_modules="basic-fc,basic-win32,basic-x,basic-atsui,basic-coretext"
 hangul_modules="hangul-fc"
 hebrew_modules="hebrew-fc"
 indic_modules="indic-fc,indic-lang"
@@ -543,12 +562,14 @@ INCLUDED_X_MODULES=
 INCLUDED_FC_MODULES=
 INCLUDED_WIN32_MODULES=
 INCLUDED_ATSUI_MODULES=
+INCLUDED_CORE_TEXT_MODULES=
 INCLUDED_LANG_MODULES=
 
 AC_SUBST(INCLUDED_X_MODULES)
 AC_SUBST(INCLUDED_FC_MODULES)
 AC_SUBST(INCLUDED_WIN32_MODULES)
 AC_SUBST(INCLUDED_ATSUI_MODULES)
+AC_SUBST(INCLUDED_CORE_TEXT_MODULES)
 AC_SUBST(INCLUDED_LANG_MODULES)
 
 IFS="${IFS= 	}"; pango_save_ifs="$IFS"; IFS=", "
@@ -564,6 +585,7 @@ for module in $included_modules; do
     *-fc)	INCLUDED_FC_MODULES="$INCLUDED_FC_MODULES $included_path" ;;
     *-win32)	INCLUDED_WIN32_MODULES="$INCLUDED_WIN32_MODULES $included_path" ;;
     *-atsui)	INCLUDED_ATSUI_MODULES="$INCLUDED_ATSUI_MODULES $included_path" ;;
+    *-coretext) INCLUDED_CORE_TEXT_MODULES="$INCLUDED_CORE_TEXT_MODULES $included_path" ;;
     *-lang)	INCLUDED_LANG_MODULES="$INCLUDED_LANG_MODULES $included_path" ;;
     *)		IFS="$pango_save_ifs"; AC_MSG_ERROR([specified module $module not recognized]) ;;
   esac
@@ -576,6 +598,7 @@ AM_CONDITIONAL(INCLUDE_BASIC_FC,	echo $included_modules | egrep '(^|,)basic-fc($
 AM_CONDITIONAL(INCLUDE_BASIC_WIN32,	echo $included_modules | egrep '(^|,)basic-win32($|,)' 	> /dev/null)
 AM_CONDITIONAL(INCLUDE_BASIC_X,		echo $included_modules | egrep '(^|,)basic-x($|,)' 	> /dev/null)
 AM_CONDITIONAL(INCLUDE_BASIC_ATSUI,	echo $included_modules | egrep '(^|,)basic-atsui($|,)' 	> /dev/null)
+AM_CONDITIONAL(INCLUDE_BASIC_CORE_TEXT,	echo $included_modules | egrep '(^|,)basic-coretext($|,)'	> /dev/null)
 AM_CONDITIONAL(INCLUDE_HANGUL_FC,	echo $included_modules | egrep '(^|,)hangul-fc($|,)' 	> /dev/null)
 AM_CONDITIONAL(INCLUDE_HEBREW_FC,	echo $included_modules | egrep '(^|,)hebrew-fc($|,)' 	> /dev/null)
 AM_CONDITIONAL(INCLUDE_INDIC_FC,	echo $included_modules | egrep '(^|,)indic-fc($|,)' 	> /dev/null)
@@ -592,6 +615,7 @@ AM_CONDITIONAL(DYNAMIC_BASIC_FC,	echo $dynamic_modules | egrep '(^|,)basic-fc($|
 AM_CONDITIONAL(DYNAMIC_BASIC_WIN32,	echo $dynamic_modules | egrep '(^|,)basic-win32($|,)' 	> /dev/null)
 AM_CONDITIONAL(DYNAMIC_BASIC_X,		echo $dynamic_modules | egrep '(^|,)basic-x($|,)' 	> /dev/null)
 AM_CONDITIONAL(DYNAMIC_BASIC_ATSUI,	echo $dynamic_modules | egrep '(^|,)basic-atsui($|,)' 	> /dev/null)
+AM_CONDITIONAL(DYNAMIC_BASIC_CORE_TEXT,	echo $dynamic_modules | egrep '(^|,)basic-coretext($|,)' 	> /dev/null)
 AM_CONDITIONAL(DYNAMIC_HANGUL_FC,	echo $dynamic_modules | egrep '(^|,)hangul-fc($|,)'	> /dev/null)
 AM_CONDITIONAL(DYNAMIC_HEBREW_FC,	echo $dynamic_modules | egrep '(^|,)hebrew-fc($|,)' 	> /dev/null)
 AM_CONDITIONAL(DYNAMIC_INDIC_FC,	echo $dynamic_modules | egrep '(^|,)indic-fc($|,)' 	> /dev/null)
@@ -886,6 +910,35 @@ cat >> pango/module-defs-atsui.c <<EOTEXT
 EOTEXT
 ])
 
+AC_CONFIG_COMMANDS([pango/module-defs-coretext.c],
+[
+### CoreText modules
+cat > pango/module-defs-coretext.c <<EOTEXT
+/* Autogenerated by configure. Do not edit */
+
+#include "module-defs.h"
+
+PangoIncludedModule _pango_included_core_text_modules@<:@@:>@ = {
+EOTEXT
+
+IFS="${IFS= 	}"; pango_save_ifs="$IFS"; IFS=","
+for module in $included_modules; do
+  if echo $module | egrep -- "-atsui($|,)" > /dev/null; then
+    module_c=`echo $module | sed s/-/_/`
+    cat >> pango/module-defs-coretext.c <<EOTEXT
+ { _pango_${module_c}_script_engine_list, _pango_${module_c}_script_engine_init, _pango_${module_c}_script_engine_exit, _pango_${module_c}_script_engine_create },
+EOTEXT
+  fi
+done
+
+IFS="$pango_save_ifs"
+
+cat >> pango/module-defs-coretext.c <<EOTEXT
+ { NULL, NULL, NULL, NULL },
+};
+EOTEXT
+])
+
 AC_CONFIG_COMMANDS([pango/module-defs-lang.c],
 [
 ### lang modules
diff --git a/modules/basic/Makefile.am b/modules/basic/Makefile.am
index 93604c9..a264d70 100644
--- a/modules/basic/Makefile.am
+++ b/modules/basic/Makefile.am
@@ -54,6 +54,16 @@ libpango_basic_win32_la_SOURCES = basic-win32.c
 libpango_basic_win32_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_basic_win32
 
 if HAVE_CAIRO_ATSUI
+if HAVE_CORE_TEXT
+INCLUDES += $(CAIRO_CFLAGS)
+if INCLUDE_BASIC_CORE_TEXT
+noinst_LTLIBRARIES += libpango-basic-coretext.la
+else
+if DYNAMIC_BASIC_CORE_TEXT
+module_LTLIBRARIES += pango-basic-coretext.la
+endif
+endif
+else
 INCLUDES += $(ATSUI_CFLAGS) $(CAIRO_CFLAGS)
 if INCLUDE_BASIC_ATSUI
 noinst_LTLIBRARIES += libpango-basic-atsui.la
@@ -63,6 +73,13 @@ module_LTLIBRARIES += pango-basic-atsui.la
 endif
 endif
 endif
+endif
+
+pango_basic_coretext_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS) -framework Carbon
+pango_basic_coretext_la_LIBADD = $(pangocoretextlibs)
+pango_basic_coretext_la_SOURCES = basic-coretext.c
+libpango_basic_coretext_la_SOURCES = basic-coretext.c
+libpango_basic_coretext_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_basic_coretext
 
 pango_basic_atsui_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS) -framework Carbon
 pango_basic_atsui_la_LIBADD = $(pangoatsuilibs)
diff --git a/modules/basic/basic-coretext.c b/modules/basic/basic-coretext.c
new file mode 100644
index 0000000..1670710
--- /dev/null
+++ b/modules/basic/basic-coretext.c
@@ -0,0 +1,232 @@
+/* Pango
+ * basic-coretext.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 <glib.h>
+#include <string.h>
+#include <Carbon/Carbon.h>
+#include "pango-engine.h"
+#include "pango-utils.h"
+#include "pango-fontmap.h"
+#include "pangocoretext.h"
+
+/* No extra fields needed */
+typedef PangoEngineShape      BasicEngineCoreText;
+typedef PangoEngineShapeClass BasicEngineCoreTextClass ;
+
+#define SCRIPT_ENGINE_NAME "BasicScriptEngineCoreText"
+#define RENDER_TYPE PANGO_RENDER_TYPE_CORE_TEXT
+
+static PangoEngineScriptInfo basic_scripts[] = {
+  { PANGO_SCRIPT_COMMON,   "" }
+};
+
+static PangoEngineInfo script_engines[] = {
+  {
+    SCRIPT_ENGINE_NAME,
+    PANGO_ENGINE_TYPE_SHAPE,
+    RENDER_TYPE,
+    basic_scripts, G_N_ELEMENTS(basic_scripts)
+  }
+};
+
+static void
+set_glyph (PangoFont        *font,
+	   PangoGlyphString *glyphs,
+	   int               i,
+	   int               offset,
+	   PangoGlyph        glyph)
+{
+  PangoRectangle logical_rect;
+
+  glyphs->glyphs[i].glyph = glyph;
+
+  glyphs->glyphs[i].geometry.x_offset = 0;
+  glyphs->glyphs[i].geometry.y_offset = 0;
+
+  glyphs->log_clusters[i] = offset;
+  pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
+  glyphs->glyphs[i].geometry.width = logical_rect.width;
+}
+
+static void
+basic_engine_shape (PangoEngineShape    *engine,
+		    PangoFont           *font,
+		    const char          *text,
+		    gint                 length,
+		    const PangoAnalysis *analysis,
+		    PangoGlyphString    *glyphs)
+{
+  const char *p;
+  char *copy;
+  CTLineRef line;
+  CFStringRef cstr;
+  CFDictionaryRef attributes;
+  CFAttributedStringRef attstr;
+  PangoCoreTextFont *cfont = PANGO_CORE_TEXT_FONT (font);
+  PangoCoverage *coverage;
+  CFArrayRef runs;
+  CTRunRef run;
+  CFIndex i, glyph_count;
+  const CGGlyph *cgglyphs;
+
+  CFTypeRef keys[] = {
+      (CFTypeRef) kCTFontAttributeName
+  };
+
+  CFTypeRef values[] = {
+      pango_core_text_font_get_ctfont (cfont)
+  };
+
+  attributes = CFDictionaryCreate (kCFAllocatorDefault,
+                                   (const void **)keys,
+                                   (const void **)values,
+                                   1,
+                                   &kCFCopyStringDictionaryKeyCallBacks,
+                                   &kCFTypeDictionaryValueCallBacks);
+
+  copy = g_strndup (text, length + 1);
+  copy[length] = 0;
+
+  cstr = CFStringCreateWithCString (kCFAllocatorDefault, copy,
+                                    kCFStringEncodingUTF8);
+  g_free (copy);
+
+  attstr = CFAttributedStringCreate (kCFAllocatorDefault,
+                                     cstr,
+                                     attributes);
+
+  line = CTLineCreateWithAttributedString (attstr);
+
+  runs = CTLineGetGlyphRuns (line);
+
+  run = CFArrayGetValueAtIndex (runs, 0);
+  glyph_count = CTRunGetGlyphCount (run);
+  cgglyphs = CTRunGetGlyphsPtr (run);
+
+  p = text;
+  pango_glyph_string_set_size (glyphs, glyph_count);
+  coverage = pango_font_get_coverage (PANGO_FONT (cfont),
+                                      analysis->language);
+
+  for (i = 0; i < glyph_count; i++)
+    {
+      gunichar wc;
+      gunichar mirrored_ch;
+
+      wc = g_utf8_get_char (p);
+
+      if (analysis->level % 2)
+	if (pango_get_mirror_char (wc, &mirrored_ch))
+	  wc = mirrored_ch;
+
+      if (wc == 0xa0)	/* non-break-space */
+	wc = 0x20;
+
+      if (pango_is_zero_width (wc))
+	{
+	  set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY);
+	}
+      else
+	{
+          PangoCoverageLevel result;
+
+          result = pango_coverage_get (coverage, wc);
+
+          if (result != PANGO_COVERAGE_NONE)
+            {
+              set_glyph (font, glyphs, i, p - text, cgglyphs[i]);
+
+              if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK)
+                {
+                  if (i > 0)
+                    {
+                      PangoRectangle logical_rect, ink_rect;
+
+                      glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width,
+                                                              glyphs->glyphs[i].geometry.width);
+                      glyphs->glyphs[i-1].geometry.width = 0;
+                      glyphs->log_clusters[i] = glyphs->log_clusters[i-1];
+
+                      /* Some heuristics to try to guess how overstrike glyphs are
+                       * done and compensate
+                       */
+                      pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect);
+                      if (logical_rect.width == 0 && ink_rect.x == 0)
+                        glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2;
+                    }
+                }
+            }
+          else
+            {
+              set_glyph (font, glyphs, i, p - text,
+                         PANGO_GET_UNKNOWN_GLYPH (wc));
+            }
+        }
+
+      p = g_utf8_next_char (p);
+    }
+
+  CFRelease (line);
+  CFRelease (attstr);
+  CFRelease (cstr);
+  CFRelease (attributes);
+  pango_coverage_unref (coverage);
+}
+
+static void
+basic_engine_core_text_class_init (PangoEngineShapeClass *class)
+{
+  class->script_shape = basic_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (BasicEngineCoreText, basic_engine_core_text,
+				basic_engine_core_text_class_init, NULL);
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+  basic_engine_core_text_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+			  int              *n_engines)
+{
+  *engines = script_engines;
+  *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+  if (!strcmp (id, SCRIPT_ENGINE_NAME))
+    return g_object_new (basic_engine_core_text_type, NULL);
+  else
+    return NULL;
+}
+
diff --git a/pango/Makefile.am b/pango/Makefile.am
index 176d70a..df1596d 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 ca22701..7eac8fb 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 0000000..420e1c9
--- /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 0000000..81747ac
--- /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 0000000..752dfdd
--- /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 0000000..e05a1d4
--- /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 ae917d0..9404264 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 0000000..b8cf671
--- /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 0000000..dd5cff8
--- /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 0000000..4d3ebb9
--- /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 0000000..22dd9cb
--- /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__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]