Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "fitz.h"
  2. #include "muxps.h"
  3.  
  4. #ifdef _MSC_VER
  5. #include <winsock2.h>
  6. #else
  7. #include <sys/time.h>
  8. #endif
  9.  
  10. char *output = NULL;
  11. float resolution = 72;
  12.  
  13. int showxml = 0;
  14. int showtext = 0;
  15. int showtime = 0;
  16. int showmd5 = 0;
  17. int savealpha = 0;
  18. int uselist = 1;
  19.  
  20. fz_colorspace *colorspace;
  21. fz_glyph_cache *glyphcache;
  22. char *filename;
  23.  
  24. struct {
  25.         int count, total;
  26.         int min, max;
  27.         int minpage, maxpage;
  28. } timing;
  29.  
  30. static void die(fz_error error)
  31. {
  32.         fz_catch(error, "aborting");
  33.         exit(1);
  34. }
  35.  
  36. static void usage(void)
  37. {
  38.         fprintf(stderr,
  39.                 "usage: xpsdraw [options] input.xps [pages]\n"
  40.                 "\t-o -\toutput filename (%%d for page number)\n"
  41.                 "\t\tsupported formats: pgm, ppm, pam, png\n"
  42.                 "\t-r -\tresolution in dpi (default: 72)\n"
  43.                 "\t-a\tsave alpha channel (only pam and png)\n"
  44.                 "\t-g\trender in grayscale\n"
  45.                 "\t-m\tshow timing information\n"
  46.                 "\t-t\tshow text (-tt for xml)\n"
  47.                 "\t-x\tshow display list\n"
  48.                 "\t-d\tdisable use of display list\n"
  49.                 "\t-5\tshow md5 checksums\n"
  50.                 "\tpages\tcomma separated list of ranges\n");
  51.         exit(1);
  52. }
  53.  
  54. static int gettime(void)
  55. {
  56.         static struct timeval first;
  57.         static int once = 1;
  58.         struct timeval now;
  59.         if (once)
  60.         {
  61.                 gettimeofday(&first, NULL);
  62.                 once = 0;
  63.         }
  64.         gettimeofday(&now, NULL);
  65.         return (now.tv_sec - first.tv_sec) * 1000 + (now.tv_usec - first.tv_usec) / 1000;
  66. }
  67.  
  68. static int isrange(char *s)
  69. {
  70.         while (*s)
  71.         {
  72.                 if ((*s < '0' || *s > '9') && *s != '-' && *s != ',')
  73.                         return 0;
  74.                 s++;
  75.         }
  76.         return 1;
  77. }
  78.  
  79. static void
  80. xps_run_page(xps_context *ctx, xps_page *page, fz_device *dev, fz_matrix ctm)
  81. {
  82.         ctx->dev = dev;
  83.         xps_parse_fixed_page(ctx, ctm, page);
  84.         ctx->dev = NULL;
  85. }
  86.  
  87. static void drawpage(xps_context *ctx, int pagenum)
  88. {
  89.         xps_page *page;
  90.         fz_display_list *list;
  91.         fz_device *dev;
  92.         int start;
  93.         int code;
  94.  
  95.         if (showtime)
  96.         {
  97.                 start = gettime();
  98.         }
  99.  
  100.         code = xps_load_page(&page, ctx, pagenum - 1);
  101.         if (code)
  102.                 die(fz_rethrow(code, "cannot load page %d in file '%s'", pagenum, filename));
  103.  
  104.         list = NULL;
  105.  
  106.         if (uselist)
  107.         {
  108.                 list = fz_new_display_list();
  109.                 dev = fz_new_list_device(list);
  110.                 xps_run_page(ctx, page, dev, fz_identity);
  111.                 fz_free_device(dev);
  112.         }
  113.  
  114.         if (showxml)
  115.         {
  116.                 dev = fz_new_trace_device();
  117.                 printf("<page number=\"%d\">\n", pagenum);
  118.                 if (list)
  119.                         fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox);
  120.                 else
  121.                         xps_run_page(ctx, page, dev, fz_identity);
  122.                 printf("</page>\n");
  123.                 fz_free_device(dev);
  124.         }
  125.  
  126.         if (showtext)
  127.         {
  128.                 fz_text_span *text = fz_new_text_span();
  129.                 dev = fz_new_text_device(text);
  130.                 if (list)
  131.                         fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox);
  132.                 else
  133.                         xps_run_page(ctx, page, dev, fz_identity);
  134.                 fz_free_device(dev);
  135.                 printf("[Page %d]\n", pagenum);
  136.                 if (showtext > 1)
  137.                         fz_debug_text_span_xml(text);
  138.                 else
  139.                         fz_debug_text_span(text);
  140.                 printf("\n");
  141.                 fz_free_text_span(text);
  142.         }
  143.  
  144.         if (showmd5 || showtime)
  145.                 printf("page %s %d", filename, pagenum);
  146.  
  147.         if (output || showmd5 || showtime)
  148.         {
  149.                 float zoom;
  150.                 fz_matrix ctm;
  151.                 fz_rect rect;
  152.                 fz_bbox bbox;
  153.                 fz_pixmap *pix;
  154.  
  155.                 rect.x0 = rect.y0 = 0;
  156.                 rect.x1 = page->width;
  157.                 rect.y1 = page->height;
  158.  
  159.                 zoom = resolution / 96;
  160.                 ctm = fz_translate(0, -page->height);
  161.                 ctm = fz_concat(ctm, fz_scale(zoom, zoom));
  162.                 bbox = fz_round_rect(fz_transform_rect(ctm, rect));
  163.  
  164.                 /* TODO: banded rendering and multi-page ppm */
  165.  
  166.                 pix = fz_new_pixmap_with_rect(colorspace, bbox);
  167.  
  168.                 if (savealpha)
  169.                         fz_clear_pixmap(pix);
  170.                 else
  171.                         fz_clear_pixmap_with_color(pix, 255);
  172.  
  173.                 dev = fz_new_draw_device(glyphcache, pix);
  174.                 if (list)
  175.                         fz_execute_display_list(list, dev, ctm, bbox);
  176.                 else
  177.                         xps_run_page(ctx, page, dev, ctm);
  178.                 fz_free_device(dev);
  179.  
  180.                 if (output)
  181.                 {
  182.                         char buf[512];
  183.                         sprintf(buf, output, pagenum);
  184.                         if (strstr(output, ".pgm") || strstr(output, ".ppm") || strstr(output, ".pnm"))
  185.                                 fz_write_pnm(pix, buf);
  186.                         else if (strstr(output, ".pam"))
  187.                                 fz_write_pam(pix, buf, savealpha);
  188.                         else if (strstr(output, ".png"))
  189.                                 fz_write_png(pix, buf, savealpha);
  190.                 }
  191.  
  192.                 if (showmd5)
  193.                 {
  194.                         fz_md5 md5;
  195.                         unsigned char digest[16];
  196.                         int i;
  197.  
  198.                         fz_md5_init(&md5);
  199.                         fz_md5_update(&md5, pix->samples, pix->w * pix->h * pix->n);
  200.                         fz_md5_final(&md5, digest);
  201.  
  202.                         printf(" ");
  203.                         for (i = 0; i < 16; i++)
  204.                                 printf("%02x", digest[i]);
  205.                 }
  206.  
  207.                 fz_drop_pixmap(pix);
  208.         }
  209.  
  210.         if (list)
  211.                 fz_free_display_list(list);
  212.  
  213.         if (showtime)
  214.         {
  215.                 int end = gettime();
  216.                 int diff = end - start;
  217.  
  218.                 if (diff < timing.min)
  219.                 {
  220.                         timing.min = diff;
  221.                         timing.minpage = pagenum;
  222.                 }
  223.                 if (diff > timing.max)
  224.                 {
  225.                         timing.max = diff;
  226.                         timing.maxpage = pagenum;
  227.                 }
  228.                 timing.total += diff;
  229.                 timing.count ++;
  230.  
  231.                 printf(" %dms", diff);
  232.         }
  233.  
  234.         if (showmd5 || showtime)
  235.                 printf("\n");
  236. }
  237.  
  238. static void drawrange(xps_context *ctx, char *range)
  239. {
  240.         int page, spage, epage;
  241.         char *spec, *dash;
  242.  
  243.         spec = fz_strsep(&range, ",");
  244.         while (spec)
  245.         {
  246.                 dash = strchr(spec, '-');
  247.  
  248.                 if (dash == spec)
  249.                         spage = epage = xps_count_pages(ctx);
  250.                 else
  251.                         spage = epage = atoi(spec);
  252.  
  253.                 if (dash)
  254.                 {
  255.                         if (strlen(dash) > 1)
  256.                                 epage = atoi(dash + 1);
  257.                         else
  258.                                 epage = xps_count_pages(ctx);
  259.                 }
  260.  
  261.                 spage = CLAMP(spage, 1, xps_count_pages(ctx));
  262.                 epage = CLAMP(epage, 1, xps_count_pages(ctx));
  263.  
  264.                 if (spage < epage)
  265.                         for (page = spage; page <= epage; page++)
  266.                                 drawpage(ctx, page);
  267.                 else
  268.                         for (page = spage; page >= epage; page--)
  269.                                 drawpage(ctx, page);
  270.  
  271.                 spec = fz_strsep(&range, ",");
  272.         }
  273. }
  274.  
  275. int main(int argc, char **argv)
  276. {
  277.         int grayscale = 0;
  278.         int accelerate = 1;
  279.         xps_context *ctx;
  280.         int code;
  281.         int c;
  282.  
  283.         while ((c = fz_getopt(argc, argv, "o:p:r:Aadgmtx5")) != -1)
  284.         {
  285.                 switch (c)
  286.                 {
  287.                 case 'o': output = fz_optarg; break;
  288.                 case 'r': resolution = atof(fz_optarg); break;
  289.                 case 'A': accelerate = 0; break;
  290.                 case 'a': savealpha = 1; break;
  291.                 case 'm': showtime++; break;
  292.                 case 't': showtext++; break;
  293.                 case 'x': showxml++; break;
  294.                 case '5': showmd5++; break;
  295.                 case 'g': grayscale++; break;
  296.                 case 'd': uselist = 0; break;
  297.                 default: usage(); break;
  298.                 }
  299.         }
  300.  
  301.         if (fz_optind == argc)
  302.                 usage();
  303.  
  304.         if (!showtext && !showxml && !showtime && !showmd5 && !output)
  305.         {
  306.                 printf("nothing to do\n");
  307.                 exit(0);
  308.         }
  309.  
  310.         if (accelerate)
  311.                 fz_accelerate();
  312.  
  313.         glyphcache = fz_new_glyph_cache();
  314.  
  315.         colorspace = fz_device_rgb;
  316.         if (grayscale)
  317.                 colorspace = fz_device_gray;
  318.         if (output && strstr(output, ".pgm"))
  319.                 colorspace = fz_device_gray;
  320.         if (output && strstr(output, ".ppm"))
  321.                 colorspace = fz_device_rgb;
  322.  
  323.         timing.count = 0;
  324.         timing.total = 0;
  325.         timing.min = 1 << 30;
  326.         timing.max = 0;
  327.         timing.minpage = 0;
  328.         timing.maxpage = 0;
  329.  
  330.         if (showxml)
  331.                 printf("<?xml version=\"1.0\"?>\n");
  332.  
  333.         while (fz_optind < argc)
  334.         {
  335.                 filename = argv[fz_optind++];
  336.  
  337.                 code = xps_open_file(&ctx, filename);
  338.                 if (code)
  339.                         die(fz_rethrow(code, "cannot open document: %s", filename));
  340.  
  341.                 if (showxml)
  342.                         printf("<document name=\"%s\">\n", filename);
  343.  
  344.                 if (fz_optind == argc || !isrange(argv[fz_optind]))
  345.                         drawrange(ctx, "1-");
  346.                 if (fz_optind < argc && isrange(argv[fz_optind]))
  347.                         drawrange(ctx, argv[fz_optind++]);
  348.  
  349.                 if (showxml)
  350.                         printf("</document>\n");
  351.  
  352.                 xps_free_context(ctx);
  353.         }
  354.  
  355.         if (showtime)
  356.         {
  357.                 printf("total %dms / %d pages for an average of %dms\n",
  358.                         timing.total, timing.count, timing.total / timing.count);
  359.                 printf("fastest page %d: %dms\n", timing.minpage, timing.min);
  360.                 printf("slowest page %d: %dms\n", timing.maxpage, timing.max);
  361.         }
  362.  
  363.         fz_free_glyph_cache(glyphcache);
  364.  
  365.         return 0;
  366. }
  367.