I've been working recently on redoing the Pango support in gnome-print;
here's a first pass at a patch.
It's actually not that conceptually different from what Jean did
with gnome_print_pango_layout_print() ... it doesn't create a new
Pango backend, but simply uses the FT2 backend and converts
PangoFont to GnomeFont when creating the GnomeGlyphList structures.
Differences:
* I've added some API so that it works the same way that I want to do
Cairo integration. This means:
- The fact that there isn't a separate backend is hidden
- The API has provisions for doing resolution optimized layout,
something that we'll need to do for Cairo though it doesn't
make sense for gnome-print.
* I've changed how PangoFont => GnomeFont works so that instead of
doing it at a "naming" level, it actually maps according to font
file.
* I've added API for drawing PangoLayoutLine and PangoGlyphString
as well as entire PangoLayouts.
* I've rewritten the drawing code from scratch to use PangoLayoutIter,
support more underline types, etc.
Other notes:
* Since this is the first time I've really touched the gnome-print
code (or even used the gnome-print APIs), if someone wants to
review the changes that would be good.
* I'd consider this patch "done" other than review comments;
it's reasonably well documented and commented and should
be pretty much complete. The one thing I can think of that
needs fixing is:
http://bugzilla.gnome.org/show_bug.cgi?id=114431
But that mostly comes up for menu-style partial-word underlines.
* The patch makes gnome-print require CVS head Pango but for a
pretty surface reason; all that is being used is the
new underline and strikethrough font metrics. It would be
pretty easy to add a configure check and fallbacks for that.
* Code is written for simplicity rather than performance; some
of the gnome_print_gsave/grestore could be optimized away.
The next thing in my sights is to get the gtkhtml and gtksourceview
(gedit) printing code using this stuff. That, I think, should be
a pretty good test for whether the API and implementation is
right.
Regards,
Owen
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/libgnomeprint/ChangeLog,v
retrieving revision 1.394
diff -u -p -u -r1.394 ChangeLog
--- ChangeLog 11 Mar 2004 21:14:21 -0000 1.394
+++ ChangeLog 4 Jun 2004 00:52:08 -0000
@@ -1,3 +1,23 @@
+Thu Jun 3 19:21:22 2004 Owen Taylor <otaylor redhat com>
+
+ * configure.in: Require version 1.5 of Pango and the
+ PangoFT2 library.
+
+ * libgnomeprint/gnome-print-pango.[ch]: Extend printing
+ API to allow printing layout lines and glyph strings
+ as well as entire layouts. Reimplement from scratch.
+
+ * libgnomeprint/gnome-fontmap.[ch]: Add a hash table from
+ filename/index to font face to the font map.
+
+ * libgnomeprint/gnome-font-face.[ch] Add
+ gnome_font_face_find_from_filename() to
+ gnome_font_find_from_filename() allow looking up faces by
+ filename. This allows us to reliably convert a PangoFont into a
+ GnomeFont.
+
+ * tests/pango.c tests/Makefile.am: Add a test case for Pango layouts
+
2004-03-11 Jody Goldberg <jody gnome org>
* configure.in : post release bump
Index: configure.in
===================================================================
RCS file: /cvs/gnome/libgnomeprint/configure.in,v
retrieving revision 1.279
diff -u -p -u -r1.279 configure.in
--- configure.in 11 Mar 2004 21:14:21 -0000 1.279
+++ configure.in 4 Jun 2004 00:52:08 -0000
@@ -132,7 +132,7 @@ dnl pkg-config checks
dnl =================
glib_modules="glib-2.0 >= 1.3.10 gobject-2.0 >= 1.3.10 gmodule-2.0 >= 1.3.10"
libart_modules="libart-2.0 >= 2.3.7"
-pango_modules="pango >= 0.21"
+pango_modules="pango >= 1.5 pangoft2 >= 1.5"
libxml2_modules="libxml-2.0 >= 2.4.23"
fontconfig_modules="fontconfig >= 1.0"
PKG_CHECK_MODULES(GP, [ $glib_modules $libart_modules $pango_modules $libxml2_modules $libbonobo_modules $fontconfig_modules ])
Index: doc/reference/libgnomeprint-docs.sgml
===================================================================
RCS file: /cvs/gnome/libgnomeprint/doc/reference/libgnomeprint-docs.sgml,v
retrieving revision 1.7
diff -u -p -u -r1.7 libgnomeprint-docs.sgml
--- doc/reference/libgnomeprint-docs.sgml 1 Feb 2004 10:18:32 -0000 1.7
+++ doc/reference/libgnomeprint-docs.sgml 4 Jun 2004 00:52:08 -0000
@@ -4,6 +4,7 @@
<!ENTITY gnome-font SYSTEM "xml/gnome-font.xml">
<!ENTITY gnome-glyphlist SYSTEM "xml/gnome-glyphlist.xml">
<!ENTITY gnome-pgl SYSTEM "xml/gnome-pgl.xml">
+<!ENTITY gnome-print-pango SYSTEM "xml/gnome-print-pango.xml">
<!ENTITY gnome-print-config SYSTEM "xml/gnome-print-config.xml">
<!ENTITY gnome-print-job SYSTEM "xml/gnome-print-job.xml">
<!ENTITY gnome-print-paper SYSTEM "xml/gnome-print-paper.xml">
@@ -62,6 +63,7 @@ for instance, the current version of GNO
&gnome-print-job;
&gnome-print-paper;
&gnome-print;
+ &gnome-print-pango;
&gnome-print-unit;
&gnome-rfont;
</part>
Index: doc/reference/libgnomeprint-sections.txt
===================================================================
RCS file: /cvs/gnome/libgnomeprint/doc/reference/libgnomeprint-sections.txt,v
retrieving revision 1.6
diff -u -p -u -r1.6 libgnomeprint-sections.txt
--- doc/reference/libgnomeprint-sections.txt 6 Jan 2003 19:06:03 -0000 1.6
+++ doc/reference/libgnomeprint-sections.txt 4 Jun 2004 00:52:08 -0000
@@ -8,6 +8,7 @@ gnome_font_face_find_closest_from_weight
gnome_font_face_find_closest_from_pango_font
gnome_font_face_find_closest_from_pango_description
gnome_font_face_find_from_family_and_style
+gnome_font_face_find_from_filename
gnome_font_face_get_font
gnome_font_face_get_font_default
gnome_font_face_get_name
@@ -70,6 +71,7 @@ gnome_font_find_closest_from_weight_slan
gnome_font_find
gnome_font_find_closest
gnome_font_find_from_full_name
+gnome_font_find_from_filename
gnome_font_find_closest_from_full_name
gnome_font_list
gnome_font_list_free
@@ -183,6 +185,20 @@ GNOME_PRINT_CONTEXT
GNOME_IS_PRINT_CONTEXT
GNOME_TYPE_PRINT_CONTEXT
gnome_print_context_get_type
+</SECTION>
+
+<SECTION>
+<FILE>gnome-print-pango</FILE>
+<TITLE>Pango Integration</TITLE>
+gnome_print_pango_font_map_new
+gnome_print_pango_get_default_font_map
+gnome_print_pango_create_context
+gnome_print_pango_update_context
+gnome_print_pango_create_layout
+gnome_print_pango_glyph_string
+gnome_print_pango_layout_line
+gnome_print_pango_layout
+gnome_print_pango_layout_print
</SECTION>
<SECTION>
Index: doc/reference/tmpl/gnome-font-face.sgml
===================================================================
RCS file: /cvs/gnome/libgnomeprint/doc/reference/tmpl/gnome-font-face.sgml,v
retrieving revision 1.2
diff -u -p -u -r1.2 gnome-font-face.sgml
--- doc/reference/tmpl/gnome-font-face.sgml 2 Jun 2002 10:27:39 -0000 1.2
+++ doc/reference/tmpl/gnome-font-face.sgml 4 Jun 2004 00:52:08 -0000
@@ -87,6 +87,16 @@ gnome-font-face
@Returns:
+<!-- ##### FUNCTION gnome_font_face_find_from_filename ##### -->
+<para>
+
+</para>
+
+ filename:
+ index_:
+ Returns:
+
+
<!-- ##### FUNCTION gnome_font_face_get_font ##### -->
<para>
Index: doc/reference/tmpl/gnome-font.sgml
===================================================================
RCS file: /cvs/gnome/libgnomeprint/doc/reference/tmpl/gnome-font.sgml,v
retrieving revision 1.3
diff -u -p -u -r1.3 gnome-font.sgml
--- doc/reference/tmpl/gnome-font.sgml 2 Jun 2002 10:27:39 -0000 1.3
+++ doc/reference/tmpl/gnome-font.sgml 4 Jun 2004 00:52:08 -0000
@@ -293,6 +293,17 @@ gnome-font
@Returns:
+<!-- ##### FUNCTION gnome_font_find_from_filename ##### -->
+<para>
+
+</para>
+
+ filename:
+ index_:
+ size:
+ Returns:
+
+
<!-- ##### FUNCTION gnome_font_find_closest_from_full_name ##### -->
<para>
Index: doc/reference/tmpl/gnome-print-pango.sgml
===================================================================
RCS file: doc/reference/tmpl/gnome-print-pango.sgml
diff -N doc/reference/tmpl/gnome-print-pango.sgml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ doc/reference/tmpl/gnome-print-pango.sgml 4 Jun 2004 00:52:08 -0000
@@ -0,0 +1,200 @@
+<!-- ##### SECTION Title ##### -->
+Pango Integration
+
+<!-- ##### SECTION Short_Description ##### -->
+Using gnome-print with Pango
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The functions in this section allow you to use gnome-print to
+draw text using the sophisticated layout and internationalization
+capabilities of the Pango library. In general, for a GNOME
+application, these are the text APIs you should be using.
+</para>
+<para>
+There are a number of different types of objects involved in
+using #Pango with gnome-print.
+</para>
+<variablelist>
+ <varlistentry>
+ <term><link linkend="PangoFontMap">PangoFontMap</link></term>
+ <listitem>
+ <para>
+ A <link linkend="PangoFontMap">PangoFontMap</link> contains
+ the information necessary to resolve abstract font names
+ to particular fonts on the system. A font map appropriate
+ for use with gnome-print is created using
+<link
+linkend="gnome-print-pango-font-map-new"><function>gnome_print_pango_font_map_new()</function></link>.
+ Normally instead of creating a new font map, you can just
+ use the global default font map returned by
+<link
+linkend="gnome-print-pango-get-default-font-map"><function>gnome_print_pango_get_default_font_map()</function></link>.
+ The only exception to this is if you need to use lower level
+ Pango APIs to customize how the font name to font lookup is
+ done, since modifying the global default font map isn't allowed.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><link linkend="PangoContext">PangoContext</link></term>
+ <listitem>
+ <para>
+ Information about doing layout for a particular output device
+ with a particular set of options is
+ encapsulated into a <link
+ linkend="PangoContext">PangoContext</link>. Contexts for
+ gnome-print are created using
+ <link
+linkend="gnome-print-pango-create-context"><function>gnome_print_pango_create_context()</function></link>
+ </para>
+ <para>
+ A Pango context created in this way is not specific to a
+ particular <link
+ linkend="GnomePrintContext">GnomePrintContext</link> but
+ before using a Pango context to do layout for a gnome-print
+ context, it's necessary to call
+ <link
+linkend="gnome-print-pango-update-context"><function>gnome_print_pango_update_context()</function></link>.
+ This function also needs to be called if when the current
+ transformation matrix changes.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><link linkend="PangoLayout">PangoLayout</link></term>
+ <listitem>
+ <para>
+ A <link linkend="PangoLayout">PangoLayout</link> holds one or more paragraphs of text
+ and encapsulates all the necessary logic needed to
+ line wrap and lay out the text. Once you have a
+ #PangoContext, you can create a layout using
+ <link linkend="pango_layout_new"><function>pango_layout_new()</function></link>.
+ </para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+<para>
+In the normal case, a <link linkend="PangoFontMap">PangoFontMap</link>
+created directly with <link
+linkend="gnome-print-pango-create-layout"><function>gnome_print_pango_create_layout()</function></link>
+is all that is needed. A simple example that uses Pango to draw a string centered
+in a page looks like:
+</para>
+
+<informalexample><programlisting>
+static void
+draw_hello_world (GnomePrintContext *gpc,
+ double page_width,
+ double page_height)
+{
+ PangoLayout *layout = gnome_print_pango_create_layout (gpc);
+ int pango_width, pango_height;
+ double width, height;
+
+ pango_layout_set_text (layout, "Hello World");
+
+ pango_layout_get_size (layout, &pango_width, &pango_height);
+ width = (double) pango_width / PANGO_SCALE;
+ height = (double) pango_height / PANGO_SCALE;
+
+ gnome_print_moveto (gpc,
+ (page_width - width) / 2,
+ (page_width - height)/ 2);
+ gnome_print_pango_layout (gpc, layout);
+
+ g_object_unref (layout);
+}
+</programlisting></informalexample>
+
+<para>
+Note the need to convert from Pango units to the floating point
+units that gnome-print uses by dividing by
+<link linkend="PANGO-SCALE-CAPS"><literal>PANGO_SCALE</literal></link>.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### FUNCTION gnome_print_pango_font_map_new ##### -->
+<para>
+
+</para>
+
+ Returns:
+
+
+<!-- ##### FUNCTION gnome_print_pango_get_default_font_map ##### -->
+<para>
+
+</para>
+
+ Returns:
+
+
+<!-- ##### FUNCTION gnome_print_pango_create_context ##### -->
+<para>
+
+</para>
+
+ fontmap:
+ Returns:
+
+
+<!-- ##### FUNCTION gnome_print_pango_update_context ##### -->
+<para>
+
+</para>
+
+ context:
+ gpc:
+
+
+<!-- ##### FUNCTION gnome_print_pango_create_layout ##### -->
+<para>
+
+</para>
+
+ gpc:
+ Returns:
+
+
+<!-- ##### FUNCTION gnome_print_pango_glyph_string ##### -->
+<para>
+
+</para>
+
+ gpc:
+ font:
+ glyphs:
+
+
+<!-- ##### FUNCTION gnome_print_pango_layout_line ##### -->
+<para>
+
+</para>
+
+ gpc:
+ line:
+
+
+<!-- ##### FUNCTION gnome_print_pango_layout ##### -->
+<para>
+
+</para>
+
+ gpc:
+ layout:
+
+
+<!-- ##### FUNCTION gnome_print_pango_layout_print ##### -->
+<para>
+
+</para>
+
+ gpc:
+ pl:
+
+
Index: libgnomeprint/gnome-font-face.c
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-font-face.c,v
retrieving revision 1.75
diff -u -p -u -r1.75 gnome-font-face.c
--- libgnomeprint/gnome-font-face.c 24 Jan 2004 22:38:14 -0000 1.75
+++ libgnomeprint/gnome-font-face.c 4 Jun 2004 00:52:08 -0000
@@ -646,6 +646,55 @@ gnome_font_face_find_from_family_and_sty
return face;
}
+/**
+ * gnome_font_face_find_from_filename:
+ * @filename: filename of a font face in the system font database
+ * @index_: index of the face within @filename. (Font formats such as
+ * TTC/TrueType Collections can have multiple fonts within
+ * a single file.
+ *
+ * Looks up the #GnomeFontFace for a particular pair of filename and
+ * index of the font within the file. The font must already be within
+ * the system font database; this can't be used to access arbitrary
+ * fonts on disk.
+ *
+ * Return value: the matching #GnomeFontFace, if any, otherwise %NULL
+ **/
+GnomeFontFace *
+gnome_font_face_find_from_filename (const guchar *filename, gint index_)
+{
+ GPFontMap * map;
+ GPFontEntry match_e;
+ GPFontEntry * e;
+
+ /* The hash table for map->filenamedict uses this GPFontEntry
+ * itself as a key but only the file/index are used as input
+ * to the hash and equal functions.
+ */
+ match_e.file = (guchar *)filename;
+ match_e.index = index_;
+
+ map = gp_fontmap_get ();
+
+ e = g_hash_table_lookup (map->filenamedict, &match_e);
+ if (!e) {
+ gp_fontmap_release (map);
+ return NULL;
+ }
+
+ if (e->face) {
+ gnome_font_face_ref (e->face);
+ gp_fontmap_release (map);
+ return e->face;
+ }
+
+ gff_face_from_entry (e);
+
+ gp_fontmap_release (map);
+
+ return (e->face);
+}
+
GnomeFontFace *
gnome_font_face_find_closest_from_pango_font (PangoFont *pfont)
{
Index: libgnomeprint/gnome-font-face.h
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-font-face.h,v
retrieving revision 1.18
diff -u -p -u -r1.18 gnome-font-face.h
--- libgnomeprint/gnome-font-face.h 6 Jan 2003 19:06:04 -0000 1.18
+++ libgnomeprint/gnome-font-face.h 4 Jun 2004 00:52:08 -0000
@@ -58,6 +58,7 @@ GnomeFontFace *gnome_font_face_find_clos
GnomeFontFace *gnome_font_face_find_closest_from_pango_font (PangoFont *pfont);
GnomeFontFace *gnome_font_face_find_closest_from_pango_description (const PangoFontDescription *desc);
GnomeFontFace *gnome_font_face_find_from_family_and_style (const guchar *family, const guchar *style);
+GnomeFontFace *gnome_font_face_find_from_filename (const guchar *filename, gint index_);
/*
* Create font
Index: libgnomeprint/gnome-font.c
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-font.c,v
retrieving revision 1.88
diff -u -p -u -r1.88 gnome-font.c
--- libgnomeprint/gnome-font.c 24 Jan 2004 22:38:14 -0000 1.88
+++ libgnomeprint/gnome-font.c 4 Jun 2004 00:52:08 -0000
@@ -348,6 +348,39 @@ gnome_font_find_closest_from_full_name (
return font;
}
+/**
+ * gnome_font_find_from_filename:
+ * @filename: filename of a font face in the system font database
+ * @index_: index of the face within @filename. (Font formats such as
+ * TTC/TrueType Collections can have multiple fonts within
+ * a single file.
+ * @size: size (in points) at which to load the font
+ *
+ * Creates a font using the filename and index of the face within the file to
+ * identify the #GnomeFontFace. The font must already be within
+ * the system font database; this can't be used to access arbitrary
+ * fonts on disk.
+ *
+ * Return value: a newly created font if the face could be located,
+ * otherwise %NULL
+ **/
+GnomeFont *
+gnome_font_find_from_filename (const guchar *filename, gint index_, gdouble size)
+{
+ GnomeFontFace *face;
+ GnomeFont *font;
+
+ face = gnome_font_face_find_from_filename (filename, index_);
+ if (!face)
+ return NULL;
+
+ font = gnome_font_face_get_font_full (face, size, NULL);
+
+ gnome_font_face_unref (face);
+
+ return font;
+}
+
/* Find the closest weight matching the family name, weight, and italic
specs. */
Index: libgnomeprint/gnome-font.h
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-font.h,v
retrieving revision 1.44
diff -u -p -u -r1.44 gnome-font.h
--- libgnomeprint/gnome-font.h 6 Jan 2003 19:06:04 -0000 1.44
+++ libgnomeprint/gnome-font.h 4 Jun 2004 00:52:08 -0000
@@ -123,8 +123,10 @@ gdouble gnome_font_get_underline_thick
GnomeFont *gnome_font_find (const guchar *name, gdouble size);
GnomeFont *gnome_font_find_closest (const guchar *name, gdouble size);
GnomeFont *gnome_font_find_from_full_name (const guchar *string);
+GnomeFont *gnome_font_find_from_filename (const guchar *filename, gint index_, gdouble size);
GnomeFont *gnome_font_find_closest_from_full_name (const guchar *string);
GnomeFont *gnome_font_find_closest_from_weight_slant (const guchar *family, GnomeFontWeight weight, gboolean italic, gdouble size);
+
/* Lists */
GList *gnome_font_list (void);
Index: libgnomeprint/gnome-fontmap.c
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-fontmap.c,v
retrieving revision 1.41
diff -u -p -u -r1.41 gnome-fontmap.c
--- libgnomeprint/gnome-fontmap.c 24 Jan 2004 22:38:14 -0000 1.41
+++ libgnomeprint/gnome-fontmap.c 4 Jun 2004 00:52:08 -0000
@@ -89,6 +89,8 @@ gp_fontmap_unref (GPFontMap * map)
g_hash_table_destroy (map->familydict);
if (map->fontdict)
g_hash_table_destroy (map->fontdict);
+ if (map->filenamedict)
+ g_hash_table_destroy (map->filenamedict);
if (map->familylist) {
g_hash_table_remove (familylist2map, map->familylist);
g_list_free (map->familylist);
@@ -335,6 +337,7 @@ gp_fontmap_load_fontconfig (GPFontMap *m
e = fcpattern_to_gp_font_entry (font);
if (e) {
g_hash_table_insert (map->fontdict, e->name, e);
+ g_hash_table_insert (map->filenamedict, e, e);
map->num_fonts++;
map->fonts = g_slist_prepend (map->fonts, e);
}
@@ -383,6 +386,23 @@ gp_fontmap_sort (GPFontMap *map)
}
}
+static guint
+filename_hash (gconstpointer v)
+{
+ const GPFontEntry *e = v;
+
+ return g_str_hash (e->file) ^ (e->index << 16);
+}
+
+static gboolean
+filename_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ const GPFontEntry *e1 = v1;
+ const GPFontEntry *e2 = v2;
+
+ return (e1->index == e2->index) && strcmp (e1->file, e2->file) == 0;
+}
static GPFontMap *
gp_fontmap_load (void)
@@ -393,6 +413,7 @@ gp_fontmap_load (void)
map->refcount = 1;
map->num_fonts = 0;
map->fontdict = g_hash_table_new (g_str_hash, g_str_equal);
+ map->filenamedict = g_hash_table_new (filename_hash, filename_equal);
map->familydict = g_hash_table_new (g_str_hash, g_str_equal);
gp_fontmap_load_fontconfig (map);
Index: libgnomeprint/gnome-fontmap.h
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-fontmap.h,v
retrieving revision 1.23
diff -u -p -u -r1.23 gnome-fontmap.h
--- libgnomeprint/gnome-fontmap.h 24 Jan 2004 22:38:14 -0000 1.23
+++ libgnomeprint/gnome-fontmap.h 4 Jun 2004 00:52:08 -0000
@@ -51,8 +51,9 @@ struct _GPFontMap {
gint refcount;
gint num_fonts;
- GHashTable *fontdict; /* Name -> FontEntry */
- GHashTable *familydict; /* Family name -> FamilyEntry */
+ GHashTable *fontdict; /* Name -> FontEntry */
+ GHashTable *familydict; /* Family name -> FamilyEntry */
+ GHashTable *filenamedict; /* File/index -> FontEntry */
GSList *fonts; /* List of FontEntries, sorted A-Z */
GSList *families; /* List of FamilyEntries, sorted A-Z */
Index: libgnomeprint/gnome-print-pango.c
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-print-pango.c,v
retrieving revision 1.1
diff -u -p -u -r1.1 gnome-print-pango.c
--- libgnomeprint/gnome-print-pango.c 11 Mar 2004 21:12:33 -0000 1.1
+++ libgnomeprint/gnome-print-pango.c 4 Jun 2004 00:52:08 -0000
@@ -1,9 +1,11 @@
/*
* gnome-print-pango.c
*
- * Copyright (C) 2003
+ * Copyright (C) 2003 Jean Bréfort <jean brefort ac-dijon fr>
+ * Copyright (C) 2004 Red Hat, Inc.
*
* Developed by Jean Bréfort <jean brefort ac-dijon fr>
+ * Rewritten by Owen Taylor <otaylor redhat com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -21,210 +23,628 @@
* Boston, MA 02111-1307, USA.
*/
-#include "gnome-print-pango.h"
+#define PANGO_ENABLE_BACKEND /* Needed to access PangoFcFont.font_pattern */
-void gnome_print_pango_layout_print (GnomePrintContext *gpc, PangoLayout* pl) {
- gint i, top, bottom;
- GnomeFont *font;
- GnomeFontFace *face;
+#include <config.h>
+
+#include <libgnomeprint/gnome-print-pango.h>
+#include <libgnomeprint/gnome-print-private.h>
+#include <libgnomeprint/gp-gc-private.h>
+
+#include <pango/pangofc-font.h>
+#include <pango/pangoft2.h>
+
+/* This function gets called to convert a matched pattern into what
+ * we'll use to actually load the font. We turn off hinting since we
+ * want metrics that are independent of scale.
+ */
+static void
+substitute_func (FcPattern *pattern, gpointer data)
+{
+ FcPatternDel (pattern, FC_HINTING);
+ FcPatternAddBool (pattern, FC_HINTING, FALSE);
+}
+
+/**
+ * gnome_print_pango_font_map_new:
+ *
+ * Creates a new #PangoFontMap object suitable for use with
+ * gnome-print. In most cases, you probably want to use
+ * gnome_print_pango_get_default_font_map () instead.
+ *
+ * Return value: a newly created #PangoFontMap object
+ **/
+PangoFontMap *
+gnome_print_pango_font_map_new (void)
+{
+ PangoFontMap *fontmap = NULL;
+ PangoFT2FontMap *ft2fontmap;
+
+ fontmap = pango_ft2_font_map_new ();
+ ft2fontmap = PANGO_FT2_FONT_MAP (fontmap);
+
+ pango_ft2_font_map_set_resolution (ft2fontmap, 72, 72);
+ pango_ft2_font_map_set_default_substitute (ft2fontmap, substitute_func, NULL, NULL);
+
+ return fontmap;
+}
+
+/**
+ * gnome_print_pango_get_default_font_map:
+ *
+ * Gets a singleton #PangoFontMap object suitable for
+ * use with gnome-print.
+ *
+ * Return value: the default #PangoFontMap object for gnome-print. The
+ * returned object is owned by gnome-print and should not be modified.
+ * (If you need to set custom options, create a new font map with
+ * gnome_print_pango_font_map_new().) The reference count is
+ * <emphasis>not</emphasis> increased.
+ **/
+PangoFontMap *
+gnome_print_pango_get_default_font_map (void)
+{
+ static PangoFontMap *fontmap = NULL;
+
+ if (!fontmap)
+ fontmap = gnome_print_pango_font_map_new ();
+
+ return fontmap;
+}
+
+/**
+ * gnome_print_pango_create_context:
+ * @fontmap: a #PangoFontMap from gnome_print_pango_get_default_font_map()
+ * or gnome_print_pango_create_font_map().
+ *
+ * Creates a new #PangoContext object for the specified fontmap.
+ *
+ * Return value: a newly created #PangoContext object
+ **/
+PangoContext *
+gnome_print_pango_create_context (PangoFontMap *fontmap)
+{
+ return pango_ft2_font_map_create_context (PANGO_FT2_FONT_MAP (fontmap));
+}
+
+/**
+ * gnome_print_pango_update_context:
+ * @context: a #PangoContext from gnome_print_pango_create_context().
+ * @gpc: a #GnomePrintContext
+ *
+ * Update a context so that layout done with it reflects the
+ * current state of @gpc. In general, every time you use a
+ * #PangoContext with a different #GnomePrintContext, or
+ * you change the transformation matrix of the #GnomePrintContext
+ * (other than pure translations) you should call this function.
+ * You also need to call pango_layout_context_changed() for any
+ * #PangoLayout objects that exit for the #PangoContext.
+ *
+ * This function currently does nothing and that isn't expected
+ * to change for gnome-print. The main benefit of calling it
+ * is that your code will be properly prepared for conversion
+ * to use with future rendering systems such as Cairo where
+ * the corresponding operation will actually do something.
+ */
+void
+gnome_print_pango_update_context (PangoContext *context,
+ GnomePrintContext *gpc)
+
+{
+ /* nothing */
+}
+
+/**
+ * gnome_print_pango_create_layout:
+ * @gpc: a #GnomePrintContext
+ *
+ * Convenience function that creates a new #PangoContext, updates
+ * it for rendering to @gpc, and then creates a #PangoLayout for
+ * that #PangoContext. Generally this function suffices for
+ * most usage of gnome-print with Pango and you don't need to
+ * deal with the #PangoContext directly.
+ *
+ * Return value: the newly created #PangoLayout. Free with
+ * g_object_unref() when you are done with it.
+ **/
+PangoLayout *
+gnome_print_pango_create_layout (GnomePrintContext *gpc)
+{
+ PangoFontMap *fontmap = gnome_print_pango_get_default_font_map ();
+ PangoContext *context = gnome_print_pango_create_context (fontmap);
+ /* gnome_print_pango_update_context (gpc, context); */
+
+ PangoLayout *layout = pango_layout_new (context);
+
+ g_object_unref (context);
+
+ return layout;
+}
+
+/* Finds the #GnomeFont corresponding to a #PangoFont. This differs
+ * from gnome_font_face_find_closest_from_pango_font() because it
+ * requires a PangoFcFont not an arbitrary font and works off the
+ * filename rather than making guesses about name correspondences.
+ */
+static GnomeFont *
+font_from_pango_font (PangoFont *font)
+{
+ PangoFcFont *fcfont;
+ FcChar8 *filename;
+ gint id;
+ gdouble size;
+
+ if (!PANGO_IS_FC_FONT (font))
+ return NULL;
+
+ fcfont = PANGO_FC_FONT (font);
+
+ if (FcPatternGetString (fcfont->font_pattern, FC_FILE, 0, &filename) != FcResultMatch)
+ return NULL;
+
+ if (FcPatternGetInteger (fcfont->font_pattern, FC_INDEX, 0, &id) != FcResultMatch)
+ return NULL;
+
+ if (FcPatternGetDouble (fcfont->font_pattern, FC_SIZE, 0, &size) != FcResultMatch)
+ return NULL;
+
+ return gnome_font_find_from_filename (filename, id, size);
+}
+
+/**
+ * gnome_print_pango_glyph_string:
+ * @gpc: a #GnomePrintContext
+ * @font: the #PangoFont that the glyphs in @glyphs are from
+ * @glyphs: a #PangoGlyphString
+ *
+ * Draws the glyphs in @glyphs into the specified #GnomePrintContext.
+ * Positioning information in @glyphs is transformed by the current
+ * transformation matrix, the glyphs are drawn in the current color,
+ * and the glyphs are positioned so that the left edge of the baseline
+ * is at the current point.
+ **/
+void
+gnome_print_pango_glyph_string (GnomePrintContext *gpc, PangoFont *font, PangoGlyphString *glyphs)
+{
GnomeGlyphList *glyph_list;
- GSList *extra_attrs_list;
- PangoFontDescription *desc;
- PangoGlyphItem *item;
- PangoRectangle logical_rect, ink_rect, rect;
- PangoLayout *layout;
- ArtDRect art_rect;
- const char *text = pango_layout_get_text (pl);
- gboolean foreground_set;
- guint16 foreground_red = 0, foreground_green = 0, foreground_blue = 0;
- gboolean background_set;
- guint16 background_red = 0, background_green = 0, background_blue = 0;
- PangoLayoutIter *iter = pango_layout_get_iter (pl);
- gdouble scale[6] = {1., 0., 0., 1., 0., 0.};
- gdouble space;
- gboolean strikethrough, underline, slant;
-#if 0
- GtkTextAppearance* appearance;
-#endif
- int underline_type;
- PangoAlignment align = pango_layout_get_alignment (pl);
+ GnomeFont *gnome_font;
+ gint x_off = 0;
+ gint i;
- pango_layout_get_extents (pl, NULL, &logical_rect);
- gnome_print_gsave (gpc);
- switch (align) {
- case PANGO_ALIGN_CENTER:
- gnome_print_translate (gpc, - (double) logical_rect.width / 2., 0.);
- break;
- case PANGO_ALIGN_RIGHT:
- gnome_print_translate (gpc, - (double) logical_rect.width, 0.);
- break;
- default:
- break;
+ gnome_font = font_from_pango_font (font);
+ if (!gnome_font)
+ return;
+
+ glyph_list = gnome_glyphlist_new ();
+
+ gnome_glyphlist_font (glyph_list, gnome_font);
+ g_object_unref (gnome_font);
+
+ gnome_glyphlist_color (glyph_list, gp_gc_get_rgba (gpc->gc));
+
+ for (i = 0; i < glyphs->num_glyphs; i++) {
+ PangoGlyphInfo *gi = &glyphs->glyphs[i];
+ int x = x_off + gi->geometry.x_offset;
+ int y = gi->geometry.y_offset;
+
+ gnome_glyphlist_moveto (glyph_list,
+ (gdouble) x / PANGO_SCALE, (gdouble) y / PANGO_SCALE);
+ gnome_glyphlist_glyph (glyph_list, gi->glyph);
+
+ x_off += glyphs->glyphs[i].geometry.width;
}
- do {
- item = pango_layout_iter_get_run (iter);
- if (!item) break;
- strikethrough = underline = foreground_set = background_set = FALSE;
-#if 0
- appearance = NULL;
-#endif
- desc = pango_font_describe (item->item->analysis.font);
- face = gnome_font_face_find_closest_from_weight_slant (
- pango_font_description_get_family (desc),
- (GnomeFontWeight) pango_font_description_get_weight (desc),
- (pango_font_description_get_style (desc) != PANGO_STYLE_NORMAL));
- font = gnome_font_face_get_font (face,
- pango_font_description_get_size(desc) / PANGO_SCALE, 72, 72);
- if (font == NULL)
- {
- g_warning ("No font file for font.");
+
+ gnome_print_glyphlist (gpc, glyph_list);
+ gnome_glyphlist_unref (glyph_list);
+}
+
+typedef struct
+{
+ PangoUnderline uline;
+ gboolean strikethrough;
+ PangoColor *fg_color;
+ PangoColor *bg_color;
+ PangoRectangle *shape_ink_rect;
+ PangoRectangle *shape_logical_rect;
+ gint rise;
+} ItemProperties;
+
+/* Retrieves the properties we care about for a single run in an
+ * easily accessible structure rather than a list of attributes
+ */
+static void
+get_item_properties (PangoItem *item, ItemProperties *properties)
+{
+ GSList *tmp_list = item->analysis.extra_attrs;
+
+ properties->uline = PANGO_UNDERLINE_NONE;
+ properties->strikethrough = FALSE;
+ properties->fg_color = NULL;
+ properties->bg_color = NULL;
+ properties->rise = 0;
+ properties->shape_ink_rect = NULL;
+ properties->shape_logical_rect = NULL;
+
+ while (tmp_list) {
+ PangoAttribute *attr = tmp_list->data;
+
+ switch (attr->klass->type) {
+ case PANGO_ATTR_UNDERLINE:
+ properties->uline = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_STRIKETHROUGH:
+ properties->strikethrough = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_FOREGROUND:
+ properties->fg_color = &((PangoAttrColor *)attr)->color;
+ break;
+
+ case PANGO_ATTR_BACKGROUND:
+ properties->bg_color = &((PangoAttrColor *)attr)->color;
+ break;
+
+ case PANGO_ATTR_SHAPE:
+ properties->shape_logical_rect = &((PangoAttrShape *)attr)->logical_rect;
+ properties->shape_ink_rect = &((PangoAttrShape *)attr)->ink_rect;
+ break;
+
+ case PANGO_ATTR_RISE:
+ properties->rise = ((PangoAttrInt *)attr)->value;
+ break;
+
+ default:
+ break;
+ }
+ tmp_list = tmp_list->next;
+ }
+}
+
+/*
+ * Couple of helper functions to work in Pango units rather than doubles
+ */
+static void
+rect_filled (GnomePrintContext *gpc, gint x, gint y, gint width, gint height)
+{
+ gnome_print_rect_filled (gpc,
+ (gdouble) x / PANGO_SCALE, (gdouble) y / PANGO_SCALE,
+ (gdouble) width / PANGO_SCALE, (gdouble) height / PANGO_SCALE);
+}
+
+static void
+translate (GnomePrintContext *gpc, gint x, gint y)
+{
+ gnome_print_translate (gpc,
+ (gdouble) x / PANGO_SCALE, (gdouble) y / PANGO_SCALE);
+}
+
+static void
+moveto (GnomePrintContext *gpc, gint x, gint y)
+{
+ gnome_print_moveto (gpc,
+ (gdouble) x / PANGO_SCALE, (gdouble) y / PANGO_SCALE);
+}
+
+/* It's easiest for us to work in coordinates where the current point (which
+ * determines the origin of drawing for the #PangoGlyphString, #PangoLayout,
+ * or #PangoLayoutLine) is at the origin. This function changes the CTM to
+ * that coordinate system.
+ */
+static void
+current_point_to_origin (GnomePrintContext *gpc)
+{
+ const gdouble *ctm;
+ const ArtPoint *cp;
+ gdouble affine[6];
+
+ ctm = gp_gc_get_ctm (gpc->gc);
+ cp = gp_gc_get_currentpoint (gpc->gc);
+
+ affine[0] = ctm[0];
+ affine[1] = ctm[1];
+ affine[2] = ctm[2];
+ affine[3] = ctm[3];
+ affine[4] = cp->x;
+ affine[5] = cp->y;
+
+ gp_gc_setmatrix (gpc->gc, affine);
+}
+
+/* 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
+draw_error_underline (GnomePrintContext *gpc, gdouble x, gdouble y, gdouble width, gdouble height)
+{
+ gdouble square = height / HEIGHT_SQUARES;
+ gdouble unit_width = (HEIGHT_SQUARES - 1) * square;
+ gint width_units = (width + unit_width / 2) / unit_width;
+ gdouble y_top, y_bottom;
+ gint i;
+
+ x += (width - width_units * unit_width);
+ width = width_units * unit_width;
+
+ gnome_print_newpath (gpc);
+
+ y_top = y + height;
+ y_bottom = y;
+
+ /* Bottom of squiggle */
+ gnome_print_moveto (gpc, x - square / 2, y_top - square / 2); /* A */
+ for (i = 0; i < width_units; i += 2) {
+ gdouble x_middle = x + (i + 1) * unit_width;
+ gdouble x_right = x + (i + 2) * unit_width;
+
+ gnome_print_lineto (gpc, x_middle, y_bottom); /* B */
+
+ if (i + 1 == width_units)
+ /* Nothing */;
+ else if (i + 2 == width_units)
+ gnome_print_lineto (gpc, x_right + square / 2, y_top - square / 2); /* D */
+ else
+ gnome_print_lineto (gpc, x_right, y_top - square); /* C */
+ }
+
+ /* Top of squiggle */
+ for (i -= 2; i >= 0; i -= 2) {
+ gdouble x_left = x + i * unit_width;
+ gdouble x_middle = x + (i + 1) * unit_width;
+ gdouble x_right = x + (i + 2) * unit_width;
+
+ if (i + 1 == width_units)
+ gnome_print_lineto (gpc, x_middle + square / 2, y_bottom + square / 2); /* G */
+ else {
+ if (i + 2 == width_units)
+ gnome_print_lineto (gpc, x_right, y_top); /* E */
+ gnome_print_lineto (gpc, x_middle, y_bottom + square); /* F */
+ }
+
+ gnome_print_lineto (gpc, x_left, y_top); /* H */
+ }
+
+ gnome_print_closepath (gpc);
+ gnome_print_fill (gpc);
+}
+
+/* Helper function to draw the underline for one layout run; the descent field gives
+ * the descent of the ink for the actual text in the layout run.
+ */
+static void
+draw_underline (GnomePrintContext *gpc, PangoFontMetrics *metrics, PangoUnderline uline, gint x, gint width, gint descent)
+{
+ gint underline_thickness = pango_font_metrics_get_underline_thickness (metrics);
+ gint underline_position = pango_font_metrics_get_underline_position (metrics);
+ gint y_off = 0; /* Quiet GCC */
+
+ switch (uline) {
+ case PANGO_UNDERLINE_NONE:
+ g_assert_not_reached();
+ break;
+ case PANGO_UNDERLINE_SINGLE:
+ y_off = underline_position - underline_thickness;
+ break;
+ case PANGO_UNDERLINE_DOUBLE:
+ y_off = underline_position - underline_thickness;
+ break;
+ case PANGO_UNDERLINE_LOW:
+ y_off = - 2 * underline_thickness - descent;
+ break;
+ case PANGO_UNDERLINE_ERROR:
+ draw_error_underline (gpc,
+ (gdouble) x / PANGO_SCALE,
+ (gdouble) (underline_position - 3 * underline_thickness) / PANGO_SCALE,
+ (gdouble) width / PANGO_SCALE,
+ (gdouble) (3 * underline_thickness) / PANGO_SCALE);
+ return;
+ }
+
+ rect_filled (gpc,
+ x, y_off,
+ width, underline_thickness);
+
+ if (uline == PANGO_UNDERLINE_DOUBLE)
+ {
+ rect_filled (gpc,
+ x, y_off - 2 * underline_thickness,
+ width, underline_thickness);
+ }
+}
+
+/* Helper function to draw a strikethrough for one layout run
+ */
+static void
+draw_strikethrough (GnomePrintContext *gpc, PangoFontMetrics *metrics, gint x, gint width)
+{
+ gint strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics);
+ gint strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics);
+
+ rect_filled (gpc,
+ x, strikethrough_position - strikethrough_thickness,
+ width, strikethrough_thickness);
+}
+
+/**
+ * gnome_print_pango_layout_line:
+ * @gpc: a #GnomePrintContext
+ * @line: a #PangoLayoutLine
+ *
+ * Draws the text in @line into the specified #GnomePrintContext. The
+ * text is drawn in the current color unless that has been overridden
+ * by attributes set on the layout and the glyphs are positioned so
+ * that the left edge of the baseline is at the current point.
+ **/
+void
+gnome_print_pango_layout_line (GnomePrintContext *gpc, PangoLayoutLine *line)
+{
+ GSList *tmp_list = line->runs;
+ PangoRectangle overall_rect;
+ PangoRectangle logical_rect;
+ PangoRectangle ink_rect;
+ gint x_off = 0;
+
+ gnome_print_gsave (gpc);
+
+ current_point_to_origin (gpc);
+
+ pango_layout_line_get_extents (line, NULL, &overall_rect);
+
+ while (tmp_list) {
+ ItemProperties properties;
+ PangoLayoutRun *run = tmp_list->data;
+
+ tmp_list = tmp_list->next;
+
+ get_item_properties (run->item, &properties);
+
+ if (properties.shape_logical_rect) {
+ x_off += properties.shape_logical_rect->width;
continue;
}
- glyph_list = gnome_glyphlist_new ();
- extra_attrs_list = item->item->analysis.extra_attrs;
- top = pango_layout_iter_get_baseline(iter) / PANGO_SCALE;
- pango_layout_iter_get_char_extents (iter, &logical_rect);
- bottom = 0;
- while (extra_attrs_list)
- {
- PangoAttribute *attr = extra_attrs_list->data;
- PangoAttrType attr_type = attr->klass->type;
- switch (attr_type) {
- case PANGO_ATTR_STYLE:
- g_warning("style");
- break;
- case PANGO_ATTR_RISE:
- bottom = ((PangoAttrInt *) attr)->value / PANGO_SCALE;
- break;
- case PANGO_ATTR_FOREGROUND:
- foreground_set = TRUE;
- foreground_red = ((PangoAttrColor *) attr)->color.red;
- foreground_green = ((PangoAttrColor *) attr)->color.green;
- foreground_blue = ((PangoAttrColor *) attr)->color.blue;
- break;
- case PANGO_ATTR_BACKGROUND:
- background_set = TRUE;
- background_red = ((PangoAttrColor *) attr)->color.red;
- background_green = ((PangoAttrColor *) attr)->color.green;
- background_blue = ((PangoAttrColor *) attr)->color.blue;
- break;
- case PANGO_ATTR_UNDERLINE:
- underline_type = ((PangoAttrInt *) attr)->value;
- underline = TRUE;
- break;
- case PANGO_ATTR_STRIKETHROUGH:
- strikethrough = TRUE;
- break;
- case PANGO_ATTR_SHAPE:
- g_warning ("Pango attribute PANGO_ATTR_SHAPE not supported");
- break;
- case PANGO_ATTR_SCALE:
- g_warning ("Pango attribute PANGO_ATTR_SCALE not supported");
- break;
- default:
-#if 0
- if (attr_type == gtk_text_attr_appearance_type)
- appearance = &((GtkTextAttrAppearance *)attr)->appearance;
-#endif
- break;
- }
- extra_attrs_list = extra_attrs_list->next;
- }
- pango_layout_iter_get_run_extents (iter, &ink_rect, &logical_rect);
- layout = pango_layout_new (pango_layout_get_context (pl));
- pango_layout_set_font_description (layout, desc);
- pango_layout_set_text (layout, text + item->item->offset, item->item->length);
- pango_layout_get_extents (layout, &rect, NULL);
- g_object_unref (layout);
- if (background_set)
- {
- gnome_print_setrgbcolor (gpc, (float) background_red / 0xFFFF,
- (float) background_green / 0xFFFF, (float) background_blue / 0xFFFF);
- gnome_print_rect_filled (gpc, logical_rect.x / PANGO_SCALE,
- logical_rect.y / PANGO_SCALE,
- (float) logical_rect.width / PANGO_SCALE,
- (float) + logical_rect.height / PANGO_SCALE);
- }
- gnome_print_setrgbcolor (gpc, (float) foreground_red / 0xFFFF,
- (float) foreground_green / 0xFFFF, (float) foreground_blue / 0xFFFF);
- if (strikethrough
-#if 0
- || (appearance && appearance->strikethrough)
-#endif
- ) {
- gnome_print_setlinewidth (gpc, .75);
- gnome_print_setlinecap (gpc, 0);
- gnome_print_moveto (gpc, logical_rect.x / PANGO_SCALE,
- - bottom + top - (0.22 * logical_rect.height) / PANGO_SCALE);
- gnome_print_lineto (gpc, (logical_rect.x + logical_rect.width) / PANGO_SCALE,
- - bottom + top - (0.22 * logical_rect.height) / PANGO_SCALE);
- gnome_print_stroke (gpc);
- }
- if (underline) {
- gnome_print_setlinewidth (gpc, .75);
- gnome_print_setlinecap (gpc, 0);
- switch (underline_type) {
- case PANGO_UNDERLINE_NONE:
- break;
- case PANGO_UNDERLINE_DOUBLE:
- gnome_print_moveto (gpc, logical_rect.x / PANGO_SCALE,
- - bottom + top + 3.0);
- gnome_print_lineto (gpc, (logical_rect.x + logical_rect.width) / PANGO_SCALE,
- - bottom + top + 3.0);
- gnome_print_stroke (gpc);
- /* Fall through */
- case PANGO_UNDERLINE_SINGLE:
- gnome_print_moveto (gpc, logical_rect.x / PANGO_SCALE,
- - bottom + top + 1.0);
- gnome_print_lineto (gpc, (logical_rect.x + logical_rect.width) / PANGO_SCALE,
- - bottom + top + 1.0);
- gnome_print_stroke (gpc);
- break;
- case PANGO_UNDERLINE_LOW:
- gnome_print_moveto (gpc, logical_rect.x / PANGO_SCALE,
- - bottom + top + logical_rect.y / PANGO_SCALE + 1.0);
- gnome_print_lineto (gpc, (logical_rect.x + logical_rect.width) / PANGO_SCALE,
- - bottom + top + logical_rect.y / PANGO_SCALE + 1.0);
- gnome_print_stroke (gpc);
- break;
- }
- }
- gnome_print_moveto (gpc, logical_rect.x / PANGO_SCALE,
- - bottom + top);
- gnome_glyphlist_font (glyph_list, font);
- for (i = 0; i < item->glyphs->num_glyphs; i++)
- {
- gnome_glyphlist_glyph (glyph_list, item->glyphs->glyphs[i].glyph);
- }
- gnome_glyphlist_bbox (glyph_list, scale, 0, &art_rect);
- slant = (ink_rect.width / PANGO_SCALE)> (art_rect.x1 - art_rect.x0);
- if (item->glyphs->num_glyphs > 1) {
- space = (((double) ink_rect.width / PANGO_SCALE - art_rect.x1 + art_rect.x0) - (slant)? top * 0.3: 0.)
- / (item->glyphs->num_glyphs - 1);
- gnome_glyphlist_unref (glyph_list);
- glyph_list = gnome_glyphlist_new ();
- gnome_print_moveto (gpc, logical_rect.x / PANGO_SCALE,
- - bottom + top);
- gnome_glyphlist_font (glyph_list, font);
- gnome_glyphlist_letterspace (glyph_list, space);
- for (i = 0; i < item->glyphs->num_glyphs; i++)
- {
- gnome_glyphlist_glyph (glyph_list, item->glyphs->glyphs[i].glyph);
- }
- }
- gnome_print_gsave(gpc);
- if (slant) {
- /*simulate slanted font*/
- double matrix [6] = {
- 1.,
- 0., .15, -1., .0, .0};
- gnome_print_concat (gpc, matrix);
- } else
- gnome_print_scale(gpc, 1., -1.);
- gnome_print_glyphlist (gpc, glyph_list);
- gnome_print_grestore(gpc);
- gnome_glyphlist_unref (glyph_list);
- } while (pango_layout_iter_next_run (iter));
+
+ gnome_print_gsave (gpc);
+
+ translate (gpc, x_off, properties.rise);
+ gnome_print_moveto (gpc, 0, 0);
+
+ if (properties.uline == PANGO_UNDERLINE_NONE && !properties.strikethrough)
+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
+ NULL, &logical_rect);
+ else
+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
+ &ink_rect, &logical_rect);
+
+ if (properties.bg_color) {
+ if (!properties.fg_color)
+ gnome_print_gsave (gpc);
+
+ gnome_print_setrgbcolor (gpc,
+ (gdouble) properties.bg_color->red / 0xFFFF,
+ (gdouble) properties.bg_color->green / 0xFFFF,
+ (gdouble) properties.bg_color->blue / 0xFFFF);
+
+ rect_filled (gpc,
+ logical_rect.x, - overall_rect.y - overall_rect.height,
+ logical_rect.width, overall_rect.height);
+
+ if (!properties.fg_color)
+ gnome_print_grestore (gpc);
+ }
+
+ if (properties.fg_color) {
+ gnome_print_setrgbcolor (gpc,
+ (gdouble) properties.fg_color->red / 0xFFFF,
+ (gdouble) properties.fg_color->green / 0xFFFF,
+ (gdouble) properties.fg_color->blue / 0xFFFF);
+ }
+
+ gnome_print_pango_glyph_string (gpc, run->item->analysis.font, run->glyphs);
+
+ if (properties.uline != PANGO_UNDERLINE_NONE || properties.strikethrough) {
+ PangoFontMetrics *metrics = pango_font_get_metrics (run->item->analysis.font,
+ run->item->analysis.language);
+
+ if (properties.uline != PANGO_UNDERLINE_NONE)
+ draw_underline (gpc, metrics,
+ properties.uline,
+ ink_rect.x,
+ ink_rect.width,
+ ink_rect.y + ink_rect.height);
+
+ if (properties.strikethrough)
+ draw_strikethrough (gpc, metrics,
+ ink_rect.x,
+ ink_rect.width);
+
+ pango_font_metrics_unref (metrics);
+ }
+
+ gnome_print_grestore (gpc);
+
+ x_off += logical_rect.width;
+ }
+
+ gnome_print_grestore (gpc);
+}
+
+/**
+ * gnome_print_pango_layout:
+ * @gpc: a #GnomePrintContext
+ * @layout: a #PangoLayout
+ *
+ * Draws the text in @layout into the specified #GnomePrintContext. The
+ * text is drawn in the current color unless that has been overridden
+ * by attributes set on the layout and the glyphs are positioned so
+ * that the left edge of the baseline is at the current point.
+ **/
+void
+gnome_print_pango_layout (GnomePrintContext *gpc, PangoLayout *layout)
+{
+ PangoLayoutIter *iter;
+
+ g_return_if_fail (GNOME_IS_PRINT_CONTEXT (gpc));
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ gnome_print_gsave (gpc);
+
+ current_point_to_origin (gpc);
+
+ iter = pango_layout_get_iter (layout);
+
+ do {
+ PangoRectangle logical_rect;
+ PangoLayoutLine *line;
+ int baseline;
+
+ line = pango_layout_iter_get_line (iter);
+
+ pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+ baseline = pango_layout_iter_get_baseline (iter);
+
+ moveto (gpc, logical_rect.x, - baseline);
+ gnome_print_pango_layout_line (gpc, line);
+
+ } while (pango_layout_iter_next_line (iter));
+
pango_layout_iter_free (iter);
+
+ gnome_print_grestore (gpc);
+}
+
+/**
+ * gnome_print_pango_layout_print:
+ * @gpc: a #GnomePrintContext
+ * @pl: the #PangoLayout to print
+ *
+ * Draws the text in @pl into the specified #GnomePrintContext. The
+ * text is drawn in the current color unless that has been overridden
+ * by attributes set on the layout and the glyphs are positioned so
+ * that the left edge of the baseline is at the point (0, 0). This function
+ * is obsolete; use gnome_print_pango_layout() instead.
+ **/
+void
+gnome_print_pango_layout_print (GnomePrintContext *gpc, PangoLayout* pl)
+{
+ gnome_print_gsave (gpc);
+ gnome_print_moveto (gpc, 0, 0);
+ gnome_print_pango_layout (gpc, pl);
gnome_print_grestore (gpc);
}
Index: libgnomeprint/gnome-print-pango.h
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-print-pango.h,v
retrieving revision 1.1
diff -u -p -u -r1.1 gnome-print-pango.h
--- libgnomeprint/gnome-print-pango.h 11 Mar 2004 21:12:33 -0000 1.1
+++ libgnomeprint/gnome-print-pango.h 4 Jun 2004 00:52:08 -0000
@@ -1,9 +1,11 @@
/*
* gnome-print-pango.h
*
- * Copyright (C) 2003
+ * Copyright (C) 2003 Jean Bréfort <jean brefort ac-dijon fr>
+ * Copyright (C) 2004 Red Hat, Inc.
*
* Developed by Jean Bréfort <jean brefort ac-dijon fr>
+ * Rewritten by Owen Taylor <otaylor redhat com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -29,6 +31,20 @@
G_BEGIN_DECLS
+PangoFontMap *gnome_print_pango_font_map_new (void);
+PangoFontMap *gnome_print_pango_get_default_font_map (void);
+PangoContext *gnome_print_pango_create_context (PangoFontMap *fontmap);
+void gnome_print_pango_update_context (PangoContext *context,
+ GnomePrintContext *gpc);
+PangoLayout *gnome_print_pango_create_layout (GnomePrintContext *gpc);
+
+void gnome_print_pango_glyph_string (GnomePrintContext *gpc, PangoFont *font, PangoGlyphString *glyphs);
+void gnome_print_pango_layout_line (GnomePrintContext *gpc, PangoLayoutLine *line);
+void gnome_print_pango_layout (GnomePrintContext *gpc, PangoLayout *layout);
+
+
+/* Deprecated interface
+ */
void gnome_print_pango_layout_print (GnomePrintContext *gpc, PangoLayout* pl);
G_END_DECLS
Index: tests/Makefile.am
===================================================================
RCS file: /cvs/gnome/libgnomeprint/tests/Makefile.am,v
retrieving revision 1.32
diff -u -p -u -r1.32 Makefile.am
--- tests/Makefile.am 6 Aug 2003 08:03:43 -0000 1.32
+++ tests/Makefile.am 4 Jun 2004 00:52:08 -0000
@@ -2,7 +2,7 @@ SUBDIRS = files output tools
AM_CFLAGS=$(WARN_CFLAGS)
-noinst_PROGRAMS = generate gpa-test fonts simple
+noinst_PROGRAMS = generate gpa-test fonts simple pango
INCLUDES = \
-I$(top_srcdir) \
@@ -21,6 +21,10 @@ generate_LDADD = $(print_libs)
simple_SOURCES = simple.c
simple_LDFLAGS =
simple_LDADD = $(print_libs)
+
+pango_SOURCES = pango.c
+pango_LDFLAGS =
+pango_LDADD = $(print_libs)
EXTRA_DIST = quit.txt run-test.pl quit.txt
Index: tests/pango.c
===================================================================
RCS file: tests/pango.c
diff -N tests/pango.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/pango.c 4 Jun 2004 00:52:08 -0000
@@ -0,0 +1,179 @@
+/*
+ * This test program tests drawing a PangoLayout to a Postscript or PDF file
+ *
+ * Assembled from other tests by Owen Taylor <otaylor redhat com>
+ */
+#include <libgnomeprint/gnome-print.h>
+#include <libgnomeprint/gnome-print-job.h>
+#include <libgnomeprint/gnome-print-pango.h>
+
+#include <popt.h>
+
+#define TOP_MARGIN 36.
+#define LEFT_MARGIN 72.
+#define RIGHT_MARGIN 72.
+
+static char *prog_name;
+static const char *input_file;
+static char *text;
+static int len;
+static gchar* options_font = NULL;
+static gboolean options_markup = FALSE;
+static gchar* options_output = NULL;
+static gboolean options_pdf = FALSE;
+static int options_rotate = 0;
+
+double page_width, page_height;
+double margin_left, margin_right, margin_top, margin_bottom;
+
+static poptContext popt;
+
+static const struct poptOption options[] = {
+ { "markup", 'm', POPT_ARG_NONE, &options_markup, 0,
+ "Input uses Pango markup", NULL},
+ { "font", 'f', POPT_ARG_STRING, &options_font, 0,
+ "Specify the font", NULL},
+ { "output", 'o', POPT_ARG_STRING, &options_output, 0,
+ "Specify the output file", NULL},
+ { "pdf", 'p', POPT_ARG_NONE, &options_pdf, 0,
+ "Generate a pdf file instead of a Postscript one", NULL},
+ { "rotate", 'r', POPT_ARG_INT, &options_rotate, 0,
+ "Angle at which to rotate results" },
+ POPT_AUTOHELP
+ { NULL }
+};
+
+static void
+fail (const char *format, ...)
+{
+ const char *msg;
+
+ va_list vap;
+ va_start (vap, format);
+ msg = g_strdup_vprintf (format, vap);
+ g_printerr ("%s: %s\n", prog_name, msg);
+
+ exit (1);
+}
+
+static void
+my_draw (GnomePrintContext *gpc)
+{
+ PangoLayout *layout;
+ int width, height;
+ gnome_print_beginpage (gpc, "1");
+
+ layout = gnome_print_pango_create_layout (gpc);
+ if (options_font) {
+ PangoFontDescription *desc = pango_font_description_from_string (options_font);
+ pango_layout_set_font_description (layout, desc);
+ pango_font_description_free (desc);
+ }
+
+ pango_layout_set_width (layout, (page_width - LEFT_MARGIN - RIGHT_MARGIN) * PANGO_SCALE);
+ if (options_markup)
+ pango_layout_set_markup (layout, text, len);
+ else
+ pango_layout_set_text (layout, text, len);
+ pango_layout_get_size (layout, &width, &height);
+
+ gnome_print_translate (gpc, page_width / 2, page_height / 2);
+ gnome_print_rotate (gpc, options_rotate);
+ gnome_print_translate (gpc,
+ - (double) width / (2 * PANGO_SCALE), (double) height / (2 * PANGO_SCALE));
+
+ gnome_print_moveto (gpc, 0, 0);
+ gnome_print_pango_layout (gpc, layout);
+ g_object_unref (layout);
+
+ gnome_print_showpage (gpc);
+}
+
+static void
+my_print (void)
+{
+ GnomePrintJob *job;
+ GnomePrintContext *gpc;
+ GnomePrintConfig *config;
+ gchar *out_file;
+
+ job = gnome_print_job_new (NULL);
+ gpc = gnome_print_job_get_context (job);
+ config = gnome_print_job_get_config (job);
+
+ if (options_pdf) {
+ if (!gnome_print_config_set (config, "Printer", "PDF"))
+ fail ("Could not set the printer to PDF\n");
+ } else {
+ gnome_print_config_set (config, "Printer", "GENERIC");
+ }
+
+ out_file = options_output ? g_strdup (options_output) : g_strdup_printf ("o.%s", options_pdf ? "pdf" : "ps");
+ gnome_print_job_print_to_file (job, out_file);
+ g_free (out_file);
+
+ gnome_print_config_set (config, GNOME_PRINT_KEY_PAPER_SIZE, "USLetter");
+
+ /* Layout size */
+ gnome_print_job_get_page_size (job, &page_width, &page_height);
+
+ my_draw (gpc);
+
+ gnome_print_job_close (job);
+ gnome_print_job_print (job);
+
+ g_object_unref (G_OBJECT (config));
+ g_object_unref (G_OBJECT (gpc));
+ g_object_unref (G_OBJECT (job));
+}
+
+static void
+usage (gchar *error)
+{
+ if (error)
+ g_printerr ("Error: %s\n\n", error);
+
+ if (error)
+ poptPrintHelp (popt, stderr, 0);
+ else
+ poptPrintHelp (popt, stdout, 0);
+
+ exit (-1);
+}
+
+int
+main (int argc, char * argv[])
+{
+ GError *error = NULL;
+ int ret;
+
+ g_type_init ();
+
+ prog_name = g_path_get_basename (argv[0]);
+
+ popt = poptGetContext ("pango", argc, (const char **)argv, options, 0);
+
+ ret = poptGetNextOpt (popt);
+ if (ret != -1) {
+ usage (NULL);
+ }
+
+ input_file = poptGetArg (popt);
+ if (!input_file)
+ usage ("Input file not specified");
+
+ if (!g_file_get_contents (input_file, &text, &len, &error))
+ fail ("%s\n", error->message);
+ if (!g_utf8_validate (text, len, NULL))
+ fail ("Text is not valid UTF-8");
+
+ /* Make sure we have valid markup
+ */
+ if (options_markup &&
+ !pango_parse_markup (text, -1, 0, NULL, NULL, NULL, &error))
+ fail ("Cannot parse input as markup: %s", error->message);
+
+ my_print ();
+
+ return 0;
+}
Attachment:
signature.asc
Description: This is a digitally signed message part