diff options
37 files changed, 887 insertions, 402 deletions
@@ -1,3 +1,36 @@ +2005-07-19 Owen Taylor <otaylor@redhat.com> + + * pango/pango-fcfontmap.[ch]: Rework handling of context-specific + options: drop get_render_key() and add a opaque "context + key" (get_context_key() and friends). Also add a function to get + the resolution. + + * pango/pango-fcfontmap.c pango/pangofc-font.h: + - Move the 'lang' into the fontset key lookup and get rid of the + funky list-of-hash-tables + - Make lookups of fontsets and fonts dependent on the context key + for the context. + - Simplify the pattern/fontset caching to have one finite-size + cache rather than an infinite first-level and a finite-size + second level. + + * pango/pangocairo.h pango/pangocairo-private.h + pango/pangocairo-fontmap.c: Add + pango_cairo_context_get/set_resolution(), + pango_cairo_context_set/get_font_options to allow controlling the + resolution and font rendering options for a specific PangoContext. + + * pango/pangocairo-fcfont.c pango/pangocairo-fcfontmap + pango/pangocairo-win32font.c: Implement resolution and font + options handling adapt to related Cairo changes. + + * docs/pango-sections.txt docs/Makefile.am pango/pangowin32.c: + Doc updates and build fixes. + + * pango/pangofc-fontmap.c (pango_fc_make_pattern): Create + patterns with FC_SIZE as well as FC_PIXEL_SIZE to work around + a libgnomeprint bug. (#309477) + 2005-07-09 Tor Lillqvist <tml@novell.com> * configure.in: Call AC_CANONICAL_HOST before looking at $host. diff --git a/ChangeLog.pre-1-10 b/ChangeLog.pre-1-10 index 792aa91d..e1242eac 100644 --- a/ChangeLog.pre-1-10 +++ b/ChangeLog.pre-1-10 @@ -1,3 +1,36 @@ +2005-07-19 Owen Taylor <otaylor@redhat.com> + + * pango/pango-fcfontmap.[ch]: Rework handling of context-specific + options: drop get_render_key() and add a opaque "context + key" (get_context_key() and friends). Also add a function to get + the resolution. + + * pango/pango-fcfontmap.c pango/pangofc-font.h: + - Move the 'lang' into the fontset key lookup and get rid of the + funky list-of-hash-tables + - Make lookups of fontsets and fonts dependent on the context key + for the context. + - Simplify the pattern/fontset caching to have one finite-size + cache rather than an infinite first-level and a finite-size + second level. + + * pango/pangocairo.h pango/pangocairo-private.h + pango/pangocairo-fontmap.c: Add + pango_cairo_context_get/set_resolution(), + pango_cairo_context_set/get_font_options to allow controlling the + resolution and font rendering options for a specific PangoContext. + + * pango/pangocairo-fcfont.c pango/pangocairo-fcfontmap + pango/pangocairo-win32font.c: Implement resolution and font + options handling adapt to related Cairo changes. + + * docs/pango-sections.txt docs/Makefile.am pango/pangowin32.c: + Doc updates and build fixes. + + * pango/pangofc-fontmap.c (pango_fc_make_pattern): Create + patterns with FC_SIZE as well as FC_PIXEL_SIZE to work around + a libgnomeprint bug. (#309477) + 2005-07-09 Tor Lillqvist <tml@novell.com> * configure.in: Call AC_CANONICAL_HOST before looking at $host. diff --git a/docs/Makefile.am b/docs/Makefile.am index 21b2da15..7bee28a1 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -27,6 +27,8 @@ IGNORE_HFILES= \ modules.h \ pangocairo-private.h \ pangocairo-fc.h \ + pangocairo-win32.h \ + pango-color-table.h \ pango-engine-private.h \ pango-impl-utils.h \ pango-glyph-item-private.h \ diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt index 6838df62..e195d3df 100644 --- a/docs/pango-sections.txt +++ b/docs/pango-sections.txt @@ -669,6 +669,9 @@ pango_win32_render_layout_line pango_win32_render_layout pango_win32_get_unknown_glyph pango_win32_font_get_glyph_index +pango_win32_font_select_font +pango_win32_font_done_font +pango_win32_font_get_metrics_factor pango_win32_get_debug_flag pango_win32_get_dc PangoWin32FontCache @@ -778,8 +781,10 @@ pango_cairo_font_map_get_default pango_cairo_font_map_set_resolution pango_cairo_font_map_get_resolution pango_cairo_font_map_create_context -pango_cairo_context_set_hinting -pango_cairo_context_get_hinting +pango_cairo_context_set_resolution +pango_cairo_context_get_resolution +pango_cairo_context_set_font_options +pango_cairo_context_get_font_options pango_cairo_update_context pango_cairo_create_layout pango_cairo_update_layout diff --git a/docs/tmpl/coverage-maps.sgml b/docs/tmpl/coverage-maps.sgml index d673d65e..5dc89ff1 100644 --- a/docs/tmpl/coverage-maps.sgml +++ b/docs/tmpl/coverage-maps.sgml @@ -17,6 +17,9 @@ to represent that information. </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### ENUM PangoCoverageLevel ##### --> <para> Used to indicate how well a font can represent a particular ISO 10646 diff --git a/docs/tmpl/engines.sgml b/docs/tmpl/engines.sgml index fb7fdfd2..063c7454 100644 --- a/docs/tmpl/engines.sgml +++ b/docs/tmpl/engines.sgml @@ -28,6 +28,9 @@ function is used when building a catalog of all available modules. </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoEngineInfo ##### --> <para> The #PangoEngineInfo structure contains information about a particular diff --git a/docs/tmpl/fonts.sgml b/docs/tmpl/fonts.sgml index 18adc5cf..4e5caa62 100644 --- a/docs/tmpl/fonts.sgml +++ b/docs/tmpl/fonts.sgml @@ -19,6 +19,9 @@ to load a font of a given description. </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoFontDescription ##### --> <para> The #PangoFontDescription structure represents the description @@ -610,6 +613,15 @@ Returns %TRUE if @object is a #PangoFont. @Returns: +<!-- ##### FUNCTION pango_font_get_font_map ##### --> +<para> + +</para> + +@font: +@Returns: + + <!-- ##### STRUCT PangoFontFamily ##### --> <para> The #PangoFontFamily structure is used to represent a family of related diff --git a/docs/tmpl/freetype-fonts.sgml b/docs/tmpl/freetype-fonts.sgml index 9877c200..b554fe57 100644 --- a/docs/tmpl/freetype-fonts.sgml +++ b/docs/tmpl/freetype-fonts.sgml @@ -14,6 +14,9 @@ Functions for shape engines to manipulate FreeType fonts </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoFT2FontMap ##### --> <para> The #PangoFT2FontMap is the #PangoFontMap implementation for FreeType fonts. diff --git a/docs/tmpl/glyphs.sgml b/docs/tmpl/glyphs.sgml index 35b4fbe8..0f9c1bfe 100644 --- a/docs/tmpl/glyphs.sgml +++ b/docs/tmpl/glyphs.sgml @@ -17,6 +17,9 @@ glyphs. </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### MACRO PANGO_SCALE ##### --> <para> The PANGO_SCALE macro represents the scale between dimensions used diff --git a/docs/tmpl/layout.sgml b/docs/tmpl/layout.sgml index 8f0cb26c..43fdfa55 100644 --- a/docs/tmpl/layout.sgml +++ b/docs/tmpl/layout.sgml @@ -19,6 +19,9 @@ at once. </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoLayout ##### --> <para> The #PangoLayout structure represents and entire paragraph diff --git a/docs/tmpl/main.sgml b/docs/tmpl/main.sgml index a1b46787..cbb6b880 100644 --- a/docs/tmpl/main.sgml +++ b/docs/tmpl/main.sgml @@ -17,6 +17,9 @@ various steps of this process. </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoContext ##### --> <para> The #PangoContext structure stores global information diff --git a/docs/tmpl/modules.sgml b/docs/tmpl/modules.sgml index 2d74a8ad..a4dd32ac 100644 --- a/docs/tmpl/modules.sgml +++ b/docs/tmpl/modules.sgml @@ -14,6 +14,9 @@ Support for loadable modules </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoIncludedModule ##### --> <para> The #PangoIncludedModule structure for a statically linked module diff --git a/docs/tmpl/opentype.sgml b/docs/tmpl/opentype.sgml index c8487c13..fde93bee 100644 --- a/docs/tmpl/opentype.sgml +++ b/docs/tmpl/opentype.sgml @@ -14,6 +14,9 @@ Obtaining information from OpenType tables </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### TYPEDEF PangoOTTag ##### --> <para> The <type>PangoOTTag</type> typedef is used to represent TrueType and OpenType diff --git a/docs/tmpl/pango-engine-lang.sgml b/docs/tmpl/pango-engine-lang.sgml index 79b08f21..42ddfb07 100644 --- a/docs/tmpl/pango-engine-lang.sgml +++ b/docs/tmpl/pango-engine-lang.sgml @@ -14,6 +14,9 @@ Rendering-system independent script engines </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoEngineLang ##### --> <para> </para> diff --git a/docs/tmpl/pango-engine-shape.sgml b/docs/tmpl/pango-engine-shape.sgml index d1aff7d0..8b6c8b98 100644 --- a/docs/tmpl/pango-engine-shape.sgml +++ b/docs/tmpl/pango-engine-shape.sgml @@ -14,6 +14,9 @@ Rendering-system dependent script engines </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoEngineShape ##### --> <para> </para> diff --git a/docs/tmpl/pango-renderer.sgml b/docs/tmpl/pango-renderer.sgml index f88a679b..5ffd48bc 100644 --- a/docs/tmpl/pango-renderer.sgml +++ b/docs/tmpl/pango-renderer.sgml @@ -18,6 +18,9 @@ destinations can be created. </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoRenderer ##### --> <para> diff --git a/docs/tmpl/pangocairo.sgml b/docs/tmpl/pangocairo.sgml index 9223957a..da1d7e3f 100644 --- a/docs/tmpl/pangocairo.sgml +++ b/docs/tmpl/pangocairo.sgml @@ -139,6 +139,9 @@ int main (int argc, char **argv) </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoCairoFontMap ##### --> <para> @@ -191,6 +194,42 @@ int main (int argc, char **argv) @Returns: +<!-- ##### FUNCTION pango_cairo_context_set_resolution ##### --> +<para> + +</para> + +@context: +@dpi: + + +<!-- ##### FUNCTION pango_cairo_context_get_resolution ##### --> +<para> + +</para> + +@context: +@Returns: + + +<!-- ##### FUNCTION pango_cairo_context_set_font_options ##### --> +<para> + +</para> + +@context: +@options: + + +<!-- ##### FUNCTION pango_cairo_context_get_font_options ##### --> +<para> + +</para> + +@context: +@Returns: + + <!-- ##### FUNCTION pango_cairo_update_context ##### --> <para> diff --git a/docs/tmpl/pangofc-decoder.sgml b/docs/tmpl/pangofc-decoder.sgml index ad033b6a..b8191c73 100644 --- a/docs/tmpl/pangofc-decoder.sgml +++ b/docs/tmpl/pangofc-decoder.sgml @@ -15,6 +15,9 @@ for handling a font that is encoded in a custom way. </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoFcDecoder ##### --> <para> diff --git a/docs/tmpl/pangofc-font.sgml b/docs/tmpl/pangofc-font.sgml index c87b2617..6bea63f4 100644 --- a/docs/tmpl/pangofc-font.sgml +++ b/docs/tmpl/pangofc-font.sgml @@ -31,6 +31,9 @@ Fontconfig-based backend involves deriving from both </variablelist> </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoFcFont ##### --> <para> diff --git a/docs/tmpl/pangofc-fontmap.sgml b/docs/tmpl/pangofc-fontmap.sgml index 649f8787..e24dc050 100644 --- a/docs/tmpl/pangofc-fontmap.sgml +++ b/docs/tmpl/pangofc-fontmap.sgml @@ -31,6 +31,9 @@ Fontconfig-based backend involves deriving from both </variablelist> </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoFcFontMap ##### --> <para> @@ -44,7 +47,13 @@ Fontconfig-based backend involves deriving from both @default_substitute: @new_font: -@get_render_key: +@get_resolution: +@context_key_get: +@context_key_copy: +@context_key_free: +@context_key_hash: +@context_key_equal: +@context_substitute: @create_font: <!-- ##### FUNCTION pango_fc_font_description_from_pattern ##### --> diff --git a/docs/tmpl/scripts.sgml b/docs/tmpl/scripts.sgml index 33e81760..562342fe 100644 --- a/docs/tmpl/scripts.sgml +++ b/docs/tmpl/scripts.sgml @@ -16,6 +16,9 @@ and of ranges within a larger text string. </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoScriptIter ##### --> <para> diff --git a/docs/tmpl/tab-stops.sgml b/docs/tmpl/tab-stops.sgml index 85672a5f..d131b162 100644 --- a/docs/tmpl/tab-stops.sgml +++ b/docs/tmpl/tab-stops.sgml @@ -14,6 +14,9 @@ Structures for storing Tab Stops </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoTabArray ##### --> <para> A <structname>PangoTabArray</structname> struct contains an array diff --git a/docs/tmpl/text-attributes.sgml b/docs/tmpl/text-attributes.sgml index 7c5fa9da..70245462 100644 --- a/docs/tmpl/text-attributes.sgml +++ b/docs/tmpl/text-attributes.sgml @@ -18,6 +18,9 @@ of attributes applied to a portion of text. </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### ENUM PangoAttrType ##### --> <para> distinguishes between different types of attributes. Along with the diff --git a/docs/tmpl/win32-fonts.sgml b/docs/tmpl/win32-fonts.sgml index 863b8500..50a9133f 100644 --- a/docs/tmpl/win32-fonts.sgml +++ b/docs/tmpl/win32-fonts.sgml @@ -14,6 +14,9 @@ Functions for shape engines to manipulate Win32 fonts </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### MACRO PANGO_RENDER_TYPE_WIN32 ##### --> <para> A string constant identifying the Win32 renderer. The associated quark (see @@ -97,6 +100,33 @@ g_quark_from_string()) is used to identify the renderer in pango_find_map(). @Returns: +<!-- ##### FUNCTION pango_win32_font_select_font ##### --> +<para> + +</para> + +@font: +@hdc: +@Returns: + + +<!-- ##### FUNCTION pango_win32_font_done_font ##### --> +<para> + +</para> + +@font: + + +<!-- ##### FUNCTION pango_win32_font_get_metrics_factor ##### --> +<para> + +</para> + +@font: +@Returns: + + <!-- ##### FUNCTION pango_win32_get_debug_flag ##### --> <para> diff --git a/docs/tmpl/x-fonts.sgml b/docs/tmpl/x-fonts.sgml index bd5a9a6d..ee19346b 100644 --- a/docs/tmpl/x-fonts.sgml +++ b/docs/tmpl/x-fonts.sgml @@ -17,6 +17,9 @@ unpredictable results. Use the <link linkend="pango-Xft-Fonts-and-Rendering">Xft </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### MACRO PANGO_RENDER_TYPE_X ##### --> <para> A string constant identifying the X renderer. The associated quark (see diff --git a/docs/tmpl/xft-fonts.sgml b/docs/tmpl/xft-fonts.sgml index fc4d6cae..a572c94b 100644 --- a/docs/tmpl/xft-fonts.sgml +++ b/docs/tmpl/xft-fonts.sgml @@ -39,6 +39,9 @@ overring the #PangoXftRendererClass virtual functions </para> +<!-- ##### SECTION Stability_Level ##### --> + + <!-- ##### STRUCT PangoXftFont ##### --> <para> diff --git a/pango/pangocairo-fc.h b/pango/pangocairo-fc.h index 8e0d9a5d..7903f03b 100644 --- a/pango/pangocairo-fc.h +++ b/pango/pangocairo-fc.h @@ -50,13 +50,6 @@ PangoFcFont *_pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap, const PangoFontDescription *desc, FcPattern *pattern); -gboolean _pango_cairo_fc_get_render_key (PangoCairoFcFontMap *cffontmap, - PangoContext *context, - const PangoFontDescription *desc, - int *xsize, - int *ysize, - guint *flags); - G_END_DECLS #endif /* __PANGOCAIRO_FC_H__ */ diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c index 5b06be81..cc7b3136 100644 --- a/pango/pangocairo-fcfont.c +++ b/pango/pangocairo-fcfont.c @@ -51,6 +51,7 @@ struct _PangoCairoFcFont cairo_scaled_font_t *scaled_font; cairo_matrix_t font_matrix; cairo_matrix_t ctm; + cairo_font_options_t *options; GHashTable *glyph_info; }; @@ -104,9 +105,11 @@ pango_cairo_fc_font_get_scaled_font (PangoCairoFont *font) cairo_font_face_t *font_face; font_face = pango_cairo_fc_font_get_font_face (font); + cffont->scaled_font = cairo_scaled_font_create (font_face, &cffont->font_matrix, - &cffont->ctm); + &cffont->ctm, + cffont->options); /* Failure of the above should only occur for out of memory, * we can't proceed at that point @@ -151,6 +154,8 @@ pango_cairo_fc_font_finalize (GObject *object) cairo_font_face_destroy (cffont->font_face); if (cffont->scaled_font) cairo_scaled_font_destroy (cffont->scaled_font); + if (cffont->options) + cairo_font_options_destroy (cffont->options); g_hash_table_destroy (cffont->glyph_info); @@ -308,96 +313,22 @@ pango_cairo_fc_font_init (PangoCairoFcFont *cffont) ********************/ static double -transformed_length (const PangoMatrix *matrix, - double dx, - double dy) +get_font_size (PangoCairoFcFontMap *cffontmap, + PangoContext *context, + const PangoFontDescription *desc) { - double tx = (dx * matrix->xx + dy * matrix->xy); - double ty = (dx * matrix->yx + dy * matrix->yy); - - return sqrt (tx * tx + ty * ty); -} - -/* Adapted from cairo_matrix.c:_cairo_matrix_compute_scale_factors. - */ -static void -compute_scale_factors (const PangoMatrix *matrix, - double *sx, - double *sy) -{ - double det; - - det = matrix->xx * matrix->yy - matrix->xy * matrix->xx; - - if (det == 0) - *sx = *sy = 0; - else - { - double major, minor; - major = transformed_length (matrix, 1, 0); - /* - * ignore mirroring - */ - if (det < 0) - det = -det; - if (major) - minor = det / major; - else - minor = 0.0; - - *sx = major; - *sy = minor; - } -} - -gboolean -_pango_cairo_fc_get_render_key (PangoCairoFcFontMap *cffontmap, - PangoContext *context, - const PangoFontDescription *desc, - int *xsize, - int *ysize, - guint *flags) -{ - const PangoMatrix *matrix; - double xscale, yscale; - double size; - - matrix = pango_context_get_matrix (context); - if (matrix) - { - compute_scale_factors (matrix, &xscale, &yscale); - } - else - { - xscale = 1.; - yscale = 1.; - } - if (pango_font_description_get_size_is_absolute (desc)) - size = pango_font_description_get_size (desc); + return pango_font_description_get_size (desc); else - size = cffontmap->dpi * pango_font_description_get_size (desc) / 72.; - - *xsize = (int) (xscale * size + 0.5); - *ysize = (int) (xscale * size + 0.5); - - *flags = pango_cairo_context_get_hinting (context); - - if (matrix) { - if (xscale == 0. && yscale == 0.) - return FALSE; - else - { - return (matrix->yx / xscale < 1. / 65536. && - matrix->xy / yscale < 1. / 65536. && - matrix->xx > 0 && - matrix->yy > 0); - } + double dpi = pango_cairo_context_get_resolution (context); + + if (dpi <= 0) + dpi = cffontmap->dpi; + + return dpi * pango_font_description_get_size (desc) / 72.; } - else - return TRUE; } PangoFcFont * @@ -430,11 +361,8 @@ _pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap, } else cairo_matrix_init_identity (&cffont->font_matrix); - - if (pango_font_description_get_size_is_absolute (desc)) - size = pango_font_description_get_size (desc); - else - size = cffontmap->dpi * pango_font_description_get_size (desc) / 72.; + + size = get_font_size (cffontmap, context, desc); cairo_matrix_scale (&cffont->font_matrix, size / PANGO_SCALE, size / PANGO_SCALE); @@ -450,5 +378,7 @@ _pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap, else cairo_matrix_init_identity (&cffont->ctm); + cffont->options = cairo_font_options_copy (_pango_cairo_context_get_merged_font_options (context)); + return PANGO_FC_FONT (cffont); } diff --git a/pango/pangocairo-fcfontmap.c b/pango/pangocairo-fcfontmap.c index e032c9d5..15752e2a 100644 --- a/pango/pangocairo-fcfontmap.c +++ b/pango/pangocairo-fcfontmap.c @@ -18,6 +18,7 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ +#include <cairo-ft.h> #include "pangofc-fontmap.h" #include "pangocairo.h" @@ -43,7 +44,7 @@ pango_cairo_fc_font_map_set_resolution (PangoCairoFontMap *cfontmap, } static double -pango_cairo_fc_font_map_get_resolution (PangoCairoFontMap *cfontmap) +pango_cairo_fc_font_map_get_resolution_cairo (PangoCairoFontMap *cfontmap) { PangoCairoFcFontMap *cffontmap = PANGO_CAIRO_FC_FONT_MAP (cfontmap); @@ -65,7 +66,7 @@ static void cairo_font_map_iface_init (PangoCairoFontMapIface *iface) { iface->set_resolution = pango_cairo_fc_font_map_set_resolution; - iface->get_resolution = pango_cairo_fc_font_map_get_resolution; + iface->get_resolution = pango_cairo_fc_font_map_get_resolution_cairo; iface->get_renderer = pango_cairo_fc_font_map_get_renderer; } @@ -90,32 +91,71 @@ pango_cairo_fc_font_map_context_substitute (PangoFcFontMap *fcfontmap, PangoContext *context, FcPattern *pattern) { - PangoCairoFcFontMap *cffontmap = PANGO_CAIRO_FC_FONT_MAP (fcfontmap); - FcValue v; - FcConfigSubstitute (NULL, pattern, FcMatchPattern); - if (FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch) - FcPatternAddDouble (pattern, FC_DPI, cffontmap->dpi); - - if (!pango_cairo_context_get_hinting (context)) - FcPatternAddBool (pattern, FC_HINTING, FcFalse); + cairo_ft_font_options_substitute (_pango_cairo_context_get_merged_font_options (context), + pattern); FcDefaultSubstitute (pattern); } -static gboolean -pango_cairo_fc_font_map_get_render_key (PangoFcFontMap *fcfontmap, - PangoContext *context, - const PangoFontDescription *desc, - int *xsize, - int *ysize, - guint *flags) +static double +pango_cairo_fc_font_map_get_resolution_fc (PangoFcFontMap *fcfontmap, + PangoContext *context) +{ + PangoCairoFcFontMap *cffontmap = PANGO_CAIRO_FC_FONT_MAP (fcfontmap); + double dpi; + + if (context) + { + dpi = pango_cairo_context_get_resolution (context); + + if (dpi <= 0) + dpi = cffontmap->dpi; + } + else + dpi = cffontmap->dpi; + + return dpi; +} + +static gconstpointer +pango_cairo_fc_font_map_context_key_get (PangoFcFontMap *fcfontmap, + PangoContext *context) +{ + return _pango_cairo_context_get_merged_font_options (context); +} + +static gpointer +pango_cairo_fc_font_map_context_key_copy (PangoFcFontMap *fcfontmap, + gconstpointer key) +{ + return cairo_font_options_copy (key); +} + +static void +pango_cairo_fc_font_map_context_key_free (PangoFcFontMap *fcfontmap, + gpointer key) +{ + cairo_font_options_destroy (key); +} + + +static guint32 +pango_cairo_fc_font_map_context_key_hash (PangoFcFontMap *fcfontmap, + gconstpointer key) { - return _pango_cairo_fc_get_render_key (PANGO_CAIRO_FC_FONT_MAP (fcfontmap), - context, desc, xsize, ysize, flags); + return (guint32)cairo_font_options_hash (key); } +static gboolean +pango_cairo_fc_font_map_context_key_equal (PangoFcFontMap *fcfontmap, + gconstpointer key_a, + gconstpointer key_b) +{ + return cairo_font_options_equal (key_a, key_b); +} + static PangoFcFont * pango_cairo_fc_font_map_create_font (PangoFcFontMap *fcfontmap, PangoContext *context, @@ -133,8 +173,16 @@ pango_cairo_fc_font_map_class_init (PangoCairoFcFontMapClass *class) PangoFcFontMapClass *fcfontmap_class = PANGO_FC_FONT_MAP_CLASS (class); gobject_class->finalize = pango_cairo_fc_font_map_finalize; + fcfontmap_class->context_substitute = pango_cairo_fc_font_map_context_substitute; - fcfontmap_class->get_render_key = pango_cairo_fc_font_map_get_render_key; + fcfontmap_class->get_resolution = pango_cairo_fc_font_map_get_resolution_fc; + + fcfontmap_class->context_key_get = pango_cairo_fc_font_map_context_key_get; + fcfontmap_class->context_key_copy = pango_cairo_fc_font_map_context_key_copy; + fcfontmap_class->context_key_free = pango_cairo_fc_font_map_context_key_free; + fcfontmap_class->context_key_hash = pango_cairo_fc_font_map_context_key_hash; + fcfontmap_class->context_key_equal = pango_cairo_fc_font_map_context_key_equal; + fcfontmap_class->create_font = pango_cairo_fc_font_map_create_font; } diff --git a/pango/pangocairo-fontmap.c b/pango/pangocairo-fontmap.c index 5b72375c..51681377 100644 --- a/pango/pangocairo-fontmap.c +++ b/pango/pangocairo-fontmap.c @@ -139,7 +139,7 @@ pango_cairo_font_map_set_resolution (PangoCairoFontMap *fontmap, * pango_cairo_font_map_get_resolution: * @fontmap: a #PangoCairoFontMap * - * Gets the resolutions for the fontmap. See pango_cairo_font_map_set_resolution. + * Gets the resolution for the fontmap. See pango_cairo_font_map_set_resolution() * * Return value: the resolution in "dots per inch" * @@ -192,6 +192,51 @@ _pango_cairo_font_map_get_renderer (PangoCairoFontMap *fontmap) return (* PANGO_CAIRO_FONT_MAP_GET_IFACE (fontmap)->get_renderer) (fontmap); } +typedef struct _PangoCairoContextInfo PangoCairoContextInfo; + +struct _PangoCairoContextInfo +{ + double dpi; + + cairo_font_options_t *set_options; + cairo_font_options_t *surface_options; + cairo_font_options_t *merged_options; +}; + +static void +free_context_info (PangoCairoContextInfo *info) +{ + if (info->set_options) + cairo_font_options_destroy (info->set_options); + if (info->surface_options) + cairo_font_options_destroy (info->surface_options); + if (info->merged_options) + cairo_font_options_destroy (info->merged_options); + + free (info); +} + +static PangoCairoContextInfo * +get_context_info (PangoContext *context, + gboolean create) +{ + PangoCairoContextInfo *info = g_object_get_data (G_OBJECT (context), + "pango-cairo-context-info"); + if (!info && create) + { + info = g_new (PangoCairoContextInfo, 1); + info->dpi = -1.0; + info->set_options = NULL; + info->surface_options = NULL; + info->merged_options = NULL; + + g_object_set_data_full (G_OBJECT (context), "pango-cairo-context-info", + info, (GDestroyNotify)free_context_info); + } + + return info; +} + /** * pango_cairo_update_context: * @cr: a Cairo context @@ -209,7 +254,9 @@ void pango_cairo_update_context (cairo_t *cr, PangoContext *context) { + PangoCairoContextInfo *info = get_context_info (context, TRUE); cairo_matrix_t cairo_matrix; + cairo_surface_t *target; PangoMatrix pango_matrix; g_return_if_fail (cr != NULL); @@ -224,71 +271,149 @@ pango_cairo_update_context (cairo_t *cr, pango_matrix.y0 = cairo_matrix.y0; pango_context_set_matrix (context, &pango_matrix); -} - -typedef struct _PangoCairoContextInfo PangoCairoContextInfo; -struct _PangoCairoContextInfo -{ - gboolean hinting; -}; + if (!info->surface_options) + info->surface_options = cairo_font_options_create (); -static PangoCairoContextInfo * -get_context_info (PangoContext *context, - gboolean create) -{ - PangoCairoContextInfo *info = g_object_get_data (G_OBJECT (context), - "pango-cairo-context-info"); - if (!info && create) + target = cairo_get_target (cr); + cairo_surface_get_font_options (target, info->surface_options); + + if (info->merged_options) { - info = g_new (PangoCairoContextInfo, 1); - info->hinting = TRUE; - - g_object_set_data_full (G_OBJECT (context), "pango-cairo-context-info", - info, (GDestroyNotify)g_free); + cairo_font_options_destroy (info->merged_options); + info->merged_options = NULL; } - - return info; } /** - * pango_cairo_context_set_hinting: + * pango_cairo_context_set_resolution: * @context: a #PangoContext, from pango_cairo_font_map_create_context() - * @hinting: %TRUE if hinting should be enabled. + * @dpi: the resolution in "dots per inch". (Physical inches aren't actually + * involved; the terminology is conventional.) A 0 or negative value + * means to use the resolution from the font map. * - * Sets whether outlines and font metrics should be hinted for this - * context. Hinting is the process of adjusting outlines so that they - * render better when drawn onto a pixel grid. When hinting is - * enabled, font metrics such as character widths and font ascent and - * descent are quantized to integer pixel values. + * Sets the resolution for the context. This is a scale factor between + * points specified in a #PangoFontDescription and Cairo units. The + * default value is 96, meaning that a 10 point font will be 13 + * units high. (10 * 96. / 72. = 13.3). + * + * Since: 1.10 + **/ +void +pango_cairo_context_set_resolution (PangoContext *context, + double dpi) +{ + PangoCairoContextInfo *info = get_context_info (context, TRUE); + info->dpi = dpi; +} + +/** + * pango_cairo_context_get_resolution: + * @context: a #PangoContext, from pango_cairo_font_map_create_context() * - * If layouts have been previously created for this context, it is - * necessary to call pango_layout_context_changed() in order to update - * the layouts. + * Gets the resolution for the context. See pango_cairo_context_set_resolution() + * + * Return value: the resolution in "dots per inch". A negative value will + * be returned if no resolution has previously been set. + * + * Since: 1.10 **/ +double +pango_cairo_context_get_resolution (PangoContext *context) +{ + PangoCairoContextInfo *info = get_context_info (context, FALSE); + + if (info) + return info->dpi; + else + return -1.0; +} + +/** + * pango_cairo_context_set_font_options: + * @context: a #PangoContext, from pango_cairo_font_map_create_context() + * @options: a #cairo_font_options_t, or %NULL to unset any previously set + * options. A copy is made. + * + * Sets the font options used when rendering text with this context. + * These options override any options that pango_cairo_update_context() + * derives from the target surface. + */ void -pango_cairo_context_set_hinting (PangoContext *context, - gboolean hinting) +pango_cairo_context_set_font_options (PangoContext *context, + const cairo_font_options_t *options) { + g_return_if_fail (PANGO_IS_CONTEXT (context)); + PangoCairoContextInfo *info = get_context_info (context, TRUE); - info->hinting = hinting != FALSE; + + if (info->set_options) + cairo_font_options_destroy (info->set_options); + + if (options) + info->set_options = cairo_font_options_copy (options); + else + info->set_options = NULL; + + if (info->merged_options) + { + cairo_font_options_destroy (info->merged_options); + info->merged_options = NULL; + } } /** - * pango_cairo_context_get_hinting: + * pango_cairo_get_font_options: * @context: a #PangoContext, from pango_cairo_font_map_create_context() * - * Gets whether hinting is enabled for this context. See - * pango_cairo_context_set_hinting() + * Retrieves any font rendering options previously set with + * pango_cairo_font_map_set_font_options(). This functions not report options + * that are derived from the target surface by pango_cairo_update_context() * - * Return value: %TRUE if hinting is enabled. + * Return value: the font options previously set on the context, or %NULL + * if no options have been set. This value is owned by the context + * and must not be modified or freed. **/ -gboolean -pango_cairo_context_get_hinting (PangoContext *context) +const cairo_font_options_t * +pango_cairo_context_get_font_options (PangoContext *context) { + g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL); + PangoCairoContextInfo *info = get_context_info (context, FALSE); - return !info || info->hinting; + if (info) + return info->set_options; + else + return NULL; +} + +/** + * _pango_cairo_context_merge_font_options: + * @context: a #PangoContext + * @options: a #cairo_font_options_t + * + * Merge together options from the target surface and explicitly set + * on the context. + * + * Return value: the combined set of font options. This value is owned + * by the context and must not be modified or freed. + **/ +const cairo_font_options_t * +_pango_cairo_context_get_merged_font_options (PangoContext *context) +{ + PangoCairoContextInfo *info = get_context_info (context, TRUE); + + if (!info->merged_options) + { + info->merged_options = cairo_font_options_create (); + + if (info->surface_options) + cairo_font_options_merge (info->merged_options, info->surface_options); + if (info->set_options) + cairo_font_options_merge (info->merged_options, info->set_options); + } + + return info->merged_options; } /** diff --git a/pango/pangocairo-private.h b/pango/pangocairo-private.h index 0c544bd8..e7e124b0 100644 --- a/pango/pangocairo-private.h +++ b/pango/pangocairo-private.h @@ -73,6 +73,8 @@ typedef struct _PangoCairoRenderer PangoCairoRenderer; GType pango_cairo_renderer_get_type (void); +const cairo_font_options_t *_pango_cairo_context_get_merged_font_options (PangoContext *context); + G_END_DECLS #endif /* __PANGOCAIRO_PRIVATE_H__ */ diff --git a/pango/pangocairo-win32font.c b/pango/pangocairo-win32font.c index 93e0e0a3..8493d8f8 100644 --- a/pango/pangocairo-win32font.c +++ b/pango/pangocairo-win32font.c @@ -51,7 +51,8 @@ struct _PangoCairoWin32Font cairo_matrix_t font_matrix; cairo_matrix_t ctm; - + cairo_font_options_t *options; + PangoFontMetrics *metrics; }; @@ -111,7 +112,8 @@ pango_cairo_win32_font_get_scaled_font (PangoCairoFont *font) font_face = pango_cairo_win32_font_get_font_face (font); cffont->scaled_font = cairo_scaled_font_create (font_face, &cffont->font_matrix, - &cffont->ctm); + &cffont->ctm, + cffont->options); /* Failure of the above should only occur for out of memory, * we can't proceed at that point @@ -158,6 +160,9 @@ pango_cairo_win32_font_finalize (GObject *object) if (cwfont->scaled_font) cairo_scaled_font_destroy (cwfont->scaled_font); + if (cwfont->options) + cairo_font_options_destroy (cwfont->options); + G_OBJECT_CLASS (pango_cairo_win32_font_parent_class)->finalize (object); } @@ -296,6 +301,7 @@ _pango_cairo_win32_font_new (PangoCairoWin32FontMap *cwfontmap, PangoWin32Font *win32font; const PangoMatrix *pango_ctm; double size; + double dpi; cwfont = g_object_new (PANGO_TYPE_CAIRO_WIN32_FONT, NULL); win32font = PANGO_WIN32_FONT (cwfont); @@ -306,11 +312,21 @@ _pango_cairo_win32_font_new (PangoCairoWin32FontMap *cwfontmap, win32font->win32face = face; size = (double) pango_font_description_get_size (desc) / PANGO_SCALE; + + if (context) + { + dpi = pango_cairo_context_get_resolution (context); + + if (dpi <= 0) + dpi = cwfontmap->dpi; + } + else + dpi = cwfontmap->dpi; if (!pango_font_description_get_size_is_absolute (desc)) - size *= cwfontmap->dpi / 72.; + size *= dpi / 72.; - /* FIXME: THis is a pixel size, so not really what we want for describe(), + /* FIXME: This is a pixel size, so not really what we want for describe(), * but it's what we need when computing the scale factor. */ win32font->size = size * PANGO_SCALE; @@ -334,5 +350,7 @@ _pango_cairo_win32_font_new (PangoCairoWin32FontMap *cwfontmap, win32font->size, &win32font->logfont); + cffont->options = cairo_font_options_copy (_pango_cairo_context_get_merged_font_options (context)); + return PANGO_FONT (cwfont); } diff --git a/pango/pangocairo.h b/pango/pangocairo.h index ba0949fc..c14fab4f 100644 --- a/pango/pangocairo.h +++ b/pango/pangocairo.h @@ -62,9 +62,13 @@ PangoContext *pango_cairo_font_map_create_context (PangoCairoFontMap *fontmap); void pango_cairo_update_context (cairo_t *cr, PangoContext *context); -void pango_cairo_context_set_hinting (PangoContext *context, - gboolean hinting); -gboolean pango_cairo_context_get_hinting (PangoContext *context); +void pango_cairo_context_set_font_options (PangoContext *context, + const cairo_font_options_t *options); +const cairo_font_options_t *pango_cairo_context_get_font_options (PangoContext *context); + +void pango_cairo_context_set_resolution (PangoContext *context, + double dpi); +double pango_cairo_context_get_resolution (PangoContext *context); /* Convenience */ diff --git a/pango/pangofc-font.h b/pango/pangofc-font.h index f3db9a86..42282c53 100644 --- a/pango/pangofc-font.h +++ b/pango/pangofc-font.h @@ -71,6 +71,8 @@ struct _PangoFcFont FcPattern *font_pattern; /* fully resolved pattern */ PangoFontMap *fontmap; /* associated map */ + gpointer context_key; /* used internally */ + PangoMatrix matrix; /* used internally */ PangoFontDescription *description; GSList *metrics_by_lang; diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c index 7804c2e0..a6436f49 100644 --- a/pango/pangofc-fontmap.c +++ b/pango/pangofc-fontmap.c @@ -34,6 +34,8 @@ typedef struct _PangoFcFace PangoFcFace; typedef struct _PangoFcFamily PangoFcFamily; typedef struct _PangoFcPatternSet PangoFcPatternSet; typedef struct _PangoFcFindFuncInfo PangoFcFindFuncInfo; +typedef struct _FontsetHashKey FontsetHashKey; +typedef struct _FontHashKey FontHashKey; #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)) @@ -45,17 +47,15 @@ typedef struct _PangoFcFindFuncInfo PangoFcFindFuncInfo; struct _PangoFcFontMapPrivate { - /* We have one map from PangoFontDescription -> PangoXftPatternSet - * per language tag. - */ - GList *fontset_hash_list; + GHashTable *fontset_hash; /* Maps PangoFontDescription -> PangoFcPatternSet */ + /* pattern_hash is used to make sure we only store one copy of * each identical pattern. (Speeds up lookup). */ GHashTable *pattern_hash; GHashTable *coverage_hash; /* Maps font file name/id -> PangoCoverage */ - GHashTable *fonts; /* Maps XftPattern -> PangoXftFont */ + GHashTable *font_hash; /* Maps FcPattern -> PangoFcFont */ GQueue *fontset_cache; /* Recently used fontsets */ @@ -104,6 +104,8 @@ struct _PangoFcPatternSet FcPattern **patterns; PangoFontset *fontset; GList *cache_link; + + FontsetHashKey *key; }; struct _PangoFcFindFuncInfo @@ -129,6 +131,8 @@ static void pango_fc_font_map_list_families (PangoFontMap PangoFontFamily ***families, int *n_families); +static void pango_fc_font_map_cache_fontset (PangoFcFontMap *fcfontmap, + PangoFcPatternSet *patterns); static void pango_fc_pattern_set_free (PangoFcPatternSet *patterns); @@ -139,6 +143,16 @@ static guint pango_fc_coverage_key_hash (PangoFcCoverageKey *key); static gboolean pango_fc_coverage_key_equal (PangoFcCoverageKey *key1, PangoFcCoverageKey *key2); +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); + +static guint fontset_hash_key_hash (const FontsetHashKey *key); +static gboolean fontset_hash_key_equal (const FontsetHashKey *key_a, + const FontsetHashKey *key_b); +static void fontset_hash_key_free (FontsetHashKey *key); + G_DEFINE_TYPE (PangoFcFontMap, pango_fc_font_map, PANGO_TYPE_FONT_MAP) static void @@ -163,7 +177,15 @@ pango_fc_font_map_init (PangoFcFontMap *fcfontmap) priv->n_families = -1; - priv->fonts = g_hash_table_new ((GHashFunc)g_direct_hash, NULL); + priv->font_hash = g_hash_table_new_full ((GHashFunc)font_hash_key_hash, + (GEqualFunc)font_hash_key_equal, + (GDestroyNotify)font_hash_key_free, + NULL); + priv->fontset_hash = g_hash_table_new_full ((GHashFunc)fontset_hash_key_hash, + (GEqualFunc)fontset_hash_key_equal, + (GDestroyNotify)fontset_hash_key_free, + (GDestroyNotify)pango_fc_pattern_set_free); + priv->coverage_hash = g_hash_table_new_full ((GHashFunc)pango_fc_coverage_key_hash, (GEqualFunc)pango_fc_coverage_key_equal, (GDestroyNotify)g_free, @@ -237,30 +259,63 @@ pango_fc_coverage_key_equal (PangoFcCoverageKey *key1, return key1->id == key2->id && strcmp (key1->filename, key2->filename) == 0; } -typedef struct _FontsetHashListNode FontsetHashListNode; -typedef struct _FontsetHashKey FontsetHashKey; - -struct _FontsetHashListNode { - GHashTable *fontset_hash; +struct _FontsetHashKey { + PangoFcFontMap *fontmap; + PangoMatrix matrix; PangoLanguage *language; + PangoFontDescription *desc; + int size; /* scaled via the current DPI */ + gpointer context_key; }; -struct _FontsetHashKey { - PangoFontDescription *desc; - int x_size; - int y_size; - guint flags; +struct _FontHashKey { + PangoFcFontMap *fontmap; + PangoMatrix matrix; + FcPattern *pattern; + 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 fontset_hash_key_equal (const FontsetHashKey *key_a, const FontsetHashKey *key_b) { - if (key_a->x_size == key_b->x_size && - key_a->y_size == key_b->y_size && - key_a->flags == key_b->flags && - pango_font_description_equal (key_a->desc, key_b->desc)) - return TRUE; + if (key_a->size == key_b->size && + pango_font_description_equal (key_a->desc, key_b->desc) && + 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) + { + if (key_a->context_key) + return PANGO_FC_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; } @@ -268,13 +323,33 @@ fontset_hash_key_equal (const FontsetHashKey *key_a, static guint fontset_hash_key_hash (const FontsetHashKey *key) { - return (key->x_size << 16) ^ (key->y_size) ^ (key->flags) ^ pango_font_description_hash (key->desc); + 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_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap, + key->context_key); + + /* 1237 is just an abitrary prime */ + return (hash ^ + (guint)key->language ^ + (key->size * 1237) ^ + pango_font_description_hash (key->desc)); } static void fontset_hash_key_free (FontsetHashKey *key) { pango_font_description_free (key->desc); + + if (key->context_key) + PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap, + key->context_key); + g_free (key); } @@ -283,84 +358,83 @@ fontset_hash_key_copy (FontsetHashKey *old) { FontsetHashKey *key = g_new (FontsetHashKey, 1); - key->x_size = old->x_size; - key->y_size = old->y_size; - key->flags = old->flags; + key->fontmap = old->fontmap; + key->matrix = old->matrix; + key->language = old->language; key->desc = pango_font_description_copy (old->desc); - + key->size = old->size; + if (old->context_key) + key->context_key = PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_copy (key->fontmap, + old->context_key); + else + key->context_key = NULL; + return key; } -/* Get the description => fontset map for a particular - * language tag. - */ -static GHashTable * -pango_fc_get_fontset_hash (PangoFcFontMap *fcfontmap, - PangoLanguage *language) -{ - PangoFcFontMapPrivate *priv = fcfontmap->priv; - - /* We treat NULL as a distinct language tag, but - * we should actually determine the real language - * tag it corresponds to to avoid duplicate entries - * in the list. - */ - GList *tmp_list = priv->fontset_hash_list; - while (tmp_list) +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 && + key_a->pattern == key_b->pattern) { - FontsetHashListNode *node = tmp_list->data; - if (node->language == language) - { - if (tmp_list != priv->fontset_hash_list) - { - /* Put the found node at the beginning - */ - priv->fontset_hash_list = g_list_remove_link (priv->fontset_hash_list, tmp_list); - priv->fontset_hash_list->prev = tmp_list; - tmp_list->next = priv->fontset_hash_list; - priv->fontset_hash_list = tmp_list; - } - - return node->fontset_hash; - } - - tmp_list = tmp_list->next; + if (key_a->context_key) + return PANGO_FC_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; +} - { - FontsetHashListNode *node = g_new (FontsetHashListNode, 1); - priv->fontset_hash_list = g_list_prepend (priv->fontset_hash_list, node); - - node->fontset_hash = - g_hash_table_new_full ((GHashFunc)fontset_hash_key_hash, - (GEqualFunc)fontset_hash_key_equal, - (GDestroyNotify)fontset_hash_key_free, - (GDestroyNotify)pango_fc_pattern_set_free); - node->language = language; +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); - return node->fontset_hash; - } + if (key->context_key) + hash ^= PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap, + key->context_key); + + return (hash ^ (guint32)key->pattern); } static void -pango_fc_clear_pattern_hashes (PangoFcFontMap *fcfontmap) +font_hash_key_free (FontHashKey *key) { - PangoFcFontMapPrivate *priv = fcfontmap->priv; - GList *tmp_list; + if (key->context_key) + PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap, + key->context_key); + + g_free (key); +} - tmp_list = priv->fontset_hash_list; - while (tmp_list) - { - FontsetHashListNode *node = tmp_list->data; - - g_hash_table_destroy (node->fontset_hash); - g_free (node); +static FontHashKey * +font_hash_key_copy (FontHashKey *old) +{ + FontHashKey *key = g_new (FontHashKey, 1); + + key->fontmap = old->fontmap; + key->matrix = old->matrix; + key->pattern = old->pattern; + if (old->context_key) + key->context_key = PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_copy (key->fontmap, + old->context_key); + else + key->context_key = NULL; - tmp_list = tmp_list->next; - } - - g_list_free (priv->fontset_hash_list); - priv->fontset_hash_list = NULL; + return key; } /** @@ -408,8 +482,8 @@ pango_fc_font_map_finalize (GObject *object) g_queue_free (priv->fontset_cache); g_hash_table_destroy (priv->coverage_hash); - if (priv->fonts) - g_hash_table_destroy (priv->fonts); + if (priv->font_hash) + g_hash_table_destroy (priv->font_hash); if (priv->pattern_hash) g_hash_table_destroy (priv->pattern_hash); @@ -428,30 +502,89 @@ pango_fc_font_map_finalize (GObject *object) G_OBJECT_CLASS (pango_fc_font_map_parent_class)->finalize (object); } +static void +get_context_matrix (PangoContext *context, + PangoMatrix *matrix) +{ + const PangoMatrix *set_matrix = pango_context_get_matrix (context); + static const PangoMatrix identity = PANGO_MATRIX_INIT; + + if (set_matrix) + *matrix = *set_matrix; + else + *matrix = identity; +} + +static void +font_hash_key_for_context (PangoFcFontMap *fcfontmap, + PangoContext *context, + FontHashKey *key) +{ + key->fontmap = fcfontmap; + get_context_matrix (context, &key->matrix); + + if (PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get) + key->context_key = (gpointer)PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get (fcfontmap, context); + else + key->context_key = NULL; +} + /* Add a mapping from xfont->font_pattern to xfont */ static void pango_fc_font_map_add (PangoFcFontMap *fcfontmap, + PangoContext *context, PangoFcFont *fcfont) { PangoFcFontMapPrivate *priv = fcfontmap->priv; + FontHashKey key; + FontHashKey *key_copy; g_assert (fcfont->fontmap == NULL); - - g_hash_table_insert (priv->fonts, - fcfont->font_pattern, + + fcfont->fontmap = g_object_ref (fcfontmap); + + font_hash_key_for_context (fcfontmap, context, &key); + key.pattern = fcfont->font_pattern; + + key_copy = font_hash_key_copy (&key); + fcfont->context_key = key_copy->context_key; + fcfont->matrix = key.matrix; + + g_hash_table_insert (priv->font_hash, + font_hash_key_copy (&key), fcfont); } +static PangoFcFont * +pango_fc_font_map_lookup (PangoFcFontMap *fcfontmap, + PangoContext *context, + FcPattern *pattern) +{ + PangoFcFontMapPrivate *priv = fcfontmap->priv; + FontHashKey key; + + font_hash_key_for_context (fcfontmap, context, &key); + key.pattern = pattern; + + return g_hash_table_lookup (priv->font_hash, &key); +} + /* Remove mapping from xfont->font_pattern to xfont */ void _pango_fc_font_map_remove (PangoFcFontMap *fcfontmap, PangoFcFont *fcfont) { PangoFcFontMapPrivate *priv = fcfontmap->priv; + FontHashKey key; + + key.fontmap = fcfontmap; + key.matrix = fcfont->matrix; + key.pattern = fcfont->font_pattern; + key.context_key = fcfont->context_key; - g_hash_table_remove (priv->fonts, - fcfont->font_pattern); + g_hash_table_remove (priv->font_hash, &key); fcfont->fontmap = NULL; + fcfont->context_key = NULL; g_object_unref (fcfontmap); } @@ -646,13 +779,12 @@ pango_fc_convert_width_to_fc (PangoStretch pango_stretch) static FcPattern * pango_fc_make_pattern (const PangoFontDescription *description, PangoLanguage *language, - double pixel_size) + double pixel_size, + double dpi) { FcPattern *pattern; int slant; int weight; - double size; - gboolean size_is_absolute; char **families; int i; #ifdef FC_WIDTH @@ -665,15 +797,21 @@ pango_fc_make_pattern (const PangoFontDescription *description, width = pango_fc_convert_width_to_fc (pango_font_description_get_stretch (description)); #endif - size = (double) pango_font_description_get_size (description) / PANGO_SCALE; - size_is_absolute = pango_font_description_get_size_is_absolute (description); - + /* The reason for passing in FC_SIZE as well as FC_PIXEL_SIZE is + * to work around a bug in libgnomeprint where it doesn't look + * for FC_PIXEL_SIZE. See http://bugzilla.gnome.org/show_bug.cgi?id=169020 + * + * Putting FC_SIZE in here slightly reduces the efficiency + * of caching of patterns and fonts when working with multiple different + * dpi values. + */ pattern = FcPatternBuild (NULL, FC_WEIGHT, FcTypeInteger, weight, FC_SLANT, FcTypeInteger, slant, #ifdef FC_WIDTH FC_WIDTH, FcTypeInteger, width, #endif + FC_SIZE, FcTypeDouble, pixel_size * (72. / dpi), FC_PIXEL_SIZE, FcTypeDouble, pixel_size, NULL); @@ -694,8 +832,7 @@ static PangoFont * pango_fc_font_map_new_font (PangoFontMap *fontmap, PangoContext *context, const PangoFontDescription *description, - FcPattern *match, - gboolean cache) + FcPattern *match) { PangoFcFontMapClass *class; PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap; @@ -713,15 +850,10 @@ pango_fc_font_map_new_font (PangoFontMap *fontmap, if (priv->closed) return NULL; - /* Look up cache */ - if (cache) - { - fcfont = g_hash_table_lookup (priv->fonts, match); + fcfont = pango_fc_font_map_lookup (fcfontmap, context, match); + if (fcfont) + return g_object_ref (fcfont); - if (fcfont) - return g_object_ref (fcfont); - } - class = PANGO_FC_FONT_MAP_GET_CLASS (fontmap); if (class->create_font) @@ -763,10 +895,7 @@ pango_fc_font_map_new_font (PangoFontMap *fontmap, FcPatternDestroy (pattern); } - if (cache) - pango_fc_font_map_add (fcfontmap, fcfont); - - fcfont->fontmap = g_object_ref (fcfontmap); + pango_fc_font_map_add (fcfontmap, context, fcfont); /* * Give any custom decoders a crack at this font now that it's been @@ -828,9 +957,12 @@ pango_fc_default_substitute (PangoFcFontMap *fontmap, } static gdouble -pango_fc_font_map_get_dpi (PangoFcFontMap *fcfontmap, - PangoContext *context) +pango_fc_font_map_get_resolution (PangoFcFontMap *fcfontmap, + PangoContext *context) { + if (PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->get_resolution) + return PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->get_resolution (fcfontmap, context); + if (fcfontmap->priv->dpi < 0) { FcResult result = FcResultNoMatch; @@ -855,65 +987,58 @@ pango_fc_font_map_get_dpi (PangoFcFontMap *fcfontmap, return fcfontmap->priv->dpi; } -static double -transformed_length (const PangoMatrix *matrix, - double dx, - double dy) +static int +get_unscaled_size (PangoFcFontMap *fcfontmap, + PangoContext *context, + const PangoFontDescription *desc) { - double tx = (dx * matrix->xx + dy * matrix->xy); - double ty = (dx * matrix->yx + dy * matrix->yy); + int size = pango_font_description_get_size (desc); + + if (pango_font_description_get_size_is_absolute (desc)) + return size; + else + { + double dpi = pango_fc_font_map_get_resolution (fcfontmap, context); - return sqrt (tx * tx + ty * ty); + return (int)(0.5 + size * dpi / 72.); + } } -static gboolean -pango_fc_font_map_get_render_key (PangoFcFontMap *fcfontmap, - PangoContext *context, - const PangoFontDescription *desc, - int *x_size, - int *y_size, - guint *flags) -{ - if (PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->get_render_key) - return PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->get_render_key (fcfontmap, context, desc, x_size, y_size, flags); +/* + * Based on cairo-matrix.c:_cairo_matrix_compute_scale_factors() + * + * Copyright 2005, Keith Packard + */ +static int +get_scaled_size (FontsetHashKey *key) +{ + PangoMatrix *matrix = &key->matrix; + double det = matrix->xx * matrix->yy - matrix->yx * matrix->xy; + + if (det == 0) + { + return 0.0; + } else { - double size; - const PangoMatrix *matrix; - gboolean retval = TRUE; - - if (pango_font_description_get_size_is_absolute (desc)) - size = pango_font_description_get_size (desc); - else - size = pango_fc_font_map_get_dpi (fcfontmap, context) * pango_font_description_get_size (desc) / 72.; - - if (context) - matrix = pango_context_get_matrix (context); - else - matrix = NULL; + double x = matrix->xx; + double y = matrix->yx; + double major, minor; - *x_size = size; - *y_size = size; + major = sqrt (x*x + y*y); - if (matrix) - { - double xl = transformed_length (matrix, 1., 0.); - double yl = transformed_length (matrix, 0., 1.); - - if (xl != 0. && yl != 0.) - { - *x_size = (int)(xl * *x_size + 0.5); - *y_size = (int)(yl * *y_size + 0.5); - - retval = (matrix->yx / xl < 1 / 65536. && matrix->xy / yl < 1 / 65536.); - } - else - retval = FALSE; - } - - *flags = 0; + /* + * ignore mirroring + */ + if (det < 0) + det = - det; + + if (major) + minor = det / major; + else + minor = 0.0; - return retval; + return minor * (key->size / 1024.); } } @@ -921,38 +1046,42 @@ static PangoFcPatternSet * pango_fc_font_map_get_patterns (PangoFontMap *fontmap, PangoContext *context, const PangoFontDescription *desc, - PangoLanguage *language, - gboolean *cache_out) + PangoLanguage *language) { PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap; + PangoFcFontMapPrivate *priv = fcfontmap->priv; FcPattern *pattern, *font_pattern; FcResult res; int f; PangoFcPatternSet *patterns; FcFontSet *font_patterns; - GHashTable *fontset_hash; FontsetHashKey key; - gboolean cache; if (!language && context) language = pango_context_get_language (context); - - fontset_hash = pango_fc_get_fontset_hash (fcfontmap, language); + + key.fontmap = fcfontmap; + get_context_matrix (context, &key.matrix); + key.language = language; key.desc = pango_font_description_copy_static (desc); pango_font_description_unset_fields (key.desc, PANGO_FONT_MASK_SIZE); + key.size = get_unscaled_size (fcfontmap, context, desc); + + if (PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get) + key.context_key = (gpointer)PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get (fcfontmap, context); + else + key.context_key = NULL; - cache = pango_fc_font_map_get_render_key (fcfontmap, context, desc, &key.x_size, &key.y_size, &key.flags); - if (cache_out) - *cache_out = cache; - - patterns = g_hash_table_lookup (fontset_hash, &key); + patterns = g_hash_table_lookup (priv->fontset_hash, &key); if (patterns == NULL) { - pattern = pango_fc_make_pattern (desc, language, key.y_size / 1024.); - - pango_fc_default_substitute (fcfontmap, context, pattern); + pattern = pango_fc_make_pattern (desc, language, + get_scaled_size (&key), + pango_fc_font_map_get_resolution (fcfontmap, context)); + pango_fc_default_substitute (fcfontmap, context, pattern); + font_patterns = FcFontSort (NULL, pattern, FcTrue, NULL, &res); if (!font_patterns) @@ -995,15 +1124,18 @@ pango_fc_font_map_get_patterns (PangoFontMap *fontmap, } } - FcPatternDestroy (pattern); - FcFontSetSortDestroy (font_patterns); - g_hash_table_insert (fontset_hash, - fontset_hash_key_copy (&key), + patterns->key = fontset_hash_key_copy (&key); + g_hash_table_insert (priv->fontset_hash, + patterns->key, patterns); } + if ((!patterns->cache_link || + patterns->cache_link != priv->fontset_cache->head)) + pango_fc_font_map_cache_fontset (fcfontmap, patterns); + pango_font_description_free (key.desc); return patterns; @@ -1014,14 +1146,14 @@ pango_fc_font_map_load_font (PangoFontMap *fontmap, PangoContext *context, const PangoFontDescription *description) { - PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, description, NULL, NULL); + PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, description, NULL); if (!patterns) return NULL; if (patterns->n_patterns > 0) { return pango_fc_font_map_new_font (fontmap, context, description, - patterns->patterns[0], FALSE); + patterns->patterns[0]); } return NULL; @@ -1033,8 +1165,7 @@ pango_fc_pattern_set_free (PangoFcPatternSet *patterns) int i; if (patterns->fontset) - g_object_remove_weak_pointer (G_OBJECT (patterns->fontset), - (gpointer *)&patterns->fontset); + g_object_unref (patterns->fontset); for (i = 0; i < patterns->n_patterns; i++) FcPatternDestroy (patterns->patterns[i]); @@ -1068,10 +1199,9 @@ pango_fc_font_map_cache_fontset (PangoFcFontMap *fcfontmap, { PangoFcPatternSet *tmp_patterns = g_queue_pop_tail (cache); tmp_patterns->cache_link = NULL; - g_object_unref (tmp_patterns->fontset); + g_hash_table_remove (priv->fontset_hash, tmp_patterns->key); } - g_object_ref (patterns->fontset); patterns->cache_link = g_list_prepend (NULL, patterns); } @@ -1084,17 +1214,14 @@ pango_fc_font_map_load_fontset (PangoFontMap *fontmap, const PangoFontDescription *desc, PangoLanguage *language) { - gboolean cache; - PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, desc, language, &cache); - PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap); - PangoFcFontMapPrivate *priv = fcfontmap->priv; + PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, desc, language); PangoFontset *result; int i; if (!patterns) return NULL; - if (!patterns->fontset || !cache) + if (!patterns->fontset) { PangoFontsetSimple *simple; simple = pango_fontset_simple_new (language); @@ -1105,33 +1232,26 @@ pango_fc_font_map_load_fontset (PangoFontMap *fontmap, PangoFont *font; font = pango_fc_font_map_new_font (fontmap, context, desc, - patterns->patterns[i], cache); + patterns->patterns[i]); if (font) pango_fontset_simple_append (simple, font); } - if (cache) - { - patterns->fontset = PANGO_FONTSET (simple); - g_object_add_weak_pointer (G_OBJECT (patterns->fontset), - (gpointer *)&patterns->fontset); - } + patterns->fontset = PANGO_FONTSET (simple); } - else - result = g_object_ref (patterns->fontset); - if (cache && - (!patterns->cache_link || - patterns->cache_link != priv->fontset_cache->head)) - pango_fc_font_map_cache_fontset (fcfontmap, patterns); - + result = g_object_ref (patterns->fontset); + return result; } static void -uncache_patterns (PangoFcPatternSet *patterns) +uncache_patterns (PangoFcPatternSet *patterns, + PangoFcFontMap *fcfontmap) { - g_object_unref (patterns->fontset); + PangoFcFontMapPrivate *priv = fcfontmap->priv; + + g_hash_table_remove (priv->fontset_hash, patterns->key); } static void @@ -1140,7 +1260,7 @@ pango_fc_font_map_clear_fontset_cache (PangoFcFontMap *fcfontmap) PangoFcFontMapPrivate *priv = fcfontmap->priv; GQueue *cache = priv->fontset_cache; - g_list_foreach (cache->head, (GFunc)uncache_patterns, NULL); + g_list_foreach (cache->head, (GFunc)uncache_patterns, fcfontmap); g_list_free (cache->head); cache->head = NULL; cache->tail = NULL; @@ -1165,11 +1285,7 @@ pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap) { fcfontmap->priv->dpi = -1; - /* Clear the fontset cache first, since any entries - * in the fontset_cache must also be in the pattern cache. - */ pango_fc_font_map_clear_fontset_cache (fcfontmap); - pango_fc_clear_pattern_hashes (fcfontmap); } static void @@ -1338,10 +1454,12 @@ pango_fc_font_map_shutdown (PangoFcFontMap *fcfontmap) PangoFcFontMapPrivate *priv = fcfontmap->priv; pango_fc_font_map_cache_clear (fcfontmap); + g_hash_table_destroy (priv->fontset_hash); + priv->fontset_hash = NULL; - g_hash_table_foreach (priv->fonts, (GHFunc)cleanup_font, NULL); - g_hash_table_destroy (priv->fonts); - priv->fonts = NULL; + g_hash_table_foreach (priv->font_hash, (GHFunc)cleanup_font, NULL); + g_hash_table_destroy (priv->font_hash); + priv->font_hash = NULL; priv->closed = TRUE; } @@ -1613,7 +1731,7 @@ pango_fc_face_list_sizes (PangoFontFace *face, if (FcPatternGetDouble (fontset->fonts[i], FC_PIXEL_SIZE, 0, &size) == FcResultMatch) { if (dpi < 0) - dpi = pango_fc_font_map_get_dpi (fcface->family->fontmap, NULL); + dpi = pango_fc_font_map_get_resolution (fcface->family->fontmap, NULL); size_i = (int) (PANGO_SCALE * size * 72.0 / dpi); g_array_append_val (size_array, size_i); diff --git a/pango/pangofc-fontmap.h b/pango/pangofc-fontmap.h index a6f4d511..7e339542 100644 --- a/pango/pangofc-fontmap.h +++ b/pango/pangofc-fontmap.h @@ -64,22 +64,38 @@ struct _PangoFcFontMap * @default_substitute: Substitutes in default values for * unspecified fields in a #FcPattern. This will be called * prior to creating a font for the pattern. May be %NULL. + * Deprecated in favor of @context_substitute(). * @new_font: Creates a new #PangoFcFont for the specified * pattern of the appropriate type for this font map. The * @pattern argument must be passed to the "pattern" property * of #PangoFcFont when you call g_object_new(). Deprecated * in favor of @create_font(). - * @get_render_key: Given a context and font description, - * calculate a "key" of X and Y sizes and a flags word - * that can be used to hash the results of loading a font - * with that information. If %NULL, a default implementation - * is used. + * @get_resolution: Gets the resolution (the scale factor + * between logical and absolute font sizes) that the backend + * will use for a particular fontmap and context. @context + * may be null. + * @context_key_get: Gets an opaque key holding backend + * specific options for the context that will affect + * fonts created by create_font(). The result must point to + * persistant storage owned by the fontmap. This key + * is used to index hash tables used to look up fontsets + * and fonts. + * @context_key_copy: Copies a context key. Pango uses this + * to make a persistant copy of the value returned from + * @context_key_get. + * @context_key_free: Frees a context key copied with + * @context_key_copy. + * @context_key_hash: Gets a hash value for a context key + * @context_key_equal: Compares two context keys for equality. * @create_font: Creates a new #PangoFcFont for the specified * pattern of the appropriate type for this font map using * information from the context that is passed in. The * @pattern argument must be passed to the "pattern" property * of #PangoFcFont when you call g_object_new(). Deprecated * in favor of @create_font(). If %NULL, new_font() is used. + * @context_substitute: Substitutes in default values for + * unspecified fields in a #FcPattern. This will be called + * prior to creating a font for the pattern. May be %NULL. * * Class structure for #PangoFcFontMap. **/ @@ -96,12 +112,21 @@ struct _PangoFcFontMapClass PangoFcFont *(*new_font) (PangoFcFontMap *fontmap, FcPattern *pattern); - gboolean (*get_render_key) (PangoFcFontMap *fcfontmap, - PangoContext *context, - const PangoFontDescription *desc, - int *xsize, - int *ysize, - guint *flags); + double (*get_resolution) (PangoFcFontMap *fcfontmap, + PangoContext *context); + + gconstpointer (*context_key_get) (PangoFcFontMap *fcfontmap, + PangoContext *context); + gpointer (*context_key_copy) (PangoFcFontMap *fcfontmap, + gconstpointer key); + void (*context_key_free) (PangoFcFontMap *fcfontmap, + gpointer key); + guint32 (*context_key_hash) (PangoFcFontMap *fcfontmap, + gconstpointer key); + gboolean (*context_key_equal) (PangoFcFontMap *fcfontmap, + gconstpointer key_a, + gconstpointer key_b); + void (*context_substitute) (PangoFcFontMap *fontmap, PangoContext *context, FcPattern *pattern); @@ -114,6 +139,8 @@ struct _PangoFcFontMapClass /* Padding for future expansion */ void (*_pango_reserved1) (void); void (*_pango_reserved2) (void); + void (*_pango_reserved3) (void); + void (*_pango_reserved4) (void); }; PangoContext * pango_fc_font_map_create_context (PangoFcFontMap *fcfontmap); diff --git a/pango/pangowin32.c b/pango/pangowin32.c index 5c231f43..a3a706e0 100644 --- a/pango/pangowin32.c +++ b/pango/pangowin32.c @@ -697,8 +697,7 @@ pango_win32_font_logfont (PangoFont *font) /** * pango_win32_font_select_font: * @font: a #PangoFont from the Win32 backend - * @scale: location to store a scale factor from Windows - * units to Pango Units. + * @hdc: a windows device context * * Selects the font into the specified DC and changes the mapping mode * and world transformation of the DC appropriately for the font. @@ -706,7 +705,9 @@ pango_win32_font_logfont (PangoFont *font) * to SaveDC and RestoreDC. Call pango_win32_font_done_font() when * you are done using the DC to release allocated resources. * - * See + * See pango_win32_font_get_metrics_factor() for information about + * converting from the coordinate space used by this function + * into Pango units. * * Return value: %TRUE if the operation succeeded. **/ |