merge FLT
[m17n/m17n-lib.git] / example / mdump.c
1 /* mdump.c -- Dump text image                           -*- coding: euc-jp; -*-
2    Copyright (C) 2003, 2004, 2005, 2006, 2007
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21    02111-1307, USA.  */
22
23 /***en
24     @enpage m17n-dump dump text image
25
26     @section m17n-dump-synopsis SYNOPSIS
27
28     m17n-dump [ OPTION ... ] [ FILE ]
29
30     @section m17n-dump-description DESCRIPTION
31
32     Dump a text as PNG image file.
33
34     The PNG file is written to a file created in the current directory
35     with the name "BASE.png" where BASE is the basename of FILE.  If
36     FILE is omitted, text is read from standard input, and the image
37     is dumped into the file "output.png".
38
39     The following OPTIONs are available.
40
41     <ul>
42
43     <li> -s SIZE
44
45     SIZE is the font size in point.  The default font size is 12 point.
46
47     <li> -d DPI
48
49     DPI is the resolution in dots per inch.  The default resolution is
50     300 dpi.
51
52     <li> -p PAPER
53
54     PAPER is the paper size: a4, a4r, a5, a5r, b5, b5r, letter, WxH,
55     or W.  In the case of WxH, W and H are the width and height in
56     millimeter.  In the case of W, W is the width in millimeter.  If
57     this option is specified, PAPER limits the image size.  If FILE is
58     too large for a single page, multiple files with the names
59     "BASE.01.png", "BASE.02.png", etc. are created.
60
61     <li> -m MARGIN
62
63     MARGIN is the horizontal and vertical margin in millimeter.  The
64     default margin is 20 mm.  It is ignored when PAPER is not
65     specified.
66
67     <li> -c POS
68
69     POS is the character position of cursor to draw.  By default,
70     cursor is not drawn.
71
72     <li> -x
73
74     FILE is assumed to be an XML file generated by the serialize
75     facility of the m17n library, and FILE is deserialized before an
76     image is created.
77
78     <li> -w
79
80     Each line is broken at word boundary.
81
82     <li> -f FILTER
83
84     FILTER is a string containing a shell command line.  If this
85     option is specified, the PNG image is not written info a
86     file but is given to FILTER as standard input.  If FILTER
87     contains "%s", that part is replaced by a basename of FILE.
88     So, the default behaviour is the same as specifying "cat >
89     %s.png" as FILTER.
90
91     If FILTER is just "-", the PNG image is written to stdout.
92
93     <li> -a
94
95     Enable anti-alias drawing.
96
97     <li> --family FAMILY
98
99     Prefer a font whose family name is FAMILY.
100
101     <li> --language LANG
102
103     Prefer a font specified for the language LANG.  LANG must be a
104     2-letter code of ISO 630 (e.g. "en" for English).
105
106     <li> -fg FOREGROUND
107
108     Specify the text color.  The supported color names are those of
109     HTML 4.0 and "#RRGGBB" notation.
110
111     <li> -bg BACKGROUND
112
113     Specify the background color.  The supported color names are the
114     same as FOREGROUND, except that if "transparent" is specified,
115     make the background transparent.
116
117     <li> -r
118
119     Specify that the orientation of the text is right-to-left.
120
121     <li> -q
122
123     Quiet mode.  Don't print any messages.
124
125     <li> --version
126
127     Print the version number.
128
129     <li> -h, --help
130
131     Print this message.
132
133     </ul>
134 */
135 /***ja
136     @japage m17n-dump ¥Æ¥­¥¹¥È²èÁü¤Î¥À¥ó¥×
137
138     @section m17n-dump-synopsis SYNOPSIS
139
140     m17n-dump [ OPTION ... ] [ FILE ]
141
142     @section m17n-dump-description DESCRIPTION
143
144     ¥Æ¥­¥¹¥È¤ò PNG ²èÁü¤È¤·¤Æ¥À¥ó¥×¤¹¤ë¡£ 
145
146     PNG ²èÁü¤Ï¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ëºî¤é¤ì¤¿ "BASE.png" ¤È¤¤¤¦Ì¾Á°¤Î 
147     ¥Õ¥¡¥¤¥ë¤Ë½ñ¤­¹þ¤Þ¤ì¤ë¡£¤³¤³¤Ç BASE ¤ÏFILE ¤Î basename ¤Ç¤¢¤ë¡£ 
148     FILE ¤¬¾Êά¤µ¤ì¤ì¤Ð¡¢¥Æ¥­¥¹¥È¤Ïɸ½àÆþÎϤ«¤éÆɤޤ졢²èÁü¤Ï 
149     "output.png" ¤Ë¥À¥ó¥×¤µ¤ì¤ë¡£
150
151     °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ­¤ë¡£
152
153     <ul>
154
155     <li> -s SIZE
156
157     SIZE ¤Ï¥Õ¥©¥ó¥È¤ÎÂ礭¤µ¤ò¥Ý¥¤¥ó¥Èñ°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç¥Õ¥©¥ë
158     ¥È¤ÎÂ礭¤µ¤Ï 12 ¥Ý¥¤¥ó¥È¡£
159
160     <li> -d DPI
161
162     DPI ¤Ï²òÁüÅÙ¤ò£±¥¤¥ó¥Á¤¢¤¿¤ê¤Î¥É¥Ã¥Èñ°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç¥Õ¥© 
163     ¥ë¥È¤Î²òÁüÅ٤Ϡ300 dpi¡£
164
165     <li> -p PAPER
166
167     PAPER ¤Ï¤Ú¡¼¥Ñ¥µ¥¤¥º : a4, a4r, a5, a5r, b5, b5r, letter, WxH ¤Þ¤¿
168     ¤Ï W¡£ WxH ¤Î¾ì¹ç¡¢ W ¤È H ¤ÏÉý¤È¹â¤µ¤ò¥ß¥ê¥á¡¼¥¿Ã±°Ì¤Ç¼¨¤·¤¿¤â¤Î¡£
169     W ¤Î¾ì¹ç¡¢ W ¤ÏÉý¤ò¥ß¥ê¥á¡¼¥¿Ã±°Ì¤Ç¼¨¤·¤¿¤â¤Î¡£¤³¤Î¥ª¥×¥·¥ç¥ó¤¬»ØÄê
170     ¤µ¤ì¤Æ¤¤¤ë¾ì¹ç¤Ï¡¢ PAPER ¤¬²èÁü¥µ¥¤¥º¤òÀ©¸Â¤¹ ¤ë¡£FILE ¤¬ 1 ¥Ú¡¼¥¸
171     ¤ËǼ¤Þ¤é¤Ê¤¤¤Û¤ÉÂ礭¤¤¾ì¹ç¤Ï¡¢"BASE.01.png", "BASE.02.png" Åù¤Î̾Á°
172     ¤Î¤Ä¤¤¤¿Ê£¿ô¤Î¥Õ¥¡¥¤¥ë¤¬ºî¤é¤ì¤ë¡£
173
174     <li> -m MARGIN
175
176     MARGIN ¤Ï¿åÊ¿¡¢¿âľ¥Þ¡¼¥¸¥ó¤ò¥ß¥ê¥á¡¼¥¿Ã±°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç 
177     ¥Õ¥©¥ë¥È¤Î¥Þ¡¼¥¸¥ó¤Ï 20 mm¡£PAPER ¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð̵»ë¤µ¤ì¤ë¡£
178
179     <li> -c POS
180
181     POS ¤Ï¥«¡¼¥½¥ë¤Îʸ»ú°ÌÃÖ¡£¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¡¢¥«¡¼¥½¥ë¤ÏÉÁ¤«¤ì¤Ê¤¤¡£
182
183     <li> -x
184
185     FILE ¤Ï m17n ¥é¥¤¥Ö¥é¥ê¤Î¥·¥ê¥¢¥é¥¤¥ºµ¡Ç½¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿ XML ¥Õ¥¡ 
186     ¥¤¥ë¤Ç¤¢¤ê¡¢²èÁü¤òÀ¸À®¤¹¤ëÁ°¤Ë¥Ç¥·¥ê¥¢¥é¥¤¥º¤µ¤ì¤ë¡£
187
188     <li> -w
189
190     ¸ì¤Î¶­³¦¤Ç²þ¹Ô¤¹¤ë¡£ 
191
192     <li> -f FILTER
193
194     FILTER ¤Ï¥·¥§¥ë¥³¥Þ¥ó¥É¹Ô¤ò´Þ¤àʸ»úÎó¤Ç¤¢¤ë¡£¤³¤Î¥ª¥×¥·¥ç¥ó¤¬»ØÄê
195     ¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢PNG ²èÁü¤Ï¥Õ¥¡¥¤¥ë¤Ë½ñ¤«¤ì¤ë¤Î¤Ç¤Ï¤Ê¤¯¡¢FILTER ¤Ë 
196     É¸½àÆþÎϤȤ·¤ÆÅϤµ¤ì¤ë¡£ FILTER ¤¬ "%s" ¤ò´Þ¤ó¤Ç¤¤¤ì¤Ð¡¢¤½¤ì¤Ï FILE 
197     ¤Î¥Ù¡¼¥¹¥Í¡¼¥à¤ËÃÖ¤­´¹¤¨¤é¤ì¤ë¡£¤³¤Î¥×¥í¥°¥é¥à¤Î¥Ç¥Õ¥©¥ë¥È¤Î¿¶Éñ¤¤
198     ¤È¡¢FILTER ¤Ë "cat > %s.png" ¤ò»ØÄꤷ¤¿¾ì¹ç¤Î¿¶Éñ¤ÏƱ°ì¤Ç¤¢¤ë¡£
199
200     ¤â¤· FILTER ¤¬Ã±¤Ë "-" ¤Ç¤¢¤ì¤Ð¡¢ PNG ²èÁü¤Ï stdout ¤Ë½ÐÎϤµ¤ì¤ë¡£
201
202     <li> -a
203
204     ¥¢¥ó¥Á¥¨¥¤¥ê¥¢¥¹½èÍý¤ò¹Ô¤¦¡£
205
206     <li> --family FAMILY
207
208     ¥Õ¥¡¥ß¥ê¥£Ì¾¤¬ FAMILY ¤Î¥Õ¥©¥ó¥È¤òÍ¥ÀèŪ¤Ë»È¤¦¡£
209
210     <li> --language LANG
211
212     ¸À¸ì LANG ÍѤ˻ØÄꤵ¤ì¤¿¥Õ¥©¥ó¥È¤òÍ¥ÀèŪ¤Ë»È¤¦¡£LANG ¤Ï ISO 630 ¤Î
213     £²Ê¸»ú¥³¡¼¥É¡ÊÎ㡧±Ñ¸ì¤Ï "en" ¡Ë¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
214
215     <li> -fg FOREGROUND
216
217     ¥Æ¥­¥¹¥È¤Î¿§¤ò»ØÄꤹ¤ë¡£HTML 4.0 ¤Î¿§¤Î̾Á°¤ª¤è¤Ó "#RRGGBB" µ­Ë¡¤ò
218     ¥µ¥Ý¡¼¥È¡£
219
220     <li> -bg BACKGROUND
221
222     Çطʤ理ò»ØÄꤹ¤ë¡£¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ë¿§¤Î̾Á°¤Ï FOREGROUND Æ±¤¸¡£
223     ¤¿¤À¤·¡¢¤â¤· "transparent" ¤¬»ØÄꤵ¤ì¤¿¤éÇطʤòÆ©ÌÀ¤Ë¤¹¤ë¡£
224
225     <li> -r
226
227     Specify that the orientation of the text is right-to-left.
228
229     <li> -q
230
231     °ìÀڤΥá¥Ã¥»¡¼¥¸¤òɽ¼¨¤·¤Ê¤¤¡£ 
232
233     <li> --version
234
235     ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
236
237     <li> -h, --help
238
239     ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£ 
240
241     </ul>
242 */
243
244 #ifndef FOR_DOXYGEN
245
246 #include <stdio.h>
247 #include <stdlib.h>
248 #include <string.h>
249 #include <ctype.h>
250 #include <libgen.h>
251
252 #if defined (HAVE_FREETYPE) && defined (HAVE_GD)
253 #include <gd.h>
254
255 #include <m17n-gui.h>
256 #include <m17n-misc.h>
257
258 /* Enumuration of the supported paper types.  */
259 enum paper_type
260   {
261     PAPER_A4,
262     PAPER_A4R,
263     PAPER_A5,
264     PAPER_A5R,
265     PAPER_B5,
266     PAPER_B5R,
267     PAPER_LETTER,
268     PAPER_USER,
269     PAPER_NOLIMIT
270   };
271
272 /* Array of paper sizes for the supported paper types.  */
273 struct
274 {
275   int width, height;            /* in millimeter */
276 } paper_size[PAPER_NOLIMIT] = {
277   { 210, 297 },                 /* a4 */
278   { 297, 210 },                 /* a4r */
279   { 148, 210 },                 /* a5 */
280   { 210, 148 },                 /* a5r */
281   { 250, 176 },                 /* b5 */
282   { 176, 250 },                 /* b5r */
283   { 216, 279 },                 /* letter */
284 };
285
286
287 /* Print the usage of this program (the name is PROG), and exit with
288    EXIT_CODE.  */
289
290 void
291 help_exit (char *prog, int exit_code)
292 {
293   char *p = prog;
294
295   while (*p)
296     if (*p++ == '/')
297       prog = p;
298
299   printf ("Usage: %s [ OPTION ...] [ FILE ]\n", prog);
300   printf ("Dump a text as a PNG image into a file.\n");
301   printf ("  The PNG file is created in the current directory\n");
302   printf ("    with the name \"BASE.png\" where BASE is the basename of FILE.\n");
303   printf ("  If FILE is omitted, text is read from standard input, and\n");
304   printf ("    dumped into the file \"output.png\".\n");
305   printf ("The following OPTIONs are available.\n");
306   printf ("  %-13s %s", "-s SIZE",
307           "Font size in 1/10 point (default 120).\n");
308   printf ("  %-13s %s", "-d DPI",
309           "Resolution in dots per inch (defualt 300).\n");
310   printf ("  %-13s %s", "-p PAPER",
311           "Paper size; a4, a4r, a5, a5r, b5, b5r, letter, W, or WxH.\n");
312   printf ("  %-13s %s", "-m MARGIN",
313           "Marginal space in millimeter (default 20).\n");
314   printf ("  %-13s %s", "-c POS",
315           "Character position of cursor to draw (default no cursor)\n");
316   printf ("  %-13s %s", "-x",
317           "FILE is assumed to be an XML file.\n");
318   printf ("  %-13s %s", "-f FILTER",
319           "String containing a shell command line to be used as a filter.\n");
320   printf ("  %-13s %s", "-w", "Each line is broken at word boundary.\n");
321   printf ("  %-13s %s", "-a", "Enable anti-alias drawing.\n");
322   printf ("  %-13s %s", "--family FAMILY", 
323           "Prefer a font whose family is FAMILY.\n");
324   printf ("  %-13s %s", "--language LANG", 
325           "Prefer a font specified for the langauge LANG.\n");
326   printf ("  %-13s %s", "-r", 
327           "Specify that the orientation of the text is right-to-left.\n");
328   printf ("  %-13s %s", "-fg FOREGROUND",
329           "Specify the text color (HTML 4.0 color names or \"#RRGGBB\").\n");
330   printf ("  %-13s %s", "-bg BACKGROUND",
331           "Specify the background color (\"transparent\" for transparent)\n");
332   printf ("  %-13s %s", "-q", "Quiet mode.  Don't print any messages.\n");
333   printf ("  %-13s %s", "--version", "Print the version number.\n");
334   printf ("  %-13s %s", "-h, --help", "Print this message.\n");
335   exit (exit_code);
336 }
337
338
339 /* Format MSG by FMT and print the result to the stderr, and exit.  */
340
341 #define FATAL_ERROR(fmt, arg)   \
342   do {                          \
343     fprintf (stderr, fmt, arg); \
344     exit (1);                   \
345   } while (0)
346
347
348 /* Move POS to the next line head in M-text MT whose length is LEN.
349    If POS is already on the last line, set POS to LEN.  */
350
351 #define NEXTLINE(pos, len)                      \
352   do {                                          \
353     pos = mtext_character (mt, pos, len, '\n'); \
354     if (pos < 0)                                \
355       pos = len;                                \
356     else                                        \
357       pos++;                                    \
358   } while (0)
359
360
361 /* Find the range of M-text MT that fits in one page of height HEIGHT
362    when drawn from the character position POS.  Set RECT->y to the
363    Y-offset of the first baseline.  */
364
365 int
366 find_page_end (MFrame *frame, int height, MText *mt, int pos,
367                MDrawControl *control, MDrawMetric *rect)
368 {
369   int len = mtext_len (mt);
370   int to = pos;
371   int y = 0, yoff;
372
373   while (to < len)
374     {
375       int next = to;
376
377       NEXTLINE (next, len);
378       mdraw_text_extents (frame, mt, to, next, control, NULL, NULL, rect);
379       if (to == pos)
380         yoff = rect->y;
381       if (y + rect->height > height)
382         {
383           MDrawGlyphInfo info;
384
385           while (to < next)
386             {
387               mdraw_glyph_info (frame, mt, to, to, control, &info);
388               if (y + info.metrics.height > height)
389                 break;
390               y += info.metrics.height;
391               to = info.line_to;
392             }
393           break;
394         }
395       y += rect->height;
396       to = next;
397     }
398
399   rect->y = yoff;
400   return to;
401 }
402
403 /* Dump the image in IMAGE into a file whose name is generated from
404    FILENAME and PAGE_INDEX (if it is not zero).  */
405
406 void
407 dump_image (gdImagePtr image, char *filename, char *filter,
408             int page_index, int quiet_mode)
409 {
410   FILE *fp;
411
412   if (page_index)
413     {
414       char *name = alloca (strlen (filename) + 8);
415
416       sprintf (name, "%s.%02d", filename, page_index);
417       filename = name;
418     }
419
420   if (filter)
421     {
422       if (filter[0] == '-' && filter[1] == '\0')
423         fp = stdout;
424       else
425         {
426           char *command = alloca (strlen (filename) + strlen (filter) + 1);
427
428           sprintf (command, filter, filename);
429           fp = popen (command, "w");
430           if (! fp)
431             FATAL_ERROR ("Can't run the command \"%s\"\n", command);
432           if (! quiet_mode)
433             printf ("Running \"%s\" ... ", command);
434         }
435     }
436   else
437     {
438       char *fullname = alloca (strlen (filename) + 5);
439
440       sprintf (fullname, "%s.png", filename);
441       fp = fopen (fullname, "w");
442       if (! fp)
443         FATAL_ERROR ("Can't write to \"%s\"\n", fullname);
444       if (! quiet_mode)
445         printf ("Writing %s ... ", fullname);
446     }
447
448   /* Generate PNG.  */
449   gdImagePng (image, fp);
450   if (fp != stderr)
451     fclose (fp);
452   if (! quiet_mode)
453     printf (" done (%dx%d)\n", image->sx, image->sy);
454 }
455
456 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
457
458 int
459 main (int argc, char **argv)
460 {
461   int fontsize = 120;
462   int paper = PAPER_NOLIMIT;
463   int dpi = 300;
464   int margin = 20;
465   int xml = 0;
466   FILE *fp = stdin;
467   int cursor_pos = -1;
468   int quiet_mode = 0;
469   int break_by_word = 0;
470   char *filter = NULL;
471   int paper_width, paper_height;
472   int anti_alias = 0;
473   char *family_name = NULL;
474   char *lang_name = NULL;
475   char *fg_color = NULL, *bg_color = NULL;
476   int transparent = 0;
477   int r2l = 0;
478   int i;
479   int page_index;
480   gdImagePtr image;
481   int bg_rgb;
482
483   MFrame *frame;
484   MText *mt;
485   MDrawControl control;
486   MDrawMetric rect;
487   char *filename = "output";
488   int len, from;
489   char *fontset_name = "generic";
490
491
492   /* Parse the command line arguments.  */
493   for (i = 1; i < argc; i++)
494     {
495       if (! strcmp (argv[i], "--help")
496                || ! strcmp (argv[i], "-h")
497                || ! strcmp (argv[i], "-?"))
498         help_exit (argv[0], 0);
499       else if (! strcmp (argv[i], "--version"))
500         {
501           printf ("m17n-dump (m17n library) %s\n", M17NLIB_VERSION_NAME);
502           printf ("Copyright (C) 2007 AIST, JAPAN\n");
503           exit (0);
504         }
505       else if (! strcmp (argv[i], "-s") && i + 1< argc)
506         {
507           fontsize = atoi (argv[++i]);
508           if (! fontsize)
509             FATAL_ERROR ("Invalid font size: %s\n", argv[i]);
510         }
511       else if (! strcmp (argv[i], "-p") && i + 1< argc)
512         {
513           int w, h;
514
515           i++;
516           if (! strcmp (argv[i], "a4"))
517             paper = PAPER_A4;
518           else if (! strcmp (argv[i], "a4r"))
519             paper = PAPER_A4R;
520           else if (! strcmp (argv[i], "a5"))
521             paper = PAPER_A5;
522           else if (! strcmp (argv[i], "a5r"))
523             paper = PAPER_A5R;
524           else if (! strcmp (argv[i], "b5"))
525             paper = PAPER_B5;
526           else if (! strcmp (argv[i], "b5r"))
527             paper = PAPER_B5R;
528           else if (! strcmp (argv[i], "letter"))
529             paper = PAPER_LETTER;
530           else if (sscanf (argv[i], "%dx%d", &w, &h) == 2
531                    && w > 0 && h > 0)
532             {
533               paper = PAPER_USER;
534               paper_size[paper].width = w;
535               paper_size[paper].height = h;
536             }
537           else if (sscanf (argv[i], "%d", &w) == 1
538                    && w > 0)
539             {
540               paper = PAPER_USER;
541               paper_size[paper].width = w;
542               paper_size[paper].height = 0;
543             }
544           else
545             FATAL_ERROR ("Invalid paper type: %s\n", argv[i]);
546         }
547       else if (! strcmp (argv[i], "-d") && i + 1< argc)
548         {
549           dpi = atoi (argv[++i]);
550           if (! dpi)
551             FATAL_ERROR ("Invalid resolution: %s\n", argv[i]);
552         }
553       else if (! strcmp (argv[i], "-m") && i + 1< argc)
554         {
555           margin = atoi (argv[++i]);
556           if (margin < 0)
557             FATAL_ERROR ("Invalid margin: %s\n", argv[i]);
558         }
559       else if (! strcmp (argv[i], "-c") && i + 1< argc)
560         {
561           cursor_pos = atoi (argv[++i]);
562           if (cursor_pos < 0)
563             FATAL_ERROR ("Invalid cursor position: %s\n", argv[i]);
564         }
565       else if (! strcmp (argv[i], "-f") && i + 1< argc)
566         {
567           filter = argv[++i];
568         }
569       else if (! strcmp (argv[i], "-x"))
570         {
571           xml = 1;
572         }
573       else if (! strcmp (argv[i], "-w"))
574         {
575           break_by_word = 1;
576         }
577       else if (! strcmp (argv[i], "-q"))
578         {
579           quiet_mode = 1;
580         }
581       else if (! strcmp (argv[i], "-a"))
582         {
583           anti_alias = 1;
584         }
585       else if (! strcmp (argv[i], "--family"))
586         {
587           family_name = argv[++i];
588         }
589       else if (! strcmp (argv[i], "--language"))
590         {
591           lang_name = argv[++i];
592         }
593       else if (! strcmp (argv[i], "-r"))
594         {
595           r2l = 1;
596         }
597       else if (argv[i][0] != '-')
598         {
599           fp = fopen (argv[i], "r");
600           if (! fp)
601             FATAL_ERROR ("Fail to open the file %s!\n", argv[i]);
602           filename = basename (argv[i]);
603         }
604       else if (! strcmp (argv[i], "--fontset"))
605         {
606           fontset_name = argv[++i];
607         }
608       else if (! strcmp (argv[i], "-fg"))
609         {
610           if (i + 1 == argc)
611             {
612               fprintf (stderr, "Foreground color not specified\n");
613               help_exit (argv[0], 1);
614             }
615           fg_color = argv[++i];
616         }
617       else if (! strcmp (argv[i], "-bg"))
618         {
619           if (i + 1 == argc)
620             {
621               fprintf (stderr, "Background color not specified\n");
622               help_exit (argv[0], 1);
623             }
624           i++;
625           if (! strcmp (argv[i], "transparent"))
626             transparent = 1;
627           else
628             bg_color = argv[i];
629         }
630       else
631         {
632           fprintf (stderr, "Unknown or invalid option: %s\n", argv[i]);
633           help_exit (argv[0], 1);
634         }
635     }
636
637   /* Initialize the m17n library.  */
638   M17N_INIT ();
639   if (merror_code != MERROR_NONE)
640     FATAL_ERROR ("%s\n", "Fail to initialize the m17n library.");
641
642   mt = mconv_decode_stream (Mcoding_utf_8, fp);
643   fclose (fp);
644   if (xml)
645     mt = mtext_deserialize (mt);
646   if (! mt)
647     FATAL_ERROR ("%s\n", "Fail to decode the input file or stream!");
648
649   len = mtext_len (mt);
650   if (lang_name)
651     mtext_put_prop (mt, 0, len, Mlanguage, msymbol (lang_name));
652
653   if (paper == PAPER_NOLIMIT)
654     paper_width = paper_height = margin = 0;
655   else
656     {
657       paper_width = paper_size[paper].width * dpi / 25.4;
658       paper_height = paper_size[paper].height * dpi / 25.4;
659       margin = margin * dpi / 25.4;
660     }
661
662   {
663     MPlist *plist = mplist (), *p;
664     MFontset *fontset = mfontset (fontset_name);
665     MFace *face = mface ();
666
667     mface_put_prop (face, Mfontset, fontset);
668     mface_put_prop (face, Msize, (void *) (fontsize * dpi / 100));
669     if (family_name)
670       {
671         char *p;
672
673         for (p = family_name; *p; p++)
674           if (isupper (*p)) *p = tolower (*p);
675         mface_put_prop (face, Mfamily, msymbol (family_name));
676       }
677     if (fg_color)
678       mface_put_prop (face, Mforeground, msymbol (fg_color));
679     if (bg_color)
680       mface_put_prop (face, Mbackground, msymbol (bg_color));
681     p = mplist_add (plist, Mdevice, msymbol ("gd"));
682     p = mplist_add (p, Mface, face);
683     m17n_object_unref (face);
684     frame = mframe (plist);
685     m17n_object_unref (plist);
686     if (! frame)
687       FATAL_ERROR ("%s\n", "Can't open a frame (perhaps no font available)!");
688   }
689
690   memset (&control, 0, sizeof control);
691   control.two_dimensional = 1;
692   control.enable_bidi = 1;
693   control.anti_alias = anti_alias;
694   control.orientation_reversed = r2l;
695   if (cursor_pos >= 0)
696     {
697       control.with_cursor = 1;
698       if (cursor_pos > len)
699         cursor_pos = len;
700       control.cursor_pos = cursor_pos;
701       control.cursor_width = -1;
702     }
703   else
704     control.ignore_formatting_char = 1;
705   if (break_by_word)
706     control.line_break = mdraw_default_line_break;
707
708   if (paper == PAPER_NOLIMIT)
709     {
710       control.max_line_width = 0;
711       mdraw_text_extents (frame, mt, 0, len, &control, NULL, NULL, &rect);
712       paper_width = rect.width;
713       paper_height = rect.height;
714     }
715   else
716     {
717       control.max_line_width = paper_width - margin * 2;
718       if (paper_height == 0)
719         {
720           mdraw_text_extents (frame, mt, 0, len, &control, NULL, NULL, &rect);
721           paper_height = rect.height + margin * 2;
722         }
723     }
724
725 #if HAVE_GD > 1
726   image = gdImageCreateTrueColor (paper_width, paper_height);
727 #else
728   image = gdImageCreate (paper_width, paper_height);
729 #endif
730   from = 0;
731   page_index = 1;
732
733   if (transparent)
734     {
735       MFace *face = mframe_get_prop (frame, Mface);
736       MSymbol fg = mface_get_prop (face, Mforeground);
737       int rgb_value = 0;
738
739       if (fg)
740         rgb_value = (int) msymbol_get (fg, msymbol ("  rgb"));
741       if (rgb_value == 0xFFFFFF)
742         bg_rgb = gdImageColorAllocate (image, 0, 0, 0);
743       else
744         bg_rgb = gdImageColorAllocate (image, 255, 255, 255);
745       gdImageColorTransparent (image, bg_rgb);
746 #if HAVE_GD > 1
747       gdImageAlphaBlending (image, 0);
748 #endif
749     }
750   else
751     {
752       MFace *face = mframe_get_prop (frame, Mface);
753       MSymbol bg = mface_get_prop (face, Mbackground);
754       if (bg)
755         {
756           int rgb_value = (int) msymbol_get (bg, msymbol ("  rgb"));
757           bg_rgb = gdImageColorAllocate (image, rgb_value >> 16, 
758                                          (rgb_value >> 8) & 255, 
759                                          rgb_value & 255);
760         }
761       else
762         bg_rgb = gdImageColorAllocate (image, 255, 255, 255);
763     }
764
765   while (from < len)
766     {
767       int to;
768
769       if (paper == PAPER_NOLIMIT || paper_size[paper].height == 0)
770         to = len;
771       else
772         to = find_page_end (frame, paper_height - margin * 2, mt, from,
773                             &control, &rect);
774
775       gdImageFilledRectangle (image, 0, 0, paper_width - 1, paper_height - 1,
776                               bg_rgb);
777       if (! r2l)
778         mdraw_text_with_control (frame, image,
779                                  margin, margin - rect.y,
780                                  mt, from, to, &control);
781       else
782         mdraw_text_with_control (frame, image,
783                                  paper_width - margin, margin - rect.y,
784                                  mt, from, to, &control);
785       dump_image (image, filename, filter,
786                   ((from > 0 || to < len) ? page_index : 0),
787                   quiet_mode);
788
789       from = to;
790       page_index++;
791     }
792
793   m17n_object_unref (frame);
794   m17n_object_unref (mt);
795   M17N_FINI ();
796   gdImageDestroy (image);
797   exit (0);
798 }
799
800 #else  /* not HAVE_FREETYPE nor HAVE_GD */
801
802 int
803 main (int argc, char **argv)
804 {
805   fprintf (stderr, "Can't run without Freetype and GD library!\n");
806   exit (1);
807 }
808
809 #endif  /* not HAVE_FREETYPE nor HAVE_GD */
810 #endif /* not FOR_DOXYGEN */