Embedding font data



Hi,

As I said in December, I need methods to download font data (i.e. font
files in memory) to gnome-print. Attached is a patch to implement this.
I have tested it with the print-preview in gpdf and I've written a test
program using the print job (and hence print-meta) with ps and pdf
printers.

Comments?

Thanks,
	Martin
? OOBR
? cscope.files
? cscope.out
? tests/NimbusRomNo9L-ReguItal.pfb
? tests/font-embedding
? tests/font-embedding.c
cvs server: Diffing .
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/libgnomeprint/ChangeLog,v
retrieving revision 1.312
diff -u -r1.312 ChangeLog
--- ChangeLog	13 Mar 2003 21:50:03 -0000	1.312
+++ ChangeLog	14 Mar 2003 16:46:06 -0000
@@ -1,3 +1,37 @@
+2003-03-14  Martin Kretzschmar  <m_kretzschmar gmx net>
+
+	* libgnomeprint/gnome-font-private.h: add fields to GnomeFontFace
+	for storing font data
+
+	* libgnomeprint/gnome-font-face.c (gnome_font_face_finalize)
+	(gnome_font_face_download, gff_unlink_temp_file)
+	(gff_write_temp_data_file, gff_font_entry_type_from_data):
+	implement font embedding
+	(gff_entry_fill_in_face, gnome_font_face_find)
+	(gnome_font_face_find_closest): rename gff_face_from_entry to
+	gff_entry_fill_in_face which is what it does
+
+	* libgnomeprint/gnome-font-face.h: add prototype for
+	gnome_font_face_download guarded by _UNSTABLE_API
+
+	* libgnomeprint/gnome-print-meta.c (METAFILE_SIGNATURE): bump to
+	3.1
+	(GnomeMetaType): add FONT_DATA pseudo opcode
+	(GnomeMetaFontType, GnomeMetaEmbeddedFace)
+	(gnome_print_meta_init, meta_showpage, meta_glyphlist)
+	(meta_close, gpm_skip_string, gpm_render, embedded_face_destroy)
+	(gpm_font_face_use_fill_slot, gpm_font_face_download_real)
+	(gpm_queue_font_face_download, gpm_encode_downloaded_font_face)
+	(gpm_encode_font, download_font, decode_font): implement
+	serialization of downloaded font data in a meta file
+
+	* tests/font-embedding.c: test font embedding
+
+	* tests/Makefile.am: built font-embedding test program
+
+	* tests/generate.c (parse_command_line),
+	* libgnomeprint/gnome-print-job.c (gnome_print_job_print): fix typo
+	
 2003-03-13  Christian Rose  <menthos menthos com>
 
 	* configure.in: Added "ml" to ALL_LINGUAS.
cvs server: Diffing data
cvs server: Diffing data/models
cvs server: Diffing data/printers
cvs server: Diffing doc
cvs server: Diffing doc/reference
cvs server: Diffing doc/reference/tmpl
cvs server: Diffing fonts
cvs server: Diffing installer
cvs server: Diffing libgnomeprint
Index: libgnomeprint/gnome-font-face.c
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-font-face.c,v
retrieving revision 1.69
diff -u -r1.69 gnome-font-face.c
--- libgnomeprint/gnome-font-face.c	2 Feb 2003 21:20:53 -0000	1.69
+++ libgnomeprint/gnome-font-face.c	14 Mar 2003 16:46:10 -0000
@@ -33,9 +33,12 @@
 #include <string.h>
 #include <stdarg.h>
 #include <locale.h>
+#include <unistd.h>
 
 #include <freetype/ftoutln.h>
 
+#define GNOME_PRINT_UNSTABLE_API
+
 #include <libgnomeprint/gnome-print-private.h>
 #include <libgnomeprint/gnome-font-private.h>
 #include <libgnomeprint/gnome-print-i18n.h>
@@ -186,6 +189,11 @@
 		face->psname = NULL;
 	}
 
+	if (face->font_data) {
+		g_free (face->font_data);
+		face->font_data = NULL;
+	}
+
 	/* Fonts should reference us */
 	g_assert (face->fonts == NULL);
 
@@ -494,7 +502,7 @@
  * Creates new face and creates link with FontEntry
  */
 static void
-gff_face_from_entry (GPFontEntry *e)
+gff_entry_fill_in_face (GPFontEntry *e)
 {
 	GnomeFontFace *face;
 
@@ -527,7 +535,7 @@
 			return e->face;
 		}
 
-		gff_face_from_entry (e);
+		gff_entry_fill_in_face (e);
 
 		gp_fontmap_release (map);
 
@@ -559,7 +567,7 @@
 		if (e->face) {
 			gnome_font_face_ref (e->face);
 		} else {
-			gff_face_from_entry (e);
+			gff_entry_fill_in_face (e);
 		}
 		face = e->face;
 	}
@@ -674,6 +682,100 @@
 	family_name = pango_font_description_get_family (desc);
 
 	return gnome_font_face_find_closest_from_weight_slant (family_name, weight, italic);
+}
+
+/* from /usr/share/misc/magic of debian's file 3.40 */
+#define TRUETYPE_MAGIC "\000\001\000\000\000"
+#define TRUETYPE_MAGIC_LENGTH 5
+#define TYPE1_MAGIC "%!PS-AdobeFont-1."
+#define TYPE1_MAGIC_LENGTH 17
+
+static GPFontEntryType
+gff_font_entry_type_from_data (const guchar *font_data, gsize length)
+{
+	if (length > TYPE1_MAGIC_LENGTH + 6
+		 && !memcmp (font_data + 6, TYPE1_MAGIC, TYPE1_MAGIC_LENGTH))
+		return GP_FONT_ENTRY_TYPE1; /* PFB */
+	else if (length > TYPE1_MAGIC_LENGTH
+		 && !memcmp (font_data, TYPE1_MAGIC, TYPE1_MAGIC_LENGTH))
+		return GP_FONT_ENTRY_TYPE1; /* PFA */
+	else if (length > TRUETYPE_MAGIC_LENGTH 
+	    && !memcmp (font_data, TRUETYPE_MAGIC, TRUETYPE_MAGIC_LENGTH))
+		return GP_FONT_ENTRY_TRUETYPE;
+	else
+		return GP_FONT_ENTRY_UNKNOWN;
+}
+
+static gchar*
+gff_write_temp_data_file (const guchar *font_data, gsize length)
+{
+	gint fd;
+	gchar *temp_name;
+	FILE *file;
+	size_t written;
+
+	fd = g_file_open_tmp ("gnome-print-XXXXXX", &temp_name, NULL);
+	if (fd <= -1)
+		return NULL;
+
+	file = fdopen (fd, "wb");
+	written = fwrite (font_data, length, 1, file);
+	fclose (file);
+	if (written != 1) {
+		unlink (temp_name);
+		return NULL;
+	}
+
+	return temp_name;
+}
+
+static void
+gff_unlink_temp_file (gpointer data, GObject *object)
+{
+	unlink ((gchar *)data);
+}
+
+GnomeFontFace *gnome_font_face_download (const guchar *family, const guchar *species, GnomeFontWeight weight, gboolean italic, const guchar *font_data, gsize length)
+{
+	GPFontEntry *entry;
+	gchar *temp_fname;
+	GnomeFontFace *face;
+
+	g_return_val_if_fail (family != NULL, NULL);
+	g_return_val_if_fail (font_data != NULL, NULL);
+	g_return_val_if_fail (length > 0, NULL);
+
+	temp_fname = gff_write_temp_data_file (font_data, length);
+	if (temp_fname == NULL) {
+		g_warning ("Could not create temporary file for embedded font");
+		return NULL;
+	}
+
+	entry = g_new0 (GPFontEntry, 1);
+	entry->type = gff_font_entry_type_from_data (font_data, length);
+	entry->file = temp_fname;
+	entry->refcount = 1;
+	entry->face = NULL;
+	entry->speciesname = g_strdup (species 
+				       ? species
+				       : (const guchar *)"Regular");
+	entry->weight = entry->speciesname; /* FIXME here and in fcpattern_to_gp_font_entry */
+	entry->Weight = weight;
+	entry->familyname = g_strdup (family);
+	entry->name = g_strconcat (family, " ", entry->speciesname, NULL);
+	entry->italic_angle = italic ? -15 : 0;
+	entry->is_alias = FALSE;
+
+	gff_entry_fill_in_face (entry);	
+	face = entry->face;
+
+	face->is_downloaded = TRUE;
+	face->font_data = g_memdup (font_data, length);
+	face->data_length = length;
+
+	g_object_weak_ref (G_OBJECT (face), gff_unlink_temp_file, temp_fname);
+
+	return face;
 }
 
 /* This returns GList of (guchar *) */
Index: libgnomeprint/gnome-font-face.h
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-font-face.h,v
retrieving revision 1.18
diff -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	14 Mar 2003 16:46:11 -0000
@@ -59,6 +59,10 @@
 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);
 
+#ifdef GNOME_PRINT_UNSTABLE_API
+GnomeFontFace *gnome_font_face_download (const guchar *family, const guchar *species, GnomeFontWeight weight, gboolean italic, const guchar *font_data, gsize length);
+#endif
+
 /*
  * Create font
  *
Index: libgnomeprint/gnome-font-private.h
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-font-private.h,v
retrieving revision 1.32
diff -u -r1.32 gnome-font-private.h
--- libgnomeprint/gnome-font-private.h	2 Feb 2003 21:20:53 -0000	1.32
+++ libgnomeprint/gnome-font-private.h	14 Mar 2003 16:46:11 -0000
@@ -57,15 +57,19 @@
 struct _GnomeFontFace {
 	GObject object;
 
-	GPFontEntry * entry;   /* Pointer to our fontmap entry */
-	gint num_glyphs;       /* Glyph storage */
+	GPFontEntry * entry;    /* Pointer to our fontmap entry */
+	gint num_glyphs;        /* Glyph storage */
 	GFFGlyphInfo * glyphs;
 	
-	gdouble ft2ps;         /* FT -> PostScript scaling coefficent */
-	ArtDRect bbox;         /* Face bounding box */
-	FT_Face ft_face;       /* FreeType stuff */
-	GSList *fonts;         /* Our fonts */
-	gchar *psname;         /* The postscript name of the font */
+	gdouble ft2ps;          /* FT -> PostScript scaling coefficent */
+	ArtDRect bbox;          /* Face bounding box */
+	FT_Face ft_face;        /* FreeType stuff */
+	GSList *fonts;          /* Our fonts */
+	gchar *psname;          /* The postscript name of the font */
+
+	gboolean is_downloaded;
+	guchar *font_data;
+	gsize data_length;
 };
 
 struct _GnomeFontFaceClass {
@@ -123,6 +127,7 @@
 
 #define GFF_LOADED(f) ((f)->ft_face || gff_load ((GnomeFontFace *) f))
 
+#define GNOME_FONT_IS_DOWNLOADED(f) (f->face->is_downloaded)
 
 /*
  * Returns PostScript name for glyph
Index: libgnomeprint/gnome-print-job.c
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-print-job.c,v
retrieving revision 1.59
diff -u -r1.59 gnome-print-job.c
--- libgnomeprint/gnome-print-job.c	12 Mar 2003 19:29:31 -0000	1.59
+++ libgnomeprint/gnome-print-job.c	14 Mar 2003 16:46:13 -0000
@@ -433,7 +433,7 @@
  * @job: A closed GnomePrintJob.
  * 
  * Print the pages stored in the GnomePrintJob to
- * the phyisical printing device.
+ * the physical printing device.
  *
  * Return value: GNOME_PRINT_OK on success GNOME_PRINT_ERROR_UNKNOWN otherwise
  **/
Index: libgnomeprint/gnome-print-meta.c
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-print-meta.c,v
retrieving revision 1.61
diff -u -r1.61 gnome-print-meta.c
--- libgnomeprint/gnome-print-meta.c	6 Jan 2003 19:06:05 -0000	1.61
+++ libgnomeprint/gnome-print-meta.c	14 Mar 2003 16:46:18 -0000
@@ -25,10 +25,14 @@
  *  Copyright (C) 1999-2003 Ximian Inc. and authors
  */
 
+#define GNOME_PRINT_UNSTABLE_API
+
 #include <config.h>
 #include <math.h>
 #include <string.h>
 
+#include <libgnomeprint/gnome-font-face.h>
+#include <libgnomeprint/gnome-font-private.h>
 #include <libgnomeprint/gnome-glyphlist-private.h>
 #include <libgnomeprint/gnome-print-private.h>
 #include <libgnomeprint/gnome-print-meta.h>
@@ -43,6 +47,9 @@
 
 	gint page;    /* Start of current page */
 	gint pagenum; /* Number of current page, or -1 */
+
+	GHashTable *embedded_faces;
+	GHashTable *queued_faces;
 };
 
 typedef struct _GnomePrintMetaClass GnomePrintMetaClass;
@@ -54,7 +61,7 @@
 
 /* Note: this must continue to be the same length  as "GNOME_METAFILE-0.0" */
 
-#define METAFILE_SIGNATURE "GNOME_METAFILE-3.0"
+#define METAFILE_SIGNATURE "GNOME_METAFILE-3.1"
 #define METAFILE_SIGNATURE_SIZE 18
 #define METAFILE_HEADER_SIZE (METAFILE_SIGNATURE_SIZE + 4)
 #define PAGE_SIGNATURE "PAGE"
@@ -75,6 +82,7 @@
 	GNOME_META_COLOR,
 	GNOME_META_LINE,
 	GNOME_META_DASH,
+	GNOME_META_FONT_DATA,
 } GnomeMetaType;
 
 typedef enum {
@@ -83,6 +91,18 @@
 	GNOME_META_DOUBLE_I386        /* IEEE-xxxx little endian.  */
 } GnomeMetaDoubleType;
 
+typedef enum {
+	GNOME_META_FONT_FONTMAP,      /* A font from the fontmap */
+	GNOME_META_FONT_EMBEDDED,     /* A font embedded in the meta file */
+} GnomeMetaFontType;
+
+typedef struct {
+	GnomePrintMeta *meta;
+	GnomeFontFace *face;
+	gint offset;
+	GSList *uses;
+} GnomeMetaEmbeddedFace;
+
 #define GPM_ENSURE_SPACE(m,s) (((m)->b_length + (s) <= (m)->b_size) || gpm_ensure_space (m, s))
 
 static void gnome_print_meta_class_init (GnomePrintMetaClass *klass);
@@ -114,8 +134,17 @@
 static void gpm_encode_bpath (GnomePrintContext *pc, const ArtBpath *bpath);
 static const char *gpm_decode_bpath (const char *data, ArtBpath **bpath);
 
+static const guchar *gpm_skip_string (const guchar *data);
 static const guchar *gpm_decode_string (const guchar *data, guchar **dest);
 
+static void embedded_face_destroy (GnomeMetaEmbeddedFace *eface);
+static void gpm_font_face_use_fill_slot (gpointer data, gpointer user_data);
+static gboolean gpm_font_face_download_real (gpointer key, gpointer value, gpointer user_data);
+static void gpm_queue_font_face_download (GnomePrintContext *pc, GnomeFontFace *face, gint32 use);
+static void gpm_encode_downloaded_font_face (GnomePrintContext *pc, GnomeFontFace *face);
+static void gpm_encode_font (GnomePrintContext *pc, GnomeFont *font);
+static const guchar *decode_font (GnomePrintContext *pc, const guchar *data, const guchar *data_start, GnomeFont **dest);
+
 /* Encoding and decoding of header data */
 static void gpm_encode_int_header (GnomePrintContext *pc, gint32 value);
 static const guchar *gpm_decode_int_header (const guchar *data, gint32 *dest);
@@ -180,6 +209,9 @@
 
 	meta->page = 0;
 	meta->pagenum = -1;
+
+	meta->embedded_faces = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)embedded_face_destroy);
+	meta->queued_faces = g_hash_table_new (NULL, NULL);
 }
 
 static void
@@ -231,6 +263,11 @@
 	/* Encode showpage */
 	gpm_encode_int (ctx, GNOME_META_SHOWPAGE);
 
+	/* Encode font data */
+	g_hash_table_foreach_remove (meta->queued_faces,
+				     gpm_font_face_download_real,
+				     meta);
+
 	/* Save page length */
 	len = g_htonl (meta->b_length - meta->page - PAGE_HEADER_SIZE);
 	memcpy (meta->buf + meta->page + PAGE_SIGNATURE_SIZE, &len, 4);
@@ -351,8 +388,7 @@
 			gpm_encode_double (pc, gl->rules[i].value.dval);
 			break;
 		case GGL_FONT:
-			gpm_encode_double (pc, gnome_font_get_size (gl->rules[i].value.font));
-			gpm_encode_string (pc, gnome_font_get_name (gl->rules[i].value.font));
+			gpm_encode_font (pc, gl->rules[i].value.font);
 			break;
 		default:
 			break;
@@ -374,6 +410,9 @@
 
 	memcpy (meta->buf + METAFILE_SIGNATURE_SIZE, &len, 4);
 
+	g_hash_table_destroy (meta->embedded_faces);
+	g_hash_table_destroy (meta->queued_faces);
+
 	return GNOME_PRINT_OK;
 }
 
@@ -532,6 +571,14 @@
 }
 
 static const guchar *
+gpm_skip_string (const guchar *data)
+{
+	gint32 len;
+	data = decode_int (data, &len);
+	return data + len;
+}
+	
+static const guchar *
 gpm_decode_string (const guchar *data, guchar **dest)
 {
 	gint32 len;
@@ -545,8 +592,10 @@
 static gint
 gpm_render (GnomePrintContext *dest, const guchar *data, gint pos, gint len, gboolean pageops)
 {
+	const guchar *data_start;
 	const guchar *end;
 
+	data_start = data;
 	data = data + pos;
 	end = data + len;
 
@@ -661,13 +710,8 @@
 						break;
 					case GGL_FONT: {
 						GnomeFont *font;
-						guchar *name;
-						data = decode_double (data, &dval);
-						data = gpm_decode_string (data, &name);
-						font = gnome_font_find (name, dval);
-						if (font == NULL)
-							g_warning ("Cannot find font: %s\n", name);
-						g_free (name);
+	
+						data = decode_font (dest, data, data_start, &font);
 						gl->rules[i].value.font = font;
 						break;
 					}
@@ -715,6 +759,17 @@
 			g_free (values);
 			break;
 		}
+		case GNOME_META_FONT_DATA: {
+			gint32 data_len;
+
+			data = gpm_skip_string (data);
+			data = gpm_skip_string (data);
+			data = decode_int (data, &ival);
+			data = decode_int (data, &ival);
+			data = decode_int (data, &data_len);
+			data += data_len;
+			break;
+		}
 		default:
 			g_warning ("Serious print meta data corruption %d", opcode);
 			break;
@@ -826,7 +881,7 @@
 	retval = gnome_print_buffer_mmap (&b, filename);
 	if (retval != GNOME_PRINT_OK)
 		return retval;
-	
+
 	retval = gnome_print_meta_render_data (ctx, b.buf, b.buf_size);
 
 	gnome_print_buffer_munmap (&b);
@@ -858,7 +913,7 @@
 	retval = gnome_print_buffer_mmap (&b, filename);
 	if (retval != GNOME_PRINT_OK)
 		return retval;
-	
+
 	retval = gnome_print_meta_render_data_page (ctx, b.buf, b.buf_size, page, pageops);
 
 	gnome_print_buffer_munmap (&b);
@@ -1057,8 +1112,208 @@
 	return data;
 }
 
+static void
+embedded_face_destroy (GnomeMetaEmbeddedFace *eface)
+{
+	g_object_unref (G_OBJECT (eface->meta));
+	g_object_unref (G_OBJECT (eface->face));
+	g_free (eface);
+}
+
+static void
+gpm_font_face_use_fill_slot (gpointer data, gpointer user_data)
+{
+	gint32 font_face_use;
+	GnomeMetaEmbeddedFace *eface;	
+	gint32 noffset;
+
+	font_face_use = GPOINTER_TO_INT (data);
+	eface = (GnomeMetaEmbeddedFace *)user_data;
+	noffset = g_htonl (eface->offset);
+
+	memcpy (eface->meta->buf + font_face_use, &noffset, sizeof (gint32));
+}
+
+static gboolean
+gpm_font_face_download_real (gpointer key, gpointer value, gpointer user_data)
+{	
+	GnomePrintContext *pc;
+	GnomePrintMeta *meta;
+	GnomeMetaEmbeddedFace *eface;
+	
+	pc = GNOME_PRINT_CONTEXT (user_data);
+	meta = GNOME_PRINT_META (pc);
+	eface = (GnomeMetaEmbeddedFace *)value;
+	eface->offset = meta->b_length;
+
+	gpm_encode_int (pc, GNOME_META_FONT_DATA);
+	gpm_encode_string (pc, gnome_font_face_get_family_name (eface->face));
+	gpm_encode_string (pc, gnome_font_face_get_species_name (eface->face));
+	gpm_encode_int (pc, gnome_font_face_get_weight_code (eface->face));
+	gpm_encode_int (pc, gnome_font_face_is_italic (eface->face));
+	gpm_encode_int (pc, eface->face->data_length);
+	gpm_encode_block (pc, eface->face->font_data, eface->face->data_length);
+	g_slist_foreach (eface->uses,
+			 gpm_font_face_use_fill_slot,
+			 eface);
+
+	g_slist_free (eface->uses);
+	eface->uses = NULL;
+	
+	g_hash_table_insert (meta->embedded_faces, eface->face, eface);
+
+	return TRUE;
+}
+
+static void
+gpm_queue_font_face_download (GnomePrintContext *pc, GnomeFontFace *face, gint32 use)
+{
+	GnomePrintMeta *meta;
+	GnomeMetaEmbeddedFace *eface;
+
+	meta = GNOME_PRINT_META (pc);
+
+	eface = g_hash_table_lookup (meta->queued_faces, face);
+	if (!eface) {
+		eface = g_new0 (GnomeMetaEmbeddedFace, 1);
+		eface->meta = meta;
+		g_object_ref (G_OBJECT (meta));
+		eface->face = face;
+		g_object_ref (G_OBJECT (face));
+		g_hash_table_insert (meta->queued_faces, face, eface);
+	}
+	eface->uses = g_slist_prepend (eface->uses, GINT_TO_POINTER (use));
+}
+
+static void
+gpm_encode_downloaded_font_face (GnomePrintContext *pc, GnomeFontFace *face)
+{
+	GnomePrintMeta *meta;
+	GnomeMetaEmbeddedFace *eface;
+	gint32 offset;
+
+	meta = GNOME_PRINT_META (pc);
+
+	eface = g_hash_table_lookup (meta->embedded_faces, face);
+	if (eface) {
+		offset = eface->offset;
+	} else {
+		gpm_queue_font_face_download (pc, face, meta->b_length);
+
+		offset = -1;
+	}
+
+	gpm_encode_int_header (pc, offset);
+}
+
+static void
+gpm_encode_font (GnomePrintContext *pc, GnomeFont *font)
+{
+	if (!GNOME_FONT_IS_DOWNLOADED (font)) {
+		gpm_encode_int (pc, GNOME_META_FONT_FONTMAP);
+		gpm_encode_double (pc, gnome_font_get_size (font));
+		gpm_encode_string (pc, gnome_font_get_name (font));
+	} else {
+		gpm_encode_int (pc, GNOME_META_FONT_EMBEDDED);
+		gpm_encode_double (pc, gnome_font_get_size (font));
+		gpm_encode_downloaded_font_face (pc, gnome_font_get_face (font));
+	}
+}
+
+static GnomeFont *
+download_font (GnomePrintContext *dest, const guchar *data, gdouble size)
+{
+	GHashTable *hash;
+	gpointer hash_key;
+	GnomeFontFace *face;
+	GnomeFont *font;
+
+	hash = g_object_get_data (G_OBJECT (dest), "meta-replay-fonts");
+	if (hash == NULL) {
+		hash = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref);
+		g_object_set_data_full (G_OBJECT (dest), "meta-replay-fonts", hash, (GDestroyNotify)g_hash_table_destroy);
+	}
+
+	hash_key = (gpointer)data;
+	face = g_hash_table_lookup (hash, hash_key);
+	if (face == NULL) {
+		gint32 ival;
+
+		data = decode_int (data, &ival);
+		if (ival != GNOME_META_FONT_DATA) {
+			g_warning ("Serious print meta data corruption (embedded font)");
+			face = gnome_font_face_find ("Serif");
+		} else {
+			guchar *family;
+			guchar *species;
+			GnomeFontWeight weight;
+			gboolean italic;
+			gint32 ival;
+			gsize len;
+			
+			data = gpm_decode_string (data, &family);
+			data = gpm_decode_string (data, &species);
+			data = decode_int (data, &ival);
+			weight = (GnomeFontWeight)ival;
+			data = decode_int (data, &ival);
+			italic = (gboolean)ival;
+			data = decode_int (data, &ival);
+			len = (gsize)ival;
+
+			face = gnome_font_face_download (family, species, weight,
+							 italic, data, len);
+
+			g_free (family);
+			g_free (species);
+		}
+
+		g_hash_table_insert (hash, hash_key, face);
+	}
+
+	font = gnome_font_face_get_font_default (face, size);
+
+	return font;
+}
+
+static const guchar *
+decode_font (GnomePrintContext *pc, const guchar *data, const guchar *data_start, GnomeFont **dest)
+{
+	gint32 font_type;
+	gdouble size;
+	GnomeFont *font;
+	guchar *name;
+	gint32 offset;
+
+	data = decode_int (data, &font_type);
+
+	switch ((GnomeMetaFontType) font_type) {
+	case GNOME_META_FONT_FONTMAP:
+		data = decode_double (data, &size);
+		data = gpm_decode_string (data, &name);
+		font = gnome_font_find (name, size);
+		if (font == NULL)
+			g_warning ("Cannot find font: %s\n", name);
+		g_free (name);
+		*dest = font;
+		break;
+	case GNOME_META_FONT_EMBEDDED:
+		data = decode_double (data, &size);
+		data = gpm_decode_int_header (data, &offset);
+		font = download_font (pc, data_start + offset, size);
+		if (font == NULL)
+			g_warning ("Cannot process embedded font.\n");
+		*dest = font;
+		break;
+	default:
+		g_warning ("Serious print meta data corruption: font type %d", font_type);
+		break;
+	}
+
+	return data;
+}
+
 /*
- * Less compact, but gauranteed size (just makes things easier to encode
+ * Less compact, but guaranteed size (just makes things easier to encode
  * fixed size data like headers)
  */
 
@@ -1082,4 +1337,3 @@
 
 	return data + sizeof (gint32);
 }
-
cvs server: Diffing libgnomeprint/drivers
cvs server: Diffing libgnomeprint/gpa
cvs server: Diffing libgnomeprint/modules
cvs server: Diffing libgnomeprint/modules/cups
cvs server: Diffing libgnomeprint/transports
cvs server: Diffing po
cvs server: Diffing tests
Index: tests/Makefile.am
===================================================================
RCS file: /cvs/gnome/libgnomeprint/tests/Makefile.am,v
retrieving revision 1.31
diff -u -r1.31 Makefile.am
--- tests/Makefile.am	2 Feb 2003 21:20:53 -0000	1.31
+++ tests/Makefile.am	14 Mar 2003 16:46:19 -0000
@@ -2,7 +2,7 @@
 
 CFLAGS=$(WARN_CFLAGS)
 
-noinst_PROGRAMS = generate gpa-test fonts simple
+noinst_PROGRAMS = generate gpa-test fonts simple font-embedding
 
 INCLUDES = \
 	-I$(top_srcdir) \
@@ -32,3 +32,7 @@
 fonts_SOURCES = fonts.c
 fonts_LDFLAGS =
 fonts_LDADD = $(print_libs)
+
+font_embedding_SOURCES = font-embedding.c
+font_embedding_LDFLAGS =
+font_embedding_LDADD = $(print_libs)
Index: tests/generate.c
===================================================================
RCS file: /cvs/gnome/libgnomeprint/tests/generate.c,v
retrieving revision 1.19
diff -u -r1.19 generate.c
--- tests/generate.c	11 Mar 2003 08:36:07 -0000	1.19
+++ tests/generate.c	14 Mar 2003 16:46:20 -0000
@@ -615,7 +615,7 @@
 		*backend = BACKEND_UNKNOWN;
 
 	if (*backend == BACKEND_UNKNOWN)
-		usage ("Backend not specicied or invalid.");
+		usage ("Backend not specified or invalid.");
 	
 	if (replay_str && replay_str[0] != '\0') {
 		FILE *file;
cvs server: Diffing tests/files
cvs server: Diffing tests/output
cvs server: Diffing tests/tools
/*
 * Test embedding of font faces as chunks of memory
 *
 * derived from Chema's simple.c template
 */
#define GNOME_PRINT_UNSTABLE_API

#include <string.h>
#include <libgnomeprint/gnome-print.h>
#include <libgnomeprint/gnome-print-job.h>
#include <libgnomeprint/gnome-font.h>
#include <libgnomeprint/gnome-font-face.h>

/* for testing FontEntryType */
#include <libgnomeprint/gnome-font-private.h>
#include <libgnomeprint/gnome-fontmap.h>

#define TEXT "The quick brown fox jumps over the lazy dog."

/* FIXME before check in */
#define SAMPLE_PFB_FILE "/usr/share/texmf/fonts/type1/urw/palatino/uplb8a.pfb"
#define SAMPLE_TTF_FILE "/home/martin/.fonts/tt2001gn.ttf"

static void
my_draw (GnomePrintContext *gpc, GnomeFontFace *gff, GnomeFontFace *gff2)
{
	GnomeFont *font, *font2, *font3;

	font = gnome_font_face_get_font_default (gff, 12);
        font2 = gnome_font_face_get_font_default (gff2, 20);
        font3 = gnome_font_face_get_font_default (gff2, 10);

	gnome_print_beginpage (gpc, "1");
	gnome_print_setfont (gpc, font);
	gnome_print_moveto (gpc, 100, 180);
	gnome_print_show (gpc, TEXT);
	gnome_print_showpage (gpc);

        gnome_print_beginpage (gpc, "2");
        gnome_print_setfont (gpc, font);
	gnome_print_moveto (gpc, 100, 180);
	gnome_print_show (gpc, TEXT);
        gnome_print_setfont (gpc, font2);
	gnome_print_moveto (gpc, 100, 360);
	gnome_print_show (gpc, TEXT);
	gnome_print_showpage (gpc);

        gnome_print_beginpage (gpc, "2");
        gnome_print_setfont (gpc, font3);
	gnome_print_moveto (gpc, 100, 180);
	gnome_print_show (gpc, TEXT);
	gnome_print_showpage (gpc);

        g_object_unref (G_OBJECT (font));
        g_object_unref (G_OBJECT (font2));
        g_object_unref (G_OBJECT (font3));
}

static void
my_test (GnomePrintContext *gpc)
{
        gchar *font_data;
	gsize font_length;
	GnomeFontFace *gff, *gff2;       

	if (g_file_get_contents (SAMPLE_PFB_FILE, &font_data, &font_length,
				 NULL) == FALSE)
		g_assert_not_reached ();

	gff = gnome_font_face_download ("FontFamilyName", "Italic",
					GNOME_FONT_REGULAR, TRUE,
					(const guchar *)font_data,
					font_length);
	g_free (font_data);

	/* check if parameters end up in the right attributes */
	g_assert (gff != NULL);
	g_assert (GNOME_IS_FONT_FACE (gff));
	g_assert (strcmp (gnome_font_face_get_name (gff),
			  "FontFamilyName Italic") == 0);
	g_assert (strcmp (gnome_font_face_get_family_name (gff),
			  "FontFamilyName") == 0);
	g_assert (strcmp (gnome_font_face_get_species_name (gff),
			  "Italic") == 0);
        g_assert (gff->entry->type == GP_FONT_ENTRY_TYPE1);

	/* the following calls require successful loading of the font data */
	g_assert (gnome_font_face_lookup_default (gff, (gint)'A') == 133);
	g_assert (strcmp (gnome_font_face_get_glyph_ps_name (gff, 133),
			  "A") == 0);

	if (g_file_get_contents (SAMPLE_TTF_FILE, &font_data, &font_length,
				 NULL) == FALSE)
		g_assert_not_reached ();

	gff2 = gnome_font_face_download ("AnotherFontFamilyName", "Italic",
					GNOME_FONT_REGULAR, TRUE,
					(const guchar *)font_data,
					font_length);
	g_free (font_data);

        g_assert (gff2->entry->type == GP_FONT_ENTRY_TRUETYPE);

	my_draw (gpc, gff, gff2);
	
	g_object_unref (gff);
        g_object_unref (gff2);
}

static void
my_print (void)
{
	GnomePrintJob *job;
	GnomePrintContext *gpc;
	GnomePrintConfig *config;
	
	job = gnome_print_job_new (NULL);
	gpc = gnome_print_job_get_context (job);
	config = gnome_print_job_get_config (job);

        gnome_print_config_set (config, "Printer", "GENERIC");
        gnome_print_job_print_to_file (job, "o.ps");
#if 0
	gnome_print_config_set (config, "Printer", "PDF");
	gnome_print_job_print_to_file (job, "o.pdf");
#endif
	gnome_print_config_set (config, GNOME_PRINT_KEY_PAPER_SIZE, "USLetter");
	
	my_test (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));
}

int
main (int argc, char * argv[])
{
	g_type_init ();
	
	my_print ();

	g_print ("Done...\n");

	return 0;
}


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