diff options
Diffstat (limited to 'pango')
-rw-r--r-- | pango/Makefile.am | 27 | ||||
-rw-r--r-- | pango/pango-attributes.c | 35 | ||||
-rw-r--r-- | pango/pango-attributes.h | 3 | ||||
-rw-r--r-- | pango/pango-layout.c | 23 | ||||
-rw-r--r-- | pango/pangocairo-fc.h | 54 | ||||
-rw-r--r-- | pango/pangocairo-fcfont.c | 508 | ||||
-rw-r--r-- | pango/pangocairo-fcfontmap.c | 140 | ||||
-rw-r--r-- | pango/pangocairo-font.c | 69 | ||||
-rw-r--r-- | pango/pangocairo-fontmap.c | 285 | ||||
-rw-r--r-- | pango/pangocairo-private.h | 78 | ||||
-rw-r--r-- | pango/pangocairo-render.c | 354 | ||||
-rw-r--r-- | pango/pangocairo.h | 84 | ||||
-rw-r--r-- | pango/pangofc-font.c | 48 | ||||
-rw-r--r-- | pango/pangofc-fontmap.c | 28 | ||||
-rw-r--r-- | pango/pangofc-fontmap.h | 10 | ||||
-rw-r--r-- | pango/pangofc-private.h | 7 | ||||
-rw-r--r-- | pango/pangoft2-private.h | 8 | ||||
-rw-r--r-- | pango/pangoft2.c | 34 |
18 files changed, 1713 insertions, 82 deletions
diff --git a/pango/Makefile.am b/pango/Makefile.am index 56af60f0..7142b8d3 100644 --- a/pango/Makefile.am +++ b/pango/Makefile.am @@ -213,6 +213,33 @@ libpangoxft_1_0_la_SOURCES = \ pangoxft-render.c +# ------------------- libpangocairo ------------------- + +if HAVE_CAIRO +pangoinclude_HEADERS += pangocairo.h +lib_LTLIBRARIES += libpangocairo-1.0.la +endif + +libpangocairo_1_0_la_LDFLAGS = -version-info $(LT_VERSION_INFO) $(no_undefined) +libpangocairo_1_0_la_LIBADD = libpangoft2-$(PANGO_API_VERSION).la libpango-$(PANGO_API_VERSION).la $(CAIRO_LIBS) $(GLIB_LIBS) +libpangocairo_1_0_la_DEPENDENCIES = libpango-$(PANGO_API_VERSION).la + +libpangocairo_1_0_la_SOURCES = \ + pangocairo-font.c \ + pangocairo-fontmap.c \ + pangocairo-render.c \ + pangocairo-private.h + +if HAVE_CAIRO_FREETYPE +libpangocairo_1_0_la_LIBADD += $(FREETYPE_LIBS) +libpangocairo_1_0_la_DEPENDENCIES += libpangoft2-$(PANGO_API_VERSION).la + +libpangocairo_1_0_la_SOURCES += \ + pangocairo-fcfont.c \ + pangocairo-fcfontmap.c \ + pangocairo-fc.h +endif + # ------------------- libpangowin32 ------------------- if HAVE_WIN32 diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index 3191c029..edf0d966 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -402,8 +402,11 @@ static PangoAttribute * pango_attr_size_copy (const PangoAttribute *attr) { const PangoAttrSize *size_attr = (PangoAttrSize *)attr; - - return pango_attr_size_new_internal (size_attr->size, size_attr->absolute); + + if (attr->klass->type == PANGO_ATTR_ABSOLUTE_SIZE) + return pango_attr_size_new_absolute (size_attr->size); + else + return pango_attr_size_new (size_attr->size); } static void @@ -419,8 +422,7 @@ pango_attr_size_equal (const PangoAttribute *attr1, const PangoAttrSize *size_attr1 = (const PangoAttrSize *)attr1; const PangoAttrSize *size_attr2 = (const PangoAttrSize *)attr2; - return (size_attr1->size == size_attr2->size && - size_attr1->absolute == size_attr2->absolute); + return size_attr1->size == size_attr2->size; } static PangoAttribute * @@ -428,15 +430,22 @@ pango_attr_size_new_internal (int size, gboolean absolute) { PangoAttrSize *result; + static const PangoAttrClass klass = { PANGO_ATTR_SIZE, pango_attr_size_copy, pango_attr_size_destroy, pango_attr_size_equal }; + static const PangoAttrClass absolute_klass = { + PANGO_ATTR_ABSOLUTE_SIZE, + pango_attr_size_copy, + pango_attr_size_destroy, + pango_attr_size_equal + }; result = g_new (PangoAttrSize, 1); - result->attr.klass = &klass; + result->attr.klass = absolute ? &absolute_klass : &klass; result->size = size; result->absolute = absolute; @@ -458,8 +467,8 @@ pango_attr_size_new (int size) } /** - * pango_attr_size_absolute_new: - * @size: the font size, in #PANGO_SCALE<!-- -->ths of a device units. + * pango_attr_size_new_absolute: + * @size: the font size, in #PANGO_SCALE<!-- -->ths of a device unit. * * Create a new font-size attribute in device units. * @@ -1676,10 +1685,14 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator, if (!(mask & PANGO_FONT_MASK_SIZE)) { mask |= PANGO_FONT_MASK_SIZE; - if (((PangoAttrSize *)attr)->absolute) - pango_font_description_set_absolute_size (desc, ((PangoAttrSize *)attr)->size); - else - pango_font_description_set_size (desc, ((PangoAttrSize *)attr)->size); + pango_font_description_set_size (desc, ((PangoAttrSize *)attr)->size); + } + break; + case PANGO_ATTR_ABSOLUTE_SIZE: + if (!(mask & PANGO_FONT_MASK_SIZE)) + { + mask |= PANGO_FONT_MASK_SIZE; + pango_font_description_set_absolute_size (desc, ((PangoAttrSize *)attr)->size); } break; case PANGO_ATTR_SCALE: diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h index a1877058..f26e178f 100644 --- a/pango/pango-attributes.h +++ b/pango/pango-attributes.h @@ -85,7 +85,8 @@ typedef enum PANGO_ATTR_FALLBACK, /* PangoAttrInt */ PANGO_ATTR_LETTER_SPACING, /* PangoAttrInt */ PANGO_ATTR_UNDERLINE_COLOR, /* PangoAttrColor */ - PANGO_ATTR_STRIKETHROUGH_COLOR /* PangoAttrColor */ + PANGO_ATTR_STRIKETHROUGH_COLOR, /* PangoAttrColor */ + PANGO_ATTR_ABSOLUTE_SIZE /* PangoAttrSize */ } PangoAttrType; typedef enum { diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 53106f20..d475a945 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -3917,15 +3917,22 @@ pango_layout_line_get_extents (PangoLayoutLine *line, if (ink_rect) { - new_pos = MIN (ink_rect->x, x_pos + run_ink.x); - ink_rect->width = MAX (ink_rect->x + ink_rect->width, - x_pos + run_ink.x + run_ink.width) - new_pos; - ink_rect->x = new_pos; + if (tmp_list == line->runs) + { + *ink_rect = run_ink; + } + else + { + new_pos = MIN (ink_rect->x, x_pos + run_ink.x); + ink_rect->width = MAX (ink_rect->x + ink_rect->width, + x_pos + run_ink.x + run_ink.width) - new_pos; + ink_rect->x = new_pos; - new_pos = MIN (ink_rect->y, run_ink.y); - ink_rect->height = MAX (ink_rect->y + ink_rect->height, - run_ink.y + run_ink.height) - new_pos; - ink_rect->y = new_pos; + new_pos = MIN (ink_rect->y, run_ink.y); + ink_rect->height = MAX (ink_rect->y + ink_rect->height, + run_ink.y + run_ink.height) - new_pos; + ink_rect->y = new_pos; + } } if (logical_rect) diff --git a/pango/pangocairo-fc.h b/pango/pangocairo-fc.h new file mode 100644 index 00000000..22fd1b60 --- /dev/null +++ b/pango/pangocairo-fc.h @@ -0,0 +1,54 @@ +/* Pango + * pangocairo-fc.h: Private header file for Cairo/fontconfig combination + * + * Copyright (C) 2005 Red Hat, Inc. + * + * 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_FC_H__ +#define __PANGOCAIRO_FC_H__ + +#include "pangofc-fontmap.h" +#include "pangocairo.h" + +G_BEGIN_DECLS + +#define PANGO_TYPE_CAIRO_FC_FONT_MAP (pango_cairo_fc_font_map_get_type ()) +#define PANGO_CAIRO_FC_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FC_FONT_MAP, PangoCairoFcFontMap)) +#define PANGO_IS_CAIRO_FC_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CAIRO_FC_FONT_MAP)) + +typedef struct _PangoCairoFcFontMap PangoCairoFcFontMap; + +struct _PangoCairoFcFontMap +{ + PangoFcFontMap parent_instance; + + double dpi; + + FT_Library library; + PangoRenderer *renderer; +}; + +GType pango_cairo_fc_font_map_get_type (void); + +PangoFcFont *_pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap, + FcPattern *pattern); + +G_END_DECLS + +#endif /* __PANGOCAIRO_FC_H__ */ + diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c new file mode 100644 index 00000000..b8f4a32b --- /dev/null +++ b/pango/pangocairo-fcfont.c @@ -0,0 +1,508 @@ +/* Pango + * pangocairofc-font.c: Cairo font handling, fontconfig backend + * + * Copyright (C) 2000-2005 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 "config.h" + +#include <stdlib.h> + +#include "pango-fontmap.h" +#include "pangocairo-private.h" +#include "pangocairo-fc.h" +#include "pangofc-private.h" + +#define PANGO_TYPE_CAIRO_FC_FONT (pango_cairo_fc_font_get_type ()) +#define PANGO_CAIRO_FC_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFont)) +#define PANGO_CAIRO_FC_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFontClass)) +#define PANGO_CAIRO_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CAIRO_FC_FONT)) +#define PANGO_CAIRO_FC_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFontClass)) + +#define PANGO_CAIRO_UNKNOWN_FLAG 0x10000000 + +typedef struct _PangoCairoFcFont PangoCairoFcFont; +typedef struct _PangoCairoFcFontClass PangoCairoFcFontClass; + +struct _PangoCairoFcFont +{ + PangoFcFont font; + + FT_Face face; + cairo_font_t *cairo_font; + + int load_flags; + gboolean have_size; + + GHashTable *glyph_info; +}; + +struct _PangoCairoFcFontClass +{ + PangoFcFontClass parent_class; +}; + +GType pango_cairo_fc_font_get_type (void); + +/******************************* + * Utility functions * + *******************************/ + +static FT_Face +load_face (PangoCairoFcFont *cffont) +{ + PangoFcFont *fcfont = PANGO_FC_FONT (cffont); + FT_Library library = PANGO_CAIRO_FC_FONT_MAP (fcfont->fontmap)->library; + FT_Error error; + FcPattern *pattern; + FcChar8 *filename; + FcBool antialias, hinting, autohint; + FT_Face face = NULL; + int id; + + pattern = fcfont->font_pattern; + + cffont->load_flags = 0; + + /* disable antialiasing if requested */ + if (FcPatternGetBool (pattern, + FC_ANTIALIAS, 0, &antialias) != FcResultMatch) + antialias = FcTrue; + + if (antialias) + cffont->load_flags |= FT_LOAD_NO_BITMAP; + else + cffont->load_flags |= FT_LOAD_TARGET_MONO; + + /* disable hinting if requested */ + if (FcPatternGetBool (pattern, + FC_HINTING, 0, &hinting) != FcResultMatch) + hinting = FcTrue; + + if (!hinting) + cffont->load_flags |= FT_LOAD_NO_HINTING; + + /* force autohinting if requested */ + if (FcPatternGetBool (pattern, + FC_AUTOHINT, 0, &autohint) != FcResultMatch) + autohint = FcFalse; + + if (autohint) + cffont->load_flags |= FT_LOAD_FORCE_AUTOHINT; + + if (FcPatternGetString (pattern, FC_FILE, 0, &filename) != FcResultMatch) + goto bail; + + if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch) + goto bail; + + error = FT_New_Face (library, (char *) filename, id, &face); + + bail: + return face; +} + +static FT_Face +load_fallback_face (PangoCairoFcFont *cffont) +{ + PangoFcFont *fcfont = PANGO_FC_FONT (cffont); + FT_Library library = PANGO_CAIRO_FC_FONT_MAP (fcfont->fontmap)->library; + FcPattern *sans; + FcPattern *matched; + FcResult result; + FT_Error error; + FcChar8 *filename = NULL; + FT_Face face = NULL; + int id; + + /* FIXME: pass in a size in case Sans is bitmap */ + sans = FcPatternBuild (NULL, + FC_FAMILY, FcTypeString, "sans", + NULL); + + matched = FcFontMatch (NULL, sans, &result); + + if (FcPatternGetString (matched, FC_FILE, 0, &filename) != FcResultMatch) + goto bail; + + if (FcPatternGetInteger (matched, FC_INDEX, 0, &id) != FcResultMatch) + goto bail; + + face = NULL; + error = FT_New_Face (library, (char *) filename, id, &face); + + if (error) + { + bail: + g_warning ("Unable to open font file %s for Sans, exiting", filename); + exit (1); + } + + FcPatternDestroy (sans); + FcPatternDestroy (matched); + + return face; +} + +static cairo_font_t * +get_cairo_font (PangoCairoFcFont *cffont) +{ + PangoFcFont *fcfont = PANGO_FC_FONT (cffont); + + if (cffont->cairo_font == NULL) + { + FT_Face face = load_face (cffont); + + if (face) + cffont->cairo_font = cairo_ft_font_create_for_ft_face (face); + + if (!cffont->cairo_font) + { + gchar *name = pango_font_description_to_string (fcfont->description); + g_warning ("Cannot open font file for font %s, trying Sans", name); + g_free (name); + + if (face) + FT_Done_Face (face); + + face = load_fallback_face (cffont); + + if (face) + cffont->cairo_font = cairo_ft_font_create_for_ft_face (face); + + if (!cffont->cairo_font) + { + g_warning ("Unable create Cairo font for Sans, exiting"); + exit (1); + } + } + + cffont->face = face; + } + + return cffont->cairo_font; +} + +static void +make_current (PangoCairoFcFont *cffont, + cairo_t *cr) +{ + PangoFcFont *fcfont = PANGO_FC_FONT (cffont); + double scale; + + if (pango_font_description_get_size_is_absolute (fcfont->description)) + scale = pango_font_description_get_size (fcfont->description); + else + scale = (PANGO_CAIRO_FC_FONT_MAP (fcfont->fontmap)->dpi * + pango_font_description_get_size (fcfont->description)) / (PANGO_SCALE * 72.); + + cairo_set_font (cr, get_cairo_font (cffont)); + cairo_scale_font (cr, scale); +} + +static void +pango_cairo_fc_font_make_current (PangoCairoFont *font, + cairo_t *cr) +{ + make_current (PANGO_CAIRO_FC_FONT (font), cr); +} + +static void +cairo_font_iface_init (PangoCairoFontIface *iface) +{ + iface->make_current = pango_cairo_fc_font_make_current; +} + +G_DEFINE_TYPE_WITH_CODE (PangoCairoFcFont, pango_cairo_fc_font, PANGO_TYPE_FC_FONT, + { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT, cairo_font_iface_init) }); + +/******************************** + * Method implementations * + ********************************/ + +static void +pango_cairo_fc_font_finalize (GObject *object) +{ + PangoCairoFcFont *cffont = PANGO_CAIRO_FC_FONT (object); + + if (cffont->cairo_font) + { + cairo_font_destroy (cffont->cairo_font); + cffont->cairo_font = NULL; + + FT_Done_Face (cffont->face); + cffont->face = NULL; + } + + if (cffont->glyph_info) + g_hash_table_destroy (cffont->glyph_info); + + G_OBJECT_CLASS (pango_cairo_fc_font_parent_class)->finalize (object); +} + +static cairo_t * +get_temporary_context (PangoCairoFcFont *cffont) +{ + PangoFcFont *fcfont = PANGO_FC_FONT (cffont); + FcMatrix *fc_matrix; + cairo_t *cr; + + cr = cairo_create (); + + if (FcPatternGetMatrix (fcfont->font_pattern, + FC_MATRIX, 0, &fc_matrix) == FcResultMatch) + { + cairo_matrix_t *cairo_matrix = cairo_matrix_create (); + cairo_matrix_set_affine (cairo_matrix, + fc_matrix->xx, fc_matrix->yx, + fc_matrix->xy, fc_matrix->yy, + 0, 0); + cairo_set_matrix (cr, cairo_matrix); + cairo_matrix_destroy (cairo_matrix); + } + + make_current (cffont, cr); + + return cr; +} + +static void +get_ascent_descent (PangoCairoFcFont *cffont, + int *ascent, + int *descent) +{ + /* This is complicated in general (see pangofc-font.c:get_face_metrics(), + * but simple for hinted, untransformed fonts. cairo_glyph_extents() will + * have set up the right size on the font as a side-effect. + */ + *descent = - PANGO_UNITS_26_6 (cffont->face->size->metrics.descender); + *ascent = PANGO_UNITS_26_6 (cffont->face->size->metrics.ascender); +} + +static void +get_glyph_extents_cairo (PangoFcFont *fcfont, + PangoGlyph glyph, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + PangoCairoFcFont *cffont = PANGO_CAIRO_FC_FONT (fcfont); + cairo_text_extents_t extents; + cairo_glyph_t cairo_glyph; + cairo_t *cr; + + cairo_glyph.index = glyph; + cairo_glyph.x = 0; + cairo_glyph.y = 0; + + cr = get_temporary_context (cffont); + cairo_glyph_extents (cr, &cairo_glyph, 1, &extents); + cairo_destroy (cr); + + if (ink_rect) + { + ink_rect->x = extents.x_bearing * PANGO_SCALE; + ink_rect->y = extents.y_bearing * PANGO_SCALE; + ink_rect->width = extents.width * PANGO_SCALE; + ink_rect->height = extents.height * PANGO_SCALE; + } + + if (logical_rect) + { + int ascent, descent; + + get_ascent_descent (cffont, &ascent, &descent); + + logical_rect->x = 0; + logical_rect->y = - ascent; + logical_rect->width = extents.x_advance * PANGO_SCALE; + logical_rect->height = ascent + descent; + } +} + +typedef struct +{ + PangoRectangle ink_rect; + PangoRectangle logical_rect; +} Extents; + +static void +get_glyph_extents_raw (PangoCairoFcFont *cffont, + PangoGlyph glyph, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + Extents *extents; + + if (!cffont->glyph_info) + cffont->glyph_info = g_hash_table_new_full (NULL, NULL, + NULL, (GDestroyNotify)g_free); + + extents = g_hash_table_lookup (cffont->glyph_info, + GUINT_TO_POINTER (glyph)); + + if (!extents) + { + extents = g_new (Extents, 1); + + pango_fc_font_get_raw_extents (PANGO_FC_FONT (cffont), + FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING, + glyph, + &extents->ink_rect, + &extents->logical_rect); + + g_hash_table_insert (cffont->glyph_info, + GUINT_TO_POINTER (glyph), + extents); + } + + if (ink_rect) + *ink_rect = extents->ink_rect; + + if (logical_rect) + *logical_rect = extents->logical_rect; +} + +static void +pango_cairo_fc_font_get_glyph_extents (PangoFont *font, + PangoGlyph glyph, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + PangoCairoFcFont *cffont = PANGO_CAIRO_FC_FONT (font); + PangoFcFont *fcfont = PANGO_FC_FONT (font); + + if (!fcfont->fontmap) /* Display closed */ + goto fallback; + + if (glyph == (PangoGlyph)-1) + glyph = 0; + + if (glyph) + { + if (!fcfont->is_transformed && fcfont->is_hinted) + get_glyph_extents_cairo (fcfont, glyph, ink_rect, logical_rect); + else + get_glyph_extents_raw (cffont, glyph, ink_rect, logical_rect); + } + else + { + fallback: + + if (ink_rect) + { + ink_rect->x = 0; + ink_rect->width = 0; + ink_rect->y = 0; + ink_rect->height = 0; + } + if (logical_rect) + { + logical_rect->x = 0; + logical_rect->width = 0; + logical_rect->y = 0; + logical_rect->height = 0; + } + } +} + +static FT_Face +pango_cairo_fc_font_lock_face (PangoFcFont *font) +{ + PangoCairoFcFont *cffont = PANGO_CAIRO_FC_FONT (font); + + /* Horrible hack, we need the font's face to be sized when + * locked, but sizing is only done as a side-effect + */ + if (!cffont->have_size) + { + cairo_t *cr = get_temporary_context (cffont); + cairo_font_extents_t extents; + + cairo_current_font_extents (cr, &extents); + cairo_destroy (cr); + + cffont->have_size = TRUE; + } + + return cairo_ft_font_face (cffont->cairo_font); +} + +static void +pango_cairo_fc_font_unlock_face (PangoFcFont *font) +{ +} + +static PangoGlyph +pango_cairo_fc_font_real_get_unknown_glyph (PangoFcFont *font, + gunichar wc) +{ + return 0; +} + +static void +pango_cairo_fc_font_shutdown (PangoFcFont *fcfont) +{ + PangoCairoFcFont *cffont = PANGO_CAIRO_FC_FONT (fcfont); + if (cffont->cairo_font) + { + cairo_font_destroy (cffont->cairo_font); + cffont->cairo_font = NULL; + + FT_Done_Face (cffont->face); + cffont->face = NULL; + } +} + +static void +pango_cairo_fc_font_class_init (PangoCairoFcFontClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + PangoFontClass *font_class = PANGO_FONT_CLASS (class); + PangoFcFontClass *fc_font_class = PANGO_FC_FONT_CLASS (class); + + object_class->finalize = pango_cairo_fc_font_finalize; + + font_class->get_glyph_extents = pango_cairo_fc_font_get_glyph_extents; + + fc_font_class->lock_face = pango_cairo_fc_font_lock_face; + fc_font_class->unlock_face = pango_cairo_fc_font_unlock_face; + fc_font_class->get_unknown_glyph = pango_cairo_fc_font_real_get_unknown_glyph; + fc_font_class->shutdown = pango_cairo_fc_font_shutdown; +} + +static void +pango_cairo_fc_font_init (PangoCairoFcFont *cffont) +{ +} + +/******************** + * Private API * + ********************/ + +PangoFcFont * +_pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap, + FcPattern *pattern) +{ + g_return_val_if_fail (PANGO_IS_CAIRO_FC_FONT_MAP (cffontmap), NULL); + g_return_val_if_fail (pattern != NULL, NULL); + + return g_object_new (PANGO_TYPE_CAIRO_FC_FONT, + "pattern", pattern, + NULL); +} + diff --git a/pango/pangocairo-fcfontmap.c b/pango/pangocairo-fcfontmap.c new file mode 100644 index 00000000..0d05c422 --- /dev/null +++ b/pango/pangocairo-fcfontmap.c @@ -0,0 +1,140 @@ +/* Pango + * pangocairo-fontmap.c: Cairo font handling, fontconfig backend + * + * Copyright (C) 2000-2005 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-fontmap.h" +#include "pangocairo.h" +#include "pangocairo-private.h" +#include "pangocairo-fc.h" + +typedef struct _PangoCairoFcFontMapClass PangoCairoFcFontMapClass; + +struct _PangoCairoFcFontMapClass +{ + PangoFcFontMapClass parent_class; +}; + +static void +pango_cairo_fc_font_map_set_resolution (PangoCairoFontMap *cfontmap, + double dpi) +{ + PangoCairoFcFontMap *cffontmap = PANGO_CAIRO_FC_FONT_MAP (cfontmap); + + cffontmap->dpi = dpi; + + pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (cfontmap)); +} + +static double +pango_cairo_fc_font_map_get_resolution (PangoCairoFontMap *cfontmap) +{ + PangoCairoFcFontMap *cffontmap = PANGO_CAIRO_FC_FONT_MAP (cfontmap); + + return cffontmap->dpi; +} + +static PangoRenderer * +pango_cairo_fc_font_map_get_renderer (PangoCairoFontMap *cfontmap) +{ + PangoCairoFcFontMap *cffontmap = PANGO_CAIRO_FC_FONT_MAP (cfontmap); + + if (!cffontmap->renderer) + cffontmap->renderer = g_object_new (PANGO_TYPE_CAIRO_RENDERER, NULL); + + return cffontmap->renderer; +} + +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_renderer = pango_cairo_fc_font_map_get_renderer; +} + +G_DEFINE_TYPE_WITH_CODE (PangoCairoFcFontMap, pango_cairo_fc_font_map, PANGO_TYPE_FC_FONT_MAP, + { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT_MAP, cairo_font_map_iface_init) }); + +static void +pango_cairo_fc_font_map_finalize (GObject *object) +{ + PangoCairoFcFontMap *cffontmap = PANGO_CAIRO_FC_FONT_MAP (object); + + if (cffontmap->renderer) + g_object_unref (cffontmap->renderer); + + FT_Done_FreeType (cffontmap->library); + + G_OBJECT_CLASS (pango_cairo_fc_font_map_parent_class)->finalize (object); +} + +static void +pango_cairo_fc_font_map_default_substitute (PangoFcFontMap *fcfontmap, + 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); + FcDefaultSubstitute (pattern); +} + +static PangoFcFont * +pango_cairo_fc_font_map_new_font (PangoFcFontMap *fcfontmap, + FcPattern *pattern) +{ + return _pango_cairo_fc_font_new (PANGO_CAIRO_FC_FONT_MAP (fcfontmap), pattern); +} + +static void +pango_cairo_fc_font_map_class_init (PangoCairoFcFontMapClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + PangoFcFontMapClass *fcfontmap_class = PANGO_FC_FONT_MAP_CLASS (class); + + gobject_class->finalize = pango_cairo_fc_font_map_finalize; + fcfontmap_class->default_substitute = pango_cairo_fc_font_map_default_substitute; + fcfontmap_class->new_font = pango_cairo_fc_font_map_new_font; +} + +static void +pango_cairo_fc_font_map_init (PangoCairoFcFontMap *cffontmap) +{ + FT_Error error; + + cffontmap->library = NULL; + error = FT_Init_FreeType (&cffontmap->library); + if (error != FT_Err_Ok) + g_error ("pango_cairo_font_map_init: Could not initialize freetype"); + + cffontmap->dpi = 96.0; +} + +FT_Library +_pango_cairo_fc_font_map_get_library (PangoCairoFcFontMap *fontmap) +{ + g_return_val_if_fail (PANGO_IS_CAIRO_FC_FONT_MAP (fontmap), NULL); + + return fontmap->library; +} + diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c new file mode 100644 index 00000000..7aae83ec --- /dev/null +++ b/pango/pangocairo-font.c @@ -0,0 +1,69 @@ +/* Pango + * pangocairo-font.c: Cairo font handling + * + * Copyright (C) 2000-2005 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 "pangocairo.h" +#include "pangocairo-private.h" + +GType +pango_cairo_font_get_type (void) +{ + static GType cairo_font_type = 0; + + if (! cairo_font_type) + { + static const GTypeInfo cairo_font_info = + { + sizeof (PangoCairoFontIface), /* class_size */ + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, + NULL + }; + + cairo_font_type = + g_type_register_static (G_TYPE_INTERFACE, "PangoCairoFont", + &cairo_font_info, 0); + + g_type_interface_add_prerequisite (cairo_font_type, PANGO_TYPE_FONT); + } + + return cairo_font_type; +} + +/** + * _pango_cairo_font_get_cairo_font: + * @font: a #PangoCairoFont + * @cr: a #CairoConext + * + * Install the font and size of @font onto @cr + **/ +void +_pango_cairo_font_make_current (PangoCairoFont *font, + cairo_t *cr) +{ + g_return_if_fail (PANGO_IS_CAIRO_FONT (font)); + + return (* PANGO_CAIRO_FONT_GET_IFACE (font)->make_current) (font, cr); +} diff --git a/pango/pangocairo-fontmap.c b/pango/pangocairo-fontmap.c new file mode 100644 index 00000000..692b7786 --- /dev/null +++ b/pango/pangocairo-fontmap.c @@ -0,0 +1,285 @@ +/* Pango + * pangocairo-fontmap.c: Cairo font handling + * + * Copyright (C) 2000-2005 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 "config.h" + +#include "pangocairo.h" +#include "pangocairo-private.h" + +#ifdef HAVE_CAIRO_FREETYPE +#include "pangocairo-fc.h" +#endif + +GType +pango_cairo_font_map_get_type (void) +{ + static GType cairo_font_map_type = 0; + + if (! cairo_font_map_type) + { + static const GTypeInfo cairo_font_map_info = + { + sizeof (PangoCairoFontMapIface), /* class_size */ + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, + NULL + }; + + cairo_font_map_type = + g_type_register_static (G_TYPE_INTERFACE, "PangoCairoFontMap", + &cairo_font_map_info, 0); + + g_type_interface_add_prerequisite (cairo_font_map_type, PANGO_TYPE_FONT_MAP); + } + + return cairo_font_map_type; +} + +/** + * pango_cairo_font_map_new: + * + * Creates a new #PangoCairoFontMap object; a fontmap is used + * to cache information about available fonts, and holds + * certain global parameters such as the resolution. + * In most cases, you can use pango_cairo_font_map_get_default() + * instead. + * + * Note that the type of the returned object will depend + * on the particular font backend Cairo was compiled to use; + * You generally should only use the #PangoFontMap and + * #PangoCairoFontMap interfaces on the returned object. + * + * Return value: the newly created fontmap object. Free + * with g_object_unref(). + * + * Since: 1.10 + **/ +PangoFontMap * +pango_cairo_font_map_new (void) +{ + /* Make sure that the type system is initialized */ + g_type_init (); + + return g_object_new (PANGO_TYPE_CAIRO_FC_FONT_MAP, NULL); +} + +/** + * pango_cairo_font_map_get_default: + * + * Gets a default font map to use with Cairo. + * + * Return value: the default Cairo fontmap for Pango. This + * object is owned by Pango and must not be freed. + * + * Since: 1.10 + **/ +PangoFontMap * +pango_cairo_font_map_get_default (void) +{ + static PangoFontMap *default_font_map = NULL; + + if (!default_font_map) + default_font_map = pango_cairo_font_map_new (); + + return default_font_map; +} + +/** + * pango_cairo_font_map_set_resolution: + * @fontmap: a #PangoCairoFontMap + * @dpi: the resolution in "dots per inch". (Physical inches aren't actually + * involved; the terminology is conventional.) + * + * Sets the resolution for the fontmap. 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_font_map_set_resolution (PangoCairoFontMap *fontmap, + double dpi) +{ + g_return_if_fail (PANGO_IS_CAIRO_FONT_MAP (fontmap)); + + (* PANGO_CAIRO_FONT_MAP_GET_IFACE (fontmap)->set_resolution) (fontmap, dpi); +} + +/** + * pango_cairo_font_map_get_resolution: + * @fontmap: a #PangoCairoFontMap + * + * Gets the resolutions for the fontmap. See pango_cairo_font_map_set_resolution. + * + * Return value: the resolution in "dots per inch" + * + * Since: 1.10 + **/ +double +pango_cairo_font_map_get_resolution (PangoCairoFontMap *fontmap) +{ + g_return_val_if_fail (PANGO_IS_CAIRO_FONT_MAP (fontmap), 96.); + + return (* PANGO_CAIRO_FONT_MAP_GET_IFACE (fontmap)->get_resolution) (fontmap); +} + +/** + * pango_cairo_font_map_create_context: + * @fontmap: a #PangoCairoFontMap + * + * Create a #PangoContext for the given fontmap. + * + * Return value: the newly created context; free with g_object_unref(). + * + * Since: 1.10 + **/ +PangoContext * +pango_cairo_font_map_create_context (PangoCairoFontMap *fontmap) +{ + PangoContext *context; + + g_return_val_if_fail (PANGO_IS_CAIRO_FONT_MAP (fontmap), NULL); + + context = pango_context_new (); + pango_context_set_font_map (context, PANGO_FONT_MAP (fontmap)); + + return context; +} + +/** + * _pango_cairo_font_map_get_renderer: + * @fontmap: a #PangoCairoFontmap + * + * Gets the singleton PangoCairoRenderer for this fontmap. + * + * Return value: the singleton renderer + **/ +PangoRenderer * +_pango_cairo_font_map_get_renderer (PangoCairoFontMap *fontmap) +{ + g_return_val_if_fail (PANGO_IS_CAIRO_FONT_MAP (fontmap), NULL); + + return (* PANGO_CAIRO_FONT_MAP_GET_IFACE (fontmap)->get_renderer) (fontmap); +} + +/** + * pango_cairo_update_context: + * @cr: a Cairo context + * @context: a #PangoContext, from pango_cairo_font_map_create_context() + * + * Updates a #PangoContext previously created for use with Cairo to + * match the current transformation and target surface of a Cairo + * context. If any layouts have been created for the context, + * it's necessary to call pango_layout_context_changed() on those + * layouts. + * + * Since: 1.10 + **/ +void +pango_cairo_update_context (cairo_t *cr, + PangoContext *context) +{ + cairo_matrix_t *cairo_matrix; + PangoMatrix pango_matrix; + + g_return_if_fail (cr != NULL); + g_return_if_fail (PANGO_IS_CONTEXT (context)); + + cairo_matrix = cairo_matrix_create (); + cairo_current_matrix (cr, cairo_matrix); + cairo_matrix_get_affine (cairo_matrix, + &pango_matrix.xx, &pango_matrix.yx, + &pango_matrix.xy, &pango_matrix.yy, + &pango_matrix.x0, &pango_matrix.y0); + + pango_context_set_matrix (context, &pango_matrix); + + cairo_matrix_destroy (cairo_matrix); +} + +/** + * pango_cairo_create_layout: + * @cr: a Cairo context + * + * Creates a layout object set up to match the current transformation + * and target surface of the Cairo context. This layout can then be + * used for text measurement with functions like + * pango_layout_get_size() or drawing with functions like + * pango_cairo_show_layout(). If you change the transformation + * or target surface for @cr, you need to call pango_cairo_update_layout() + * + * This function is the most convenient way to use Cairo with Pango, + * however it is slightly inefficient since it creates a separate + * #PangoContext object for each layout. This might matter in an + * application that was laying out large amounts of text. + * + * Return value: the newly created #PangoLayout. Free with + * g_object_unref(). + * + * Since: 1.10 + **/ +PangoLayout * +pango_cairo_create_layout (cairo_t *cr) +{ + PangoFontMap *fontmap; + PangoContext *context; + PangoLayout *layout; + + g_return_val_if_fail (cr != NULL, NULL); + + fontmap = pango_cairo_font_map_get_default (); + context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap)); + layout = pango_layout_new (context); + + pango_cairo_update_context (cr, context); + g_object_unref (context); + + return layout; +} + +/** + * pango_cairo_update_layout: + * @cr: a Cairo context + * @layout: a #PangoLayout, from pango_cairo_create_layout() + * + * Updates the private #PangoContext of a #PangoLayout created with + * pango_cairo_create_layout() to match the current transformation + * and target surface of a Cairo context. + * + * Since: 1.10 + **/ +void +pango_cairo_update_layout (cairo_t *cr, + PangoLayout *layout) +{ + g_return_if_fail (cr != NULL); + g_return_if_fail (PANGO_IS_LAYOUT (layout)); + + pango_cairo_update_context (cr, pango_layout_get_context (layout)); + pango_layout_context_changed (layout); +} + diff --git a/pango/pangocairo-private.h b/pango/pangocairo-private.h new file mode 100644 index 00000000..64e9a4d9 --- /dev/null +++ b/pango/pangocairo-private.h @@ -0,0 +1,78 @@ +/* Pango + * pangocairo-private.h: private symbols for the Cairo backend + * + * Copyright (C) 2000,2004 Red Hat, Inc. + * + * 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_PRIVATE_H__ +#define __PANGOCAIRO_PRIVATE_H__ + +#include <pango/pangocairo.h> +#include <pango/pango-renderer.h> + +G_BEGIN_DECLS + +#define PANGO_CAIRO_FONT_MAP_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PANGO_TYPE_CAIRO_FONT_MAP, PangoCairoFontMapIface)) + +typedef struct _PangoCairoFontMapIface PangoCairoFontMapIface; + +struct _PangoCairoFontMapIface +{ + GTypeInterface g_iface; + + void (*set_resolution) (PangoCairoFontMap *fontmap, + double dpi); + double (*get_resolution) (PangoCairoFontMap *fontmap); + PangoRenderer *(*get_renderer) (PangoCairoFontMap *fontmap); +}; + +PangoRenderer *_pango_cairo_font_map_get_renderer (PangoCairoFontMap *cfontmap); + +#define PANGO_CAIRO_FONT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PANGO_TYPE_CAIRO_FONT, PangoCairoFontIface)) + +#define PANGO_TYPE_CAIRO_FONT (pango_cairo_font_get_type ()) +#define PANGO_CAIRO_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FONT, PangoCairoFont)) +#define PANGO_IS_CAIRO_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CAIRO_FONT)) + +typedef struct _PangoCairoFont PangoCairoFont; +typedef struct _PangoCairoFontIface PangoCairoFontIface; + +struct _PangoCairoFontIface +{ + GTypeInterface g_iface; + + void (*make_current) (PangoCairoFont *font, + cairo_t *cr); +}; + +GType pango_cairo_font_get_type (void); + +void _pango_cairo_font_make_current (PangoCairoFont *font, + cairo_t *cr); + +#define PANGO_TYPE_CAIRO_RENDERER (pango_cairo_renderer_get_type()) +#define PANGO_CAIRO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_RENDERER, PangoCairoRenderer)) +#define PANGO_IS_CAIRO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CAIRO_RENDERER)) + +typedef struct _PangoCairoRenderer PangoCairoRenderer; + +GType pango_cairo_renderer_get_type (void); + +G_END_DECLS + +#endif /* __PANGOCAIRO_PRIVATE_H__ */ diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c new file mode 100644 index 00000000..305a5e08 --- /dev/null +++ b/pango/pangocairo-render.c @@ -0,0 +1,354 @@ +/* Pango + * pangocairo-render.c: Rendering routines to Cairo surfaces + * + * Copyright (C) 2004 Red Hat, Inc. + * + * 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 "pangocairo-private.h" + +typedef struct _PangoCairoRendererClass PangoCairoRendererClass; + +#define PANGO_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_RENDERER, PangoCairoRendererClass)) +#define PANGO_IS_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CAIRO_RENDERER)) +#define PANGO_CAIRO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CAIRO_RENDERER, PangoCairoRendererClass)) + +struct _PangoCairoRenderer +{ + PangoRenderer parent_instance; + + cairo_t *cr; +}; + +struct _PangoCairoRendererClass +{ + PangoRendererClass parent_class; +}; + +G_DEFINE_TYPE (PangoCairoRenderer, pango_cairo_renderer, PANGO_TYPE_RENDERER) + +static void +set_color (PangoCairoRenderer *crenderer, + PangoRenderPart part) +{ + PangoColor *color = pango_renderer_get_color (PANGO_RENDERER (crenderer), part); + + if (color) + cairo_set_rgb_color (crenderer->cr, + color->red / 65535., + color->green / 65535., + color->blue / 65535.); +} + +static void +pango_cairo_renderer_draw_glyphs (PangoRenderer *renderer, + PangoFont *font, + PangoGlyphString *glyphs, + int x, + int y) +{ + PangoCairoRenderer *crenderer = PANGO_CAIRO_RENDERER (renderer); + + /* cairo_glyph_t is 24 bytes */ +#define MAX_STACK 40 + + int i; + int x_position = 0; + cairo_glyph_t *cairo_glyphs; + cairo_glyph_t stack_glyphs[MAX_STACK]; + + cairo_save (crenderer->cr); + + set_color (crenderer, PANGO_RENDER_PART_FOREGROUND); + + if (glyphs->num_glyphs > MAX_STACK) + cairo_glyphs = g_new (cairo_glyph_t, glyphs->num_glyphs); + else + cairo_glyphs = stack_glyphs; + + for (i = 0; i < glyphs->num_glyphs; i++) + { + PangoGlyphInfo *gi = &glyphs->glyphs[i]; + + cairo_glyphs[i].index = gi->glyph; + cairo_glyphs[i].x = (double)(x + x_position + gi->geometry.x_offset) / PANGO_SCALE; + cairo_glyphs[i].y = (double)(y + gi->geometry.y_offset) / PANGO_SCALE; + + x_position += gi->geometry.width; + } + + _pango_cairo_font_make_current (PANGO_CAIRO_FONT (font), crenderer->cr); + cairo_show_glyphs (crenderer->cr, cairo_glyphs, glyphs->num_glyphs); + + if (glyphs->num_glyphs > MAX_STACK) + g_free (cairo_glyphs); + + cairo_restore (crenderer->cr); + +#undef MAX_STACK +} + +static void +pango_cairo_renderer_draw_rectangle (PangoRenderer *renderer, + PangoRenderPart part, + int x, + int y, + int width, + int height) +{ + PangoCairoRenderer *crenderer = PANGO_CAIRO_RENDERER (renderer); + + cairo_save (crenderer->cr); + + set_color (crenderer, part); + + cairo_rectangle (crenderer->cr, + (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, + (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); + cairo_fill (crenderer->cr); + + cairo_restore (crenderer->cr); +} + +/* Draws an error underline that looks like one of: + * H E H + * /\ /\ /\ /\ /\ - + * A/ \ / \ / \ A/ \ / \ | + * \ \ / \ / /D \ \ / \ | + * \ \/ C \/ / \ \/ C \ | height = HEIGHT_SQUARES * square + * \ /\ F / \ F /\ \ | + * \ / \ / \ / \ \G | + * \ / \ / \ / \ / | + * \/ \/ \/ \/ - + * B B + * |----| + * unit_width = (HEIGHT_SQUARES - 1) * square + * + * The x, y, width, height passed in give the desired bounding box; + * x/width are adjusted to make the underline a integer number of units + * wide. + */ +#define HEIGHT_SQUARES 2.5 + +static void +pango_cairo_renderer_draw_error_underline (PangoRenderer *renderer, + int x, + int y, + int width, + int height) +{ + PangoCairoRenderer *crenderer = PANGO_CAIRO_RENDERER (renderer); + cairo_t *cr = crenderer->cr; + + double square = height / HEIGHT_SQUARES; + double unit_width = (HEIGHT_SQUARES - 1) * square; + int width_units = (width + unit_width / 2) / unit_width; + double y_top, y_bottom; + int i; + + cairo_save (cr); + + set_color (crenderer, PANGO_RENDER_PART_UNDERLINE); + + x += (width - width_units * unit_width); + width = width_units * unit_width; + + cairo_new_path (cr); + + y_top = y + height; + y_bottom = y; + + /* Bottom of squiggle */ + cairo_move_to (cr, x - square / 2, y_top - square / 2); /* A */ + for (i = 0; i < width_units; i += 2) + { + double x_middle = x + (i + 1) * unit_width; + double x_right = x + (i + 2) * unit_width; + + cairo_line_to (cr, x_middle, y_bottom); /* B */ + + if (i + 1 == width_units) + /* Nothing */; + else if (i + 2 == width_units) + cairo_line_to (cr, x_right + square / 2, y_top - square / 2); /* D */ + else + cairo_line_to (cr, x_right, y_top - square); /* C */ + } + + /* Top of squiggle */ + for (i -= 2; i >= 0; i -= 2) + { + double x_left = x + i * unit_width; + double x_middle = x + (i + 1) * unit_width; + double x_right = x + (i + 2) * unit_width; + + if (i + 1 == width_units) + cairo_line_to (cr, x_middle + square / 2, y_bottom + square / 2); /* G */ + else + { + if (i + 2 == width_units) + cairo_line_to (cr, x_right, y_top); /* E */ + cairo_line_to (cr, x_middle, y_bottom + square); /* F */ + } + + cairo_line_to (cr, x_left, y_top); /* H */ + } + + cairo_close_path (cr); + cairo_fill (cr); + + cairo_restore (cr); +} + +static void +pango_cairo_renderer_init (PangoCairoRenderer *renderer) +{ +} + +static void +pango_cairo_renderer_class_init (PangoCairoRendererClass *klass) +{ + PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass); + + renderer_class->draw_glyphs = pango_cairo_renderer_draw_glyphs; + renderer_class->draw_rectangle = pango_cairo_renderer_draw_rectangle; + renderer_class->draw_error_underline = pango_cairo_renderer_draw_error_underline; +} + +static void +current_point_to_origin (cairo_t *cr) +{ + double x, y; + + cairo_current_point (cr, &x, &y); + cairo_translate (cr, x, y); +} + +/** + * pango_cairo_show_glyphs: + * @cr: a Cairo context + * @font: a #PangoFont + * @glyphs: a #PangoGlyphString + * + * Draws the glyphs in @glyphs in the specified cairo context. + * The origin of the glyphs (the left edge of the baseline) will + * be drawn at the current point of the cairo context. + * + * Since: 1.10 + **/ +void +pango_cairo_show_glyphs (cairo_t *cr, + PangoFont *font, + PangoGlyphString *glyphs) +{ + PangoFontMap *fontmap; + PangoCairoRenderer *crenderer; + PangoRenderer *renderer; + + g_return_if_fail (cr != NULL); + g_return_if_fail (PANGO_IS_CAIRO_FONT (font)); + g_return_if_fail (glyphs != NULL); + + fontmap = PANGO_FC_FONT (font)->fontmap; + renderer = _pango_cairo_font_map_get_renderer (PANGO_CAIRO_FONT_MAP (fontmap)); + crenderer = PANGO_CAIRO_RENDERER (renderer); + + cairo_save (cr); + current_point_to_origin (cr); + + crenderer->cr = cr; + pango_renderer_draw_glyphs (renderer, font, glyphs, 0, 0); + crenderer->cr = NULL; + + cairo_restore (cr); +} + +/** + * pango_cairo_show_layout_line: + * @cr: a Cairo context + * @line: a #PangoLayoutLine + * + * Draws a #PangoLayoutLine in the specified cairo context. + * The origin of the glyphs (the left edge of the line) will + * be drawn at the current point of the cairo context. + * + * Since: 1.10 + **/ +void +pango_cairo_show_layout_line (cairo_t *cr, + PangoLayoutLine *line) +{ + PangoContext *context; + PangoFontMap *fontmap; + PangoRenderer *renderer; + PangoCairoRenderer *crenderer; + + g_return_if_fail (cr != NULL); + g_return_if_fail (line != NULL); + + context = pango_layout_get_context (line->layout); + fontmap = pango_context_get_font_map (context); + renderer = _pango_cairo_font_map_get_renderer (PANGO_CAIRO_FONT_MAP (fontmap)); + crenderer = PANGO_CAIRO_RENDERER (renderer); + + cairo_save (cr); + current_point_to_origin (cr); + + crenderer->cr = cr; + pango_renderer_draw_layout_line (renderer, line, 0, 0); + crenderer->cr = NULL; + + cairo_restore (cr); +} + +/** + * pango_cairo_show_layout: + * @cr: a Cairo context + * @layout: a Pango layout + * + * Draws a #PangoLayoutLine in the specified cairo context. + * The top-left corner of the #PangoLayout will be drawn + * at the current point of the cairo context. + * + * Since: 1.10 + **/ +void +pango_cairo_show_layout (cairo_t *cr, + PangoLayout *layout) +{ + PangoContext *context; + PangoFontMap *fontmap; + PangoRenderer *renderer; + PangoCairoRenderer *crenderer; + + g_return_if_fail (cr != NULL); + g_return_if_fail (PANGO_IS_LAYOUT (layout)); + + context = pango_layout_get_context (layout); + fontmap = pango_context_get_font_map (context); + renderer = _pango_cairo_font_map_get_renderer (PANGO_CAIRO_FONT_MAP (fontmap)); + crenderer = PANGO_CAIRO_RENDERER (renderer); + + cairo_save (cr); + current_point_to_origin (cr); + + crenderer->cr = cr; + pango_renderer_draw_layout (renderer, layout, 0, 0); + crenderer->cr = NULL; + + cairo_restore (cr); +} diff --git a/pango/pangocairo.h b/pango/pangocairo.h new file mode 100644 index 00000000..f46987a0 --- /dev/null +++ b/pango/pangocairo.h @@ -0,0 +1,84 @@ +/* Pango + * pangocairo.h: + * + * Copyright (C) 1999, 2004 Red Hat, Inc. + * + * 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_H__ +#define __PANGOCAIRO_H__ + +#include <pango/pango-context.h> +#include <pango/pangofc-fontmap.h> +#include <pango/pango-layout.h> +#include <cairo.h> + +G_BEGIN_DECLS + +/** + * PangoCairoFontMap: + * + * #PangoCairoFontMap is an interface exported by font maps for + * use with Cairo. The actual type of the font map will depend + * on the particular font technology Cairo was compiled to use. + * + * Since: 1.10 + **/ +#define PANGO_TYPE_CAIRO_FONT_MAP (pango_cairo_font_map_get_type ()) +#define PANGO_CAIRO_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FONT_MAP, PangoCairoFontMap)) +#define PANGO_IS_CAIRO_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CAIRO_FONT_MAP)) + +typedef struct _PangoCairoFontMap PangoCairoFontMap; + +/* + * PangoCairoFontMap + */ +GType pango_cairo_font_map_get_type (void); + +PangoFontMap *pango_cairo_font_map_new (void); +PangoFontMap *pango_cairo_font_map_get_default (void); + +void pango_cairo_font_map_set_resolution (PangoCairoFontMap *fontmap, + double dpi); +double pango_cairo_font_map_get_resolution (PangoCairoFontMap *fontmap); +PangoContext *pango_cairo_font_map_create_context (PangoCairoFontMap *fontmap); + +/* Update a Pango context for the current state of a cairo context + */ +void pango_cairo_update_context (cairo_t *cr, + PangoContext *context); + +/* Convenience + */ +PangoLayout *pango_cairo_create_layout (cairo_t *cr); +void pango_cairo_update_layout (cairo_t *cr, + PangoLayout *layout); + +/* + * Rendering + */ +void pango_cairo_show_glyphs (cairo_t *cr, + PangoFont *font, + PangoGlyphString *glyphs); +void pango_cairo_show_layout_line (cairo_t *cr, + PangoLayoutLine *line); +void pango_cairo_show_layout (cairo_t *cr, + PangoLayout *layout); + +G_END_DECLS + +#endif /* __PANGOCAIRO_H__ */ diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c index 71c81bc2..65620384 100644 --- a/pango/pangofc-font.c +++ b/pango/pangofc-font.c @@ -26,14 +26,9 @@ #include "pango-modules.h" #include "pango-utils.h" -#include FT_TRUETYPE_TABLES_H +#include <fontconfig/fcfreetype.h> -#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6)) -#define PANGO_PIXELS_26_6(d) \ - (((d) >= 0) ? \ - ((d) + PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6 : \ - ((d) - PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6) -#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d)) +#include FT_TRUETYPE_TABLES_H typedef struct _PangoFcMetricsInfo PangoFcMetricsInfo; @@ -57,6 +52,11 @@ struct _PangoFcFontPrivate PangoFcDecoder *decoder; }; +static gboolean pango_fc_font_real_has_char (PangoFcFont *font, + gunichar wc); +static guint pango_fc_font_real_get_glyph (PangoFcFont *font, + gunichar wc); + static void pango_fc_font_finalize (GObject *object); static void pango_fc_font_set_property (GObject *object, guint prop_id, @@ -78,6 +78,9 @@ pango_fc_font_class_init (PangoFcFontClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); PangoFontClass *font_class = PANGO_FONT_CLASS (class); + + class->has_char = pango_fc_font_real_has_char; + class->get_glyph = pango_fc_font_real_get_glyph; object_class->finalize = pango_fc_font_finalize; object_class->set_property = pango_fc_font_set_property; @@ -458,6 +461,37 @@ pango_fc_font_get_metrics (PangoFont *font, return pango_font_metrics_ref (info->metrics); } +static gboolean +pango_fc_font_real_has_char (PangoFcFont *font, + gunichar wc) +{ + FcCharSet *charset; + + if (FcPatternGetCharSet (font->font_pattern, + FC_CHARSET, 0, &charset) != FcResultMatch) + return FALSE; + + return FcCharSetHasChar (charset, wc); +} + +static guint +pango_fc_font_real_get_glyph (PangoFcFont *font, + gunichar wc) +{ + FT_Face face; + FT_UInt index; + + face = pango_fc_font_lock_face (font); + + index = FcFreeTypeCharIndex (face, wc); + if (index && index <= face->num_glyphs) + return index; + + pango_fc_font_unlock_face (font); + + return 0; +} + /** * pango_fc_font_lock_face: * @font: a #PangoFcFont. diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c index 5ac4f285..9dad20b9 100644 --- a/pango/pangofc-fontmap.c +++ b/pango/pangofc-fontmap.c @@ -246,6 +246,7 @@ struct _FontsetHashKey { PangoFontDescription *desc; int x_size; int y_size; + guint flags; }; static gboolean @@ -254,6 +255,7 @@ fontset_hash_key_equal (const FontsetHashKey *key_a, { 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; else @@ -263,7 +265,7 @@ 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) ^ pango_font_description_hash (key->desc); + return (key->x_size << 16) ^ (key->y_size) ^ (key->flags) ^ pango_font_description_hash (key->desc); } static void @@ -280,6 +282,7 @@ fontset_hash_key_copy (FontsetHashKey *old) key->x_size = old->x_size; key->y_size = old->y_size; + key->flags = old->flags; key->desc = pango_font_description_copy (old->desc); return key; @@ -803,14 +806,15 @@ transformed_length (const PangoMatrix *matrix, } static gboolean -pango_fc_font_map_get_rendered_size (PangoFcFontMap *fcfontmap, - PangoContext *context, - const PangoFontDescription *desc, - int *x_size, - int *y_size) -{ - if (PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->get_rendered_size) - return PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->get_rendered_size (fcfontmap, context, desc, x_size, y_size); +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); else { int size = pango_font_description_get_size (desc); @@ -841,6 +845,8 @@ pango_fc_font_map_get_rendered_size (PangoFcFontMap *fcfontmap, retval = FALSE; } + *flags = 0; + return retval; } } @@ -865,11 +871,11 @@ pango_fc_font_map_get_patterns (PangoFontMap *fontmap, if (!language && context) language = pango_context_get_language (context); - fontset_hash = pango_fc_get_fontset_hash (fcfontmap, language); + fontset_hash = pango_fc_get_fontset_hash (fcfontmap, language); key.desc = pango_font_description_copy_static (desc); pango_font_description_unset_fields (key.desc, PANGO_FONT_MASK_SIZE); - cache = pango_fc_font_map_get_rendered_size (fcfontmap, context, desc, &key.x_size, &key.y_size); + 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; diff --git a/pango/pangofc-fontmap.h b/pango/pangofc-fontmap.h index 318ad03c..9302a701 100644 --- a/pango/pangofc-fontmap.h +++ b/pango/pangofc-fontmap.h @@ -68,6 +68,11 @@ struct _PangoFcFontMap * 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() + * @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. * * Class structure for #PangoFcFontMap. **/ @@ -82,11 +87,12 @@ struct _PangoFcFontMapClass PangoFcFont *(*new_font) (PangoFcFontMap *fontmap, FcPattern *pattern); - gboolean (*get_rendered_size) (PangoFcFontMap *fcfontmap, + gboolean (*get_render_key) (PangoFcFontMap *fcfontmap, PangoContext *context, const PangoFontDescription *desc, int *xsize, - int *ysize); + int *ysize, + guint *flags); /*< private >*/ /* Padding for future expansion */ diff --git a/pango/pangofc-private.h b/pango/pangofc-private.h index 1b42ba16..751a87f6 100644 --- a/pango/pangofc-private.h +++ b/pango/pangofc-private.h @@ -27,6 +27,13 @@ G_BEGIN_DECLS +#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6)) +#define PANGO_PIXELS_26_6(d) \ + (((d) >= 0) ? \ + ((d) + PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6 : \ + ((d) - PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6) +#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d)) + void _pango_fc_font_shutdown (PangoFcFont *fcfont); void _pango_fc_font_map_remove (PangoFcFontMap *fcfontmap, diff --git a/pango/pangoft2-private.h b/pango/pangoft2-private.h index c0b8a7e5..ac5c85a8 100644 --- a/pango/pangoft2-private.h +++ b/pango/pangoft2-private.h @@ -26,7 +26,6 @@ #include "pangoft2.h" #include "pango-renderer.h" #include <fontconfig/fontconfig.h> -#include <fontconfig/fcfreetype.h> /* Debugging... */ /*#define DEBUGGING 1*/ @@ -47,13 +46,6 @@ #define PING(printlist) #endif -#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6)) -#define PANGO_PIXELS_26_6(d) \ - (((d) >= 0) ? \ - ((d) + PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6 : \ - ((d) - PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6) -#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d)) - typedef struct _PangoFT2Font PangoFT2Font; typedef struct _PangoFT2GlyphInfo PangoFT2GlyphInfo; typedef struct _PangoFT2Renderer PangoFT2Renderer; diff --git a/pango/pangoft2.c b/pango/pangoft2.c index d0c35358..75168307 100644 --- a/pango/pangoft2.c +++ b/pango/pangoft2.c @@ -58,10 +58,6 @@ static void pango_ft2_font_get_glyph_extents (PangoFont * static FT_Face pango_ft2_font_real_lock_face (PangoFcFont *font); static void pango_ft2_font_real_unlock_face (PangoFcFont *font); -static gboolean pango_ft2_font_real_has_char (PangoFcFont *font, - gunichar wc); -static guint pango_ft2_font_real_get_glyph (PangoFcFont *font, - gunichar wc); static PangoGlyph pango_ft2_font_real_get_unknown_glyph (PangoFcFont *font, gunichar wc); @@ -263,8 +259,6 @@ pango_ft2_font_class_init (PangoFT2FontClass *class) fc_font_class->lock_face = pango_ft2_font_real_lock_face; fc_font_class->unlock_face = pango_ft2_font_real_unlock_face; - fc_font_class->has_char = pango_ft2_font_real_has_char; - fc_font_class->get_glyph = pango_ft2_font_real_get_glyph; fc_font_class->get_unknown_glyph = pango_ft2_font_real_get_unknown_glyph; } @@ -366,34 +360,6 @@ pango_ft2_font_real_unlock_face (PangoFcFont *font) { } -static gboolean -pango_ft2_font_real_has_char (PangoFcFont *font, - gunichar wc) -{ - FcCharSet *charset; - - if (FcPatternGetCharSet (font->font_pattern, - FC_CHARSET, 0, &charset) != FcResultMatch) - return FALSE; - - return FcCharSetHasChar (charset, wc); -} - -static guint -pango_ft2_font_real_get_glyph (PangoFcFont *font, - gunichar wc) -{ - FT_Face face; - FT_UInt index; - - face = pango_ft2_font_get_face ((PangoFont *)font); - index = FcFreeTypeCharIndex (face, wc); - if (index && index <= face->num_glyphs) - return index; - - return 0; -} - static PangoGlyph pango_ft2_font_real_get_unknown_glyph (PangoFcFont *font, gunichar wc) |