--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <m17n-gui.h>
+#include <m17n-misc.h>
+
+void
+help ()
+{
+ printf ("Usage: findfont [FONT-SPEC]\n");
+ printf ("FONT-SPEC::=[FAMILY][:script=SCRIPT][:lang=LANG][:otf=OTFSPEC]\n");
+ exit (1);
+}
+
+MSymbol
+make_symbol (char *str, int len)
+{
+ char *p = alloca (len + 1);
+
+ memcpy (p, str, len);
+ p[len] = '\0';
+ return msymbol (p);
+}
+
+MFont *
+parse_font_name (char *str)
+{
+ MFont *font = mfont ();
+ char *p;
+
+ if (*str != ':')
+ {
+ for (p = str + 1; *p && *p != ':'; p++);
+ mfont_put_prop (font, Mfamily, make_symbol (str, p - str));
+ str = p;
+ }
+ while (*str == ':')
+ {
+ str++;
+ if (strncmp (str, "script=", 7) == 0)
+ {
+ str += 7;
+ for (p = str; *p && *p != ':'; p++);
+ mfont_put_prop (font, Mscript, make_symbol (str, p - str));
+ }
+ else if (strncmp (str, "lang=", 5) == 0)
+ {
+ str += 5;
+ for (p = str; *p && *p != ':'; p++);
+ mfont_put_prop (font, Mlanguage, make_symbol (str, p - str));
+ }
+ else if (strncmp (str, "otf=", 4) == 0)
+ {
+ str += 4;
+ for (p = str; *p && *p != ':'; p++);
+ mfont_put_prop (font, msymbol ("otf"), make_symbol (str, p - str));
+ }
+ else
+ {
+ for (p = str; *p && *p != ':'; p++);
+ fprintf (stderr, "Unknown option ignored: %s\n",
+ msymbol_name (make_symbol (str, p - str)));
+ }
+ str = p;
+ }
+ return font;
+}
+
+void
+print_font (MFont *font)
+{
+ MSymbol family, foundry, weight, slant, stretch;
+ char *weight_name, *slant_name, *stretch_name;
+ int len;
+ char style_name[1024];
+
+ family = mfont_get_prop (font, Mfamily);
+ foundry = mfont_get_prop (font, Mfoundry);
+ weight = mfont_get_prop (font, Mweight);
+ weight_name = weight ? msymbol_name (weight) : "";
+ slant = mfont_get_prop (font, Mstyle);
+ slant_name = slant ? msymbol_name (slant) : "";
+ stretch = mfont_get_prop (font, Mstretch);
+ stretch_name = stretch ? msymbol_name (stretch) : "";
+
+ sprintf (style_name, "%s-%s-%s", weight_name, slant_name, stretch_name);
+ printf ("%s:foundry=%s:style=%s\n",
+ msymbol_name (family), msymbol_name (foundry), style_name);
+}
+
+int
+main (int argc, char **argv)
+{
+ MPlist *plist, *p;
+ MFrame *frame;
+ char buf[256];
+
+ M17N_INIT ();
+
+ plist = mplist ();
+ mplist_add (plist, Mdevice, Mnil);
+ frame = mframe (plist);
+ m17n_object_unref (plist);
+
+ if (argc == 1)
+ {
+ printf ("Listing all available family names...\n");
+ plist = mfont_list_family_names (frame);
+
+ for (p = plist; p && mplist_key (p) != Mnil; p = mplist_next (p))
+ printf ("%s\n", msymbol_name ((MSymbol) mplist_value (p)));
+ }
+ else if (argc == 2)
+ {
+ MFont *font = parse_font_name (argv[1]);
+ MPlist *p0;
+
+ plist = mfont_list (frame, font, Mnil, 0);
+ free (font);
+ /* List up unique pairs of family and foundry of fonts in PL. */
+ for (p = plist; p && mplist_key (p) != Mnil; p = mplist_next (p))
+ print_font (mplist_value (p));
+ }
+ else
+ help ();
+
+ if (plist)
+ m17n_object_unref (plist);
+ m17n_object_unref (frame);
+ M17N_FINI ();
+ exit (0);
+}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gd.h>
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <m17n-gui.h>
+#include <m17n-misc.h>
+
+#define FONT_PT_SIZE 60
+
+gint
+delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+ return FALSE;
+}
+
+void
+destroy (GtkWidget *widget, gpointer data)
+{
+ gtk_main_quit ();
+}
+
+int
+main (int argc, char **argv)
+{
+ MSymbol lang;
+ MText *mt;
+ int nchars;
+ MFrame *frame;
+ MDrawMetric metric;
+ gdImagePtr image;
+ int bg_color;
+ unsigned char *title;
+ int allocated, len;
+ MSymbol utf8;
+ char *family_names = NULL;
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "Usage: gdkdraw LANGUAGE\n");
+ exit (1);
+ }
+
+ M17N_INIT ();
+ lang = msymbol (argv[1]);
+ mt = mlanguage_text (lang);
+ if (! mt)
+ {
+ fprintf (stderr, "No native name for the language \"%s\".\n", argv[1]);
+ exit (1);
+ }
+
+ nchars = mtext_len (mt);
+
+ /* Encode native language name in MT into the buffer TITLE. */
+ merror_code = 0;
+ utf8 = msymbol ("utf-8");
+ allocated = nchars * 4; /* Usually this is enough. */
+ title = malloc (allocated);
+ len = mconv_encode_buffer (utf8, mt, title, allocated);
+ while (len < 0 && merror_code == MCONVERSION_RESULT_INSUFFICIENT_DST)
+ {
+ allocated += allocated;
+ title = realloc (title, allocated);
+ len = mconv_encode_buffer (utf8, mt, title, allocated);
+ }
+ if (len < 0)
+ {
+ fprintf (stderr, "Encoding of native language name failed.");
+ exit (1);
+ }
+ title[len] = '\0';
+
+ {
+ MPlist *param = mplist ();
+ MFace *face = mface ();
+ MFontset *fontset = mfontset ("generic");
+
+ mface_put_prop (face, Msize, (void *) (FONT_PT_SIZE * -10));
+ mface_put_prop (face, Mfontset, fontset);
+ if (argc > 2)
+ mface_put_prop (face, Mfamily, msymbol (argv[2]));
+ mplist_add (param, Mdevice, msymbol ("gd"));
+ mplist_add (param, Mface, face);
+ frame = mframe (param);
+ m17n_object_unref (face);
+ m17n_object_unref (param);
+
+ if (! frame)
+ {
+ fprintf (stderr, "Frame creation failed. Perhaps no GD library.\n");
+ exit (1);
+ }
+ }
+
+ /* Build GD image and draw MT on it while listing up font families
+ used for drawing. */
+ {
+ MDrawControl control;
+ MDrawGlyph *glyphs;
+ int array_size, num_glyphs;
+ MPlist *family_list;
+ int family_name_len;
+ char *p;
+
+ memset (&control, 0, sizeof (control));
+ control.anti_alias = 1;
+ control.enable_bidi = 1;
+ mdraw_text_extents (frame, mt, 0, mtext_len (mt), &control,
+ &metric, NULL, NULL);
+
+ image = gdImageCreateTrueColor (metric.width, metric.height);
+ bg_color = gdImageColorAllocate (image, 255, 255, 255);
+ gdImageFilledRectangle (image, 0, 0, metric.width - 1, metric.height - 1,
+ bg_color);
+
+ array_size = nchars * 2; /* Usually this is enough. */
+ glyphs = malloc (sizeof (MDrawGlyph) * array_size);
+ if (mdraw_glyph_list (frame, mt, 0, nchars, &control, glyphs, array_size,
+ &num_glyphs) < 0)
+ {
+ array_size = num_glyphs;
+ glyphs = realloc (glyphs, sizeof (MDrawGlyph) * array_size);
+ mdraw_glyph_list (frame, mt, 0, nchars, &control, glyphs, array_size,
+ &num_glyphs);
+ }
+
+ family_list = NULL;
+ family_name_len = 0;
+ while (num_glyphs-- > 0)
+ if (glyphs[num_glyphs].font)
+ {
+ MSymbol family = mfont_get_prop (glyphs[num_glyphs].font, Mfamily);
+
+ if (! family_list)
+ {
+ family_list = mplist ();
+ mplist_add (family_list, Msymbol, family);
+ family_name_len = strlen (msymbol_name (family));
+ }
+ else if (! mplist_find_by_value (family_list, family))
+ {
+ mplist_push (family_list, Msymbol, family);
+ family_name_len += strlen (msymbol_name (family)) + 1;
+ }
+ }
+
+ mdraw_text_with_control (frame, (MDrawWindow) image,
+ - metric.x, - metric.y,
+ mt, 0, mtext_len (mt), &control);
+ m17n_object_unref (frame);
+ m17n_object_unref (mt);
+
+ if (family_list)
+ {
+ char *p = alloca (family_name_len + 1);
+ MPlist *pl = family_list;
+
+ family_names = p;
+ p += sprintf (p, "%s", msymbol_name (mplist_value (pl)));
+ for (pl = mplist_next (pl); mplist_key (pl) != Mnil;
+ pl = mplist_next (pl))
+ p += sprintf (p, ",%s", msymbol_name (mplist_value (pl)));
+ }
+ m17n_object_unref (family_list);
+ }
+
+ M17N_FINI ();
+
+ {
+ GdkPixbuf *pixbuf;
+ GtkWidget *window, *box, *text, *label;
+ int n_channels, rowstride;
+ guchar *pixels, *p;
+ int x, y;
+ PangoAttrList *attr_list;
+ PangoAttribute *attr_size, *attr_family;
+
+ gtk_init (&argc, &argv);
+
+ attr_list = pango_attr_list_new ();
+ attr_size = pango_attr_size_new (FONT_PT_SIZE * PANGO_SCALE);
+ attr_family = family_names ? pango_attr_family_new (family_names) : NULL;
+ pango_attr_list_insert (attr_list, attr_size);
+ if (attr_family)
+ pango_attr_list_insert (attr_list, attr_family);
+
+ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 0, 8,
+ metric.width, metric.height);
+ n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+ rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+ pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+ for (y = 0; y < metric.height; y++)
+ for (x = 0; x < metric.width; x++)
+ {
+ int cid = gdImageGetPixel (image, x, y);
+ p = pixels + y * rowstride + x * n_channels;
+
+ p[0] = gdImageRed (image, cid);
+ p[1] = gdImageGreen (image, cid);
+ p[2] = gdImageBlue (image, cid);
+ }
+ gdImageDestroy (image);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ box = gtk_vbox_new (FALSE, 0);
+ text = gtk_image_new_from_pixbuf (pixbuf);
+ label = gtk_label_new ((gchar *) title);
+ gtk_label_set_attributes (GTK_LABEL (label), attr_list);
+ gtk_box_pack_start (GTK_BOX (box), text, TRUE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (box), label, TRUE, FALSE, 0);
+
+ gtk_container_add (GTK_CONTAINER (window), box);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ GTK_SIGNAL_FUNC (delete_event), NULL);
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (destroy), NULL);
+ gtk_widget_show (text);
+ gtk_widget_show (label);
+ gtk_widget_show (box);
+ gtk_widget_show (window);
+ gtk_main ();
+ }
+
+ free (title);
+
+ exit (0);
+}