(main): Handle --font arg.
[m17n/m17n-lib.git] / example / mdump.c
1 /* mdump.c -- Dump text image                           -*- coding: euc-jp; -*-
2    Copyright (C) 2003, 2004, 2005
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., 59 Temple Place, Suite 330, Boston, MA
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> -r
107
108     Specify that the orientation of the text is right-to-left.
109
110     <li> -q
111
112     Quiet mode.  Don't print any messages.
113
114     <li> --version
115
116     Print the version number.
117
118     <li> -h, --help
119
120     Print this message.
121
122     </ul>
123 */
124 /***ja
125     @japage m17n-dump ¥Æ¥­¥¹¥È²èÁü¤Î¥À¥ó¥×
126
127     @section m17n-dump-synopsis SYNOPSIS
128
129     m17n-dump [ OPTION ... ] [ FILE ]
130
131     @section m17n-dump-description DESCRIPTION
132
133     ¥Æ¥­¥¹¥È¤ò PNG ²èÁü¤È¤·¤Æ¥À¥ó¥×¤¹¤ë¡£ 
134
135     PNG ²èÁü¤Ï¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ëºî¤é¤ì¤¿ "BASE.png" ¤È¤¤¤¦Ì¾Á°¤Î 
136     ¥Õ¥¡¥¤¥ë¤Ë½ñ¤­¹þ¤Þ¤ì¤ë¡£¤³¤³¤Ç BASE ¤ÏFILE ¤Î basename ¤Ç¤¢¤ë¡£ 
137     FILE ¤¬¾Êά¤µ¤ì¤ì¤Ð¡¢¥Æ¥­¥¹¥È¤Ïɸ½àÆþÎϤ«¤éÆɤޤ졢²èÁü¤Ï 
138     "output.png" ¤Ë¥À¥ó¥×¤µ¤ì¤ë¡£
139
140     °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ­¤ë¡£
141
142     <ul>
143
144     <li> -s SIZE
145
146     SIZE ¤Ï¥Õ¥©¥ó¥È¤ÎÂ礭¤µ¤ò¥Ý¥¤¥ó¥Èñ°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç¥Õ¥©¥ë
147     ¥È¤ÎÂ礭¤µ¤Ï 12 ¥Ý¥¤¥ó¥È¡£
148
149     <li> -d DPI
150
151     DPI ¤Ï²òÁüÅÙ¤ò£±¥¤¥ó¥Á¤¢¤¿¤ê¤Î¥É¥Ã¥Èñ°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç¥Õ¥© 
152     ¥ë¥È¤Î²òÁüÅ٤Ϡ300 dpi¡£
153
154     <li> -p PAPER
155
156     PAPER ¤Ï¤Ú¡¼¥Ñ¥µ¥¤¥º : a4, a4r, a5, a5r, b5, b5r, letter, WxH ¤Þ¤¿
157     ¤Ï W¡£ WxH ¤Î¾ì¹ç¡¢ W ¤È H ¤ÏÉý¤È¹â¤µ¤ò¥ß¥ê¥á¡¼¥¿Ã±°Ì¤Ç¼¨¤·¤¿¤â¤Î¡£
158     W ¤Î¾ì¹ç¡¢ W ¤ÏÉý¤ò¥ß¥ê¥á¡¼¥¿Ã±°Ì¤Ç¼¨¤·¤¿¤â¤Î¡£¤³¤Î¥ª¥×¥·¥ç¥ó¤¬»ØÄê
159     ¤µ¤ì¤Æ¤¤¤ë¾ì¹ç¤Ï¡¢ PAPER ¤¬²èÁü¥µ¥¤¥º¤òÀ©¸Â¤¹ ¤ë¡£FILE ¤¬ 1 ¥Ú¡¼¥¸
160     ¤ËǼ¤Þ¤é¤Ê¤¤¤Û¤ÉÂ礭¤¤¾ì¹ç¤Ï¡¢"BASE.01.png", "BASE.02.png" Åù¤Î̾Á°
161     ¤Î¤Ä¤¤¤¿Ê£¿ô¤Î¥Õ¥¡¥¤¥ë¤¬ºî¤é¤ì¤ë¡£
162
163     <li> -m MARGIN
164
165     MARGIN ¤Ï¿åÊ¿¡¢¿âľ¥Þ¡¼¥¸¥ó¤ò¥ß¥ê¥á¡¼¥¿Ã±°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç 
166     ¥Õ¥©¥ë¥È¤Î¥Þ¡¼¥¸¥ó¤Ï 20 mm¡£PAPER ¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð̵»ë¤µ¤ì¤ë¡£
167
168     <li> -c POS
169
170     POS ¤Ï¥«¡¼¥½¥ë¤Îʸ»ú°ÌÃÖ¡£¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¡¢¥«¡¼¥½¥ë¤ÏÉÁ¤«¤ì¤Ê¤¤¡£
171
172     <li> -x
173
174     FILE ¤Ï m17n ¥é¥¤¥Ö¥é¥ê¤Î¥·¥ê¥¢¥é¥¤¥ºµ¡Ç½¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿ XML ¥Õ¥¡ 
175     ¥¤¥ë¤Ç¤¢¤ê¡¢²èÁü¤òÀ¸À®¤¹¤ëÁ°¤Ë¥Ç¥·¥ê¥¢¥é¥¤¥º¤µ¤ì¤ë¡£
176
177     <li> -w
178
179     ¸ì¤Î¶­³¦¤Ç²þ¹Ô¤¹¤ë¡£ 
180
181     <li> -f FILTER
182
183     FILTER ¤Ï¥·¥§¥ë¥³¥Þ¥ó¥É¹Ô¤ò´Þ¤àʸ»úÎó¤Ç¤¢¤ë¡£¤³¤Î¥ª¥×¥·¥ç¥ó¤¬»ØÄê
184     ¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢PNG ²èÁü¤Ï¥Õ¥¡¥¤¥ë¤Ë½ñ¤«¤ì¤ë¤Î¤Ç¤Ï¤Ê¤¯¡¢FILTER ¤Ë 
185     É¸½àÆþÎϤȤ·¤ÆÅϤµ¤ì¤ë¡£ FILTER ¤¬ "%s" ¤ò´Þ¤ó¤Ç¤¤¤ì¤Ð¡¢¤½¤ì¤Ï FILE 
186     ¤Î¥Ù¡¼¥¹¥Í¡¼¥à¤ËÃÖ¤­´¹¤¨¤é¤ì¤ë¡£¤³¤Î¥×¥í¥°¥é¥à¤Î¥Ç¥Õ¥©¥ë¥È¤Î¿¶Éñ¤¤
187     ¤È¡¢FILTER ¤Ë "cat > %s.png" ¤ò»ØÄꤷ¤¿¾ì¹ç¤Î¿¶Éñ¤ÏƱ°ì¤Ç¤¢¤ë¡£
188
189     ¤â¤· FILTER ¤¬Ã±¤Ë "-" ¤Ç¤¢¤ì¤Ð¡¢ PNG ²èÁü¤Ï stdout ¤Ë½ÐÎϤµ¤ì¤ë¡£
190
191     <li> -a
192
193     ¥¢¥ó¥Á¥¨¥¤¥ê¥¢¥¹½èÍý¤ò¹Ô¤¦¡£
194
195     <li> --family FAMILY
196
197     ¥Õ¥¡¥ß¥ê¥£Ì¾¤¬ FAMILY ¤Î¥Õ¥©¥ó¥È¤òÍ¥ÀèŪ¤Ë»È¤¦¡£
198
199     <li> --language LANG
200
201     ¸À¸ì LANG ÍѤ˻ØÄꤵ¤ì¤¿¥Õ¥©¥ó¥È¤òÍ¥ÀèŪ¤Ë»È¤¦¡£LANG ¤Ï ISO 630 ¤Î
202     £²Ê¸»ú¥³¡¼¥É¡ÊÎ㡧±Ñ¸ì¤Ï "en" ¡Ë¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
203
204     <li> -q
205
206     °ìÀڤΥá¥Ã¥»¡¼¥¸¤òɽ¼¨¤·¤Ê¤¤¡£ 
207
208     <li> --version
209
210     ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
211
212     <li> -h, --help
213
214     ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£ 
215
216     </ul>
217 */
218
219 #ifndef FOR_DOXYGEN
220
221 #include <stdio.h>
222 #include <stdlib.h>
223 #include <string.h>
224 #include <ctype.h>
225 #include <libgen.h>
226
227 #if defined (HAVE_FREETYPE) && defined (HAVE_GD)
228 #include <gd.h>
229
230 #include <m17n-gui.h>
231 #include <m17n-misc.h>
232
233 #define PROGRAM_VERSION "1.1"
234
235 /* Enumuration of the supported paper types.  */
236 enum paper_type
237   {
238     PAPER_A4,
239     PAPER_A4R,
240     PAPER_A5,
241     PAPER_A5R,
242     PAPER_B5,
243     PAPER_B5R,
244     PAPER_LETTER,
245     PAPER_USER,
246     PAPER_NOLIMIT
247   };
248
249 /* Array of paper sizes for the supported paper types.  */
250 struct
251 {
252   int width, height;            /* in millimeter */
253 } paper_size[PAPER_NOLIMIT] = {
254   { 210, 297 },                 /* a4 */
255   { 297, 210 },                 /* a4r */
256   { 148, 210 },                 /* a5 */
257   { 210, 148 },                 /* a5r */
258   { 250, 176 },                 /* b5 */
259   { 176, 250 },                 /* b5r */
260   { 216, 279 },                 /* letter */
261 };
262
263
264 /* Print the usage of this program (the name is PROG), and exit with
265    EXIT_CODE.  */
266
267 void
268 help_exit (char *prog, int exit_code)
269 {
270   char *p = prog;
271
272   while (*p)
273     if (*p++ == '/')
274       prog = p;
275
276   printf ("Usage: %s [ OPTION ...] [ FILE ]\n", prog);
277   printf ("Dump a text as a PNG image into a file.\n");
278   printf ("  The PNG file is created in the current directory\n");
279   printf ("    with the name \"BASE.png\" where BASE is the basename of FILE.\n");
280   printf ("  If FILE is omitted, text is read from standard input, and\n");
281   printf ("    dumped into the file \"output.png\".\n");
282   printf ("The following OPTIONs are available.\n");
283   printf ("  %-13s %s", "-s SIZE",
284           "Font size in 1/10 point (default 120).\n");
285   printf ("  %-13s %s", "-d DPI",
286           "Resolution in dots per inch (defualt 300).\n");
287   printf ("  %-13s %s", "-p PAPER",
288           "Paper size; a4, a4r, a5, a5r, b5, b5r, letter, W, or WxH.\n");
289   printf ("  %-13s %s", "-m MARGIN",
290           "Marginal space in millimeter (default 20).\n");
291   printf ("  %-13s %s", "-c POS",
292           "Character position of cursor to draw (default no cursor)\n");
293   printf ("  %-13s %s", "-x",
294           "FILE is assumed to be an XML file.\n");
295   printf ("  %-13s %s", "-f FILTER",
296           "String containing a shell command line to be used as a filter.\n");
297   printf ("  %-13s %s", "-w", "Each line is broken at word boundary.\n");
298   printf ("  %-13s %s", "-a", "Enable anti-alias drawing.\n");
299   printf ("  %-13s %s", "--family FAMILY", 
300           "Prefer a font whose family is FAMILY.\n");
301   printf ("  %-13s %s", "--language LANG", 
302           "Prefer a font specified for the langauge LANG.\n");
303   printf ("  %-13s %s", "-r", 
304           "Specify that the orientation of the text is right-to-left.\n");
305   printf ("  %-13s %s", "-q", "Quiet mode.  Don't print any messages.\n");
306   printf ("  %-13s %s", "--version", "Print the version number.\n");
307   printf ("  %-13s %s", "-h, --help", "Print this message.\n");
308   exit (exit_code);
309 }
310
311
312 /* Format MSG by FMT and print the result to the stderr, and exit.  */
313
314 #define FATAL_ERROR(fmt, arg)   \
315   do {                          \
316     fprintf (stderr, fmt, arg); \
317     exit (1);                   \
318   } while (0)
319
320
321 /* Move POS to the next line head in M-text MT whose length is LEN.
322    If POS is already on the last line, set POS to LEN.  */
323
324 #define NEXTLINE(pos, len)                      \
325   do {                                          \
326     pos = mtext_character (mt, pos, len, '\n'); \
327     if (pos < 0)                                \
328       pos = len;                                \
329     else                                        \
330       pos++;                                    \
331   } while (0)
332
333
334 /* Find the range of M-text MT that fits in one page of height HEIGHT
335    when drawn from the character position POS.  Set RECT->y to the
336    Y-offset of the first baseline.  */
337
338 int
339 find_page_end (MFrame *frame, int height, MText *mt, int pos,
340                MDrawControl *control, MDrawMetric *rect)
341 {
342   int len = mtext_len (mt);
343   int to = pos;
344   int y = 0, yoff;
345
346   while (to < len)
347     {
348       int next = to;
349
350       NEXTLINE (next, len);
351       mdraw_text_extents (frame, mt, to, next, control, NULL, NULL, rect);
352       if (to == pos)
353         yoff = rect->y;
354       if (y + rect->height > height)
355         {
356           MDrawGlyphInfo info;
357
358           while (to < next)
359             {
360               mdraw_glyph_info (frame, mt, to, to, control, &info);
361               if (y + info.metrics.height > height)
362                 break;
363               y += info.metrics.height;
364               to = info.line_to;
365             }
366           break;
367         }
368       y += rect->height;
369       to = next;
370     }
371
372   rect->y = yoff;
373   return to;
374 }
375
376 /* Dump the image in IMAGE into a file whose name is generated from
377    FILENAME and PAGE_INDEX (if it is not zero).  */
378
379 void
380 dump_image (gdImagePtr image, char *filename, char *filter,
381             int page_index, int quiet_mode)
382 {
383   FILE *fp;
384
385   if (page_index)
386     {
387       char *name = alloca (strlen (filename) + 8);
388
389       sprintf (name, "%s.%02d", filename, page_index);
390       filename = name;
391     }
392
393   if (filter)
394     {
395       if (filter[0] == '-' && filter[1] == '\0')
396         fp = stdout;
397       else
398         {
399           char *command = alloca (strlen (filename) + strlen (filter) + 1);
400
401           sprintf (command, filter, filename);
402           fp = popen (command, "w");
403           if (! fp)
404             FATAL_ERROR ("Can't run the command \"%s\"\n", command);
405           if (! quiet_mode)
406             printf ("Running \"%s\" ... ", command);
407         }
408     }
409   else
410     {
411       char *fullname = alloca (strlen (filename) + 5);
412
413       sprintf (fullname, "%s.png", filename);
414       fp = fopen (fullname, "w");
415       if (! fp)
416         FATAL_ERROR ("Can't write to \"%s\"\n", fullname);
417       if (! quiet_mode)
418         printf ("Writing %s ... ", fullname);
419     }
420
421   /* Generate PNG.  */
422   gdImagePng (image, fp);
423   if (fp != stderr)
424     fclose (fp);
425   if (! quiet_mode)
426     printf (" done (%dx%d)\n", image->sx, image->sy);
427 }
428
429 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
430
431 int
432 main (int argc, char **argv)
433 {
434   int fontsize = 120;
435   int paper = PAPER_NOLIMIT;
436   int dpi = 300;
437   int margin = 20;
438   int xml = 0;
439   FILE *fp = stdin;
440   int cursor_pos = -1;
441   int quiet_mode = 0;
442   int break_by_word = 0;
443   char *filter = NULL;
444   int paper_width, paper_height;
445   int anti_alias = 0;
446   char *family_name = NULL;
447   char *lang_name = NULL;
448   int r2l = 0;
449   int i;
450   int page_index;
451   gdImagePtr image;
452   int white;
453
454   MFrame *frame;
455   MText *mt;
456   MDrawControl control;
457   MDrawMetric rect;
458   char *filename = "output";
459   int len, from;
460   char *fontset_name = "truetype";
461
462
463   /* Parse the command line arguments.  */
464   for (i = 1; i < argc; i++)
465     {
466       if (! strcmp (argv[i], "--help")
467                || ! strcmp (argv[i], "-h")
468                || ! strcmp (argv[i], "-?"))
469         help_exit (argv[0], 0);
470       else if (! strcmp (argv[i], "--version"))
471         {
472           printf ("m17n-dump (m17n library) %s\n", PROGRAM_VERSION);
473           printf ("Copyright (C) 2003, 2004 AIST, JAPAN\n");
474           exit (0);
475         }
476       else if (! strcmp (argv[i], "-s") && i + 1< argc)
477         {
478           fontsize = atoi (argv[++i]);
479           if (! fontsize)
480             FATAL_ERROR ("Invalid font size: %s\n", argv[i]);
481         }
482       else if (! strcmp (argv[i], "-p") && i + 1< argc)
483         {
484           int w, h;
485
486           i++;
487           if (! strcmp (argv[i], "a4"))
488             paper = PAPER_A4;
489           else if (! strcmp (argv[i], "a4r"))
490             paper = PAPER_A4R;
491           else if (! strcmp (argv[i], "a5"))
492             paper = PAPER_A5;
493           else if (! strcmp (argv[i], "a5r"))
494             paper = PAPER_A5R;
495           else if (! strcmp (argv[i], "b5"))
496             paper = PAPER_B5;
497           else if (! strcmp (argv[i], "b5r"))
498             paper = PAPER_B5R;
499           else if (! strcmp (argv[i], "letter"))
500             paper = PAPER_LETTER;
501           else if (sscanf (argv[i], "%dx%d", &w, &h) == 2
502                    && w > 0 && h > 0)
503             {
504               paper = PAPER_USER;
505               paper_size[paper].width = w;
506               paper_size[paper].height = h;
507             }
508           else if (sscanf (argv[i], "%d", &w) == 1
509                    && w > 0)
510             {
511               paper = PAPER_USER;
512               paper_size[paper].width = w;
513               paper_size[paper].height = 0;
514             }
515           else
516             FATAL_ERROR ("Invalid paper type: %s\n", argv[i]);
517         }
518       else if (! strcmp (argv[i], "-d") && i + 1< argc)
519         {
520           dpi = atoi (argv[++i]);
521           if (! dpi)
522             FATAL_ERROR ("Invalid resolution: %s\n", argv[i]);
523         }
524       else if (! strcmp (argv[i], "-m") && i + 1< argc)
525         {
526           margin = atoi (argv[++i]);
527           if (margin < 0)
528             FATAL_ERROR ("Invalid margin: %s\n", argv[i]);
529         }
530       else if (! strcmp (argv[i], "-c") && i + 1< argc)
531         {
532           cursor_pos = atoi (argv[++i]);
533           if (cursor_pos < 0)
534             FATAL_ERROR ("Invalid cursor position: %s\n", argv[i]);
535         }
536       else if (! strcmp (argv[i], "-f") && i + 1< argc)
537         {
538           filter = argv[++i];
539         }
540       else if (! strcmp (argv[i], "-x"))
541         {
542           xml = 1;
543         }
544       else if (! strcmp (argv[i], "-w"))
545         {
546           break_by_word = 1;
547         }
548       else if (! strcmp (argv[i], "-q"))
549         {
550           quiet_mode = 1;
551         }
552       else if (! strcmp (argv[i], "-a"))
553         {
554           anti_alias = 1;
555         }
556       else if (! strcmp (argv[i], "--family"))
557         {
558           family_name = argv[++i];
559         }
560       else if (! strcmp (argv[i], "--language"))
561         {
562           lang_name = argv[++i];
563         }
564       else if (! strcmp (argv[i], "-r"))
565         {
566           r2l = 1;
567         }
568       else if (argv[i][0] != '-')
569         {
570           fp = fopen (argv[i], "r");
571           if (! fp)
572             FATAL_ERROR ("Fail to open the file %s!\n", argv[i]);
573           filename = basename (argv[i]);
574         }
575       else if (! strcmp (argv[i], "--fontset"))
576         {
577           fontset_name = argv[++i];
578         }
579
580       else
581         {
582           fprintf (stderr, "Unknown or invalid option: %s\n", argv[i]);
583           help_exit (argv[0], 1);
584         }
585     }
586
587   /* Initialize the m17n library.  */
588   M17N_INIT ();
589   if (merror_code != MERROR_NONE)
590     FATAL_ERROR ("%s\n", "Fail to initialize the m17n library.");
591
592   mt = mconv_decode_stream (Mcoding_utf_8, fp);
593   fclose (fp);
594   if (xml)
595     mt = mtext_deserialize (mt);
596   if (! mt)
597     FATAL_ERROR ("%s\n", "Fail to decode the input file or stream!");
598
599   len = mtext_len (mt);
600   if (lang_name)
601     mtext_put_prop (mt, 0, len, Mlanguage, msymbol (lang_name));
602
603   if (paper == PAPER_NOLIMIT)
604     paper_width = paper_height = margin = 0;
605   else
606     {
607       paper_width = paper_size[paper].width * dpi / 25.4;
608       paper_height = paper_size[paper].height * dpi / 25.4;
609       margin = margin * dpi / 25.4;
610     }
611
612   {
613     MPlist *plist = mplist (), *p;
614     MFontset *fontset = mfontset (fontset_name);
615     MFace *face = mface ();
616
617     mface_put_prop (face, Mfontset, fontset);
618     mface_put_prop (face, Msize, (void *) (fontsize * dpi / 100));
619     if (family_name)
620       {
621         char *p;
622
623         for (p = family_name; *p; p++)
624           if (isupper (*p)) *p = tolower (*p);
625         mface_put_prop (face, Mfamily, msymbol (family_name));
626       }
627
628     p = mplist_add (plist, Mdevice, msymbol ("gd"));
629     p = mplist_add (p, Mface, face);
630     m17n_object_unref (face);
631     frame = mframe (plist);
632     m17n_object_unref (plist);
633     if (! frame)
634       FATAL_ERROR ("%s\n", "Can't open a frame (perhaps no font available)!");
635   }
636
637   memset (&control, 0, sizeof control);
638   control.two_dimensional = 1;
639   control.enable_bidi = 1;
640   control.anti_alias = anti_alias;
641   control.orientation_reversed = r2l;
642   if (cursor_pos >= 0)
643     {
644       control.with_cursor = 1;
645       if (cursor_pos > len)
646         cursor_pos = len;
647       control.cursor_pos = cursor_pos;
648       control.cursor_width = -1;
649     }
650   else
651     control.ignore_formatting_char = 1;
652   if (break_by_word)
653     control.line_break = mdraw_default_line_break;
654
655   if (paper == PAPER_NOLIMIT)
656     {
657       control.max_line_width = 0;
658       mdraw_text_extents (frame, mt, 0, len, &control, NULL, NULL, &rect);
659       paper_width = rect.width;
660       paper_height = rect.height;
661     }
662   else
663     {
664       control.max_line_width = paper_width - margin * 2;
665       if (paper_height == 0)
666         {
667           mdraw_text_extents (frame, mt, 0, len, &control, NULL, NULL, &rect);
668           paper_height = rect.height + margin * 2;
669         }
670     }
671
672   image = gdImageCreate (paper_width, paper_height);
673   from = 0;
674   page_index = 1;
675   white = gdImageColorAllocate (image, 255, 255, 255);
676   gdImageColorTransparent (image, white);
677   while (from < len)
678     {
679       int to;
680
681       if (paper == PAPER_NOLIMIT || paper_size[paper].height == 0)
682         to = len;
683       else
684         to = find_page_end (frame, paper_height - margin * 2, mt, from,
685                             &control, &rect);
686
687       gdImageFilledRectangle (image, 0, 0, paper_width - 1, paper_height - 1,
688                               white);
689       if (! r2l)
690         mdraw_text_with_control (frame, image,
691                                  margin, margin - rect.y,
692                                  mt, from, to, &control);
693       else
694         mdraw_text_with_control (frame, image,
695                                  paper_width - margin, margin - rect.y,
696                                  mt, from, to, &control);
697       dump_image (image, filename, filter,
698                   ((from > 0 || to < len) ? page_index : 0),
699                   quiet_mode);
700
701       from = to;
702       page_index++;
703     }
704
705   m17n_object_unref (frame);
706   m17n_object_unref (mt);
707   M17N_FINI ();
708   gdImageDestroy (image);
709   exit (0);
710 }
711
712 #else  /* not HAVE_FREETYPE nor HAVE_GD */
713
714 int
715 main (int argc, char **argv)
716 {
717   fprintf (stderr, "Can't run without Freetype and GD library!\n");
718   exit (1);
719 }
720
721 #endif  /* not HAVE_FREETYPE nor HAVE_GD */
722 #endif /* not FOR_DOXYGEN */