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 (link->kind == PDF_LURI) pdfmoz_gotouri(moz, link->dest); else if (link->kind == PDF_LGOTO) 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); } }
void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int state) { pdf_link *link; fz_matrix ctm; fz_point p; p.x = x - app->panx + app->image->x; p.y = y - app->pany + app->image->y; ctm = pdfapp_viewctm(app); ctm = fz_invertmatrix(ctm); p = fz_transformpoint(ctm, p); for (link = app->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) { wincursor(app, HAND); if (btn == 1 && state == 1) { if (fz_isstring(link->dest)) pdfapp_gotouri(app, link->dest); if (fz_isindirect(link->dest)) pdfapp_gotopage(app, link->dest); return; } } else { wincursor(app, ARROW); } if (state == 1) { if (btn == 1 && !app->iscopying) { app->ispanning = 1; app->selx = x; app->sely = y; } if (btn == 3 && !app->ispanning) { app->iscopying = 1; app->selx = x; app->sely = y; app->selr.x0 = x; app->selr.x1 = x; app->selr.y0 = y; app->selr.y1 = y; } if (btn == 4 || btn == 5) /* scroll wheel */ { int dir = btn == 4 ? 1 : -1; app->ispanning = app->iscopying = 0; if (modifiers & (1<<2)) { /* zoom in/out if ctrl is pressed */ app->zoom += 0.1 * dir; if (app->zoom > 3.0) app->zoom = 3.0; if (app->zoom < 0.1) app->zoom = 0.1; pdfapp_showpage(app, 0, 1); } else { /* scroll up/down, or left/right if shift is pressed */ int isx = (modifiers & (1<<0)); int xstep = isx ? 20 * dir : 0; int ystep = !isx ? 20 * dir : 0; pdfapp_panview(app, app->panx + xstep, app->pany + ystep); } } } else if (state == -1) { if (app->iscopying) { app->iscopying = 0; app->selr.x0 = MIN(app->selx, x); app->selr.x1 = MAX(app->selx, x); app->selr.y0 = MIN(app->sely, y); app->selr.y1 = MAX(app->sely, y); winrepaint(app); if (app->selr.x0 < app->selr.x1 && app->selr.y0 < app->selr.y1) windocopy(app); } if (app->ispanning) app->ispanning = 0; } else if (app->ispanning) { int newx = app->panx + x - app->selx; int newy = app->pany + y - app->sely; pdfapp_panview(app, newx, newy); app->selx = x; app->sely = y; } else if (app->iscopying) { app->selr.x0 = MIN(app->selx, x); app->selr.x1 = MAX(app->selx, x); app->selr.y0 = MIN(app->sely, y); app->selr.y1 = MAX(app->sely, y); winrepaint(app); } }
static fz_error * renderimage(fz_renderer *gc, fz_imagenode *node, fz_matrix ctm) { fz_error *error; fz_image *image = node->image; fz_irect bbox; fz_irect clip; int dx, dy; fz_pixmap *tile; fz_pixmap *temp; fz_matrix imgmat; fz_matrix invmat; int fa, fb, fc, fd; int u0, v0; int x0, y0; int w, h; int tileheight; DEBUG("image %dx%d %d+%d %s\n{\n", image->w, image->h, image->n, image->a, image->cs?image->cs->name:"(nil)"); bbox = fz_roundrect(fz_boundnode((fz_node*)node, ctm)); clip = fz_intersectirects(gc->clip, bbox); if (fz_isemptyrect(clip)) return fz_okay; if (image->w == 0 || image->h == 0) return fz_okay; if (image->n + image->a == 0) return fz_okay; calcimagescale(ctm, image->w, image->h, &dx, &dy); /* try to fit tile into a typical L2 cachce */ tileheight = 512 * 1024 / (image->w * (image->n + image->a)); /* tileheight must be an even multiple of dy, except for last band */ tileheight = (tileheight + dy - 1) / dy * dy; if ((dx != 1 || dy != 1) && image->h > tileheight) { int y = 0; DEBUG(" load image tile size = %dx%d\n", image->w, tileheight); error = fz_newpixmap(&tile, 0, 0, image->w, tileheight, image->n + 1); if (error) return error; error = fz_newscaledpixmap(&temp, image->w, image->h, image->n + 1, dx, dy); if (error) goto cleanup; do { if (y + tileheight > image->h) tileheight = image->h - y; tile->y = y; tile->h = tileheight; DEBUG(" tile xywh=%d %d %d %d sxsy=1/%d 1/%d\n", 0, y, image->w, tileheight, dx, dy); error = image->loadtile(image, tile); if (error) goto cleanup1; error = fz_scalepixmaptile(temp, 0, y, tile, dx, dy); if (error) goto cleanup1; y += tileheight; } while (y < image->h); fz_droppixmap(tile); tile = temp; } else { DEBUG(" load image\n"); error = fz_newpixmap(&tile, 0, 0, image->w, image->h, image->n + 1); if (error) return error; error = image->loadtile(image, tile); if (error) goto cleanup; if (dx != 1 || dy != 1) { DEBUG(" scale image 1/%d 1/%d\n", dx, dy); error = fz_scalepixmap(&temp, tile, dx, dy); if (error) goto cleanup; fz_droppixmap(tile); tile = temp; } } if (image->cs && image->cs != gc->model) { DEBUG(" convert from %s to %s\n", image->cs->name, gc->model->name); error = fz_newpixmap(&temp, tile->x, tile->y, tile->w, tile->h, gc->model->n + 1); if (error) goto cleanup; fz_convertpixmap(image->cs, tile, gc->model, temp); fz_droppixmap(tile); tile = temp; } imgmat.a = 1.0 / tile->w; imgmat.b = 0.0; imgmat.c = 0.0; imgmat.d = -1.0 / tile->h; imgmat.e = 0.0; imgmat.f = 1.0; invmat = fz_invertmatrix(fz_concat(imgmat, ctm)); w = clip.x1 - clip.x0; h = clip.y1 - clip.y0; x0 = clip.x0; y0 = clip.y0; u0 = (invmat.a * (x0+0.5) + invmat.c * (y0+0.5) + invmat.e) * 65536; v0 = (invmat.b * (x0+0.5) + invmat.d * (y0+0.5) + invmat.f) * 65536; fa = invmat.a * 65536; fb = invmat.b * 65536; fc = invmat.c * 65536; fd = invmat.d * 65536; #define PSRC tile->samples, tile->w, tile->h #define PDST(p) p->samples + ((y0-p->y) * p->w + (x0-p->x)) * p->n, p->w * p->n #define PCTM u0, v0, fa, fb, fc, fd, w, h switch (gc->flag) { case FNONE: { DEBUG(" fnone %d x %d\n", w, h); if (image->cs) error = fz_newpixmapwithrect(&gc->dest, clip, gc->model->n + 1); else error = fz_newpixmapwithrect(&gc->dest, clip, 1); if (error) goto cleanup; if (image->cs) fz_img_4c4(PSRC, PDST(gc->dest), PCTM); else fz_img_1c1(PSRC, PDST(gc->dest), PCTM); } break; case FOVER: { DEBUG(" fover %d x %d\n", w, h); if (image->cs) fz_img_4o4(PSRC, PDST(gc->over), PCTM); else fz_img_1o1(PSRC, PDST(gc->over), PCTM); } break; case FOVER | FRGB: DEBUG(" fover+rgb %d x %d\n", w, h); fz_img_w4i1o4(gc->argb, PSRC, PDST(gc->over), PCTM); break; default: assert(!"impossible flag in image span function"); } DEBUG("}\n"); fz_droppixmap(tile); return fz_okay; cleanup1: fz_droppixmap(temp); cleanup: fz_droppixmap(tile); return error; }
static void pdf_showpattern(pdf_csi *csi, pdf_pattern *pat, fz_rect bbox, int what) { pdf_gstate *gstate; fz_matrix ptm, invptm; fz_matrix oldtopctm; fz_error error; int x, y, x0, y0, x1, y1; int oldtop; pdf_gsave(csi); gstate = csi->gstate + csi->gtop; if (pat->ismask) { pdf_unsetpattern(csi, PDF_MFILL); pdf_unsetpattern(csi, PDF_MSTROKE); if (what == PDF_MFILL) { pdf_dropmaterial(&gstate->stroke); pdf_keepmaterial(&gstate->fill); gstate->stroke = gstate->fill; } if (what == PDF_MSTROKE) { pdf_dropmaterial(&gstate->fill); pdf_keepmaterial(&gstate->stroke); gstate->fill = gstate->stroke; } } else { // TODO: unset only the current fill/stroke or both? pdf_unsetpattern(csi, what); } /* don't apply softmasks to objects in the pattern as well */ if (gstate->softmask) { pdf_dropxobject(gstate->softmask); gstate->softmask = nil; } ptm = fz_concat(pat->matrix, csi->topctm); invptm = fz_invertmatrix(ptm); /* patterns are painted using the ctm in effect at the beginning of the content stream */ /* get bbox of shape in pattern space for stamping */ bbox = fz_transformrect(invptm, bbox); x0 = floorf(bbox.x0 / pat->xstep); y0 = floorf(bbox.y0 / pat->ystep); x1 = ceilf(bbox.x1 / pat->xstep); y1 = ceilf(bbox.y1 / pat->ystep); oldtopctm = csi->topctm; oldtop = csi->gtop; for (y = y0; y < y1; y++) { for (x = x0; x < x1; x++) { gstate->ctm = fz_concat(fz_translate(x * pat->xstep, y * pat->ystep), ptm); csi->topctm = gstate->ctm; error = pdf_runcsibuffer(csi, pat->resources, pat->contents); while (oldtop < csi->gtop) pdf_grestore(csi); if (error) { fz_catch(error, "cannot render pattern tile"); goto cleanup; } } } cleanup: csi->topctm = oldtopctm; pdf_grestore(csi); }
static fz_error * addshadeshape(pdf_gstate *gs, fz_node *shape, fz_shade *shade) { fz_error *error; fz_node *mask; fz_node *color; fz_node *xform; fz_node *over; fz_node *bgnd; fz_matrix ctm; fz_matrix inv; ctm = getmatrix(gs->head); inv = fz_invertmatrix(ctm); error = fz_newtransformnode(&xform, inv); if (error) return fz_rethrow(error, "cannot create transform node"); error = fz_newmasknode(&mask); if (error) { fz_dropnode(xform); return fz_rethrow(error, "cannot create mask node"); } error = fz_newshadenode(&color, shade); if (error) { fz_dropnode(mask); fz_dropnode(xform); return fz_rethrow(error, "cannot create shade node"); } if (shade->usebackground) { error = pdf_newovernode(&over, gs); if (error) { fz_dropnode(color); fz_dropnode(mask); fz_dropnode(xform); return fz_rethrow(error, "cannot create over node for background color"); } error = fz_newsolidnode(&bgnd, 1.0f, shade->cs, shade->cs->n, shade->background); if (error) { fz_dropnode(over); fz_dropnode(color); fz_dropnode(mask); fz_dropnode(xform); return fz_rethrow(error, "cannot create solid node for background color");; } fz_insertnodelast(mask, shape); fz_insertnodelast(over, bgnd); fz_insertnodelast(over, color); fz_insertnodelast(xform, over); fz_insertnodelast(mask, xform); fz_insertnodelast(gs->head, mask); } else { fz_insertnodelast(mask, shape); fz_insertnodelast(xform, color); fz_insertnodelast(mask, xform); fz_insertnodelast(gs->head, mask); } return fz_okay; }
static fz_error * addpatternshape(pdf_gstate *gs, fz_node *shape, pdf_pattern *pat, fz_colorspace *cs, float *v) { fz_error *error; fz_node *xform; fz_node *over; fz_node *mask; fz_node *link; fz_matrix ctm; fz_matrix inv; fz_matrix ptm; fz_rect bbox; int x, y, x0, y0, x1, y1; /* patterns are painted in user space */ ctm = getmatrix(gs->head); inv = fz_invertmatrix(ctm); error = fz_newmasknode(&mask); if (error) return fz_rethrow(error, "cannot create mask node"); ptm = fz_concat(pat->matrix, fz_invertmatrix(ctm)); error = fz_newtransformnode(&xform, ptm); if (error) { fz_dropnode(mask); return fz_rethrow(error, "cannot create transform node"); } error = pdf_newovernode(&over, gs); if (error) { fz_dropnode(xform); fz_dropnode(mask); return fz_rethrow(error, "cannot create over node"); } fz_insertnodelast(mask, shape); fz_insertnodelast(mask, xform); fz_insertnodelast(xform, over); xform = nil; /* over, xform, mask are now owned by the tree */ /* get bbox of shape in pattern space for stamping */ ptm = fz_concat(ctm, fz_invertmatrix(pat->matrix)); bbox = fz_boundnode(shape, ptm); /* expand bbox by pattern bbox */ bbox.x0 += pat->bbox.x0; bbox.y0 += pat->bbox.y0; bbox.x1 += pat->bbox.x1; bbox.y1 += pat->bbox.y1; x0 = fz_floor(bbox.x0 / pat->xstep); y0 = fz_floor(bbox.y0 / pat->ystep); x1 = fz_ceil(bbox.x1 / pat->xstep); y1 = fz_ceil(bbox.y1 / pat->ystep); for (y = y0; y <= y1; y++) { for (x = x0; x <= x1; x++) { ptm = fz_translate(x * pat->xstep, y * pat->ystep); error = fz_newtransformnode(&xform, ptm); if (error) return fz_rethrow(error, "cannot create transform node for stamp"); error = fz_newlinknode(&link, pat->tree); if (error) { fz_dropnode(xform); return fz_rethrow(error, "cannot create link node for stamp"); } fz_insertnodelast(xform, link); fz_insertnodelast(over, xform); } } if (pat->ismask) { error = addcolorshape(gs, mask, 1.0, cs, v); if (error) return fz_rethrow(error, "cannot add colored shape"); return fz_okay; } fz_insertnodelast(gs->head, mask); return fz_okay; }
void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int state) { pdf_link *link; fz_matrix ctm; fz_point p; p.x = x - app->panx + app->image->x; p.y = y - app->pany + app->image->y; ctm = pdfapp_viewctm(app); ctm = fz_invertmatrix(ctm); p = fz_transformpoint(ctm, p); for (link = app->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) { wincursor(app, HAND); if (btn == 1 && state == 1) { if (link->kind == PDF_LURI) pdfapp_gotouri(app, link->dest); else if (link->kind == PDF_LGOTO) pdfapp_gotopage(app, link->dest); return; } } else { wincursor(app, ARROW); } if (state == 1) { if (btn == 1 && !app->iscopying) { app->ispanning = 1; app->selx = x; app->sely = y; } if (btn == 3 && !app->ispanning) { kno_clearselect(app); //code change by kakai app->iscopying = 1; app->selx = x; app->sely = y; app->selr.x0 = x; app->selr.x1 = x; app->selr.y0 = y; app->selr.y1 = y; } if (btn == 4 || btn == 5) /* scroll wheel */ { int dir = btn == 4 ? 1 : -1; app->ispanning = app->iscopying = 0; if (modifiers & (1<<2)) { /* zoom in/out if ctrl is pressed */ app->zoom += 0.1 * dir; if (app->zoom > 3.0) app->zoom = 3.0; if (app->zoom < 0.1) app->zoom = 0.1; pdfapp_showpage(app, 0, 1); } else { /* scroll up/down, or left/right if shift is pressed */ int isx = (modifiers & (1<<0)); int xstep = isx ? 20 * dir : 0; int ystep = !isx ? 20 * dir : 0; pdfapp_panview(app, app->panx + xstep, app->pany + ystep); } } } else if (state == -1) { //Code change by Kakai //Hit testing kno_hitdata *hitdata = kno_gethitdata(app, x, y); printf("hit test char is: %c\n", hitdata->ucs); //Code change by Kakai if (app->iscopying) { app->iscopying = 0; app->selr.x0 = MIN(app->selx, x); app->selr.x1 = MAX(app->selx, x); app->selr.y0 = MIN(app->sely, y); app->selr.y1 = MAX(app->sely, y); winrepaint(app); if (app->selr.x0 < app->selr.x1 && app->selr.y0 < app->selr.y1) windocopy(app); } if (app->ispanning) app->ispanning = 0; } else if (app->ispanning) { int newx = app->panx + x - app->selx; int newy = app->pany + y - app->sely; pdfapp_panview(app, newx, newy); app->selx = x; app->sely = y; } else if (app->iscopying) { app->selr.x0 = MIN(app->selx, x); app->selr.x1 = MAX(app->selx, x); app->selr.y0 = MIN(app->sely, y); app->selr.y1 = MAX(app->sely, y); //code change by kakai //IsHighlightable and selection testing int closestx, closesty; closestx = closesty = 0; if (kno_ishighlightable(app, x, y, &closestx, &closesty) == 1) kno_onselect(app); //code change by kakai else { printf("x is %d\n", closestx); printf("y is %d\n", closesty); } //code change by kakai winrepaint(app); } }
static fz_error * renderimage(fz_renderer *gc, fz_imagenode *node, fz_matrix ctm) { fz_error *error; fz_image *image = node->image; fz_irect bbox; fz_irect clip; int dx, dy; fz_pixmap *tile; fz_pixmap *temp; fz_matrix imgmat; fz_matrix invmat; int fa, fb, fc, fd; int u0, v0; int x0, y0; int w, h; DEBUG("image %dx%d %d+%d %s\n{\n", image->w, image->h, image->n, image->a, image->cs?image->cs->name:"(nil)"); bbox = fz_roundrect(fz_boundnode((fz_node*)node, ctm)); clip = fz_intersectirects(gc->clip, bbox); if (fz_isemptyrect(clip)) return nil; calcimagescale(ctm, image->w, image->h, &dx, &dy); DEBUG(" load image\n"); error = fz_newpixmap(&tile, 0, 0, image->w, image->h, image->n + 1); if (error) return error; error = image->loadtile(image, tile); if (error) goto cleanup; if (dx != 1 || dy != 1) { DEBUG(" scale image 1/%d 1/%d\n", dx, dy); error = fz_scalepixmap(&temp, tile, dx, dy); if (error) goto cleanup; fz_droppixmap(tile); tile = temp; } if (image->cs && image->cs != gc->model) { DEBUG(" convert from %s to %s\n", image->cs->name, gc->model->name); error = fz_newpixmap(&temp, tile->x, tile->y, tile->w, tile->h, gc->model->n + 1); if (error) goto cleanup; fz_convertpixmap(image->cs, tile, gc->model, temp); fz_droppixmap(tile); tile = temp; } imgmat.a = 1.0 / tile->w; imgmat.b = 0.0; imgmat.c = 0.0; imgmat.d = -1.0 / tile->h; imgmat.e = 0.0; imgmat.f = 1.0; invmat = fz_invertmatrix(fz_concat(imgmat, ctm)); w = clip.x1 - clip.x0; h = clip.y1 - clip.y0; x0 = clip.x0; y0 = clip.y0; u0 = (invmat.a * (x0+0.5) + invmat.c * (y0+0.5) + invmat.e) * 65536; v0 = (invmat.b * (x0+0.5) + invmat.d * (y0+0.5) + invmat.f) * 65536; fa = invmat.a * 65536; fb = invmat.b * 65536; fc = invmat.c * 65536; fd = invmat.d * 65536; #define PSRC tile->samples, tile->w, tile->h #define PDST(p) p->samples + ((y0-p->y) * p->w + (x0-p->x)) * p->n, p->w * p->n #define PCTM u0, v0, fa, fb, fc, fd, w, h switch (gc->flag) { case FNONE: { DEBUG(" fnone %d x %d\n", w, h); if (image->cs) error = fz_newpixmapwithrect(&gc->dest, clip, gc->model->n + 1); else error = fz_newpixmapwithrect(&gc->dest, clip, 1); if (error) goto cleanup; if (image->cs) fz_img_4c4(PSRC, PDST(gc->dest), PCTM); else fz_img_1c1(PSRC, PDST(gc->dest), PCTM); } break; case FOVER: { DEBUG(" fover %d x %d\n", w, h); if (image->cs) fz_img_4o4(PSRC, PDST(gc->over), PCTM); else fz_img_1o1(PSRC, PDST(gc->over), PCTM); } break; case FOVER | FRGB: DEBUG(" fover+rgb %d x %d\n", w, h); fz_img_w3i1o4(gc->rgb, PSRC, PDST(gc->over), PCTM); break; default: assert(!"impossible flag in image span function"); } DEBUG("}\n"); fz_droppixmap(tile); return nil; cleanup: fz_droppixmap(tile); return error; }