moz_main.c.svn-base

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 882 行 · 第 1/2 页

SVN-BASE
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 + -
显示快捷键?