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
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 PNG image file.
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".
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.png", "BASE.02.png", 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 an
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 PNG 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 ¥Æ¥¥¹¥È¤ò PNG ²èÁü¤È¤·¤Æ¥À¥ó¥×¤¹¤ë¡£
115 PNG ²èÁü¤Ï¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ëºî¤é¤ì¤¿ "BASE.png" ¤È¤¤¤¦Ì¾Á°¤Î
116 ¥Õ¥¡¥¤¥ë¤Ë½ñ¤¹þ¤Þ¤ì¤ë¡£¤³¤³¤Ç BASE ¤ÏFILE ¤Î basename ¤Ç¤¢¤ë¡£
117 FILE ¤¬¾Êά¤µ¤ì¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ïɸ½àÆþÎϤ«¤éÆɤޤ졢²èÁü¤Ï
118 "output.png" ¤Ë¥À¥ó¥×¤µ¤ì¤ë¡£
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.png",
140 "BASE.02.png" Åù¤Î̾Á°¤Î¤Ä¤¤¤¿Ê£¿ô¤Î¥Õ¥¡¥¤¥ë¤¬ºî¤é¤ì¤ë¡£
144 MARGIN ¤Ï¿åÊ¿¡¢¿âľ¥Þ¡¼¥¸¥ó¤ò¥ß¥ê¥á¡¼¥¿Ã±°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç
145 ¥Õ¥©¥ë¥È¤Î¥Þ¡¼¥¸¥ó¤Ï 20 mm¡£PAPER ¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð̵»ë¤µ¤ì¤ë¡£
149 POS ¤Ï¥«¡¼¥½¥ë¤Îʸ»ú°ÌÃÖ¡£¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¡¢¥«¡¼¥½¥ë¤ÏÉÁ¤«¤ì¤Ê¤¤¡£
153 FILE ¤Ï m17n ¥é¥¤¥Ö¥é¥ê¤Î¥·¥ê¥¢¥é¥¤¥ºµ¡Ç½¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿ XML ¥Õ¥¡
154 ¥¤¥ë¤Ç¤¢¤ê¡¢²èÁü¤òÀ¸À®¤¹¤ëÁ°¤Ë¥Ç¥·¥ê¥¢¥é¥¤¥º¤µ¤ì¤ë¡£
162 FILTER ¤Ï¥·¥§¥ë¥³¥Þ¥ó¥É¹Ô¤ò´Þ¤àʸ»úÎó¤Ç¤¢¤ë¡£¤³¤Î¥ª¥×¥·¥ç¥ó¤¬»ØÄê
163 ¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢PNG ²èÁü¤Ï¥Õ¥¡¥¤¥ë¤Ë½ñ¤«¤ì¤ë¤Î¤Ç¤Ï¤Ê¤¯¡¢FILTER ¤Ë
164 ɸ½àÆþÎϤȤ·¤ÆÅϤµ¤ì¤ë¡£ FILTER ¤¬ "s" ¤ò´Þ¤ó¤Ç¤¤¤ì¤Ð¡¢¤½¤ì¤Ï FILE
165 ¤Î¥Ù¡¼¥¹¥Í¡¼¥à¤ËÃÖ¤´¹¤¨¤é¤ì¤ë¡£¤³¤Î¥×¥í¥°¥é¥à¤Î¥Ç¥Õ¥©¥ë¥È¤Î¿¶Éñ¤¤
166 ¤È¡¢FILTER ¤Ë "cat > s.png" ¤ò»ØÄꤷ¤¿¾ì¹ç¤Î¿¶Éñ¤ÏƱ°ì¤Ç¤¢¤ë¡£
170 °ìÀڤΥá¥Ã¥»¡¼¥¸¤òɽ¼¨¤·¤Ê¤¤¡£
174 ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
178 ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£
192 #if defined (HAVE_FREETYPE) && defined (HAVE_GD)
195 #include <m17n-gui.h>
196 #include <m17n-misc.h>
198 #define VERSION "1.0"
200 /* Enumuration of the supported paper types. */
214 /* Array of paper sizes for the supported paper types. */
217 int width, height; /* in millimeter */
218 } paper_size[PAPER_NOLIMIT] = {
219 { 210, 297 }, /* a4 */
220 { 297, 210 }, /* a4r */
221 { 148, 210 }, /* a5 */
222 { 210, 148 }, /* a5r */
223 { 250, 176 }, /* b5 */
224 { 176, 250 }, /* b5r */
225 { 216, 279 }, /* letter */
229 /* Print the usage of this program (the name is PROG), and exit with
233 help_exit (char *prog, int exit_code)
241 printf ("Usage: %s [ OPTION ...] [ FILE ]\n", prog);
242 printf ("Dump a text as a PNG image into a file.\n");
243 printf (" The PNG file is created in the current directory\n");
244 printf (" with the name \"BASE.png\" where BASE is the basename of FILE.\n");
245 printf (" If FILE is omitted, text is read from standard input, and\n");
246 printf (" dumped into the file \"output.png\".\n");
247 printf ("The following OPTIONs are available.\n");
248 printf (" %-13s %s", "-s SIZE",
249 "Font size in point (default 12).\n");
250 printf (" %-13s %s", "-d DPI",
251 "Resolution in dots per inch (defualt 300).\n");
252 printf (" %-13s %s", "-p PAPER",
253 "Paper size; a4, a4r, a5, a5r, b5, b5r, letter, or WxH.\n");
254 printf (" %-13s %s", "-m MARGIN",
255 "Marginal space in millimeter (default 20).\n");
256 printf (" %-13s %s", "-c POS",
257 "Character position of cursor to draw (default no cursor)\n");
258 printf (" %-13s %s", "-x",
259 "FILE is assumed to be an XML file.\n");
260 printf (" %-13s %s", "-f FILTER",
261 "String containing a shell command line to be used as a filter.\n");
262 printf (" %-13s %s", "-w", "Each line is broken at word boundary.\n");
263 printf (" %-13s %s", "-q", "Quiet mode. Don't print any messages.\n");
264 printf (" %-13s %s", "--version", "Print the version number.\n");
265 printf (" %-13s %s", "-h, --help", "Print this message.\n");
270 /* Format MSG by FMT and print the result to the stderr, and exit. */
272 #define FATAL_ERROR(fmt, arg) \
274 fprintf (stderr, fmt, arg); \
279 /* Move POS to the next line head in M-text MT whose length is LEN.
280 If POS is already on the last line, set POS to LEN. */
282 #define NEXTLINE(pos, len) \
284 pos = mtext_character (mt, pos, len, '\n'); \
292 /* Find the range of M-text MT that fits in one page of height HEIGHT
293 when drawn from the character position POS. Set RECT->y to the
294 Y-offset of the first baseline. */
297 find_page_end (MFrame *frame, int height, MText *mt, int pos,
298 MDrawControl *control, MDrawMetric *rect)
300 int len = mtext_len (mt);
308 NEXTLINE (next, len);
309 mdraw_text_extents (frame, mt, to, next, control, NULL, NULL, rect);
312 if (y + rect->height > height)
318 mdraw_glyph_info (frame, mt, to, to, control, &info);
319 if (y + info.this.height > height)
321 y += info.this.height;
335 /* Table to convert a byte of LSBFirst to MSBFirst. */
336 char reverse_bit_order[256];
338 /* Initialize the above table. */
341 init_reverse_bit_order ()
345 for (i = 0; i < 256; i++)
347 = (((i & 1) << 7) | ((i & 2) << 5) | ((i & 4) << 3) | ((i & 8) << 1)
348 | ((i & 16) >> 1) | ((i & 32) >> 3)
349 | ((i & 64) >> 5) | ((i & 128) >> 7));
353 /* Dump the image in IMAGE into a file whose name is generated from
354 FILENAME and PAGE_INDEX (if it is not zero). */
357 dump_image (gdImagePtr image, char *filename, char *filter,
358 int page_index, int quiet_mode)
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.png", filename);
386 fp = fopen (fullname, "w");
388 FATAL_ERROR ("Can't write to \"%s\"\n", fullname);
390 printf ("Writing %s ... ", fullname);
394 gdImagePng (image, fp);
397 printf (" done (%dx%d)\n", image->sx, image->sy);
400 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
403 main (int argc, char **argv)
406 int paper = PAPER_NOLIMIT;
413 int break_by_word = 0;
416 int paper_width, paper_height;
423 MDrawControl control;
425 char *filename = "output";
428 /* Parse the command line arguments. */
429 for (i = 1; i < argc; i++)
431 if (! strcmp (argv[i], "--help")
432 || ! strcmp (argv[i], "-h")
433 || ! strcmp (argv[i], "-?"))
434 help_exit (argv[0], 0);
435 else if (! strcmp (argv[i], "--version"))
437 printf ("mdump (m17n library) %s\n", VERSION);
438 printf ("Copyright (C) 2003, 2004 AIST, JAPAN\n");
441 else if (! strcmp (argv[i], "-s") && i + 1< argc)
443 fontsize = atoi (argv[++i]);
445 FATAL_ERROR ("Invalid font size: %s\n", argv[i]);
447 else if (! strcmp (argv[i], "-p") && i + 1< argc)
452 if (! strcmp (argv[i], "a4"))
454 else if (! strcmp (argv[i], "a4r"))
456 else if (! strcmp (argv[i], "a5"))
458 else if (! strcmp (argv[i], "a5r"))
460 else if (! strcmp (argv[i], "b5"))
462 else if (! strcmp (argv[i], "b5r"))
464 else if (! strcmp (argv[i], "letter"))
465 paper = PAPER_LETTER;
466 else if (sscanf (argv[i], "%dx%d", &w, &h) == 2
470 paper_size[paper].width = w;
471 paper_size[paper].height = h;
474 FATAL_ERROR ("Invalid paper type: %s\n", argv[i]);
476 else if (! strcmp (argv[i], "-d") && i + 1< argc)
478 dpi = atoi (argv[++i]);
480 FATAL_ERROR ("Invalid resolution: %s\n", argv[i]);
482 else if (! strcmp (argv[i], "-m") && i + 1< argc)
484 margin = atoi (argv[++i]);
486 FATAL_ERROR ("Invalid margin: %s\n", argv[i]);
488 else if (! strcmp (argv[i], "-c") && i + 1< argc)
490 cursor_pos = atoi (argv[++i]);
492 FATAL_ERROR ("Invalid cursor position: %s\n", argv[i]);
494 else if (! strcmp (argv[i], "-f") && i + 1< argc)
498 else if (! strcmp (argv[i], "-x"))
502 else if (! strcmp (argv[i], "-w"))
506 else if (! strcmp (argv[i], "-q"))
510 else if (argv[i][0] != '-')
512 fp = fopen (argv[i], "r");
514 FATAL_ERROR ("Fail to open the file %s!\n", argv[i]);
515 filename = basename (argv[i]);
519 fprintf (stderr, "Unknown or invalid option: %s\n", argv[i]);
520 help_exit (argv[0], 1);
524 /* Initialize the m17n library. */
526 if (merror_code != MERROR_NONE)
527 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library.");
529 mt = mconv_decode_stream (Mcoding_utf_8, fp);
532 mt = mtext_deserialize (mt);
534 FATAL_ERROR ("%s\n", "Fail to decode the input file or stream!");
536 len = mtext_len (mt);
538 if (paper == PAPER_NOLIMIT)
539 paper_width = paper_height = margin = 0;
542 paper_width = paper_size[paper].width * dpi / 25.4;
543 paper_height = paper_size[paper].height * dpi / 25.4;
544 margin = margin * dpi / 25.4;
548 MPlist *plist = mplist (), *p;
549 MFontset *fontset = mfontset ("truetype");
550 MFace *face = mface ();
552 mface_put_prop (face, Mfontset, fontset);
553 mface_put_prop (face, Msize, (void *) (fontsize * dpi / 100));
554 p = mplist_add (plist, Mdevice, msymbol ("gd"));
555 p = mplist_add (p, Mface, face);
556 m17n_object_unref (face);
557 frame = mframe (plist);
558 m17n_object_unref (plist);
560 FATAL_ERROR ("%s\n", "Can't open a frame (perhaps no font avairable)!");
563 memset (&control, 0, sizeof control);
564 control.as_image = 1;
565 control.two_dimensional = 1;
566 control.enable_bidi = 1;
567 control.anti_alias = 1;
570 control.with_cursor = 1;
571 if (cursor_pos > len)
573 control.cursor_pos = cursor_pos;
574 control.cursor_width = -1;
577 control.ignore_formatting_char = 1;
579 control.line_break = line_break;
581 if (paper == PAPER_NOLIMIT)
583 control.max_line_width = 0;
584 mdraw_text_extents (frame, mt, 0, len, &control, NULL, NULL, &rect);
585 paper_width = rect.width;
586 paper_height = rect.height;
589 control.max_line_width = paper_width - margin * 2;
591 image = gdImageCreate (paper_width, paper_height);
594 white = gdImageColorAllocate (image, 255, 255, 255);
599 if (paper == PAPER_NOLIMIT)
602 to = find_page_end (frame, paper_height - margin * 2, mt, from,
605 gdImageFilledRectangle (image, 0, 0, paper_width - 1, paper_height - 1,
607 mdraw_text_with_control (frame, image,
608 margin, margin - rect.y, mt, from, to,
610 dump_image (image, filename, filter,
611 ((from > 0 || to < len) ? page_index : 0),
618 m17n_object_unref (frame);
619 m17n_object_unref (mt);
621 gdImageDestroy (image);
625 #else /* not HAVE_FREETYPE nor HAVE_GD */
628 main (int argc, char **argv)
630 fprintf (stderr, "Can't run without Freetype and GD library!\n");
634 #endif /* not HAVE_FREETYPE nor HAVE_GD */
635 #endif /* not FOR_DOXYGEN */