moz_main.c
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 882 行 · 第 1/2 页
C
882 行
#include "fitz.h"#include "mupdf.h"#include <windows.h>#include <windowsx.h>#include "npapi.h"#include "npupp.h"#define PAD 5#define MSG(s) MessageBox(0,s,"MuPDF Debug",MB_OK)typedef struct pdfmoz_s pdfmoz_t;typedef struct page_s page_t;struct page_s{ fz_obj *ref; fz_obj *obj; pdf_page *page; fz_pixmap *image; int w, h; /* page size in units */ int px; /* pixel height */};struct pdfmoz_s{ NPP inst; HWND hwnd; HWND sbar; WNDPROC winproc; HCURSOR arrow, hand, wait; BITMAPINFO *dibinf; HBRUSH graybrush; int scrollpage; /* scrollbar -> page (n) */ int scrollyofs; /* scrollbar -> page offset in pixels */ int pagecount; page_t *pages; char *filename; char *doctitle; pdf_xref *xref; fz_renderer *rast; char error[1024]; /* empty if no error has occured */};void pdfmoz_warn(pdfmoz_t *moz, const char *fmt, ...){ char buf[1024]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); strcpy(moz->error, buf); InvalidateRect(moz->hwnd, NULL, FALSE); NPN_Status(moz->inst, moz->error);}void pdfmoz_error(pdfmoz_t *moz, fz_error *error){ strcpy(moz->error, error->msg); InvalidateRect(moz->hwnd, NULL, FALSE); NPN_Status(moz->inst, moz->error);}void pdfmoz_open(pdfmoz_t *moz, char *filename){ SCROLLINFO si; fz_error *error; fz_obj *obj; char *password = ""; pdf_pagetree *pages; fz_irect bbox; int rot; int i; strcpy(moz->error, ""); error = fz_newrenderer(&moz->rast, pdf_devicergb, 0, 1024 * 512); if (error) pdfmoz_error(moz, error); /* * Open PDF and load xref table */ moz->filename = filename; error = pdf_newxref(&moz->xref); if (error) pdfmoz_error(moz, error); error = pdf_loadxref(moz->xref, filename); if (error) { if (!strncmp(error->msg, "ioerror", 7)) pdfmoz_error(moz, error); error = pdf_repairxref(moz->xref, filename); if (error) pdfmoz_error(moz, error); } /* * Handle encrypted PDF files */ error = pdf_decryptxref(moz->xref); if (error) pdfmoz_error(moz, error); if (moz->xref->crypt) { int okay = pdf_setpassword(moz->xref->crypt, password); if (!okay) pdfmoz_warn(moz, "Invalid password."); } /* * Load page tree */ error = pdf_loadpagetree(&pages, moz->xref); if (error) pdfmoz_error(moz, error); moz->pagecount = pdf_getpagecount(pages); moz->pages = fz_malloc(sizeof(page_t) * moz->pagecount); for (i = 0; i < moz->pagecount; i++) { moz->pages[i].ref = fz_keepobj(pages->pref[i]); moz->pages[i].obj = fz_keepobj(pdf_getpageobject(pages, i)); moz->pages[i].page = nil; moz->pages[i].image = nil; obj = fz_dictgets(moz->pages[i].obj, "CropBox"); if (!obj) obj = fz_dictgets(moz->pages[i].obj, "MediaBox"); bbox = fz_roundrect(pdf_torect(obj)); moz->pages[i].w = bbox.x1 - bbox.x0; moz->pages[i].h = bbox.y1 - bbox.y0; rot = fz_toint(fz_dictgets(moz->pages[i].obj, "Rotate")); if ((rot / 90) % 2) { int t = moz->pages[i].w; moz->pages[i].w = moz->pages[i].h; moz->pages[i].h = t; } moz->pages[i].px = 1 + PAD; } pdf_droppagetree(pages); /* * Load meta information * TODO: move this into mupdf library */ obj = fz_dictgets(moz->xref->trailer, "Root"); if (!obj) pdfmoz_error(moz, fz_throw("syntaxerror: missing Root object")); error = pdf_loadindirect(&moz->xref->root, moz->xref, obj); if (error) pdfmoz_error(moz, error); obj = fz_dictgets(moz->xref->trailer, "Info"); if (obj) { error = pdf_loadindirect(&moz->xref->info, moz->xref, obj); if (error) pdfmoz_error(moz, error); } error = pdf_loadnametrees(moz->xref); if (error) pdfmoz_error(moz, error); moz->doctitle = filename; if (strrchr(moz->doctitle, '\\')) moz->doctitle = strrchr(moz->doctitle, '\\') + 1; if (strrchr(moz->doctitle, '/')) moz->doctitle = strrchr(moz->doctitle, '/') + 1; if (moz->xref->info) { obj = fz_dictgets(moz->xref->info, "Title"); if (obj) { error = pdf_toutf8(&moz->doctitle, obj); if (error) pdfmoz_error(moz, error); } } /* * Start at first page */ si.cbSize = sizeof(si); si.fMask = SIF_POS | SIF_RANGE; // XXX | SIF_PAGE; si.nPos = 0; si.nMin = 0; si.nMax = 1; si.nPage = 1; SetScrollInfo(moz->hwnd, SB_VERT, &si, TRUE); moz->scrollpage = 0; moz->scrollyofs = 0; InvalidateRect(moz->hwnd, NULL, FALSE);}static void decodescroll(pdfmoz_t *moz, int spos){ int i, y = 0; moz->scrollpage = 0; moz->scrollyofs = 0; for (i = 0; i < moz->pagecount; i++) { if (spos >= y && spos < y + moz->pages[i].px) { moz->scrollpage = i; moz->scrollyofs = spos - y; return; } y += moz->pages[i].px; }}fz_matrix pdfmoz_pagectm(pdfmoz_t *moz, int pagenum){ page_t *page = moz->pages + pagenum; fz_matrix ctm; float zoom; RECT rc; GetClientRect(moz->hwnd, &rc); zoom = (rc.right - rc.left) / (float) page->w; ctm = fz_identity(); ctm = fz_concat(ctm, fz_translate(0, -page->page->mediabox.y1)); ctm = fz_concat(ctm, fz_scale(zoom, -zoom)); ctm = fz_concat(ctm, fz_rotate(page->page->rotate)); return ctm;}void pdfmoz_loadpage(pdfmoz_t *moz, int pagenum){ page_t *page = moz->pages + pagenum; fz_error *error; if (page->page) return; error = pdf_loadpage(&page->page, moz->xref, page->obj); if (error) pdfmoz_error(moz, error);}void pdfmoz_drawpage(pdfmoz_t *moz, int pagenum){ page_t *page = moz->pages + pagenum; fz_error *error; fz_matrix ctm; fz_rect bbox; if (page->image) return; ctm = pdfmoz_pagectm(moz, pagenum); bbox = fz_transformaabb(ctm, page->page->mediabox); error = fz_rendertree(&page->image, moz->rast, page->page->tree, ctm, fz_roundrect(bbox), 1); if (error) pdfmoz_error(moz, error);}void pdfmoz_gotouri(pdfmoz_t *moz, fz_obj *uri){ char buf[2048]; memcpy(buf, fz_tostrbuf(uri), fz_tostrlen(uri)); buf[fz_tostrlen(uri)] = 0; NPN_GetURL(moz->inst, buf, "_blank");}int pdfmoz_getpagenum(pdfmoz_t *moz, fz_obj *obj){ int oid = fz_tonum(obj); int i; for (i = 0; i < moz->pagecount; i++) if (fz_tonum(moz->pages[i].ref) == oid) return i; return 0;}void pdfmoz_gotopage(pdfmoz_t *moz, fz_obj *obj){ int oid = fz_tonum(obj); int i, y = 0; for (i = 0; i < moz->pagecount; i++) { if (fz_tonum(moz->pages[i].ref) == oid) { SetScrollPos(moz->hwnd, SB_VERT, y, TRUE); InvalidateRect(moz->hwnd, NULL, FALSE); return; } y += moz->pages[i].px; }}void pdfmoz_onmouse(pdfmoz_t *moz, int x, int y, int click){ char buf[512]; pdf_link *link; fz_matrix ctm; fz_point p; int pi; int py; if (!moz->pages) return; pi = moz->scrollpage; py = -moz->scrollyofs; while (pi < moz->pagecount) { if (!moz->pages[pi].image) return; if (y > py && y < moz->pages[pi].px) break; py += moz->pages[pi].px; pi ++; } if (pi == moz->pagecount) return; p.x = x + moz->pages[pi].image->x; p.y = y + moz->pages[pi].image->y - py; ctm = pdfmoz_pagectm(moz, pi); ctm = fz_invertmatrix(ctm); p = fz_transformpoint(ctm, p); for (link = moz->pages[pi].page->links; link; link = link->next) { if (p.x >= link->rect.x0 && p.x <= link->rect.x1) if (p.y >= link->rect.y0 && p.y <= link->rect.y1) break; } if (link) { SetCursor(moz->hand); if (click) { if (fz_isstring(link->dest)) pdfmoz_gotouri(moz, link->dest); if (fz_isindirect(link->dest)) pdfmoz_gotopage(moz, link->dest); return; } else { if (fz_isstring(link->dest)) { memcpy(buf, fz_tostrbuf(link->dest), fz_tostrlen(link->dest)); buf[fz_tostrlen(link->dest)] = 0; NPN_Status(moz->inst, buf); } else if (fz_isindirect(link->dest)) { sprintf(buf, "Go to page %d", pdfmoz_getpagenum(moz, link->dest) + 1); NPN_Status(moz->inst, buf); } else NPN_Status(moz->inst, "Say what?"); } } else { sprintf(buf, "Page %d of %d", moz->scrollpage + 1, moz->pagecount); NPN_Status(moz->inst, buf); SetCursor(moz->arrow); }}static void drawimage(HDC hdc, pdfmoz_t *moz, fz_pixmap *image, int yofs){ int bmpstride = ((image->w * 3 + 3) / 4) * 4; char *bmpdata = fz_malloc(image->h * bmpstride); int x, y; if (!bmpdata) return; for (y = 0; y < image->h; y++) { char *p = bmpdata + y * bmpstride; char *s = image->samples + y * image->w * 4; for (x = 0; x < image->w; x++) { p[x * 3 + 0] = s[x * 4 + 3]; p[x * 3 + 1] = s[x * 4 + 2]; p[x * 3 + 2] = s[x * 4 + 1]; } } moz->dibinf->bmiHeader.biWidth = image->w; moz->dibinf->bmiHeader.biHeight = -image->h; moz->dibinf->bmiHeader.biSizeImage = image->h * bmpstride; SetDIBitsToDevice(hdc, 0, /* destx */ yofs, /* desty */ image->w, /* destw */ image->h, /* desth */ 0, /* srcx */ 0, /* srcy */ 0, /* startscan */ image->h, /* numscans */ bmpdata, /* pBits */ moz->dibinf, /* pInfo */ DIB_RGB_COLORS /* color use flag */ ); fz_free(bmpdata);}LRESULT CALLBACK
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?