Index: pango/Makefile.am =================================================================== RCS file: /cvs/gnome/pango/pango/Makefile.am,v retrieving revision 1.102 diff -u -r1.102 Makefile.am --- pango/Makefile.am 28 May 2004 22:53:24 -0000 1.102 +++ pango/Makefile.am 9 Jun 2004 19:29:31 -0000 @@ -173,7 +173,7 @@ # ------------------- libpangoft2 ------------------- if HAVE_FREETYPE -pangoinclude_HEADERS += pangoft2.h pango-ot.h +pangoinclude_HEADERS += pangoft2.h pango-ot.h pangofc-decoder.h lib_LTLIBRARIES += libpangoft2-1.0.la endif @@ -184,6 +184,7 @@ libpangoft2_1_0_la_SOURCES = \ pangofc-font.c \ pangofc-fontmap.c \ + pangofc-decoder.c \ pangofc-private.h \ pangoft2.h \ pangoft2.c \ Index: pango/pangofc-decoder.c =================================================================== RCS file: pango/pangofc-decoder.c diff -N pango/pangofc-decoder.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ pango/pangofc-decoder.c 9 Jun 2004 19:29:31 -0000 @@ -0,0 +1,92 @@ +/* Pango + * pangofc-decoder.c: Custom font encoder/decoders + * + * Copyright (C) 2004 Red Hat Software + * + * 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 "pangofc-decoder.h" + +G_DEFINE_ABSTRACT_TYPE (PangoFcDecoder, pango_fc_decoder, G_TYPE_OBJECT) + +static void +pango_fc_decoder_init (PangoFcDecoder *decoder); + +static void +pango_fc_decoder_class_init (PangoFcDecoderClass *klass); + +void +pango_fc_decoder_init (PangoFcDecoder *decoder) +{ +} + +void +pango_fc_decoder_class_init (PangoFcDecoderClass *klass) +{ +} + +/** + * pango_fc_decoder_get_charset: + * + * @decoder: A #PangoFcDecoder to use when querying the font for a + * supported #FcCharSet. + * + * @fcfont: The #PangoFcFont to query. + * + * This function will use the given decoder to generate an #FcCharSet + * of supported characters for the fcfont given. + * + * Since: 1.6 + * + */ + +FcCharSet * +pango_fc_decoder_get_charset (PangoFcDecoder *decoder, + PangoFcFont *fcfont) +{ + g_return_val_if_fail (PANGO_IS_FC_DECODER (decoder), NULL); + + return PANGO_FC_DECODER_GET_CLASS (decoder)->get_charset (fcfont); +} + +/** + * pango_fc_decoder_get_glyph: + * + * @decoder: A #PangoFcDecoder to use when querying the font. + * + * @fcfont: The #PangoFcFont to query. + * + * @wc: The unicode code point that you would like to see converted to + * a single #PangoGlyph. + * + * This function will take a given custom decoder and apply it to the + * given font and get the individual glyph from that font that + * corresponds to the unicode code point. + * + * Since: 1.6 + * + */ + +PangoGlyph +pango_fc_decoder_get_glyph (PangoFcDecoder *decoder, + PangoFcFont *fcfont, + guint32 wc) +{ + g_return_val_if_fail (PANGO_IS_FC_DECODER (decoder), 0); + + return PANGO_FC_DECODER_GET_CLASS (decoder)->get_glyph (fcfont, wc); +} Index: pango/pangofc-decoder.h =================================================================== RCS file: pango/pangofc-decoder.h diff -N pango/pangofc-decoder.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ pango/pangofc-decoder.h 9 Jun 2004 19:29:31 -0000 @@ -0,0 +1,108 @@ +/* Pango + * pangofc-decoder.h: Custom encoders/decoders on a per-font basis. + * + * Copyright (C) 2004 Red Hat Software + * + * 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 __PANGO_DECODER_H_ +#define __PANGO_DECODER_H_ + +#include +#include FT_FREETYPE_H +#include +#include + +#include +#include + +G_BEGIN_DECLS + +#define PANGO_TYPE_FC_DECODER (pango_fc_decoder_get_type()) +#define PANGO_FC_DECODER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FC_DECODER, PangoFcDecoder)) +#define PANGO_IS_FC_DECODER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FC_DECODER)) + +typedef struct _PangoFcDecoder PangoFcDecoder; +typedef struct _PangoFcDecoderClass PangoFcDecoderClass; + +#define PANGO_FC_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FC_DECODER, PangoFcDecoderClass)) +#define PANGO_IS_FC_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FC_DECODER)) +#define PANGO_FC_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FC_DECODER, PangoFcDecoderClass)) + +/** + * PangoFcDecoder: + * + * #PangoFcDecoder is a virtual base class that implementations will + * inherit from. It's the interface that is used to define a custom + * encoding for a font. Those fonts are specified using an #FcPattern + * and callbacks from Pango will happen when determining both coverage + * and character to glyph translations. + **/ + +struct _PangoFcDecoder +{ + GObject parent_instance; +}; + +/** + * PangoFcDecoderClass: + * + * @get_charset: This will return an #FcCharset given an #FcPattern + * that includes a list of supported characters in the font specified + * in that pattern. + * + * @get_glyph: This will return a single #PangoGlyph for a given + * #gunichar and the font specified in the #FcPattern that was passed + * into the function. This is called once for every character + * encountered and specified in the #get_charset method. + * + * Class structure for #PangoFcDecoder. + **/ + +struct _PangoFcDecoderClass +{ + /*< private >*/ + GObjectClass parent_class; + + /* vtable - not signals */ + /*< public >*/ + FcCharSet *(*get_charset) (PangoFcFont *fcfont); + PangoGlyph (*get_glyph) (PangoFcFont *fcfont, + guint32 wc); + + /*< private >*/ + + /* Padding for future expansion */ + void (*_pango_reserved1) (void); + void (*_pango_reserved2) (void); + void (*_pango_reserved3) (void); + void (*_pango_reserved4) (void); +}; + +GType pango_fc_decoder_get_type (void); + +FcCharSet *pango_fc_decoder_get_charset (PangoFcDecoder *decoder, + PangoFcFont *fcfont); + +PangoGlyph pango_fc_decoder_get_glyph (PangoFcDecoder *decoder, + PangoFcFont *fcfont, + guint32 wc); + +G_END_DECLS + +#endif /* __PANGO_DECODER_H_ */ + Index: pango/pangofc-font.c =================================================================== RCS file: /cvs/gnome/pango/pango/pangofc-font.c,v retrieving revision 1.6 diff -u -r1.6 pangofc-font.c --- pango/pangofc-font.c 27 May 2004 19:41:09 -0000 1.6 +++ pango/pangofc-font.c 9 Jun 2004 19:29:31 -0000 @@ -48,6 +48,15 @@ PROP_PATTERN }; +typedef struct _PangoFcFontPrivate PangoFcFontPrivate; + +#define PANGO_FC_FONT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PANGO_TYPE_FC_FONT, PangoFcFontPrivate)) + +struct _PangoFcFontPrivate +{ + PangoFcDecoder *decoder; +}; + static void pango_fc_font_class_init (PangoFcFontClass *class); static void pango_fc_font_finalize (GObject *object); static void pango_fc_font_set_property (GObject *object, @@ -114,6 +123,8 @@ "Pattern", "The fontconfig pattern for this font", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (object_class, sizeof (PangoFcFontPrivate)); } static void @@ -127,6 +138,7 @@ pango_fc_font_finalize (GObject *object) { PangoFcFont *fcfont = PANGO_FC_FONT (object); + PangoFcFontPrivate *priv = PANGO_FC_FONT_GET_PRIVATE (fcfont); g_slist_foreach (fcfont->metrics_by_lang, (GFunc)free_metrics_info, NULL); g_slist_free (fcfont->metrics_by_lang); @@ -137,6 +149,9 @@ FcPatternDestroy (fcfont->font_pattern); pango_font_description_free (fcfont->description); + if (priv->decoder) + _pango_fc_font_set_decoder (fcfont, NULL); + parent_class->finalize (object); } @@ -206,9 +221,17 @@ PangoLanguage *language) { PangoFcFont *fcfont = (PangoFcFont *)font; + PangoFcFontPrivate *priv = PANGO_FC_FONT_GET_PRIVATE (fcfont); + FcCharSet *charset; + + if (priv->decoder) + { + charset = pango_fc_decoder_get_charset (priv->decoder, fcfont); + return _pango_fc_font_map_fc_to_coverage (charset); + } return _pango_fc_font_map_get_coverage (PANGO_FC_FONT_MAP (fcfont->fontmap), - fcfont->font_pattern); + fcfont); } static void @@ -472,8 +495,17 @@ pango_fc_font_has_char (PangoFcFont *font, gunichar wc) { + PangoFcFontPrivate *priv = PANGO_FC_FONT_GET_PRIVATE (font); + FcCharSet *charset; + g_return_val_if_fail (PANGO_IS_FC_FONT (font), FALSE); + if (priv->decoder) + { + charset = pango_fc_decoder_get_charset (priv->decoder, font); + return FcCharSetHasChar (charset, wc); + } + return PANGO_FC_FONT_GET_CLASS (font)->has_char (font, wc); } @@ -495,8 +527,13 @@ pango_fc_font_get_glyph (PangoFcFont *font, gunichar wc) { + PangoFcFontPrivate *priv = PANGO_FC_FONT_GET_PRIVATE (font); + g_return_val_if_fail (PANGO_IS_FC_FONT (font), 0); + if (priv->decoder) + return pango_fc_decoder_get_glyph (priv->decoder, font, wc); + return PANGO_FC_FONT_GET_CLASS (font)->get_glyph (font, wc); } @@ -576,4 +613,52 @@ } pango_fc_font_unlock_face (font); +} + +/** + * _pango_fc_font_get_decoder + * + * + * @font: a #PangoFcFont + * + * This will return any custom decoder set on this font. + * + * Returns: The custom decoder + * + * Since: 1.6 + **/ + +PangoFcDecoder * +_pango_fc_font_get_decoder (PangoFcFont *font) +{ + PangoFcFontPrivate *priv = PANGO_FC_FONT_GET_PRIVATE (font); + + return priv->decoder; +} + +/** + * _pango_fc_font_set_decoder + * + * @font: a #PangoFcFont + * @decoder: a #PangoFcDecoder to set for this font + * + * This sets a custom decoder for this font. Any previous decoder + * will be released before this one is set. + * + * Since: 1.6 + **/ + +void +_pango_fc_font_set_decoder (PangoFcFont *font, + PangoFcDecoder *decoder) +{ + PangoFcFontPrivate *priv = PANGO_FC_FONT_GET_PRIVATE (font); + + if (priv->decoder) + g_object_unref (priv->decoder); + + priv->decoder = decoder; + + if (priv->decoder) + g_object_ref (priv->decoder); } Index: pango/pangofc-fontmap.c =================================================================== RCS file: /cvs/gnome/pango/pango/pangofc-fontmap.c,v retrieving revision 1.21 diff -u -r1.21 pangofc-fontmap.c --- pango/pangofc-fontmap.c 28 May 2004 22:53:24 -0000 1.21 +++ pango/pangofc-fontmap.c 9 Jun 2004 19:29:31 -0000 @@ -31,6 +31,7 @@ typedef struct _PangoFcFace PangoFcFace; typedef struct _PangoFcFamily PangoFcFamily; typedef struct _PangoFcPatternSet PangoFcPatternSet; +typedef struct _PangoFcFindFuncSet PangoFcFindFuncSet; #define PANGO_FC_TYPE_FAMILY (pango_fc_family_get_type ()) #define PANGO_FC_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FC_TYPE_FAMILY, PangoFcFamily)) @@ -60,6 +61,9 @@ PangoFcFamily **families; int n_families; /* -1 == uninitialized */ + /* Decoders */ + GSList *findfuncs; + guint closed : 1; }; @@ -98,6 +102,14 @@ GList *cache_link; }; +struct _PangoFcFindFuncSet +{ + PangoFcDecoderFindFunc findfunc; + gpointer user_data; + GDestroyNotify dnotify; + gpointer ddata; +}; + static GType pango_fc_family_get_type (void); static GType pango_fc_face_get_type (void); @@ -330,11 +342,57 @@ priv->fontset_hash_list = NULL; } +/** + * pango_fc_font_map_add_find_func: + * @fcfontmap: The #PangoFcFontMap to add this method to. + *o + * @factory: The #PangoFcDecoderFindFunc callback function + * + * @user_data: User data. + * + * @dnotify: A #GDestroyNotify callback that will be called when the + * fontmap is finalized and the decoder is released. + * + * @ddata: User data for the destruction notification callback. + * + * This function saves a callback method in the #PangoFcFontMap that + * will be called whenever new fonts are created. If the function + * returns a #PangoFcDecoder, that decoder will be used to determine + * both coverage via a #FcCharSet and a one-to-one mapping of + * characters to glyphs. This will allow applications to have + * application-specific encodings for various fonts. + * + * Since: 1.6. + * + */ + +void pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap, + PangoFcDecoderFindFunc findfunc, + gpointer user_data, + GDestroyNotify dnotify, + gpointer ddata) +{ + PangoFcFontMapPrivate *priv = fcfontmap->priv; + PangoFcFindFuncSet *set; + + set = g_new (PangoFcFindFuncSet, 1); + + set->findfunc = findfunc; + set->user_data = user_data; + set->dnotify = dnotify; + set->ddata = ddata; + + priv->findfuncs = g_slist_append (priv->findfuncs, set); +} + + + static void pango_fc_font_map_finalize (GObject *object) { PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (object); PangoFcFontMapPrivate *priv = fcfontmap->priv; + PangoFcFindFuncSet *set; pango_fc_font_map_cache_clear (fcfontmap); g_queue_free (priv->fontset_cache); @@ -346,6 +404,16 @@ if (priv->pattern_hash) g_hash_table_destroy (priv->pattern_hash); + while (priv->findfuncs) + { + set = priv->findfuncs->data; + if (set->dnotify) + set->dnotify (set->ddata); + + g_free (set); + priv->findfuncs = g_slist_remove_link (priv->findfuncs, priv->findfuncs); + } + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -594,6 +662,9 @@ PangoFcFontMapPrivate *priv = fcfontmap->priv; FcPattern *pattern; PangoFcFont *fcfont; + PangoFcDecoder *decoder; + PangoFcDecoderFindFunc findfunc; + GSList *tmp_find; /* Returning NULL here actually violates a contract * that loading load_font() will never return NULL. @@ -640,6 +711,26 @@ fcfont->fontmap = g_object_ref (fcfontmap); + /* + * Give any custom decoders a crack at this font now that it's been + * created. + */ + tmp_find = priv->findfuncs; + + while(tmp_find) + { + findfunc = ((PangoFcFindFuncSet *)tmp_find->data)->findfunc; + + decoder = findfunc (match, ((PangoFcFindFuncSet *)tmp_find->data)->user_data); + if (decoder) + { + _pango_fc_font_set_decoder (fcfont, decoder); + break; + } + + tmp_find = tmp_find->next; + } + return (PangoFont *)fcfont; } @@ -948,25 +1039,22 @@ PangoCoverage * _pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap, - FcPattern *pattern) + PangoFcFont *fcfont) { PangoFcFontMapPrivate *priv = fcfontmap->priv; PangoFcCoverageKey key; PangoCoverage *coverage; - FcChar32 map[FC_CHARSET_MAP_SIZE]; - FcChar32 ucs4, pos; FcCharSet *charset; - int i; /* * Assume that coverage information is identified by * a filename/index pair; there shouldn't be any reason * this isn't true, but it's not specified anywhere */ - if (FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &key.filename) != FcResultMatch) + if (FcPatternGetString (fcfont->font_pattern, FC_FILE, 0, (FcChar8 **) &key.filename) != FcResultMatch) return NULL; - if (FcPatternGetInteger (pattern, FC_INDEX, 0, &key.id) != FcResultMatch) + if (FcPatternGetInteger (fcfont->font_pattern, FC_INDEX, 0, &key.id) != FcResultMatch) return NULL; coverage = g_hash_table_lookup (priv->coverage_hash, &key); @@ -977,9 +1065,36 @@ * Pull the coverage out of the pattern, this * doesn't require loading the font */ - if (FcPatternGetCharSet (pattern, FC_CHARSET, 0, &charset) != FcResultMatch) + if (FcPatternGetCharSet (fcfont->font_pattern, FC_CHARSET, 0, &charset) != FcResultMatch) return NULL; + + coverage = _pango_fc_font_map_fc_to_coverage (charset); + /* Awful hack so Hangul Tone marks get rendered with the same + * font and in the same run as other Hangul characters. If a font + * covers the first composed Hangul glyph, then it is declared to cover + * the Hangul tone marks. This hack probably needs to be formalized + * by choosing fonts for scripts rather than individual code points. + */ + if (pango_coverage_get (coverage, 0xac00) == PANGO_COVERAGE_EXACT) + { + pango_coverage_set (coverage, 0x302e, PANGO_COVERAGE_EXACT); + pango_coverage_set (coverage, 0x302f, PANGO_COVERAGE_EXACT); + } + + pango_fc_font_map_set_coverage (fcfontmap, &key, coverage); + + return coverage; +} + +PangoCoverage * +_pango_fc_font_map_fc_to_coverage (FcCharSet *charset) +{ + PangoCoverage *coverage; + FcChar32 ucs4, pos; + FcChar32 map[FC_CHARSET_MAP_SIZE]; + int i; + /* * Convert an Fc CharSet into a pango coverage structure. Sure * would be nice to just use the Fc structure in place... @@ -1006,20 +1121,6 @@ } } - /* Awful hack so Hangul Tone marks get rendered with the same - * font and in the same run as other Hangul characters. If a font - * covers the first composed Hangul glyph, then it is declared to cover - * the Hangul tone marks. This hack probably needs to be formalized - * by choosing fonts for scripts rather than individual code points. - */ - if (pango_coverage_get (coverage, 0xac00) == PANGO_COVERAGE_EXACT) - { - pango_coverage_set (coverage, 0x302e, PANGO_COVERAGE_EXACT); - pango_coverage_set (coverage, 0x302f, PANGO_COVERAGE_EXACT); - } - - pango_fc_font_map_set_coverage (fcfontmap, &key, coverage); - return coverage; } Index: pango/pangofc-fontmap.h =================================================================== RCS file: /cvs/gnome/pango/pango/pangofc-fontmap.h,v retrieving revision 1.1 diff -u -r1.1 pangofc-fontmap.h --- pango/pangofc-fontmap.h 3 Aug 2003 02:35:20 -0000 1.1 +++ pango/pangofc-fontmap.h 9 Jun 2004 19:29:31 -0000 @@ -24,6 +24,7 @@ #include #include +#include #include G_BEGIN_DECLS @@ -97,6 +98,15 @@ #endif GType pango_fc_font_map_get_type (void); + +typedef PangoFcDecoder * (*PangoFcDecoderFindFunc) (FcPattern *pattern, + gpointer user_data); + +void pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap, + PangoFcDecoderFindFunc findfunc, + gpointer user_data, + GDestroyNotify dnotify, + gpointer ddata); PangoFontDescription *pango_fc_font_description_from_pattern (FcPattern *pattern, gboolean include_size); Index: pango/pangofc-private.h =================================================================== RCS file: /cvs/gnome/pango/pango/pangofc-private.h,v retrieving revision 1.1 diff -u -r1.1 pangofc-private.h --- pango/pangofc-private.h 3 Aug 2003 02:35:20 -0000 1.1 +++ pango/pangofc-private.h 9 Jun 2004 19:29:31 -0000 @@ -29,10 +29,15 @@ void _pango_fc_font_shutdown (PangoFcFont *fcfont); -void _pango_fc_font_map_remove (PangoFcFontMap *fcfontmap, - PangoFcFont *fcfont); -PangoCoverage *_pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap, - FcPattern *pattern); +void _pango_fc_font_map_remove (PangoFcFontMap *fcfontmap, + PangoFcFont *fcfont); +PangoCoverage *_pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap, + PangoFcFont *fcfont); +PangoCoverage *_pango_fc_font_map_fc_to_coverage (FcCharSet *charset); + +PangoFcDecoder *_pango_fc_font_get_decoder (PangoFcFont *font); +void _pango_fc_font_set_decoder (PangoFcFont *font, + PangoFcDecoder *decoder); G_END_DECLS