static mume_matrix_t _pdf_doc_get_matrix( struct _pdf_doc *self, int pageno, float zoom, int rotate) { mume_matrix_t m; fz_matrix ctm = fz_identity; fz_rect mbox = self->media_boxes[pageno]; int rotation = (self->page_rotates[pageno] + rotate) % 360; if (rotation < 0) rotation = rotation + 360; if (90 == rotation) { ctm = fz_concat(ctm, fz_translate(-mbox.x0, -mbox.y0)); } else if (180 == rotation) { ctm = fz_concat(ctm, fz_translate(-mbox.x1, -mbox.y0)); } else if (270 == rotation) { ctm = fz_concat(ctm, fz_translate(-mbox.x1, -mbox.y1)); } else { ctm = fz_concat(ctm, fz_translate(-mbox.x0, -mbox.y1)); } ctm = fz_concat(ctm, fz_scale(zoom, -zoom)); ctm = fz_concat(ctm, fz_rotate(rotation)); m.a = ctm.a; m.b = ctm.b; m.c = ctm.c; m.d = ctm.d; m.e = ctm.e; m.f = ctm.f; return m; }
static void xps_paint_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect viewbox, int tile_mode, struct closure *c) { fz_matrix ttm; xps_paint_tiling_brush_clipped(ctx, ctm, viewbox, c); if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y) { ttm = fz_concat(fz_translate(viewbox.x1 * 2, 0), ctm); ttm = fz_concat(fz_scale(-1, 1), ttm); xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c); } if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y) { ttm = fz_concat(fz_translate(0, viewbox.y1 * 2), ctm); ttm = fz_concat(fz_scale(1, -1), ttm); xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c); } if (tile_mode == TILE_FLIP_X_Y) { ttm = fz_concat(fz_translate(viewbox.x1 * 2, viewbox.y1 * 2), ctm); ttm = fz_concat(fz_scale(-1, -1), ttm); xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c); } }
static void pdf_showspace(pdf_csi *csi, float tadj) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_fontdesc *fontdesc = gstate->font; if (fontdesc->wmode == 0) csi->tm = fz_concat(fz_translate(tadj * gstate->scale, 0), csi->tm); else csi->tm = fz_concat(fz_translate(0, tadj), csi->tm); }
void showspace(pdf_csi *csi, float tadj) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_font *font = gstate->font; if (font->super.wmode == 0) csi->tm = fz_concat(fz_translate(tadj * gstate->scale, 0), csi->tm); else csi->tm = fz_concat(fz_translate(0, tadj), csi->tm); }
/* Create transform to fit appearance stream to annotation Rect */ void pdf_annot_transform(fz_context *ctx, pdf_annot *annot, fz_matrix *annot_ctm) { fz_rect bbox, rect; fz_matrix matrix; float w, h, x, y; pdf_to_rect(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME_Rect), &rect); pdf_xobject_bbox(ctx, annot->ap, &bbox); pdf_xobject_matrix(ctx, annot->ap, &matrix); fz_transform_rect(&bbox, &matrix); if (bbox.x1 == bbox.x0) w = 0; else w = (rect.x1 - rect.x0) / (bbox.x1 - bbox.x0); if (bbox.y1 == bbox.y0) h = 0; else h = (rect.y1 - rect.y0) / (bbox.y1 - bbox.y0); x = rect.x0 - bbox.x0; y = rect.y0 - bbox.y0; fz_pre_scale(fz_translate(annot_ctm, x, y), w, h); }
static fz_matrix pdfViewctm(PDFContext* ctx) { fz_matrix ctm; ctm = fz_identity(); ctm = fz_concat(ctm, fz_translate(0, -ctx->page->mediabox.y1)); ctm = fz_concat(ctm, fz_scale(ctx->zoom, -ctx->zoom)); ctm = fz_concat(ctm, fz_rotate(ctx->rotate + ctx->page->rotate)); return ctm; }
void pdf_showspace(pdf_csi *csi, float tadj) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_fontdesc *fontdesc = gstate->font; if (!fontdesc) { fz_warn("cannot draw text since font and size not set"); return; } if (fontdesc->wmode == 0) csi->tm = fz_concat(fz_translate(tadj * gstate->scale, 0), csi->tm); else csi->tm = fz_concat(fz_translate(0, tadj), csi->tm); }
fz_matrix pdfapp_viewctm(pdfapp_t *app) { fz_matrix ctm; ctm = fz_identity(); ctm = fz_concat(ctm, fz_translate(0, -app->page->mediabox.y1)); ctm = fz_concat(ctm, fz_scale(app->zoom, -app->zoom)); ctm = fz_concat(ctm, fz_rotate(app->rotate + app->page->rotate)); return ctm; }
pdf_page * pdf_create_page(pdf_document *doc, fz_rect mediabox, int res, int rotate) { pdf_page *page = NULL; pdf_obj *pageobj; float userunit = 1; fz_context *ctx = doc->ctx; fz_matrix ctm, tmp; fz_rect realbox; page = fz_malloc_struct(ctx, pdf_page); fz_try(ctx) { page->resources = NULL; page->contents = NULL; page->transparency = 0; page->links = NULL; page->annots = NULL; page->me = pageobj = pdf_new_dict(doc, 4); pdf_dict_puts_drop(pageobj, "Type", pdf_new_name(doc, "Page")); page->mediabox.x0 = fz_min(mediabox.x0, mediabox.x1) * userunit; page->mediabox.y0 = fz_min(mediabox.y0, mediabox.y1) * userunit; page->mediabox.x1 = fz_max(mediabox.x0, mediabox.x1) * userunit; page->mediabox.y1 = fz_max(mediabox.y0, mediabox.y1) * userunit; pdf_dict_puts_drop(pageobj, "MediaBox", pdf_new_rect(doc, &page->mediabox)); /* Snap page->rotate to 0, 90, 180 or 270 */ if (page->rotate < 0) page->rotate = 360 - ((-page->rotate) % 360); if (page->rotate >= 360) page->rotate = page->rotate % 360; page->rotate = 90*((page->rotate + 45)/90); if (page->rotate > 360) page->rotate = 0; pdf_dict_puts_drop(pageobj, "Rotate", pdf_new_int(doc, page->rotate)); fz_pre_rotate(fz_scale(&ctm, 1, -1), -page->rotate); realbox = page->mediabox; fz_transform_rect(&realbox, &ctm); fz_pre_scale(fz_translate(&tmp, -realbox.x0, -realbox.y0), userunit, userunit); fz_concat(&ctm, &ctm, &tmp); page->ctm = ctm; /* Do not create a Contents, as an empty Contents dict is not * valid. See Bug 694712 */ } fz_catch(ctx) { pdf_drop_obj(page->me); fz_free(ctx, page); fz_rethrow_message(ctx, "Failed to create page"); } return page; }
static fz_matrix pdfapp_viewctm(pdfapp_t *app) { fz_matrix ctm; ctm = fz_identity; ctm = fz_concat(ctm, fz_translate(0, -app->page_bbox.y1)); if (app->xref) ctm = fz_concat(ctm, fz_scale(app->resolution/72.0f, -app->resolution/72.0f)); else ctm = fz_concat(ctm, fz_scale(app->resolution/96.0f, app->resolution/96.0f)); ctm = fz_concat(ctm, fz_rotate(app->rotate + app->page_rotate)); return ctm; }
QImage Pdf::page(int i) { pdf_page* page = pdf_load_page(xref, i); if (page == 0) { printf("cannot load page %d\n", i); return QImage(); } static const float resolution = 300.0; const float zoom = resolution / 72.0; fz_matrix ctm = fz_translate(0, -page->mediabox.y1); ctm = fz_concat(ctm, fz_scale(zoom, -zoom)); ctm = fz_concat(ctm, fz_rotate(page->rotate)); fz_bbox bbox = fz_round_rect(fz_transform_rect(ctm, page->mediabox)); fz_pixmap* pix = fz_new_pixmap_with_rect(ctx, fz_device_gray, bbox); fz_clear_pixmap_with_color(pix, 255); fz_device* dev = fz_new_draw_device(ctx, cache, pix); pdf_run_page(xref, page, dev, ctm); fz_free_device(dev); int w = pix->w; int h = pix->h; QImage image(w, h, QImage::Format_MonoLSB); QVector<QRgb> ct(2); ct[0] = qRgb(255, 255, 255); ct[1] = qRgb(0, 0, 0); image.setColorTable(ct); uchar* s = pix->samples; int stride = image.bytesPerLine(); int bytes = w >> 3; for (int line = 0; line < h; ++line) { uchar* d = image.bits() + stride * line; for (int col = 0; col < bytes; ++col) { uchar data = 0; for (int i = 0; i < 8; ++i) { uchar v = *s++; s++; data >>= 1; if (v < 128) data |= 0x80; } *d++ = data; } } fz_drop_pixmap(ctx, pix); pdf_free_page(ctx, page); return image; }
static void fz_draw_end_tile(fz_context *ctx, void *user) { fz_draw_device *dev = user; fz_pixmap *tile = dev->dest; float xstep, ystep; fz_matrix ctm, ttm; fz_rect area; int x0, y0, x1, y1, x, y; if (dev->top > 0) { dev->top--; #ifdef DUMP_GROUP_BLENDS dump_spaces(dev->top, "Tile end\n"); #endif xstep = dev->stack[dev->top].xstep; ystep = dev->stack[dev->top].ystep; area = dev->stack[dev->top].area; ctm = dev->stack[dev->top].ctm; dev->scissor = dev->stack[dev->top].scissor; dev->dest = dev->stack[dev->top].dest; dev->blendmode = dev->stack[dev->top].blendmode; x0 = floorf(area.x0 / xstep); y0 = floorf(area.y0 / ystep); x1 = ceilf(area.x1 / xstep); y1 = ceilf(area.y1 / ystep); ctm.e = tile->x; ctm.f = tile->y; for (y = y0; y < y1; y++) { for (x = x0; x < x1; x++) { ttm = fz_concat(fz_translate(x * xstep, y * ystep), ctm); tile->x = ttm.e; tile->y = ttm.f; fz_paint_pixmap_with_rect(dev->dest, tile, 255, dev->scissor); } } fz_drop_pixmap(ctx, tile); } if (dev->blendmode & FZ_BLEND_KNOCKOUT) fz_knockout_begin(ctx, dev); }
JNIEXPORT void JNICALL Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal( JNIEnv *env, jobject thiz, int page) { float zoom; fz_matrix ctm; fz_obj *pageobj; fz_bbox bbox; fz_error error; fz_device *dev; pdf_page *currentPage; /* In the event of an error, ensure we give a non-empty page */ pageWidth = 100; pageHeight = 100; LOGE("Goto page %d...", page); if (currentPageList != NULL) { fz_freedisplaylist(currentPageList); currentPageList = NULL; } pagenum = page; pageobj = pdf_getpageobject(xref, pagenum); if (pageobj == NULL) return; error = pdf_loadpage(¤tPage, xref, pageobj); if (error) return; zoom = resolution / 72; currentMediabox = currentPage->mediabox; currentRotate = currentPage->rotate; ctm = fz_translate(0, -currentMediabox.y1); ctm = fz_concat(ctm, fz_scale(zoom, -zoom)); ctm = fz_concat(ctm, fz_rotate(currentRotate)); bbox = fz_roundrect(fz_transformrect(ctm, currentMediabox)); pageWidth = bbox.x1-bbox.x0; pageHeight = bbox.y1-bbox.y0; /* Render to list */ currentPageList = fz_newdisplaylist(); dev = fz_newlistdevice(currentPageList); error = pdf_runpage(xref, currentPage, dev, fz_identity); pdf_freepage(currentPage); if (error) LOGE("cannot make displaylist from page %d", pagenum); fz_freedevice(dev); }
static void pdf_transform_annot(pdf_annot *annot) { fz_matrix matrix = annot->ap->matrix; fz_rect bbox = annot->ap->bbox; fz_rect rect = annot->rect; float w, h, x, y; bbox = fz_transform_rect(matrix, bbox); w = (rect.x1 - rect.x0) / (bbox.x1 - bbox.x0); h = (rect.y1 - rect.y0) / (bbox.y1 - bbox.y0); x = rect.x0 - bbox.x0; y = rect.y0 - bbox.y0; annot->matrix = fz_concat(fz_scale(w, h), fz_translate(x, y)); }
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; }
QImage render(qreal dpiX, qreal dpiY, const QRectF& rect) { if (m_init) { fz_scale(&m_matrix, dpiX / 72.0f, dpiY / 72.0f); fz_bound_page(m_ctx, m_page, &m_bound); fz_transform_rect(&m_bound, &m_matrix); m_init = false; } if (!m_list) { m_list = fz_new_display_list(m_ctx); } if (!m_dev) { m_dev = fz_new_list_device(m_ctx, m_list); fz_run_page(m_ctx, m_page, m_dev, &m_matrix, 0); } fz_matrix tile; fz_translate(&tile, -m_bound.x0, -m_bound.y0); fz_pre_translate(&tile, -rect.x(), -rect.y()); fz_rect tr; tr.x0 = tr.y0 = 0.0; int width = tr.x1 = rect.width(); int height = tr.y1 = rect.height(); QImage image(width, height, QImage::Format_RGB32); image.fill(Qt::white); // TODO: configurable fz_pixmap* pixmap = fz_new_pixmap_with_data(m_ctx, fz_device_bgr(m_ctx), image.width(), image.height(), image.bits()); fz_device *device = fz_new_draw_device(m_ctx, pixmap); fz_run_display_list(m_ctx, m_list, device, &tile, &tr, 0); fz_drop_device(m_ctx, device); fz_drop_pixmap(m_ctx, pixmap); return image; }
static void fz_draw_end_tile(void *user) { fz_draw_device *dev = user; fz_pixmap *tile = dev->dest; float xstep, ystep; fz_matrix ctm, ttm; fz_rect area; int x0, y0, x1, y1, x, y; if (dev->top > 0) { dev->top--; xstep = dev->stack[dev->top].xstep; ystep = dev->stack[dev->top].ystep; area = dev->stack[dev->top].area; ctm = dev->stack[dev->top].ctm; dev->scissor = dev->stack[dev->top].scissor; dev->dest = dev->stack[dev->top].dest; x0 = floorf(area.x0 / xstep); y0 = floorf(area.y0 / ystep); x1 = ceilf(area.x1 / xstep); y1 = ceilf(area.y1 / ystep); ctm.e = tile->x; ctm.f = tile->y; for (y = y0; y < y1; y++) { for (x = x0; x < x1; x++) { ttm = fz_concat(fz_translate(x * xstep, y * ystep), ctm); tile->x = ttm.e; tile->y = ttm.f; fz_paint_pixmap_with_rect(dev->dest, tile, 255, dev->scissor); } } fz_drop_pixmap(tile); } }
static void drawtxt(int pagenum) { fz_error error; pdf_textline *line; fz_matrix ctm; drawloadpage(pagenum, NULL); ctm = fz_concat( fz_translate(0, -drawpage->mediabox.y1), fz_scale(drawzoom, -drawzoom)); error = pdf_loadtextfromtree(&line, drawpage->tree, ctm); if (error) die(error); pdf_debugtextline(line); pdf_droptextline(line); drawfreepage(); }
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; }
/* Some explaination of the parameters here is warranted. See: http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes Add an arc segment to path, that describes a section of an elliptical arc from the current point of path to (point_x,point_y), such that: The arc segment is taken from an elliptical arc of semi major radius size_x, semi minor radius size_y, where the semi major axis of the ellipse is rotated by rotation_angle. If is_large_arc, then the arc segment is selected to be > 180 degrees. If is_clockwise, then the arc sweeps clockwise. */ static void xps_draw_arc(fz_context *doc, fz_path *path, float size_x, float size_y, float rotation_angle, int is_large_arc, int is_clockwise, float point_x, float point_y) { fz_matrix rotmat, revmat; fz_matrix mtx; fz_point pt; float rx, ry; float x1, y1, x2, y2; float x1t, y1t; float cxt, cyt, cx, cy; float t1, t2, t3; float sign; float th1, dth; pt = fz_currentpoint(doc, path); x1 = pt.x; y1 = pt.y; x2 = point_x; y2 = point_y; rx = size_x; ry = size_y; if (is_clockwise != is_large_arc) sign = 1; else sign = -1; fz_rotate(&rotmat, rotation_angle); fz_rotate(&revmat, -rotation_angle); /* http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes */ /* Conversion from endpoint to center parameterization */ /* F.6.6.1 -- ensure radii are positive and non-zero */ rx = fabsf(rx); ry = fabsf(ry); if (rx < 0.001f || ry < 0.001f || (x1 == x2 && y1 == y2)) { fz_lineto(doc, path, x2, y2); return; } /* F.6.5.1 */ pt.x = (x1 - x2) / 2; pt.y = (y1 - y2) / 2; fz_transform_vector(&pt, &revmat); x1t = pt.x; y1t = pt.y; /* F.6.6.2 -- ensure radii are large enough */ t1 = (x1t * x1t) / (rx * rx) + (y1t * y1t) / (ry * ry); if (t1 > 1) { rx = rx * sqrtf(t1); ry = ry * sqrtf(t1); } /* F.6.5.2 */ t1 = (rx * rx * ry * ry) - (rx * rx * y1t * y1t) - (ry * ry * x1t * x1t); t2 = (rx * rx * y1t * y1t) + (ry * ry * x1t * x1t); t3 = t1 / t2; /* guard against rounding errors; sqrt of negative numbers is bad for your health */ if (t3 < 0) t3 = 0; t3 = sqrtf(t3); cxt = sign * t3 * (rx * y1t) / ry; cyt = sign * t3 * -(ry * x1t) / rx; /* F.6.5.3 */ pt.x = cxt; pt.y = cyt; fz_transform_vector(&pt, &rotmat); cx = pt.x + (x1 + x2) / 2; cy = pt.y + (y1 + y2) / 2; /* F.6.5.4 */ { fz_point coord1, coord2, coord3, coord4; coord1.x = 1; coord1.y = 0; coord2.x = (x1t - cxt) / rx; coord2.y = (y1t - cyt) / ry; coord3.x = (x1t - cxt) / rx; coord3.y = (y1t - cyt) / ry; coord4.x = (-x1t - cxt) / rx; coord4.y = (-y1t - cyt) / ry; th1 = angle_between(coord1, coord2); dth = angle_between(coord3, coord4); if (dth < 0 && !is_clockwise) dth += (((float)M_PI / 180) * 360); if (dth > 0 && is_clockwise) dth -= (((float)M_PI / 180) * 360); } fz_pre_scale(fz_pre_rotate(fz_translate(&mtx, cx, cy), rotation_angle), rx, ry); xps_draw_arc_segment(doc, path, &mtx, th1, th1 + dth, is_clockwise); fz_lineto(doc, path, point_x, point_y); }
fz_error * showglyph(pdf_csi *csi, int cid) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_font *font = gstate->font; fz_error *error; fz_matrix tsm, trm; float w0, w1, tx, ty; fz_hmtx h; fz_vmtx v; tsm.a = gstate->size * gstate->scale; tsm.b = 0; tsm.c = 0; tsm.d = gstate->size; tsm.e = 0; tsm.f = gstate->rise; if (font->super.wmode == 1) { v = fz_getvmtx((fz_font*)font, cid); tsm.e -= v.x * gstate->size / 1000.0; tsm.f -= v.y * gstate->size / 1000.0; } trm = fz_concat(tsm, csi->tm); /* flush buffered text if face or matrix or rendermode has changed */ if (!csi->text || ((fz_font*)font) != csi->text->font || fabs(trm.a - csi->text->trm.a) > FLT_EPSILON || fabs(trm.b - csi->text->trm.b) > FLT_EPSILON || fabs(trm.c - csi->text->trm.c) > FLT_EPSILON || fabs(trm.d - csi->text->trm.d) > FLT_EPSILON || gstate->render != csi->textmode) { error = pdf_flushtext(csi); if (error) return fz_rethrow(error, "cannot finish text node (face/matrix change)"); error = fz_newtextnode(&csi->text, (fz_font*)font); if (error) return fz_rethrow(error, "cannot create text node"); csi->text->trm = trm; csi->text->trm.e = 0; csi->text->trm.f = 0; csi->textmode = gstate->render; } /* add glyph to textobject */ error = fz_addtext(csi->text, cid, trm.e, trm.f); if (error) return fz_rethrow(error, "cannot add glyph to text node"); if (font->super.wmode == 0) { h = fz_gethmtx((fz_font*)font, cid); w0 = h.w / 1000.0; tx = (w0 * gstate->size + gstate->charspace) * gstate->scale; csi->tm = fz_concat(fz_translate(tx, 0), csi->tm); } else { w1 = v.w / 1000.0; ty = w1 * gstate->size + gstate->charspace; csi->tm = fz_concat(fz_translate(0, ty), csi->tm); } return fz_okay; }
pdf_page * pdf_load_page_by_obj(pdf_document *doc, int number, pdf_obj *pageref) { fz_context *ctx = doc->ctx; pdf_page *page; pdf_annot *annot; pdf_obj *pageobj, *obj; fz_rect mediabox, cropbox, realbox; float userunit; fz_matrix mat; /* SumatraPDF: allow replacing potentially slow pdf_lookup_page_obj */ pageobj = pdf_resolve_indirect(pageref); page = fz_malloc_struct(ctx, pdf_page); page->resources = NULL; page->contents = NULL; page->transparency = 0; page->links = NULL; page->annots = NULL; page->annot_tailp = &page->annots; page->deleted_annots = NULL; page->tmp_annots = NULL; page->me = pdf_keep_obj(pageobj); page->incomplete = 0; obj = pdf_dict_gets(pageobj, "UserUnit"); if (pdf_is_real(obj)) userunit = pdf_to_real(obj); else userunit = 1; pdf_to_rect(ctx, pdf_lookup_inherited_page_item(doc, pageobj, "MediaBox"), &mediabox); if (fz_is_empty_rect(&mediabox)) { fz_warn(ctx, "cannot find page size for page %d", number + 1); mediabox.x0 = 0; mediabox.y0 = 0; mediabox.x1 = 612; mediabox.y1 = 792; } pdf_to_rect(ctx, pdf_lookup_inherited_page_item(doc, pageobj, "CropBox"), &cropbox); if (!fz_is_empty_rect(&cropbox)) fz_intersect_rect(&mediabox, &cropbox); page->mediabox.x0 = fz_min(mediabox.x0, mediabox.x1) * userunit; page->mediabox.y0 = fz_min(mediabox.y0, mediabox.y1) * userunit; page->mediabox.x1 = fz_max(mediabox.x0, mediabox.x1) * userunit; page->mediabox.y1 = fz_max(mediabox.y0, mediabox.y1) * userunit; if (page->mediabox.x1 - page->mediabox.x0 < 1 || page->mediabox.y1 - page->mediabox.y0 < 1) { fz_warn(ctx, "invalid page size in page %d", number + 1); page->mediabox = fz_unit_rect; } page->rotate = pdf_to_int(pdf_lookup_inherited_page_item(doc, pageobj, "Rotate")); /* Snap page->rotate to 0, 90, 180 or 270 */ if (page->rotate < 0) page->rotate = 360 - ((-page->rotate) % 360); if (page->rotate >= 360) page->rotate = page->rotate % 360; page->rotate = 90*((page->rotate + 45)/90); if (page->rotate > 360) page->rotate = 0; fz_pre_rotate(fz_scale(&page->ctm, 1, -1), -page->rotate); realbox = page->mediabox; fz_transform_rect(&realbox, &page->ctm); fz_pre_scale(fz_translate(&mat, -realbox.x0, -realbox.y0), userunit, userunit); fz_concat(&page->ctm, &page->ctm, &mat); fz_try(ctx) { obj = pdf_dict_gets(pageobj, "Annots"); if (obj) { page->links = pdf_load_link_annots(doc, obj, &page->ctm); pdf_load_annots(doc, page, obj); } } fz_catch(ctx) { if (fz_caught(ctx) != FZ_ERROR_TRYLATER) /* SumatraPDF: ignore annotations in case of unexpected errors */ fz_warn(ctx, "unexpectedly failed to load page annotations"); page->incomplete |= PDF_PAGE_INCOMPLETE_ANNOTS; } page->duration = pdf_to_real(pdf_dict_gets(pageobj, "Dur")); obj = pdf_dict_gets(pageobj, "Trans"); page->transition_present = (obj != NULL); if (obj) { pdf_load_transition(doc, page, obj); } // TODO: inherit page->resources = pdf_lookup_inherited_page_item(doc, pageobj, "Resources"); if (page->resources) pdf_keep_obj(page->resources); obj = pdf_dict_gets(pageobj, "Contents"); fz_try(ctx) { page->contents = pdf_keep_obj(obj); if (pdf_resources_use_blending(doc, page->resources)) page->transparency = 1; /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=2107 */ else if (!strcmp(pdf_to_name(pdf_dict_getp(pageobj, "Group/S")), "Transparency")) page->transparency = 1; for (annot = page->annots; annot && !page->transparency; annot = annot->next) if (annot->ap && pdf_resources_use_blending(doc, annot->ap->resources)) page->transparency = 1; } fz_catch(ctx) { if (fz_caught(ctx) != FZ_ERROR_TRYLATER) { pdf_free_page(doc, page); fz_rethrow_message(ctx, "cannot load page %d contents (%d 0 R)", number + 1, pdf_to_num(pageref)); } page->incomplete |= PDF_PAGE_INCOMPLETE_CONTENTS; } return page; }
static void fz_draw_end_tile(fz_device *devp) { fz_draw_device *dev = devp->user; float xstep, ystep; fz_matrix ctm, ttm, shapectm; fz_rect area; int x0, y0, x1, y1, x, y; fz_context *ctx = dev->ctx; fz_draw_state *state; if (dev->top == 0) { fz_warn(ctx, "Unexpected end_tile"); return; } state = &dev->stack[--dev->top]; xstep = state[1].xstep; ystep = state[1].ystep; area = state[1].area; ctm = state[1].ctm; x0 = floorf(area.x0 / xstep); y0 = floorf(area.y0 / ystep); x1 = ceilf(area.x1 / xstep); y1 = ceilf(area.y1 / ystep); ctm.e = state[1].dest->x; ctm.f = state[1].dest->y; if (state[1].shape) { shapectm = ctm; shapectm.e = state[1].shape->x; shapectm.f = state[1].shape->y; } #ifdef DUMP_GROUP_BLENDS dump_spaces(dev->top, ""); fz_dump_blend(dev->ctx, state[1].dest, "Tiling "); if (state[1].shape) fz_dump_blend(dev->ctx, state[1].shape, "/"); fz_dump_blend(dev->ctx, state[0].dest, " onto "); if (state[0].shape) fz_dump_blend(dev->ctx, state[0].shape, "/"); #endif for (y = y0; y < y1; y++) { for (x = x0; x < x1; x++) { ttm = fz_concat(fz_translate(x * xstep, y * ystep), ctm); state[1].dest->x = ttm.e; state[1].dest->y = ttm.f; fz_paint_pixmap_with_rect(state[0].dest, state[1].dest, 255, state[0].scissor); if (state[1].shape) { ttm = fz_concat(fz_translate(x * xstep, y * ystep), shapectm); state[1].shape->x = ttm.e; state[1].shape->y = ttm.f; fz_paint_pixmap_with_rect(state[0].shape, state[1].shape, 255, state[0].scissor); } } } fz_drop_pixmap(dev->ctx, state[1].dest); fz_drop_pixmap(dev->ctx, state[1].shape); #ifdef DUMP_GROUP_BLENDS fz_dump_blend(dev->ctx, state[0].dest, " to get "); if (state[0].shape) fz_dump_blend(dev->ctx, state[0].shape, "/"); printf("\n"); #endif if (state->blendmode & FZ_BLEND_KNOCKOUT) fz_knockout_end(dev); }
static void drawpage(xps_context *ctx, int pagenum) { xps_page *page; fz_display_list *list; fz_device *dev; int start; int code; if (showtime) { start = gettime(); } code = xps_load_page(&page, ctx, pagenum - 1); if (code) die(fz_rethrow(code, "cannot load page %d in file '%s'", pagenum, filename)); list = NULL; if (uselist) { list = fz_new_display_list(); dev = fz_new_list_device(list); xps_run_page(ctx, page, dev, fz_identity); fz_free_device(dev); } if (showxml) { dev = fz_new_trace_device(); printf("<page number=\"%d\">\n", pagenum); if (list) fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox); else xps_run_page(ctx, page, dev, fz_identity); printf("</page>\n"); fz_free_device(dev); } if (showtext) { fz_text_span *text = fz_new_text_span(); dev = fz_new_text_device(text); if (list) fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox); else xps_run_page(ctx, page, dev, fz_identity); fz_free_device(dev); printf("[Page %d]\n", pagenum); if (showtext > 1) fz_debug_text_span_xml(text); else fz_debug_text_span(text); printf("\n"); fz_free_text_span(text); } if (showmd5 || showtime) printf("page %s %d", filename, pagenum); if (output || showmd5 || showtime) { float zoom; fz_matrix ctm; fz_rect rect; fz_bbox bbox; fz_pixmap *pix; rect.x0 = rect.y0 = 0; rect.x1 = page->width; rect.y1 = page->height; zoom = resolution / 96; ctm = fz_translate(0, -page->height); ctm = fz_concat(ctm, fz_scale(zoom, zoom)); bbox = fz_round_rect(fz_transform_rect(ctm, rect)); /* TODO: banded rendering and multi-page ppm */ pix = fz_new_pixmap_with_rect(colorspace, bbox); if (savealpha) fz_clear_pixmap(pix); else fz_clear_pixmap_with_color(pix, 255); dev = fz_new_draw_device(glyphcache, pix); if (list) fz_execute_display_list(list, dev, ctm, bbox); else xps_run_page(ctx, page, dev, ctm); fz_free_device(dev); if (output) { char buf[512]; sprintf(buf, output, pagenum); if (strstr(output, ".pgm") || strstr(output, ".ppm") || strstr(output, ".pnm")) fz_write_pnm(pix, buf); else if (strstr(output, ".pam")) fz_write_pam(pix, buf, savealpha); else if (strstr(output, ".png")) fz_write_png(pix, buf, savealpha); } if (showmd5) { fz_md5 md5; unsigned char digest[16]; int i; fz_md5_init(&md5); fz_md5_update(&md5, pix->samples, pix->w * pix->h * pix->n); fz_md5_final(&md5, digest); printf(" "); for (i = 0; i < 16; i++) printf("%02x", digest[i]); } fz_drop_pixmap(pix); } if (list) fz_free_display_list(list); if (showtime) { int end = gettime(); int diff = end - start; if (diff < timing.min) { timing.min = diff; timing.minpage = pagenum; } if (diff > timing.max) { timing.max = diff; timing.maxpage = pagenum; } timing.total += diff; timing.count ++; printf(" %dms", diff); } if (showmd5 || showtime) printf("\n"); }
void drawpnm(int pagenum) { fz_error *error; fz_matrix ctm; fz_irect bbox; fz_pixmap *pix; char namebuf[256]; char buf[256]; int x, y, w, h, b, bh; int fd; drawloadpage(pagenum); ctm = fz_identity(); ctm = fz_concat(ctm, fz_translate(0, -drawpage->mediabox.y1)); ctm = fz_concat(ctm, fz_scale(drawzoom, -drawzoom)); ctm = fz_concat(ctm, fz_rotate(drawrotate + drawpage->rotate)); bbox = fz_roundrect(fz_transformaabb(ctm, drawpage->mediabox)); w = bbox.x1 - bbox.x0; h = bbox.y1 - bbox.y0; bh = h / drawbands; if (drawpattern) { sprintf(namebuf, drawpattern, drawcount++); fd = open(namebuf, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd < 0) die(fz_throw("ioerror: could not open file '%s'", namebuf)); } else fd = 1; sprintf(buf, "P6\n%d %d\n255\n", w, h); write(fd, buf, strlen(buf)); error = fz_newpixmap(&pix, bbox.x0, bbox.y0, w, bh, 4); if (error) die(error); memset(pix->samples, 0xff, pix->h * pix->w * pix->n); for (b = 0; b < drawbands; b++) { if (drawbands > 1) fprintf(stderr, "drawing band %d / %d\n", b + 1, drawbands); error = fz_rendertreeover(drawgc, pix, drawpage->tree, ctm); if (error) die(error); for (y = 0; y < pix->h; y++) { unsigned char *src = pix->samples + y * pix->w * 4; unsigned char *dst = src; for (x = 0; x < pix->w; x++) { dst[x * 3 + 0] = src[x * 4 + 1]; dst[x * 3 + 1] = src[x * 4 + 2]; dst[x * 3 + 2] = src[x * 4 + 3]; } write(fd, dst, pix->w * 3); memset(src, 0xff, pix->w * 4); } pix->y += bh; if (pix->y + pix->h > bbox.y1) pix->h = bbox.y1 - pix->y; } fz_droppixmap(pix); if (drawpattern) close(fd); drawfreepage(); }
static void drawpnm(int pagenum, struct benchmark *loadtimes, struct benchmark *drawtimes) { fz_error error; fz_matrix ctm; fz_irect bbox; fz_pixmap *pix; char name[256]; char pnmhdr[256]; int i, x, y, w, h, b, bh; int fd = -1; long start; long end; long elapsed; fz_md5 digest; if (!drawpattern) fz_md5init(&digest); drawloadpage(pagenum, loadtimes); if (benchmark) gettime(&start); ctm = fz_identity(); ctm = fz_concat(ctm, fz_translate(0, -drawpage->mediabox.y1)); ctm = fz_concat(ctm, fz_scale(drawzoom, -drawzoom)); ctm = fz_concat(ctm, fz_rotate(drawrotate + drawpage->rotate)); bbox = fz_roundrect(fz_transformaabb(ctm, drawpage->mediabox)); w = bbox.x1 - bbox.x0; h = bbox.y1 - bbox.y0; bh = h / drawbands; if (drawpattern) { sprintf(name, drawpattern, drawcount++); fd = open(name, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd < 0) die(fz_throw("ioerror: could not open file '%s'", name)); sprintf(pnmhdr, "P6\n%d %d\n255\n", w, h); write(fd, pnmhdr, strlen(pnmhdr)); } error = fz_newpixmap(&pix, bbox.x0, bbox.y0, w, bh, 4); if (error) die(error); memset(pix->samples, 0xff, pix->h * pix->w * pix->n); for (b = 0; b < drawbands; b++) { if (drawbands > 1) fprintf(stderr, "drawing band %d / %d\n", b + 1, drawbands); error = fz_rendertreeover(drawgc, pix, drawpage->tree, ctm); if (error) die(error); if (drawpattern) { for (y = 0; y < pix->h; y++) { unsigned char *src = pix->samples + y * pix->w * 4; unsigned char *dst = src; for (x = 0; x < pix->w; x++) { dst[x * 3 + 0] = src[x * 4 + 1]; dst[x * 3 + 1] = src[x * 4 + 2]; dst[x * 3 + 2] = src[x * 4 + 3]; } write(fd, dst, pix->w * 3); memset(src, 0xff, pix->w * 4); } } if (!drawpattern) fz_md5update(&digest, pix->samples, pix->h * pix->w * 4); pix->y += bh; if (pix->y + pix->h > bbox.y1) pix->h = bbox.y1 - pix->y; } fz_droppixmap(pix); if (!drawpattern) { unsigned char buf[16]; fz_md5final(&digest, buf); for (i = 0; i < 16; i++) fprintf(stderr, "%02x", buf[i]); } if (drawpattern) close(fd); drawfreepage(); if (benchmark) { gettime(&end); elapsed = end - start; if (elapsed < drawtimes->min) { drawtimes->min = elapsed; drawtimes->minpage = pagenum; } if (elapsed > drawtimes->max) { drawtimes->max = elapsed; drawtimes->maxpage = pagenum; } drawtimes->avg += elapsed; drawtimes->pages++; fprintf(stderr, " time %.3fs", elapsed / 1000000.0); } fprintf(stderr, "\n"); }
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 void pdf_showglyph(pdf_csi *csi, int cid) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_fontdesc *fontdesc = gstate->font; fz_matrix tsm, trm; float w0, w1, tx, ty; pdf_hmtx h; pdf_vmtx v; int gid; int ucsbuf[8]; int ucslen; int i; tsm.a = gstate->size * gstate->scale; tsm.b = 0; tsm.c = 0; tsm.d = gstate->size; tsm.e = 0; tsm.f = gstate->rise; ucslen = 0; if (fontdesc->tounicode) ucslen = pdf_lookupcmapfull(fontdesc->tounicode, cid, ucsbuf); if (ucslen == 0 && cid < fontdesc->ncidtoucs) { ucsbuf[0] = fontdesc->cidtoucs[cid]; ucslen = 1; } if (ucslen == 0 || (ucslen == 1 && ucsbuf[0] == 0)) { ucsbuf[0] = '?'; ucslen = 1; } gid = pdf_fontcidtogid(fontdesc, cid); if (fontdesc->wmode == 1) { v = pdf_getvmtx(fontdesc, cid); tsm.e -= v.x * gstate->size * 0.001f; tsm.f -= v.y * gstate->size * 0.001f; } trm = fz_concat(tsm, csi->tm); /* flush buffered text if face or matrix or rendermode has changed */ if (!csi->text || fontdesc->font != csi->text->font || fontdesc->wmode != csi->text->wmode || fabsf(trm.a - csi->text->trm.a) > FLT_EPSILON || fabsf(trm.b - csi->text->trm.b) > FLT_EPSILON || fabsf(trm.c - csi->text->trm.c) > FLT_EPSILON || fabsf(trm.d - csi->text->trm.d) > FLT_EPSILON || gstate->render != csi->textmode) { pdf_flushtext(csi); csi->text = fz_newtext(fontdesc->font, trm, fontdesc->wmode); csi->text->trm.e = 0; csi->text->trm.f = 0; csi->textmode = gstate->render; } /* add glyph to textobject */ fz_addtext(csi->text, gid, ucsbuf[0], trm.e, trm.f); /* add filler glyphs for one-to-many unicode mapping */ for (i = 1; i < ucslen; i++) fz_addtext(csi->text, -1, ucsbuf[i], trm.e, trm.f); if (fontdesc->wmode == 0) { h = pdf_gethmtx(fontdesc, cid); w0 = h.w * 0.001f; tx = (w0 * gstate->size + gstate->charspace) * gstate->scale; csi->tm = fz_concat(fz_translate(tx, 0), csi->tm); } if (fontdesc->wmode == 1) { w1 = v.w * 0.001f; ty = w1 * gstate->size + gstate->charspace; csi->tm = fz_concat(fz_translate(0, ty), csi->tm); } }
void xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root, void (*func)(xps_context*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*), void *user) { xml_element *node; struct closure c; char *opacity_att; char *transform_att; char *viewbox_att; char *viewport_att; char *tile_mode_att; char *viewbox_units_att; char *viewport_units_att; xml_element *transform_tag = NULL; fz_matrix transform; fz_rect viewbox; fz_rect viewport; float xstep, ystep; float xscale, yscale; int tile_mode; opacity_att = xml_att(root, "Opacity"); transform_att = xml_att(root, "Transform"); viewbox_att = xml_att(root, "Viewbox"); viewport_att = xml_att(root, "Viewport"); tile_mode_att = xml_att(root, "TileMode"); viewbox_units_att = xml_att(root, "ViewboxUnits"); viewport_units_att = xml_att(root, "ViewportUnits"); c.base_uri = base_uri; c.dict = dict; c.root = root; c.user = user; c.func = func; for (node = xml_down(root); node; node = xml_next(node)) { if (!strcmp(xml_tag(node), "ImageBrush.Transform")) transform_tag = xml_down(node); if (!strcmp(xml_tag(node), "VisualBrush.Transform")) transform_tag = xml_down(node); } xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); transform = fz_identity; if (transform_att) xps_parse_render_transform(ctx, transform_att, &transform); if (transform_tag) xps_parse_matrix_transform(ctx, transform_tag, &transform); ctm = fz_concat(transform, ctm); viewbox = fz_unit_rect; if (viewbox_att) xps_parse_rectangle(ctx, viewbox_att, &viewbox); viewport = fz_unit_rect; if (viewport_att) xps_parse_rectangle(ctx, viewport_att, &viewport); /* some sanity checks on the viewport/viewbox size */ if (fabsf(viewport.x1 - viewport.x0) < 0.01f) return; if (fabsf(viewport.y1 - viewport.y0) < 0.01f) return; if (fabsf(viewbox.x1 - viewbox.x0) < 0.01f) return; if (fabsf(viewbox.y1 - viewbox.y0) < 0.01f) return; xstep = viewbox.x1 - viewbox.x0; ystep = viewbox.y1 - viewbox.y0; xscale = (viewport.x1 - viewport.x0) / xstep; yscale = (viewport.y1 - viewport.y0) / ystep; tile_mode = TILE_NONE; if (tile_mode_att) { if (!strcmp(tile_mode_att, "None")) tile_mode = TILE_NONE; if (!strcmp(tile_mode_att, "Tile")) tile_mode = TILE_TILE; if (!strcmp(tile_mode_att, "FlipX")) tile_mode = TILE_FLIP_X; if (!strcmp(tile_mode_att, "FlipY")) tile_mode = TILE_FLIP_Y; if (!strcmp(tile_mode_att, "FlipXY")) tile_mode = TILE_FLIP_X_Y; } if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y) xstep *= 2; if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y) ystep *= 2; xps_begin_opacity(ctx, ctm, area, base_uri, dict, opacity_att, NULL); ctm = fz_concat(fz_translate(viewport.x0, viewport.y0), ctm); ctm = fz_concat(fz_scale(xscale, yscale), ctm); ctm = fz_concat(fz_translate(-viewbox.x0, -viewbox.y0), ctm); if (tile_mode != TILE_NONE) { int x0, y0, x1, y1; fz_matrix invctm = fz_invert_matrix(ctm); area = fz_transform_rect(invctm, area); x0 = floorf(area.x0 / xstep); y0 = floorf(area.y0 / ystep); x1 = ceilf(area.x1 / xstep); y1 = ceilf(area.y1 / ystep); #ifdef TILE if ((x1 - x0) * (y1 - y0) > 1) #else if (0) #endif { fz_rect bigview = viewbox; bigview.x1 = bigview.x0 + xstep; bigview.y1 = bigview.y0 + ystep; fz_begin_tile(ctx->dev, area, bigview, xstep, ystep, ctm); xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c); fz_end_tile(ctx->dev); } else { int x, y; for (y = y0; y < y1; y++) { for (x = x0; x < x1; x++) { fz_matrix ttm = fz_concat(fz_translate(xstep * x, ystep * y), ctm); xps_paint_tiling_brush(ctx, ttm, viewbox, tile_mode, &c); } } } } else { xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c); } xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL); }
JNIEXPORT jboolean JNICALL Java_com_artifex_mupdf_MuPDFCore_drawPage( JNIEnv *env, jobject thiz, jobject bitmap, int pageW, int pageH, int patchX, int patchY, int patchW, int patchH) { AndroidBitmapInfo info; void *pixels; int ret; fz_error error; fz_device *dev; float zoom; fz_matrix ctm; fz_bbox bbox; fz_pixmap *pix; float xscale, yscale; LOGI("In native method\n"); if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) { LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret); return 0; } LOGI("Checking format\n"); if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { LOGE("Bitmap format is not RGBA_8888 !"); return 0; } LOGI("locking pixels\n"); if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) { LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret); return 0; } /* Call mupdf to render display list to screen */ LOGE("Rendering page=%dx%d patch=[%d,%d,%d,%d]", pageW, pageH, patchX, patchY, patchW, patchH); pix = fz_newpixmapwithdata(colorspace, patchX, patchY, patchW, patchH, pixels); if (currentPageList == NULL) { fz_clearpixmapwithcolor(pix, 0xd0); return 0; } fz_clearpixmapwithcolor(pix, 0xff); zoom = resolution / 72; ctm = fz_translate(0, -currentMediabox.y1); ctm = fz_concat(ctm, fz_scale(zoom, -zoom)); ctm = fz_concat(ctm, fz_rotate(currentRotate)); bbox = fz_roundrect(fz_transformrect(ctm,currentMediabox)); /* Now, adjust ctm so that it would give the correct page width * heights. */ xscale = (float)pageW/(float)(bbox.x1-bbox.x0); yscale = (float)pageH/(float)(bbox.y1-bbox.y0); ctm = fz_concat(ctm, fz_scale(xscale, yscale)); dev = fz_newdrawdevice(glyphcache, pix); fz_executedisplaylist(currentPageList, dev, ctm); fz_freedevice(dev); fz_droppixmap(pix); LOGE("Rendered"); AndroidBitmap_unlockPixels(env, bitmap); return 1; }