--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <libgen.h>
+
+#include <gd.h>
+
+#include <m17n-gui.h>
+#include <m17n-misc.h>
+
+/* Format MSG by FMT and print the result to the stderr, and exit. */
+
+#define FATAL_ERROR(fmt, arg) \
+ do { \
+ printf ("0\n"); \
+ printf (fmt, arg); \
+ exit (0); \
+ } while (0)
+
+char base64_encode_table[] =
+ { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+ 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', '+', '/' };
+
+void
+base64_encode (const unsigned char *src, int length, FILE *fp)
+{
+ int i = 0;
+ int c;
+ unsigned int value;
+
+ while (i < length)
+ {
+ c = src[i++];
+ putc (base64_encode_table[0x3f & c >> 2], fp);
+ value = (0x03 & c) << 4;
+ if (i == length)
+ {
+ putc (base64_encode_table[value], fp);
+ putc ('=', fp);
+ putc ('=', fp);
+ break;
+ }
+ c = src[i++];
+ putc (base64_encode_table[value | (0x0f & c >> 4)], fp);
+ value = (0x0f & c) << 2;
+ if (i == length)
+ {
+ putc (base64_encode_table[value], fp);
+ putc ('=', fp);
+ break;
+ }
+ c = src[i++];
+ putc (base64_encode_table[value | (0x03 & c >> 6)], fp);
+ putc (base64_encode_table[0x3f & c], fp);
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ int fontsize = 240;
+ int dpi = 100;
+
+ MText *mt;
+ int i;
+ MSymbol lang, name;
+ MInputMethod *im;
+ MInputContext *ic;
+
+ int len, from, to;
+ MConverter *converter;
+ MFrame *frame;
+ MDrawControl control;
+ MDrawMetric ink, logical;
+ int ascent, descent, height, width;
+#if 0
+ int indent = 0;
+ int left_adjust;
+#endif
+ gdImagePtr work;
+ int work_white;
+
+ if (argc != 4)
+ FATAL_ERROR ("Number of arguments %d must be 4\n", argc);
+
+ M17N_INIT ();
+ if (merror_code != MERROR_NONE)
+ FATAL_ERROR ("%s\n", "Failed to initialize the m17n library.");
+
+ lang = msymbol (argv[1]);
+ name = msymbol (argv[2]);
+ im = minput_open_im (lang, name, NULL);
+ if (! im)
+ FATAL_ERROR ("%s\n", "Failed to open the input method.");
+ ic = minput_create_ic (im, NULL);
+ if (! im)
+ FATAL_ERROR ("%s\n", "Failed to create the input context.");
+ mt = mtext ();
+ for (i = 0; argv[3][i]; i++)
+ {
+ char keybuf[2];
+ MSymbol key;
+
+ keybuf[0] = argv[3][i];
+ keybuf[1] = '\0';
+ key = msymbol (keybuf);
+ if (minput_filter (ic, key, NULL) == 1)
+ continue;
+ minput_lookup (ic, key, NULL, mt);
+ }
+ if (ic->preedit)
+ mtext_cat (mt, ic->preedit);
+ len = mtext_len (mt);
+
+ mtext_put_prop (mt, 0, len, Mlanguage, lang);
+
+ {
+ MPlist *plist = mplist (), *p;
+ MFontset *fontset = mfontset ("generic");
+ MFace *face = mface ();
+
+ mface_put_prop (face, Mfontset, fontset);
+ mface_put_prop (face, Msize, (void *) (fontsize * dpi / 100));
+ p = mplist_add (plist, Mdevice, msymbol ("gd"));
+ p = mplist_add (p, Mface, face);
+ m17n_object_unref (face);
+ frame = mframe (plist);
+ m17n_object_unref (plist);
+ if (! frame)
+ FATAL_ERROR ("%s\n", "Failed to open a frame.");
+ }
+
+ memset (&control, 0, sizeof control);
+ control.enable_bidi = 1;
+
+ mdraw_text_extents (frame, mt, 0, len, &control, &ink, &logical, NULL);
+ ascent = - logical.y;
+ if (ascent < - ink.y)
+ ascent = -ink.y;
+ descent = logical.height + logical.y;
+ if (descent < ink.height + ink.y)
+ descent = ink.height + ink.y;
+ height = ascent + descent;
+ width = logical.width;
+
+ work = gdImageCreate (width, height);
+ work_white = gdImageColorAllocate (work, 255, 255, 255);
+ gdImageColorTransparent (work, work_white);
+ gdImageFilledRectangle (work, 0, 0, width - 1, height - 1, work_white);
+ mdraw_text_with_control (frame, work, 0, ascent, mt, 0, len, &control);
+
+ converter = mconv_stream_converter (msymbol ("utf-8"), stdout);
+
+ printf ("1\n");
+ from = 0;
+ {
+ MDrawMetric *ink_array, *logical_array;
+ int array_size = len * 2;
+ int num_chars;
+ unsigned char *buf;
+ int size;
+
+ ink_array = malloc (sizeof (MDrawMetric) * array_size);
+ logical_array = malloc (sizeof (MDrawMetric) * array_size);
+
+ if (mdraw_text_per_char_extents (frame, mt, 0, len, &control,
+ ink_array, logical_array,
+ array_size, &num_chars, NULL, NULL) < 0)
+ {
+ ink_array = realloc (ink_array, sizeof (MDrawMetric) * num_chars);
+ logical_array = realloc (logical_array, sizeof (MDrawMetric) * num_chars);
+ mdraw_text_per_char_extents (frame, mt, 0, len, &control,
+ ink_array, logical_array,
+ num_chars, &num_chars, NULL, NULL);
+ }
+
+ for (from = 0, i = 0; i < num_chars;)
+ {
+ gdImagePtr image;
+ int white;
+ int x = logical_array[i].x;
+
+ image = gdImageCreate (logical_array[i].width, height);
+ white = gdImageColorAllocate (image, 255, 255, 255);
+ gdImageColorTransparent (image, white);
+ gdImageCopy (image, work, 0, 0,
+ logical_array[i].x, 0, logical_array[i].width, height);
+ printf ("<img src=\"data:image/png;base64,");
+ buf = gdImagePngPtr (image, &size);
+ base64_encode (buf, size, stdout);
+ gdFree (buf);
+ gdImageDestroy (image);
+
+ while (++i < num_chars && logical_array[i].x == x);
+ if (i == num_chars)
+ to = len;
+ else
+ to = mdraw_coordinates_position (frame, mt, 0, len,
+ logical_array[i].x, 0, &control);
+ printf ("\" alt=\"");
+ mconv_encode_range (converter, mt, from, to);
+ printf ("\">");
+ from = to;
+ }
+ }
+ printf ("\n");
+
+ M17N_FINI ();
+ exit (0);
+}
+