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