/* lots of code c&p-ed directly from mupdf */#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <inttypes.h>#include <langinfo.h>#include <locale.h>#include <math.h>#include <pthread.h>#include <regex.h>#include <spawn.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <sys/uio.h>#include <unistd.h>#include <wchar.h> #ifdef LLPARANOIDP#pragma GCC diagnostic error "-Weverything"#pragma GCC diagnostic ignored "-Wpadded"#pragma GCC diagnostic ignored "-Wsign-conversion"#pragma GCC diagnostic ignored "-Wdocumentation-unknown-command"#pragma GCC diagnostic ignored "-Wdocumentation"#pragma GCC diagnostic ignored "-Wdouble-promotion"#pragma GCC diagnostic ignored "-Wimplicit-int-float-conversion"#else#pragma GCC diagnostic error "-Wcast-qual"#endif #include GL_H #define CAML_NAME_SPACE#include <caml/fail.h>#include <caml/alloc.h>#include <caml/memory.h>#include <caml/unixsupport.h> #pragma GCC diagnostic push#pragma GCC diagnostic ignored "-Wfloat-equal"#include <mupdf/fitz.h>#include <mupdf/pdf.h>#pragma GCC diagnostic pop #pragma GCC diagnostic push#ifdef __clang__#pragma GCC diagnostic ignored "-Wreserved-id-macro"#endif#include <ft2build.h>#include FT_FREETYPE_H#pragma GCC diagnostic pop #include "cutils.h" #define ARSERT(c) !(c) ? errx (1, "%s:%d " #c, __FILE__, __LINE__) : (void) 0#define ML(d) extern value ml_##d; value ml_##d#define ML0(d) extern void ml_##d; void ml_##d#define STTI(st) ((unsigned int) (st)) enum { Copen=23, Ccs, Cfreepage, Cfreetile, Csearch, Cgeometry, Creqlayout, Cpage, Ctile, Ctrimset, Csettrim, Csliceh, Cinterrupt };enum { FitWidth, FitProportional, FitPage };enum { LDfirst, LDlast };enum { LDfirstvisible, LDleft, LDright, LDdown, LDup };enum { Uuri, Utext, Utextannot, Ufileannot, Unone };enum { MarkPage, MarkBlock, MarkLine, MarkWord }; struct slice { int h; int texindex;}; struct tile { int w, h; int slicecount; int sliceheight; fz_pixmap *pixmap; struct slice slices[1];}; struct pagedim { int pageno; int rotate; int left; int tctmready; fz_irect bounds; fz_rect pagebox; fz_rect mediabox; fz_matrix ctm, zoomctm, tctm;}; struct slink { enum { SLINK, SANNOT } tag; fz_irect bbox; union { fz_link *link; pdf_annot *annot; } u;}; struct annot { fz_irect bbox; pdf_annot *annot;}; struct page { int tgen; int sgen; int agen; int pageno; int pdimno; fz_stext_page *text; fz_page *fzpage; fz_display_list *dlist; fz_link *links; int slinkcount; struct slink *slinks; int annotcount; struct annot *annots; fz_stext_char *fmark, *lmark;}; static struct { pthread_mutex_t mutex; int sliceheight; struct pagedim *pagedims; int pagecount; int pagedimcount; fz_document *doc; fz_context *ctx; int w, h; char *dcf; int pfds[2]; struct { int index, count; GLuint *ids; GLenum iform, form, ty; struct { int w, h; struct slice *slice; } *owners; } tex; fz_colorspace *colorspace; float papercolor[4]; FT_Face face; fz_pixmap *pig; pthread_t thread; fz_irect trimfuzz; GLuint stid, boid; int trimmargins, needoutline, gen, rotate, aalevel, fitmodel, trimanew, csock, dirty, utf8cs; GLfloat texcoords[8], vertices[16];} state = { .mutex = PTHREAD_MUTEX_INITIALIZER }; static void lock (const char *cap){ int ret = pthread_mutex_lock (&state.mutex); if (ret) { errx (1, "%s: pthread_mutex_lock: %d(%s)", cap, ret, strerror (ret)); }} static void unlock (const char *cap){ int ret = pthread_mutex_unlock (&state.mutex); if (ret) { errx (1, "%s: pthread_mutex_unlock: %d(%s)", cap, ret, strerror (ret)); }} static int trylock (const char *cap){ int ret = pthread_mutex_trylock (&state.mutex); if (ret && ret != EBUSY) { errx (1, "%s: pthread_mutex_trylock: %d(%s)", cap, ret, strerror (ret)); } return ret == EBUSY;} static int hasdata (int fd){ int ret, avail; ret = ioctl (fd, FIONREAD, &avail); if (ret) { err (1, errno, "hasdata: FIONREAD error ret=%d", ret); } return avail > 0;} ML (hasdata (value fd_v)){ CAMLparam1 (fd_v); CAMLreturn (Val_bool (hasdata (Int_val (fd_v))));} static void readdata (int fd, void *p, int size){ ssize_t n; again: n = read (fd, p, size); if (n < 0) { if (errno == EINTR) { goto again; } err (1, errno, "writev (fd %d, req %d, ret %zd)", fd, size, n); } if (n - size) { errx (1, "read (fd %d, req %d, ret %zd)", fd, size, n); }} static void writedata (int fd, char *p, int size){ ssize_t n; uint32_t size4 = size; struct iovec iov[2] = { { .iov_base = &size4, .iov_len = 4 }, { .iov_base = p, .iov_len = size } }; again: n = writev (fd, iov, 2); if (n < 0) { if (errno == EINTR) { goto again; } err (1, errno, "writev (fd %d, req %d, ret %zd)", fd, size + 4, n); } if (n - size - 4) { errx (1, "writev (fd %d, req %d, ret %zd)", fd, size + 4, n); }} static int readlen (int fd){ uint32_t u; readdata (fd, &u, 4); return u;} ML0 (wcmd (value fd_v, value bytes_v, value len_v)){ CAMLparam3 (fd_v, bytes_v, len_v); writedata (Int_val (fd_v), &Byte (bytes_v, 0), Int_val (len_v)); CAMLreturn0;} ML (rcmd (value fd_v)){ CAMLparam1 (fd_v); CAMLlocal1 (strdata_v); int fd = Int_val (fd_v); int len = readlen (fd); strdata_v = caml_alloc_string (len); readdata (fd, Bytes_val (strdata_v), len); CAMLreturn (strdata_v);} static void GCC_FMT_ATTR (1, 2) printd (const char *fmt, ...){ char fbuf[64]; int size = sizeof (fbuf), len; va_list ap; char *buf = fbuf; for (;;) { va_start (ap, fmt); len = vsnprintf (buf, size, fmt, ap); va_end (ap); if (len > -1) { if (len < size - 4) { writedata (state.csock, buf, len); break; } else { size = len + 5; } } else { err (1, errno, "vsnprintf for `%s' failed", fmt); } buf = realloc (buf == fbuf ? NULL : buf, size); if (!buf) { err (1, errno, "realloc for temp buf (%d bytes) failed", size); } } if (buf != fbuf) { free (buf); }} static void closedoc (void){ if (state.doc) { fz_drop_document (state.ctx, state.doc); state.doc = NULL; }} static int openxref (char *filename, char *mimetype, char *password, int w, int h, int em){ for (int i = 0; i < state.tex.count; ++i) { state.tex.owners[i].w = -1; state.tex.owners[i].slice = NULL; } closedoc (); state.dirty = 0; if (state.pagedims) { free (state.pagedims); state.pagedims = NULL; } state.pagedimcount = 0; fz_set_aa_level (state.ctx, state.aalevel); if (mimetype) { fz_stream *st = fz_open_file (state.ctx, filename); state.doc = fz_open_document_with_stream (state.ctx, mimetype, st); } else { state.doc = fz_open_document (state.ctx, filename); } if (fz_needs_password (state.ctx, state.doc)) { if (password && !*password) { printd ("pass"); return 0; } else { int ok = fz_authenticate_password (state.ctx, state.doc, password); if (!ok) { printd ("pass fail"); return 0; } } } if (w >= 0 || h >= 0 || em >=0) { fz_layout_document (state.ctx, state.doc, w, h, em); } state.pagecount = fz_count_pages (state.ctx, state.doc); if (state.pagecount < 0) { state.pagecount = 0; return 0; } return 1;} static void docinfo (void){ struct { char *tag; char *name; } tab[] = { { FZ_META_INFO_TITLE, "Title" }, { FZ_META_INFO_AUTHOR, "Author" }, { FZ_META_FORMAT, "Format" }, { FZ_META_ENCRYPTION, "Encryption" }, { FZ_META_INFO_CREATOR, "Creator" }, { FZ_META_INFO_PRODUCER, "Producer" }, { FZ_META_INFO_CREATIONDATE, "Creation date" }, { FZ_META_INFO_MODIFICATIONDATE, "Modification date"}, }; int len = 0, need; char *buf = NULL; for (size_t i = 0; i < sizeof (tab) / sizeof (*tab); ++i) { again: need = fz_lookup_metadata (state.ctx, state.doc, tab[i].tag, buf, len); if (need > 0) { if (need <= len) { printd ("info %s\t%s", tab[i].name, buf); } else { buf = realloc (buf, need); if (!buf) { err (1, errno, "docinfo realloc %d", need); } len = need; goto again; } } } free (buf); printd ("infoend");} static void unlinktile (struct tile *tile){ for (int i = 0; i < tile->slicecount; ++i) { struct slice *s = &tile->slices[i]; if (s->texindex != -1) { if (state.tex.owners[s->texindex].slice == s) { state.tex.owners[s->texindex].slice = NULL; } } }} static void freepage (struct page *page){ if (page) { fz_drop_stext_page (state.ctx, page->text); free (page->slinks); fz_drop_display_list (state.ctx, page->dlist); fz_drop_page (state.ctx, page->fzpage); free (page); }} static void freetile (struct tile *tile){ unlinktile (tile); fz_drop_pixmap (state.ctx, state.pig); state.pig = tile->pixmap; free (tile);} static void trimctm (pdf_page *page, int pindex){ struct pagedim *pdim = &state.pagedims[pindex]; if (!page) { return; } if (!pdim->tctmready) { fz_rect realbox, mediabox; fz_matrix page_ctm, ctm; ctm = fz_concat (fz_rotate (-pdim->rotate), fz_scale (1, -1)); realbox = fz_transform_rect (pdim->mediabox, ctm); pdf_page_transform (state.ctx, page, &mediabox, &page_ctm); pdim->tctm = fz_concat ( fz_invert_matrix (page_ctm), fz_concat (ctm, fz_translate (-realbox.x0, -realbox.y0))); pdim->tctmready = 1; }} static fz_matrix pagectm1 (fz_page *fzpage, struct pagedim *pdim){ fz_matrix ctm; ptrdiff_t pdimno = pdim - state.pagedims; ARSERT (pdim - state.pagedims < INT_MAX); if (pdf_specifics (state.ctx, state.doc)) { trimctm (pdf_page_from_fz_page (state.ctx, fzpage), (int) pdimno); ctm = fz_concat (pdim->tctm, pdim->ctm); } else { ctm = fz_concat (fz_translate (-pdim->mediabox.x0, -pdim->mediabox.y0), pdim->ctm); } return ctm;} static fz_matrix pagectm (struct page *page){ return pagectm1 (page->fzpage, &state.pagedims[page->pdimno]);} static void *loadpage (int pageno, int pindex){ fz_device *dev; struct page *page; page = calloc (sizeof (struct page), 1); if (!page) { err (1, errno, "calloc page %d", pageno); } page->dlist = fz_new_display_list (state.ctx, fz_infinite_rect); dev = fz_new_list_device (state.ctx, page->dlist); fz_try (state.ctx) { page->fzpage = fz_load_page (state.ctx, state.doc, pageno); fz_run_page (state.ctx, page->fzpage, dev, fz_identity, NULL); } fz_catch (state.ctx) { page->fzpage = NULL; } fz_close_device (state.ctx, dev); fz_drop_device (state.ctx, dev); page->pdimno = pindex; page->pageno = pageno; page->sgen = state.gen; page->agen = state.gen; page->tgen = state.gen; return page;} static struct tile *alloctile (int h)Lines 1–500 of 3681. Load more
/* lots of code c&p-ed directly from mupdf */ #include <ctype.h> #include <errno.h> #include <fcntl.h> #include <inttypes.h> #include <langinfo.h> #include <locale.h> #include <math.h> #include <pthread.h> #include <regex.h> #include <spawn.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/uio.h> #include <unistd.h> #include <wchar.h> #ifdef LLPARANOIDP #pragma GCC diagnostic error "-Weverything" #pragma GCC diagnostic ignored "-Wpadded" #pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" #pragma GCC diagnostic ignored "-Wdocumentation" #pragma GCC diagnostic ignored "-Wdouble-promotion" #pragma GCC diagnostic ignored "-Wimplicit-int-float-conversion" #else #pragma GCC diagnostic error "-Wcast-qual" #endif #include GL_H #define CAML_NAME_SPACE #include <caml/fail.h> #include <caml/alloc.h> #include <caml/memory.h> #include <caml/unixsupport.h> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" #include <mupdf/fitz.h> #include <mupdf/pdf.h> #pragma GCC diagnostic pop #pragma GCC diagnostic push #ifdef __clang__ #pragma GCC diagnostic ignored "-Wreserved-id-macro" #endif #include <ft2build.h> #include FT_FREETYPE_H #pragma GCC diagnostic pop #include "cutils.h" #define ARSERT(c) !(c) ? errx (1, "%s:%d " #c, __FILE__, __LINE__) : (void) 0 #define ML(d) extern value ml_##d; value ml_##d #define ML0(d) extern void ml_##d; void ml_##d #define STTI(st) ((unsigned int) (st)) enum { Copen=23, Ccs, Cfreepage, Cfreetile, Csearch, Cgeometry, Creqlayout, Cpage, Ctile, Ctrimset, Csettrim, Csliceh, Cinterrupt }; enum { FitWidth, FitProportional, FitPage }; enum { LDfirst, LDlast }; enum { LDfirstvisible, LDleft, LDright, LDdown, LDup }; enum { Uuri, Utext, Utextannot, Ufileannot, Unone }; enum { MarkPage, MarkBlock, MarkLine, MarkWord }; struct slice { int h; int texindex; }; struct tile { int w, h; int slicecount; int sliceheight; fz_pixmap *pixmap; struct slice slices[1]; }; struct pagedim { int pageno; int rotate; int left; int tctmready; fz_irect bounds; fz_rect pagebox; fz_rect mediabox; fz_matrix ctm, zoomctm, tctm; }; struct slink { enum { SLINK, SANNOT } tag; fz_irect bbox; union { fz_link *link; pdf_annot *annot; } u; }; struct annot { fz_irect bbox; pdf_annot *annot; }; struct page { int tgen; int sgen; int agen; int pageno; int pdimno; fz_stext_page *text; fz_page *fzpage; fz_display_list *dlist; fz_link *links; int slinkcount; struct slink *slinks; int annotcount; struct annot *annots; fz_stext_char *fmark, *lmark; }; static struct { pthread_mutex_t mutex; int sliceheight; struct pagedim *pagedims; int pagecount; int pagedimcount; fz_document *doc; fz_context *ctx; int w, h; char *dcf; int pfds[2]; struct { int index, count; GLuint *ids; GLenum iform, form, ty; struct { int w, h; struct slice *slice; } *owners; } tex; fz_colorspace *colorspace; float papercolor[4]; FT_Face face; fz_pixmap *pig; pthread_t thread; fz_irect trimfuzz; GLuint stid, boid; int trimmargins, needoutline, gen, rotate, aalevel, fitmodel, trimanew, csock, dirty, utf8cs; GLfloat texcoords[8], vertices[16]; } state = { .mutex = PTHREAD_MUTEX_INITIALIZER }; static void lock (const char *cap) { int ret = pthread_mutex_lock (&state.mutex); if (ret) { errx (1, "%s: pthread_mutex_lock: %d(%s)", cap, ret, strerror (ret)); } } static void unlock (const char *cap) { int ret = pthread_mutex_unlock (&state.mutex); if (ret) { errx (1, "%s: pthread_mutex_unlock: %d(%s)", cap, ret, strerror (ret)); } } static int trylock (const char *cap) { int ret = pthread_mutex_trylock (&state.mutex); if (ret && ret != EBUSY) { errx (1, "%s: pthread_mutex_trylock: %d(%s)", cap, ret, strerror (ret)); } return ret == EBUSY; } static int hasdata (int fd) { int ret, avail; ret = ioctl (fd, FIONREAD, &avail); if (ret) { err (1, errno, "hasdata: FIONREAD error ret=%d", ret); } return avail > 0; } ML (hasdata (value fd_v)) { CAMLparam1 (fd_v); CAMLreturn (Val_bool (hasdata (Int_val (fd_v)))); } static void readdata (int fd, void *p, int size) { ssize_t n; again: n = read (fd, p, size); if (n < 0) { if (errno == EINTR) { goto again; } err (1, errno, "writev (fd %d, req %d, ret %zd)", fd, size, n); } if (n - size) { errx (1, "read (fd %d, req %d, ret %zd)", fd, size, n); } } static void writedata (int fd, char *p, int size) { ssize_t n; uint32_t size4 = size; struct iovec iov[2] = { { .iov_base = &size4, .iov_len = 4 }, { .iov_base = p, .iov_len = size } }; again: n = writev (fd, iov, 2); if (n < 0) { if (errno == EINTR) { goto again; } err (1, errno, "writev (fd %d, req %d, ret %zd)", fd, size + 4, n); } if (n - size - 4) { errx (1, "writev (fd %d, req %d, ret %zd)", fd, size + 4, n); } } static int readlen (int fd) { uint32_t u; readdata (fd, &u, 4); return u; } ML0 (wcmd (value fd_v, value bytes_v, value len_v)) { CAMLparam3 (fd_v, bytes_v, len_v); writedata (Int_val (fd_v), &Byte (bytes_v, 0), Int_val (len_v)); CAMLreturn0; } ML (rcmd (value fd_v)) { CAMLparam1 (fd_v); CAMLlocal1 (strdata_v); int fd = Int_val (fd_v); int len = readlen (fd); strdata_v = caml_alloc_string (len); readdata (fd, Bytes_val (strdata_v), len); CAMLreturn (strdata_v); } static void GCC_FMT_ATTR (1, 2) printd (const char *fmt, ...) { char fbuf[64]; int size = sizeof (fbuf), len; va_list ap; char *buf = fbuf; for (;;) { va_start (ap, fmt); len = vsnprintf (buf, size, fmt, ap); va_end (ap); if (len > -1) { if (len < size - 4) { writedata (state.csock, buf, len); break; } else { size = len + 5; } } else { err (1, errno, "vsnprintf for `%s' failed", fmt); } buf = realloc (buf == fbuf ? NULL : buf, size); if (!buf) { err (1, errno, "realloc for temp buf (%d bytes) failed", size); } } if (buf != fbuf) { free (buf); } } static void closedoc (void) { if (state.doc) { fz_drop_document (state.ctx, state.doc); state.doc = NULL; } } static int openxref (char *filename, char *mimetype, char *password, int w, int h, int em) { for (int i = 0; i < state.tex.count; ++i) { state.tex.owners[i].w = -1; state.tex.owners[i].slice = NULL; } closedoc (); state.dirty = 0; if (state.pagedims) { free (state.pagedims); state.pagedims = NULL; } state.pagedimcount = 0; fz_set_aa_level (state.ctx, state.aalevel); if (mimetype) { fz_stream *st = fz_open_file (state.ctx, filename); state.doc = fz_open_document_with_stream (state.ctx, mimetype, st); } else { state.doc = fz_open_document (state.ctx, filename); } if (fz_needs_password (state.ctx, state.doc)) { if (password && !*password) { printd ("pass"); return 0; } else { int ok = fz_authenticate_password (state.ctx, state.doc, password); if (!ok) { printd ("pass fail"); return 0; } } } if (w >= 0 || h >= 0 || em >=0) { fz_layout_document (state.ctx, state.doc, w, h, em); } state.pagecount = fz_count_pages (state.ctx, state.doc); if (state.pagecount < 0) { state.pagecount = 0; return 0; } return 1; } static void docinfo (void) { struct { char *tag; char *name; } tab[] = { { FZ_META_INFO_TITLE, "Title" }, { FZ_META_INFO_AUTHOR, "Author" }, { FZ_META_FORMAT, "Format" }, { FZ_META_ENCRYPTION, "Encryption" }, { FZ_META_INFO_CREATOR, "Creator" }, { FZ_META_INFO_PRODUCER, "Producer" }, { FZ_META_INFO_CREATIONDATE, "Creation date" }, { FZ_META_INFO_MODIFICATIONDATE, "Modification date"}, }; int len = 0, need; char *buf = NULL; for (size_t i = 0; i < sizeof (tab) / sizeof (*tab); ++i) { again: need = fz_lookup_metadata (state.ctx, state.doc, tab[i].tag, buf, len); if (need > 0) { if (need <= len) { printd ("info %s\t%s", tab[i].name, buf); } else { buf = realloc (buf, need); if (!buf) { err (1, errno, "docinfo realloc %d", need); } len = need; goto again; } } } free (buf); printd ("infoend"); } static void unlinktile (struct tile *tile) { for (int i = 0; i < tile->slicecount; ++i) { struct slice *s = &tile->slices[i]; if (s->texindex != -1) { if (state.tex.owners[s->texindex].slice == s) { state.tex.owners[s->texindex].slice = NULL; } } } } static void freepage (struct page *page) { if (page) { fz_drop_stext_page (state.ctx, page->text); free (page->slinks); fz_drop_display_list (state.ctx, page->dlist); fz_drop_page (state.ctx, page->fzpage); free (page); } } static void freetile (struct tile *tile) { unlinktile (tile); fz_drop_pixmap (state.ctx, state.pig); state.pig = tile->pixmap; free (tile); } static void trimctm (pdf_page *page, int pindex) { struct pagedim *pdim = &state.pagedims[pindex]; if (!page) { return; } if (!pdim->tctmready) { fz_rect realbox, mediabox; fz_matrix page_ctm, ctm; ctm = fz_concat (fz_rotate (-pdim->rotate), fz_scale (1, -1)); realbox = fz_transform_rect (pdim->mediabox, ctm); pdf_page_transform (state.ctx, page, &mediabox, &page_ctm); pdim->tctm = fz_concat ( fz_invert_matrix (page_ctm), fz_concat (ctm, fz_translate (-realbox.x0, -realbox.y0))); pdim->tctmready = 1; } } static fz_matrix pagectm1 (fz_page *fzpage, struct pagedim *pdim) { fz_matrix ctm; ptrdiff_t pdimno = pdim - state.pagedims; ARSERT (pdim - state.pagedims < INT_MAX); if (pdf_specifics (state.ctx, state.doc)) { trimctm (pdf_page_from_fz_page (state.ctx, fzpage), (int) pdimno); ctm = fz_concat (pdim->tctm, pdim->ctm); } else { ctm = fz_concat (fz_translate (-pdim->mediabox.x0, -pdim->mediabox.y0), pdim->ctm); } return ctm; } static fz_matrix pagectm (struct page *page) { return pagectm1 (page->fzpage, &state.pagedims[page->pdimno]); } static void *loadpage (int pageno, int pindex) { fz_device *dev; struct page *page; page = calloc (sizeof (struct page), 1); if (!page) { err (1, errno, "calloc page %d", pageno); } page->dlist = fz_new_display_list (state.ctx, fz_infinite_rect); dev = fz_new_list_device (state.ctx, page->dlist); fz_try (state.ctx) { page->fzpage = fz_load_page (state.ctx, state.doc, pageno); fz_run_page (state.ctx, page->fzpage, dev, fz_identity, NULL); } fz_catch (state.ctx) { page->fzpage = NULL; } fz_close_device (state.ctx, dev); fz_drop_device (state.ctx, dev); page->pdimno = pindex; page->pageno = pageno; page->sgen = state.gen; page->agen = state.gen; page->tgen = state.gen; return page; } static struct tile *alloctile (int h)