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