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
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 m17n-dump dump text image
26 @section m17n-dump-synopsis SYNOPSIS
28 m17n-dump [ OPTION ... ] [ FILE ]
30 @section m17n-dump-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, 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.
63 MARGIN is the horizontal and vertical margin in millimeter. The
64 default margin is 20 mm. It is ignored when PAPER is not
69 POS is the character position of cursor to draw. By default,
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
80 Each line is broken at word boundary.
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 >
91 If FILTER is just "-", the PNG image is written to stdout.
95 Enable anti-alias drawing.
99 Prefer a font whose family name is FAMILY.
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).
108 Specify that the orientation of the text is right-to-left.
112 Quiet mode. Don't print any messages.
116 Print the version number.
125 @japage m17n-dump ¥Æ¥¥¹¥È²èÁü¤Î¥À¥ó¥×
127 @section m17n-dump-synopsis SYNOPSIS
129 m17n-dump [ OPTION ... ] [ FILE ]
131 @section m17n-dump-description DESCRIPTION
133 ¥Æ¥¥¹¥È¤ò PNG ²èÁü¤È¤·¤Æ¥À¥ó¥×¤¹¤ë¡£
135 PNG ²èÁü¤Ï¸½ºß¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ëºî¤é¤ì¤¿ "BASE.png" ¤È¤¤¤¦Ì¾Á°¤Î
136 ¥Õ¥¡¥¤¥ë¤Ë½ñ¤¹þ¤Þ¤ì¤ë¡£¤³¤³¤Ç BASE ¤ÏFILE ¤Î basename ¤Ç¤¢¤ë¡£
137 FILE ¤¬¾Êά¤µ¤ì¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ïɸ½àÆþÎϤ«¤éÆɤޤ졢²èÁü¤Ï
138 "output.png" ¤Ë¥À¥ó¥×¤µ¤ì¤ë¡£
140 °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ¤ë¡£
146 SIZE ¤Ï¥Õ¥©¥ó¥È¤ÎÂ礤µ¤ò¥Ý¥¤¥ó¥Èñ°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç¥Õ¥©¥ë
147 ¥È¤ÎÂ礤µ¤Ï 12 ¥Ý¥¤¥ó¥È¡£
151 DPI ¤Ï²òÁüÅÙ¤ò£±¥¤¥ó¥Á¤¢¤¿¤ê¤Î¥É¥Ã¥Èñ°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç¥Õ¥©
152 ¥ë¥È¤Î²òÁüÅÙ¤Ï 300 dpi¡£
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 ¤Î¤Ä¤¤¤¿Ê£¿ô¤Î¥Õ¥¡¥¤¥ë¤¬ºî¤é¤ì¤ë¡£
165 MARGIN ¤Ï¿åÊ¿¡¢¿âľ¥Þ¡¼¥¸¥ó¤ò¥ß¥ê¥á¡¼¥¿Ã±°Ì¤Ç¼¨¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£¥Ç
166 ¥Õ¥©¥ë¥È¤Î¥Þ¡¼¥¸¥ó¤Ï 20 mm¡£PAPER ¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð̵»ë¤µ¤ì¤ë¡£
170 POS ¤Ï¥«¡¼¥½¥ë¤Îʸ»ú°ÌÃÖ¡£¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¡¢¥«¡¼¥½¥ë¤ÏÉÁ¤«¤ì¤Ê¤¤¡£
174 FILE ¤Ï m17n ¥é¥¤¥Ö¥é¥ê¤Î¥·¥ê¥¢¥é¥¤¥ºµ¡Ç½¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿ XML ¥Õ¥¡
175 ¥¤¥ë¤Ç¤¢¤ê¡¢²èÁü¤òÀ¸À®¤¹¤ëÁ°¤Ë¥Ç¥·¥ê¥¢¥é¥¤¥º¤µ¤ì¤ë¡£
183 FILTER ¤Ï¥·¥§¥ë¥³¥Þ¥ó¥É¹Ô¤ò´Þ¤àʸ»úÎó¤Ç¤¢¤ë¡£¤³¤Î¥ª¥×¥·¥ç¥ó¤¬»ØÄê
184 ¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢PNG ²èÁü¤Ï¥Õ¥¡¥¤¥ë¤Ë½ñ¤«¤ì¤ë¤Î¤Ç¤Ï¤Ê¤¯¡¢FILTER ¤Ë
185 ɸ½àÆþÎϤȤ·¤ÆÅϤµ¤ì¤ë¡£ FILTER ¤¬ "%s" ¤ò´Þ¤ó¤Ç¤¤¤ì¤Ð¡¢¤½¤ì¤Ï FILE
186 ¤Î¥Ù¡¼¥¹¥Í¡¼¥à¤ËÃÖ¤´¹¤¨¤é¤ì¤ë¡£¤³¤Î¥×¥í¥°¥é¥à¤Î¥Ç¥Õ¥©¥ë¥È¤Î¿¶Éñ¤¤
187 ¤È¡¢FILTER ¤Ë "cat > %s.png" ¤ò»ØÄꤷ¤¿¾ì¹ç¤Î¿¶Éñ¤ÏƱ°ì¤Ç¤¢¤ë¡£
189 ¤â¤· FILTER ¤¬Ã±¤Ë "-" ¤Ç¤¢¤ì¤Ð¡¢ PNG ²èÁü¤Ï stdout ¤Ë½ÐÎϤµ¤ì¤ë¡£
193 ¥¢¥ó¥Á¥¨¥¤¥ê¥¢¥¹½èÍý¤ò¹Ô¤¦¡£
197 ¥Õ¥¡¥ß¥ê¥£Ì¾¤¬ FAMILY ¤Î¥Õ¥©¥ó¥È¤òÍ¥ÀèŪ¤Ë»È¤¦¡£
201 ¸À¸ì LANG ÍѤ˻ØÄꤵ¤ì¤¿¥Õ¥©¥ó¥È¤òÍ¥ÀèŪ¤Ë»È¤¦¡£LANG ¤Ï ISO 630 ¤Î
202 £²Ê¸»ú¥³¡¼¥É¡ÊÎ㡧±Ñ¸ì¤Ï "en" ¡Ë¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
206 °ìÀڤΥá¥Ã¥»¡¼¥¸¤òɽ¼¨¤·¤Ê¤¤¡£
210 ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
214 ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£
227 #if defined (HAVE_FREETYPE) && defined (HAVE_GD)
230 #include <m17n-gui.h>
231 #include <m17n-misc.h>
233 #define PROGRAM_VERSION "1.1"
235 /* Enumuration of the supported paper types. */
249 /* Array of paper sizes for the supported paper types. */
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 */
264 /* Print the usage of this program (the name is PROG), and exit with
268 help_exit (char *prog, int exit_code)
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");
312 /* Format MSG by FMT and print the result to the stderr, and exit. */
314 #define FATAL_ERROR(fmt, arg) \
316 fprintf (stderr, fmt, arg); \
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. */
324 #define NEXTLINE(pos, len) \
326 pos = mtext_character (mt, pos, len, '\n'); \
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. */
339 find_page_end (MFrame *frame, int height, MText *mt, int pos,
340 MDrawControl *control, MDrawMetric *rect)
342 int len = mtext_len (mt);
350 NEXTLINE (next, len);
351 mdraw_text_extents (frame, mt, to, next, control, NULL, NULL, rect);
354 if (y + rect->height > height)
360 mdraw_glyph_info (frame, mt, to, to, control, &info);
361 if (y + info.metrics.height > height)
363 y += info.metrics.height;
376 /* Dump the image in IMAGE into a file whose name is generated from
377 FILENAME and PAGE_INDEX (if it is not zero). */
380 dump_image (gdImagePtr image, char *filename, char *filter,
381 int page_index, int quiet_mode)
387 char *name = alloca (strlen (filename) + 8);
389 sprintf (name, "%s.%02d", filename, page_index);
395 if (filter[0] == '-' && filter[1] == '\0')
399 char *command = alloca (strlen (filename) + strlen (filter) + 1);
401 sprintf (command, filter, filename);
402 fp = popen (command, "w");
404 FATAL_ERROR ("Can't run the command \"%s\"\n", command);
406 printf ("Running \"%s\" ... ", command);
411 char *fullname = alloca (strlen (filename) + 5);
413 sprintf (fullname, "%s.png", filename);
414 fp = fopen (fullname, "w");
416 FATAL_ERROR ("Can't write to \"%s\"\n", fullname);
418 printf ("Writing %s ... ", fullname);
422 gdImagePng (image, fp);
426 printf (" done (%dx%d)\n", image->sx, image->sy);
429 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
432 main (int argc, char **argv)
435 int paper = PAPER_NOLIMIT;
442 int break_by_word = 0;
444 int paper_width, paper_height;
446 char *family_name = NULL;
447 char *lang_name = NULL;
456 MDrawControl control;
458 char *filename = "output";
460 char *fontset_name = "truetype";
463 /* Parse the command line arguments. */
464 for (i = 1; i < argc; i++)
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"))
472 printf ("m17n-dump (m17n library) %s\n", PROGRAM_VERSION);
473 printf ("Copyright (C) 2003, 2004 AIST, JAPAN\n");
476 else if (! strcmp (argv[i], "-s") && i + 1< argc)
478 fontsize = atoi (argv[++i]);
480 FATAL_ERROR ("Invalid font size: %s\n", argv[i]);
482 else if (! strcmp (argv[i], "-p") && i + 1< argc)
487 if (! strcmp (argv[i], "a4"))
489 else if (! strcmp (argv[i], "a4r"))
491 else if (! strcmp (argv[i], "a5"))
493 else if (! strcmp (argv[i], "a5r"))
495 else if (! strcmp (argv[i], "b5"))
497 else if (! strcmp (argv[i], "b5r"))
499 else if (! strcmp (argv[i], "letter"))
500 paper = PAPER_LETTER;
501 else if (sscanf (argv[i], "%dx%d", &w, &h) == 2
505 paper_size[paper].width = w;
506 paper_size[paper].height = h;
508 else if (sscanf (argv[i], "%d", &w) == 1
512 paper_size[paper].width = w;
513 paper_size[paper].height = 0;
516 FATAL_ERROR ("Invalid paper type: %s\n", argv[i]);
518 else if (! strcmp (argv[i], "-d") && i + 1< argc)
520 dpi = atoi (argv[++i]);
522 FATAL_ERROR ("Invalid resolution: %s\n", argv[i]);
524 else if (! strcmp (argv[i], "-m") && i + 1< argc)
526 margin = atoi (argv[++i]);
528 FATAL_ERROR ("Invalid margin: %s\n", argv[i]);
530 else if (! strcmp (argv[i], "-c") && i + 1< argc)
532 cursor_pos = atoi (argv[++i]);
534 FATAL_ERROR ("Invalid cursor position: %s\n", argv[i]);
536 else if (! strcmp (argv[i], "-f") && i + 1< argc)
540 else if (! strcmp (argv[i], "-x"))
544 else if (! strcmp (argv[i], "-w"))
548 else if (! strcmp (argv[i], "-q"))
552 else if (! strcmp (argv[i], "-a"))
556 else if (! strcmp (argv[i], "--family"))
558 family_name = argv[++i];
560 else if (! strcmp (argv[i], "--language"))
562 lang_name = argv[++i];
564 else if (! strcmp (argv[i], "-r"))
568 else if (argv[i][0] != '-')
570 fp = fopen (argv[i], "r");
572 FATAL_ERROR ("Fail to open the file %s!\n", argv[i]);
573 filename = basename (argv[i]);
575 else if (! strcmp (argv[i], "--fontset"))
577 fontset_name = argv[++i];
582 fprintf (stderr, "Unknown or invalid option: %s\n", argv[i]);
583 help_exit (argv[0], 1);
587 /* Initialize the m17n library. */
589 if (merror_code != MERROR_NONE)
590 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library.");
592 mt = mconv_decode_stream (Mcoding_utf_8, fp);
595 mt = mtext_deserialize (mt);
597 FATAL_ERROR ("%s\n", "Fail to decode the input file or stream!");
599 len = mtext_len (mt);
601 mtext_put_prop (mt, 0, len, Mlanguage, msymbol (lang_name));
603 if (paper == PAPER_NOLIMIT)
604 paper_width = paper_height = margin = 0;
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;
613 MPlist *plist = mplist (), *p;
614 MFontset *fontset = mfontset (fontset_name);
615 MFace *face = mface ();
617 mface_put_prop (face, Mfontset, fontset);
618 mface_put_prop (face, Msize, (void *) (fontsize * dpi / 100));
623 for (p = family_name; *p; p++)
624 if (isupper (*p)) *p = tolower (*p);
625 mface_put_prop (face, Mfamily, msymbol (family_name));
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);
634 FATAL_ERROR ("%s\n", "Can't open a frame (perhaps no font available)!");
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;
644 control.with_cursor = 1;
645 if (cursor_pos > len)
647 control.cursor_pos = cursor_pos;
648 control.cursor_width = -1;
651 control.ignore_formatting_char = 1;
653 control.line_break = mdraw_default_line_break;
655 if (paper == PAPER_NOLIMIT)
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;
664 control.max_line_width = paper_width - margin * 2;
665 if (paper_height == 0)
667 mdraw_text_extents (frame, mt, 0, len, &control, NULL, NULL, &rect);
668 paper_height = rect.height + margin * 2;
672 image = gdImageCreate (paper_width, paper_height);
675 white = gdImageColorAllocate (image, 255, 255, 255);
676 gdImageColorTransparent (image, white);
681 if (paper == PAPER_NOLIMIT || paper_size[paper].height == 0)
684 to = find_page_end (frame, paper_height - margin * 2, mt, from,
687 gdImageFilledRectangle (image, 0, 0, paper_width - 1, paper_height - 1,
690 mdraw_text_with_control (frame, image,
691 margin, margin - rect.y,
692 mt, from, to, &control);
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),
705 m17n_object_unref (frame);
706 m17n_object_unref (mt);
708 gdImageDestroy (image);
712 #else /* not HAVE_FREETYPE nor HAVE_GD */
715 main (int argc, char **argv)
717 fprintf (stderr, "Can't run without Freetype and GD library!\n");
721 #endif /* not HAVE_FREETYPE nor HAVE_GD */
722 #endif /* not FOR_DOXYGEN */