pdf.c 3.3 KB

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