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
6 This file is part of the m17n library.
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.
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.
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
24 @enpage mdump dump text image
26 @section mdump-synopsis SYNOPSIS
28 mdump [ OPTION ... ] [ FILE ]
30 @section mdump-description DESCRIPTION
32 Dump a text as a Netpbm image.
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".
39 The following OPTIONs are available.
45 SIZE is the font size in point. The default font size is 12 point.
49 DPI is the resolution in dots per inch. The default resolution is
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.
62 MARGIN is the horizontal and vertical margin in millimeter. The
63 default margin is 20 mm. It is ignored when PAPER is not
68 POS is the character position of cursor to draw. By default,
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
79 Each line is broken at word boundary.
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 >
92 Quiet mode. Don't print any messages.
96 Print the version number.
105 @japage mdump ¥Æ¥¥¹¥È²èÁü¤Î¥À¥ó¥×
107 @section mdump-synopsis SYNOPSIS
109 mdump [ OPTION ... ] [ FILE ]
111 @section mdump-description DESCRIPTION
113 ¥Æ¥¥¹¥È¤ò Netpbm ²èÁü¤È¤·¤Æ¥À¥ó¥×¤¹¤ë¡£
115 Netpbm ²èÁü¤Ï¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ëºî¤é¤ì¤¿ "BASE.pbm" ¤È¤¤¤¦Ì¾Á°¤Î
116 ¥Õ¥¡¥¤¥ë¤Ë½ñ¤¹þ¤Þ¤ì¤ë¡£¤³¤³¤Ç BASE ¤ÏFILE ¤Î basename ¤Ç¤¢¤ë¡£
117 FILE ¤¬¾Êά¤µ¤ì¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ïɸ½àÆþÎϤ«¤éÆɤޤ졢²èÁü¤Ï
118 "output.pbm" ¤Ë¥À¥ó¥×¤µ¤ì¤ë¡£
120 °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ¤ë¡£
126 SIZE ¤Ï¥Õ¥©¥ó¥È¤ÎÂ礤µ¤ò¥Ý¥¤¥ó¥Èñ°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç¥Õ¥©¥ë
127 ¥È¤ÎÂ礤µ¤Ï 12 ¥Ý¥¤¥ó¥È¡£
131 DPI ¤Ï²òÁüÅÙ¤ò£±¥¤¥ó¥Á¤¢¤¿¤ê¤Î¥É¥Ã¥Èñ°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç¥Õ¥©
132 ¥ë¥È¤Î²òÁüÅÙ¤Ï 300 dpi¡£
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" Åù¤Î̾Á°¤Î¤Ä¤¤¤¿Ê£¿ô¤Î¥Õ¥¡¥¤¥ë¤¬ºî¤é¤ì¤ë¡£
144 MARGIN ¤Ï¿åÊ¿¡¢¿âľ¥Þ¡¼¥¸¥ó¤ò¥ß¥ê¥á¡¼¥¿Ã±°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç
145 ¥Õ¥©¥ë¥È¤Î¥Þ¡¼¥¸¥ó¤Ï 20 mm¡£PAPER ¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð̵»ë¤µ¤ì¤ë¡£
149 POS ¤Ï¥«¡¼¥½¥ë¤Îʸ»ú°ÌÃÖ¡£¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¡¢¥«¡¼¥½¥ë¤ÏÉÁ¤«¤ì¤Ê¤¤¡£
153 FILE ¤Ï m17n ¥é¥¤¥Ö¥é¥ê¤Î¥·¥ê¥¢¥é¥¤¥ºµ¡Ç½¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿ XML ¥Õ¥¡
154 ¥¤¥ë¤Ç¤¢¤ê¡¢²èÁü¤òÀ¸À®¤¹¤ëÁ°¤Ë¥Ç¥·¥ê¥¢¥é¥¤¥º¤µ¤ì¤ë¡£
162 FILTER ¤Ï¥·¥§¥ë¥³¥Þ¥ó¥É¹Ô¤ò´Þ¤àʸ»úÎó¤Ç¤¢¤ë¡£¤³¤Î¥ª¥×¥·¥ç¥ó¤¬»ØÄê
163 ¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢Netpbm ²èÁü¤Ï¥Õ¥¡¥¤¥ë¤Ë½ñ¤«¤ì¤ë¤Î¤Ç¤Ï¤Ê¤¯¡¢FILTER ¤Ë
164 ɸ½àÆþÎϤȤ·¤ÆÅϤµ¤ì¤ë¡£ FILTER ¤¬ "s" ¤ò´Þ¤ó¤Ç¤¤¤ì¤Ð¡¢¤½¤ì¤Ï FILE
165 ¤Î¥Ù¡¼¥¹¥Í¡¼¥à¤ËÃÖ¤´¹¤¨¤é¤ì¤ë¡£¤³¤Î¥×¥í¥°¥é¥à¤Î¥Ç¥Õ¥©¥ë¥È¤Î¿¶Éñ¤¤
166 ¤È¡¢FILTER ¤Ë "cat > s.pbm" ¤ò»ØÄꤷ¤¿¾ì¹ç¤Î¿¶Éñ¤ÏƱ°ì¤Ç¤¢¤ë¡£
170 °ìÀڤΥá¥Ã¥»¡¼¥¸¤òɽ¼¨¤·¤Ê¤¤¡£
174 ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
178 ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£
190 #include <X11/Xlib.h>
192 #include <m17n-gui.h>
193 #include <m17n-misc.h>
195 #define VERSION "1.0"
197 /* Enumuration of the supported paper types. */
211 /* Array of paper sizes for the supported paper types. */
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 */
226 /* Print the usage of this program (the name is PROG), and exit with
230 help_exit (char *prog, int exit_code)
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");
267 /* Format MSG by FMT and print the result to the stderr, and exit. */
269 #define FATAL_ERROR(fmt, arg) \
271 fprintf (stderr, fmt, arg); \
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. */
279 #define NEXTLINE(pos, len) \
281 pos = mtext_character (mt, pos, len, '\n'); \
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. */
294 find_page_end (MFrame *frame, int height, MText *mt, int pos,
295 MDrawControl *control, MDrawMetric *rect)
297 int len = mtext_len (mt);
305 NEXTLINE (next, len);
306 mdraw_text_extents (frame, mt, to, next, control, NULL, NULL, rect);
309 if (y + rect->height > height)
315 mdraw_glyph_info (frame, mt, to, to, control, &info);
316 if (y + info.this.height > height)
318 y += info.this.height;
332 /* Table to convert a byte of LSBFirst to MSBFirst. */
333 char reverse_bit_order[256];
335 /* Initialize the above table. */
338 init_reverse_bit_order ()
342 for (i = 0; i < 256; 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));
350 /* Dump the image in IMAGE into a file whose name is generated from
351 FILENAME and PAGE_INDEX (if it is not zero). */
354 dump_image (XImage *image, char *filename, char *filter,
355 int white_is_zero, int page_index, int quiet_mode)
358 int pbm_bytes_per_line;
359 char *data = image->data;
364 char *name = alloca (strlen (filename) + 8);
366 sprintf (name, "%s.%02d", filename, page_index);
372 char *command = alloca (strlen (filename) + strlen (filter) + 1);
374 sprintf (command, filter, filename);
375 fp = popen (command, "w");
377 FATAL_ERROR ("Can't run the command \"%s\"\n", command);
379 printf ("Running \"%s\" ... ", command);
383 char *fullname = alloca (strlen (filename) + 5);
385 sprintf (fullname, "%s.pbm", filename);
386 fp = fopen (fullname, "w");
388 FATAL_ERROR ("Can't write to \"%s\"\n", fullname);
390 printf ("Writing %s ... ", fullname);
393 if (image->bitmap_bit_order != MSBFirst
394 || (image->byte_order != MSBFirst
395 && image->bitmap_unit != 8))
397 /* We must adjust image->data for PBM. */
398 int bytes_per_unit = image->bitmap_unit / 8;
400 for (y = 0; y < image->height; y++, data += image->bytes_per_line)
404 if (image->byte_order != MSBFirst)
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)
414 b = data[x], data[x] = data[x + 3], data[x + 3] = b;
416 b = data[x], data[x] = data[x + 1], data[x + 1] = b;
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]];
424 for (x = 0; x < image->bytes_per_line; x++)
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);
439 printf (" done (%dx%d)\n", image->width, image->height);
442 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
445 main (int argc, char **argv)
453 int paper = PAPER_NOLIMIT;
460 int break_by_word = 0;
463 int paper_width, paper_height;
468 MDrawControl control;
470 char *filename = "output";
473 /* Parse the command line arguments. */
474 for (i = 1; i < argc; i++)
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"))
482 printf ("mdump (m17n library) %s\n", VERSION);
483 printf ("Copyright (C) 2003, 2004 AIST, JAPAN\n");
486 else if (! strcmp (argv[i], "-s") && i + 1< argc)
488 fontsize = atoi (argv[++i]);
490 FATAL_ERROR ("Invalid font size: %s\n", argv[i]);
492 else if (! strcmp (argv[i], "-p") && i + 1< argc)
497 if (! strcmp (argv[i], "a4"))
499 else if (! strcmp (argv[i], "a4r"))
501 else if (! strcmp (argv[i], "a5"))
503 else if (! strcmp (argv[i], "a5r"))
505 else if (! strcmp (argv[i], "b5"))
507 else if (! strcmp (argv[i], "b5r"))
509 else if (! strcmp (argv[i], "letter"))
510 paper = PAPER_LETTER;
511 else if (sscanf (argv[i], "%dx%d", &w, &h) == 2
515 paper_size[paper].width = w;
516 paper_size[paper].height = h;
519 FATAL_ERROR ("Invalid paper type: %s\n", argv[i]);
521 else if (! strcmp (argv[i], "-d") && i + 1< argc)
523 dpi = atoi (argv[++i]);
525 FATAL_ERROR ("Invalid resolution: %s\n", argv[i]);
527 else if (! strcmp (argv[i], "-m") && i + 1< argc)
529 margin = atoi (argv[++i]);
531 FATAL_ERROR ("Invalid margin: %s\n", argv[i]);
533 else if (! strcmp (argv[i], "-c") && i + 1< argc)
535 cursor_pos = atoi (argv[++i]);
537 FATAL_ERROR ("Invalid cursor position: %s\n", argv[i]);
539 else if (! strcmp (argv[i], "-f") && i + 1< argc)
543 else if (! strcmp (argv[i], "-x"))
547 else if (! strcmp (argv[i], "-w"))
551 else if (! strcmp (argv[i], "-q"))
555 else if (argv[i][0] != '-')
557 fp = fopen (argv[i], "r");
559 FATAL_ERROR ("Fail to open the file %s!\n", argv[i]);
560 filename = basename (argv[i]);
564 fprintf (stderr, "Unknown or invalid option: %s\n", argv[i]);
565 help_exit (argv[0], 1);
569 /* Initialize the m17n library. */
571 if (merror_code != MERROR_NONE)
572 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library.");
574 mt = mconv_decode_stream (Mcoding_utf_8, fp);
577 mt = mtext_deserialize (mt);
579 FATAL_ERROR ("%s\n", "Fail to decode the input file or stream!");
581 len = mtext_len (mt);
583 if (paper == PAPER_NOLIMIT)
584 paper_width = paper_height = margin = 0;
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;
592 display = XOpenDisplay (NULL);
593 screen = DefaultScreen (display);
596 MPlist *plist = mplist (), *p;
597 MFontset *fontset = mfontset ("truetype");
598 MFace *face = mface ();
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);
609 FATAL_ERROR ("%s\n", "Can't open a frame (perhaps no font avairable)!");
612 memset (&control, 0, sizeof control);
613 control.as_image = 1;
614 control.two_dimensional = 1;
615 control.enable_bidi = 1;
618 control.with_cursor = 1;
619 if (cursor_pos > len)
621 control.cursor_pos = cursor_pos;
622 control.cursor_width = -1;
625 control.ignore_formatting_char = 1;
627 control.line_break = line_break;
629 if (paper == PAPER_NOLIMIT)
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;
637 control.max_line_width = paper_width - margin * 2;
639 pixmap = XCreatePixmap (display, RootWindow (display, screen),
640 paper_width, paper_height, 1);
641 gc = XCreateGC (display, pixmap, 0L, NULL);
649 if (paper == PAPER_NOLIMIT)
652 to = find_page_end (frame, paper_height - margin * 2, mt, from,
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,
660 XSetForeground (display, gc, BlackPixel (display, screen));
662 XDrawRectangle (display, pixmap, gc, margin, margin,
663 paper_width - margin * 2 - 1,
664 paper_height - margin * 2 - 1);
666 image = XGetImage (display, pixmap, 0, 0, paper_width, paper_height,
667 AllPlanes, XYPixmap);
669 dump_image (image, filename, filter, !WhitePixel (display, screen),
670 ((from > 0 || to < len) ? page_index : 0),
677 m17n_object_unref (frame);
678 m17n_object_unref (mt);
680 XCloseDisplay (display);
683 #endif /* not FOR_DOXYGEN */