pdf.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * pdf.c
  3. *
  4. * pdf file support for page
  5. */
  6. #include <u.h>
  7. #include <libc.h>
  8. #include <draw.h>
  9. #include <event.h>
  10. #include <bio.h>
  11. #include "page.h"
  12. typedef struct PDFInfo PDFInfo;
  13. struct PDFInfo {
  14. GSInfo;
  15. Rectangle *pagebbox;
  16. };
  17. static Image* pdfdrawpage(Document *d, int page);
  18. static char* pdfpagename(Document*, int);
  19. char *pdfprolog =
  20. #include "pdfprolog.c"
  21. ;
  22. Rectangle
  23. pdfbbox(GSInfo *gs)
  24. {
  25. char *p;
  26. char *f[4];
  27. Rectangle r;
  28. r = Rect(0,0,0,0);
  29. waitgs(gs);
  30. gscmd(gs, "/CropBox knownoget {} {[0 0 0 0]} ifelse PAGE==\n");
  31. p = Brdline(&gs->gsrd, '\n');
  32. p[Blinelen(&gs->gsrd)-1] ='\0';
  33. if(p[0] != '[')
  34. return r;
  35. if(tokenize(p+1, f, 4) != 4)
  36. return r;
  37. r = Rect(atoi(f[0]), atoi(f[1]), atoi(f[2]), atoi(f[3]));
  38. waitgs(gs);
  39. return r;
  40. }
  41. Document*
  42. initpdf(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
  43. {
  44. Document *d;
  45. PDFInfo *pdf;
  46. char *p;
  47. char *fn;
  48. char fdbuf[20];
  49. int fd;
  50. int i, npage;
  51. Rectangle bbox;
  52. if(argc > 1) {
  53. fprint(2, "can only view one pdf file at a time\n");
  54. return nil;
  55. }
  56. fprint(2, "reading through pdf...\n");
  57. if(b == nil){ /* standard input; spool to disk (ouch) */
  58. fd = spooltodisk(buf, nbuf, &fn);
  59. sprint(fdbuf, "/fd/%d", fd);
  60. b = Bopen(fdbuf, OREAD);
  61. if(b == nil){
  62. fprint(2, "cannot open disk spool file\n");
  63. wexits("Bopen temp");
  64. }
  65. }else
  66. fn = argv[0];
  67. /* sanity check */
  68. Bseek(b, 0, 0);
  69. if(!(p = Brdline(b, '\n')) && !(p = Brdline(b, '\r'))) {
  70. fprint(2, "cannot find end of first line\n");
  71. wexits("initps");
  72. }
  73. if(strncmp(p, "%PDF-", 5) != 0) {
  74. werrstr("not pdf");
  75. return nil;
  76. }
  77. /* setup structures so one free suffices */
  78. p = emalloc(sizeof(*d) + sizeof(*pdf));
  79. d = (Document*) p;
  80. p += sizeof(*d);
  81. pdf = (PDFInfo*) p;
  82. d->extra = pdf;
  83. d->b = b;
  84. d->drawpage = pdfdrawpage;
  85. d->pagename = pdfpagename;
  86. d->fwdonly = 0;
  87. if(spawngs(pdf, "-dDELAYSAFER") < 0)
  88. return nil;
  89. gscmd(pdf, "%s", pdfprolog);
  90. waitgs(pdf);
  91. setdim(pdf, Rect(0,0,0,0), ppi, 0);
  92. gscmd(pdf, "(%s) (r) file { DELAYSAFER { .setsafe } if } stopped pop pdfopen begin\n", fn);
  93. gscmd(pdf, "pdfpagecount PAGE==\n");
  94. p = Brdline(&pdf->gsrd, '\n');
  95. npage = atoi(p);
  96. if(npage < 1) {
  97. fprint(2, "no pages?\n");
  98. return nil;
  99. }
  100. d->npage = npage;
  101. d->docname = argv[0];
  102. gscmd(pdf, "Trailer\n");
  103. bbox = pdfbbox(pdf);
  104. pdf->pagebbox = emalloc(sizeof(Rectangle)*npage);
  105. for(i=0; i<npage; i++) {
  106. gscmd(pdf, "%d pdfgetpage\n", i+1);
  107. pdf->pagebbox[i] = pdfbbox(pdf);
  108. if(Dx(pdf->pagebbox[i]) <= 0)
  109. pdf->pagebbox[i] = bbox;
  110. }
  111. return d;
  112. }
  113. static Image*
  114. pdfdrawpage(Document *doc, int page)
  115. {
  116. PDFInfo *pdf = doc->extra;
  117. Image *im;
  118. gscmd(pdf, "%d DoPDFPage\n", page+1);
  119. im = readimage(display, pdf->gsdfd, 0);
  120. if(im == nil) {
  121. fprint(2, "fatal: readimage error %r\n");
  122. wexits("readimage");
  123. }
  124. waitgs(pdf);
  125. return im;
  126. }
  127. static char*
  128. pdfpagename(Document*, int page)
  129. {
  130. static char str[15];
  131. sprint(str, "p %d", page+1);
  132. return str;
  133. }