fz_irect PDFDocument::GetBoundingBox( pdf_page* page_struct, const fz_matrix& m) { assert(page_struct != nullptr); #if MUPDF_VERSION >= 10014 return fz_round_rect( fz_transform_rect(pdf_bound_page(_fz_context, page_struct), m)); #else fz_rect bbox; fz_irect ibbox; return *fz_round_rect( &ibbox, fz_transform_rect( pdf_bound_page(_fz_context, _pdf_document, page_struct, &bbox), &m)); #endif }
void fz_set_font_bbox(fz_context *ctx, fz_font *font, float xmin, float ymin, float xmax, float ymax) { if (xmin >= xmax || ymin >= ymax) { /* Invalid bbox supplied. It would be prohibitively slow to * measure the true one, so make one up. */ font->bbox.x0 = -1; font->bbox.y0 = -1; font->bbox.x1 = 2; font->bbox.y1 = 2; } else { font->bbox.x0 = xmin; font->bbox.y0 = ymin; font->bbox.x1 = xmax; font->bbox.y1 = ymax; } /* SumatraPDF: some fonts seem to use oversized bboxes (Ghostscript issue?) */ if (xmax - xmin == 1000 && ymax - ymin == 1000) { fz_matrix ctm; fz_transform_rect(&font->bbox, fz_scale(&ctm, 0.001f, 0.001f)); } }
void pdf_add_annot_quad_point(fz_context *ctx, pdf_annot *annot, fz_rect bbox) { pdf_document *doc = annot->page->doc; fz_matrix page_ctm, inv_page_ctm; pdf_obj *quad_points; check_allowed_subtypes(ctx, annot, PDF_NAME(QuadPoints), quad_point_subtypes); pdf_page_transform(ctx, annot->page, NULL, &page_ctm); fz_invert_matrix(&inv_page_ctm, &page_ctm); quad_points = pdf_dict_get(ctx, annot->obj, PDF_NAME(QuadPoints)); if (!pdf_is_array(ctx, quad_points)) { quad_points = pdf_new_array(ctx, doc, 8); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME(QuadPoints), quad_points); } /* Contrary to the specification, the points within a QuadPoint are NOT ordered * in a counterclockwise fashion. Experiments with Adobe's implementation * indicates a cross-wise ordering is intended: ul, ur, ll, lr. */ fz_transform_rect(&bbox, &inv_page_ctm); pdf_array_push_real(ctx, quad_points, bbox.x0); /* ul */ pdf_array_push_real(ctx, quad_points, bbox.y1); pdf_array_push_real(ctx, quad_points, bbox.x1); /* ur */ pdf_array_push_real(ctx, quad_points, bbox.y1); pdf_array_push_real(ctx, quad_points, bbox.x0); /* ll */ pdf_array_push_real(ctx, quad_points, bbox.y0); pdf_array_push_real(ctx, quad_points, bbox.x1); /* lr */ pdf_array_push_real(ctx, quad_points, bbox.y0); pdf_dirty_annot(ctx, annot); }
HRESULT MuPDFDoc::GotoPage(int pageNumber) { int index = FindPageInCache(pageNumber); if (index >= 0) { m_currentPage = index; return S_OK; } index = GetPageCacheIndex(pageNumber); m_currentPage = index; PageCache *pageCache = &m_pages[m_currentPage]; ClearPageCache(pageCache); /* In the event of an error, ensure we give a non-empty page */ pageCache->width = 100; pageCache->height = 100; pageCache->number = pageNumber; fz_try(m_context) { pageCache->page = fz_load_page(m_document, pageCache->number); pageCache->mediaBox = fz_bound_page(m_document, pageCache->page); // fz_bound_page determine the size of a page at 72 dpi. fz_matrix ctm = CalcConvertMatrix(); fz_bbox bbox = fz_round_rect(fz_transform_rect(ctm, pageCache->mediaBox)); pageCache->width = bbox.x1 - bbox.x0; pageCache->height = bbox.y1 - bbox.y0; } fz_catch(m_context) { return E_FAIL; } return S_OK; }
static void fz_bbox_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha) { fz_bbox *result = dev->user; fz_bbox bbox = fz_round_rect(fz_transform_rect(ctm, fz_unit_rect)); *result = fz_union_bbox(*result, bbox); }
fz_pixmap * fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz_matrix *ctm, fz_colorspace *cs, int background) { fz_rect rect; fz_irect irect; fz_pixmap *pix; fz_device *dev; fz_bound_display_list(ctx, list, &rect); fz_transform_rect(&rect, ctm); fz_round_rect(&irect, &rect); pix = fz_new_pixmap_with_bbox(ctx, cs, &irect); if (background) fz_clear_pixmap_with_value(ctx, pix, 0xFF); else fz_clear_pixmap(ctx, pix); fz_try(ctx) { dev = fz_new_draw_device(ctx, pix); fz_run_display_list(ctx, list, dev, ctm, NULL, NULL); } fz_always(ctx) { fz_drop_device(ctx, dev); } fz_catch(ctx) { fz_drop_pixmap(ctx, pix); fz_rethrow(ctx); } return pix; }
static void fz_bbox_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, fz_colorspace *colorspace, float *color, float alpha) { fz_rect r = fz_unit_rect; fz_bbox_add_rect(ctx, dev, fz_transform_rect(&r, ctm), 0); }
bool PdfCreator::AddImagePage(fz_image *image, float imgDpi) { CrashIf(!ctx || !doc); if (!ctx || !doc) return false; pdf_page *page = nullptr; fz_device *dev = nullptr; fz_var(page); fz_var(dev); fz_try(ctx) { float zoom = imgDpi ? 72 / imgDpi : 1.0f; fz_matrix ctm = { image->w * zoom, 0, 0, image->h * zoom, 0, 0 }; fz_rect bounds = fz_unit_rect; fz_transform_rect(&bounds, &ctm); page = pdf_create_page(doc, bounds, 72, 0); dev = pdf_page_write(doc, page); fz_fill_image(dev, image, &ctm, 1.0); fz_free_device(dev); dev = nullptr; pdf_insert_page(doc, page, INT_MAX); } fz_always(ctx) { fz_free_device(dev); pdf_free_page(doc, page); } fz_catch(ctx) { return false; } return true; }
void Mpdf::showPage() { fz_page *page = fz_load_page(doc, currentPage - 1); fz_matrix transform; fz_rotate(&transform, 0); fz_pre_scale(&transform, currentZoom / 100.0f, currentZoom / 100.0f); fz_rect bounds; fz_bound_page(doc, page, &bounds); fz_transform_rect(&bounds, &transform); fz_irect bbox; fz_round_rect(&bbox, &bounds); fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb, &bbox); fz_clear_pixmap_with_value(ctx, pix, 0xff); fz_device *dev = fz_new_draw_device(ctx, pix); fz_run_page(doc, page, dev, &transform, NULL); fz_free_device(dev); QString qpng = QString("%1.png").arg(currentPage); const char *ccpng = qpng.toStdString().c_str(); char *cpng = new char[strlen(ccpng) + 1]; strcpy(cpng, ccpng); fz_write_png(ctx, pix, cpng, 0); QPixmap qpix(qpng); pdfLabel->setPixmap(qpix); fz_drop_pixmap(ctx, pix); fz_free_page(doc, page); }
static void fz_text_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *img, const fz_matrix *ctm, fz_colorspace *cspace, float *color, float alpha) { fz_text_device *tdev = (fz_text_device*)dev; fz_text_page *page = tdev->page; fz_image_block *block; /* If the alpha is less than 50% then it's probably a watermark or * effect or something. Skip it */ if (alpha < 0.5) return; /* New block */ if (page->len == page->cap) { int newcap = (page->cap ? page->cap*2 : 4); page->blocks = fz_resize_array(ctx, page->blocks, newcap, sizeof(*page->blocks)); page->cap = newcap; } block = fz_malloc_struct(ctx, fz_image_block); page->blocks[page->len].type = FZ_PAGE_BLOCK_IMAGE; page->blocks[page->len].u.image = block; block->image = fz_keep_image(ctx, img); block->cspace = fz_keep_colorspace(ctx, cspace); if (cspace) memcpy(block->colors, color, sizeof(block->colors[0])*cspace->n); block->mat = *ctm; block->bbox.x0 = 0; block->bbox.y0 = 0; block->bbox.x1 = 1; block->bbox.y1 = 1; fz_transform_rect(&block->bbox, ctm); page->len++; }
static void fz_draw_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) { fz_draw_device *dev = user; fz_colorspace *model = dev->dest->colorspace; fz_pixmap *dest; fz_bbox bbox; /* area, view, xstep, ystep are in pattern space */ /* ctm maps from pattern space to device space */ if (dev->top == STACK_SIZE) { fz_warn("assert: too many buffers on stack"); return; } bbox = fz_round_rect(fz_transform_rect(ctm, view)); dest = fz_new_pixmap_with_rect(model, bbox); fz_clear_pixmap(dest); dev->stack[dev->top].scissor = dev->scissor; dev->stack[dev->top].dest = dev->dest; dev->stack[dev->top].xstep = xstep; dev->stack[dev->top].ystep = ystep; dev->stack[dev->top].area = area; dev->stack[dev->top].ctm = ctm; dev->top++; dev->scissor = bbox; dev->dest = dest; }
/* 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); }
void fz_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, const fz_rect *scissor) { if (dev->error_depth) { dev->error_depth++; return; } fz_try(ctx) { if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK) { if (scissor == NULL) { fz_rect bbox = fz_unit_rect; fz_transform_rect(&bbox, ctm); push_clip_stack(ctx, dev, &bbox, fz_device_container_stack_is_clip_image_mask); } else push_clip_stack(ctx, dev, scissor, fz_device_container_stack_is_clip_image_mask); } if (dev->clip_image_mask) dev->clip_image_mask(ctx, dev, image, ctm, scissor); } fz_catch(ctx) { dev->error_depth = 1; strcpy(dev->errmess, fz_caught_message(ctx)); /* Error swallowed */ } }
static void fz_bbox_fill_image(fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha) { fz_rect *result = dev->user; fz_rect r = fz_unit_rect; fz_union_rect(result, fz_transform_rect(&r, ctm)); }
fz_pixmap * fz_new_pixmap_from_page_contents(fz_context *ctx, fz_page *page, const fz_matrix *ctm, fz_colorspace *cs) { fz_rect rect; fz_irect irect; fz_pixmap *pix; fz_device *dev; fz_bound_page(ctx, page, &rect); fz_transform_rect(&rect, ctm); fz_round_rect(&irect, &rect); pix = fz_new_pixmap_with_bbox(ctx, cs, &irect); fz_clear_pixmap_with_value(ctx, pix, 0xFF); fz_try(ctx) { dev = fz_new_draw_device(ctx, pix); fz_run_page_contents(ctx, page, dev, ctm, NULL); } fz_always(ctx) { fz_drop_device(ctx, dev); } fz_catch(ctx) { fz_drop_pixmap(ctx, pix); fz_rethrow(ctx); } return pix; }
fz_pixmap * fz_new_pixmap_from_annot(fz_context *ctx, fz_annot *annot, const fz_matrix *ctm, fz_colorspace *cs, int alpha) { fz_rect rect; fz_irect irect; fz_pixmap *pix; fz_device *dev; fz_bound_annot(ctx, annot, &rect); fz_transform_rect(&rect, ctm); fz_round_rect(&irect, &rect); pix = fz_new_pixmap_with_bbox(ctx, cs, &irect, alpha); if (alpha) fz_clear_pixmap(ctx, pix); else fz_clear_pixmap_with_value(ctx, pix, 0xFF); fz_try(ctx) { dev = fz_new_draw_device(ctx, ctm, pix); fz_run_annot(ctx, annot, dev, &fz_identity, NULL); } fz_always(ctx) { fz_drop_device(ctx, dev); } fz_catch(ctx) { fz_drop_pixmap(ctx, pix); fz_rethrow(ctx); } return pix; }
int adjust_page_position(fz_context *ctx, pdf_document *doc, pdf_page *page, struct pos_info *pos) { /* if page is rotated we must add this to the desired rotation of the page */ pos->rotate = (pos->rotate + page->rotate) % 360; fz_matrix rotation_mtx; /* tranformation of the user-space due to the rotation */ fz_rotate(&rotation_mtx, page->rotate); /* get the media-box (with rotation applied) */ pdf_obj *media_box = juggler_lookup_inherited_page_item(ctx, doc, page->me, "MediaBox"); if(!pdf_is_array(ctx, media_box) || pdf_array_len(ctx, media_box) != 4) return(-1); /* the specification forces a valid media-box... */ fz_rect media_rect; pdf_to_rect(ctx, media_box, &media_rect); fz_transform_rect(&media_rect, &rotation_mtx); /* get trim-box */ pdf_obj *trim_box = juggler_lookup_inherited_page_item(ctx, doc, page->me, "TrimBox"); if(trim_box == NULL) trim_box = media_box; if(!pdf_is_array(ctx, trim_box) || pdf_array_len(ctx, trim_box) != 4) return(-2); fz_rect trim_rect; pdf_to_rect(ctx, trim_box, &trim_rect); fz_transform_rect(&trim_rect, &rotation_mtx); // TODO: Take scale into account double available_width = pos->width; double available_height = pos->height; double page_width = trim_rect.x1 - trim_rect.x0; double page_height = trim_rect.y1 - trim_rect.y0; /* position the page in the middle of the destination area */ pos->content_translate_x = media_rect.x0 - trim_rect.x0 + (available_width - page_width) / 2; pos->content_translate_y = media_rect.y0 - trim_rect.y0 + (available_height - page_height) / 2; /* if needed, clip the contents to the bleed-box */ if(adjust_bleed_clipping(ctx, doc, page, pos) < 0) return(-2); return(0); }
static void fz_bbox_begin_tile(fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm) { fz_bbox_data *data = dev->user; fz_rect r = *area; fz_bbox_add_rect(dev, fz_transform_rect(&r, ctm), 0); data->ignore++; }
fz_irect PDFDocument::GetBoundingBox( pdf_page* page_struct, const fz_matrix& m) { assert(page_struct != nullptr); fz_rect bbox; fz_irect ibbox; return *fz_round_rect(&ibbox, fz_transform_rect( pdf_bound_page(_fz_context, _pdf_document, page_struct, &bbox), &m)); }
void pdf_annot_rect(fz_context *ctx, pdf_annot *annot, fz_rect *rect) { fz_matrix page_ctm; pdf_page_transform(ctx, annot->page, NULL, &page_ctm); pdf_to_rect(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME_Rect), rect); fz_transform_rect(rect, &page_ctm); }
JNIEXPORT jobjectArray JNICALL Java_com_artifex_mupdf_MuPDFCore_getPageLinksInternal(JNIEnv * env, jobject thiz, int pageNumber) { jclass linkInfoClass; jmethodID ctor; jobjectArray arr; jobject linkInfo; fz_matrix ctm; float zoom; fz_link *list; fz_link *link; int count; page_cache *pc; linkInfoClass = (*env)->FindClass(env, "com/artifex/mupdf/LinkInfo"); if (linkInfoClass == NULL) return NULL; ctor = (*env)->GetMethodID(env, linkInfoClass, "<init>", "(FFFFI)V"); if (ctor == NULL) return NULL; Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(env, thiz, pageNumber); pc = &pages[current]; if (pc->page == NULL || pc->number != pageNumber) return NULL; zoom = resolution / 72; ctm = fz_scale(zoom, zoom); list = fz_load_links(doc, pc->page); count = 0; for (link = list; link; link = link->next) { if (link->dest.kind == FZ_LINK_GOTO) count++ ; } arr = (*env)->NewObjectArray(env, count, linkInfoClass, NULL); if (arr == NULL) return NULL; count = 0; for (link = list; link; link = link->next) { if (link->dest.kind == FZ_LINK_GOTO) { fz_rect rect = fz_transform_rect(ctm, link->rect); linkInfo = (*env)->NewObject(env, linkInfoClass, ctor, (float)rect.x0, (float)rect.y0, (float)rect.x1, (float)rect.y1, link->dest.ld.gotor.page); if (linkInfo == NULL) return NULL; (*env)->SetObjectArrayElement(env, arr, count, linkInfo); (*env)->DeleteLocalRef(env, linkInfo); count ++; } } return arr; }
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_rect * fz_bound_mesh_type1(fz_context *ctx, fz_shade *shade, fz_rect *bbox) { bbox->x0 = shade->u.f.domain[0][0]; bbox->y0 = shade->u.f.domain[0][1]; bbox->x1 = shade->u.f.domain[1][0]; bbox->y1 = shade->u.f.domain[1][1]; return fz_transform_rect(bbox, &shade->u.f.matrix); }
static void fz_list_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) { fz_display_node *node; node = fz_new_display_node(FZ_CMD_FILL_IMAGE, ctm, NULL, NULL, alpha); node->rect = fz_transform_rect(ctm, fz_unit_rect); node->item.image = fz_keep_pixmap(image); fz_append_display_node(user, node); }
static void fz_list_fill_image(fz_device *dev, fz_image *image, fz_matrix ctm, float alpha) { fz_display_node *node; node = fz_new_display_node(dev->ctx, FZ_CMD_FILL_IMAGE, ctm, NULL, NULL, alpha); node->rect = fz_transform_rect(ctm, fz_unit_rect); node->item.image = fz_keep_image(dev->ctx, image); fz_append_display_node(dev->user, node); }
static void fz_draw_begin_tile(fz_context *ctx, void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) { fz_draw_device *dev = user; fz_colorspace *model = dev->dest->colorspace; fz_pixmap *dest; fz_bbox bbox; /* area, view, xstep, ystep are in pattern space */ /* ctm maps from pattern space to device space */ if (dev->top == dev->stack_max) fz_grow_stack(dev); if (dev->blendmode & FZ_BLEND_KNOCKOUT) fz_knockout_begin(ctx, dev); bbox = fz_round_rect(fz_transform_rect(ctm, view)); /* We should never have a bbox that entirely covers our destination. * If we do, then the check for only 1 tile being visible above has * failed. */ /* SumatraPDF: assertion intentionally disabled assert(bbox.x0 > dev->dest->x || bbox.x1 < dev->dest->x + dev->dest->w || bbox.y0 > dev->dest->y || bbox.y1 < dev->dest->y + dev->dest->h); /* cf. http://bugs.ghostscript.com/show_bug.cgi?id=692418 */ dest = fz_new_pixmap_with_limit(ctx, model, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0); if (dest) { dest->x = bbox.x0; dest->y = bbox.y0; } else { bbox.x1 = bbox.x0; bbox.y1 = bbox.y0; dest = fz_new_pixmap_with_rect(ctx, model, bbox); } /* FIXME: See note #1 */ fz_clear_pixmap(dest); dev->stack[dev->top].scissor = dev->scissor; dev->stack[dev->top].dest = dev->dest; dev->stack[dev->top].shape = dev->shape; /* FIXME: See note #1 */ dev->stack[dev->top].blendmode = dev->blendmode | FZ_BLEND_ISOLATED; dev->stack[dev->top].xstep = xstep; dev->stack[dev->top].ystep = ystep; dev->stack[dev->top].area = area; dev->stack[dev->top].ctm = ctm; #ifdef DUMP_GROUP_BLENDS dump_spaces(dev->top, "Tile begin\n"); #endif dev->top++; dev->scissor = bbox; dev->dest = dest; }
static void fz_list_begin_page(fz_device *dev, const fz_rect *mediabox, const fz_matrix *ctm) { fz_context *ctx = dev->ctx; fz_display_node *node = fz_new_display_node(ctx, FZ_CMD_BEGIN_PAGE, ctm, NULL, NULL, 0); node->rect = *mediabox; fz_transform_rect(&node->rect, ctm); fz_append_display_node(dev->user, node); }
static int fz_bbox_begin_tile(fz_context *ctx, fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id) { fz_bbox_device *bdev = (fz_bbox_device*)dev; fz_rect r = *area; fz_bbox_add_rect(ctx, dev, fz_transform_rect(&r, ctm), 0); bdev->ignore++; return 0; }
static void xps_draw_linear_gradient(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, const fz_rect *area, struct stop *stops, int count, fz_xml *root, int spread) { float x0, y0, x1, y1; int i, mi, ma; float dx, dy, x, y, k; fz_point p1, p2; fz_matrix inv; fz_rect local_area = *area; char *start_point_att = fz_xml_att(root, "StartPoint"); char *end_point_att = fz_xml_att(root, "EndPoint"); x0 = y0 = 0; x1 = y1 = 1; if (start_point_att) xps_parse_point(ctx, doc, start_point_att, &x0, &y0); if (end_point_att) xps_parse_point(ctx, doc, end_point_att, &x1, &y1); p1.x = x0; p1.y = y0; p2.x = x1; p2.y = y1; fz_transform_rect(&local_area, fz_invert_matrix(&inv, ctm)); x = p2.x - p1.x; y = p2.y - p1.y; k = ((local_area.x0 - p1.x) * x + (local_area.y0 - p1.y) * y) / (x * x + y * y); mi = floorf(k); ma = ceilf(k); k = ((local_area.x1 - p1.x) * x + (local_area.y0 - p1.y) * y) / (x * x + y * y); mi = fz_mini(mi, floorf(k)); ma = fz_maxi(ma, ceilf(k)); k = ((local_area.x0 - p1.x) * x + (local_area.y1 - p1.y) * y) / (x * x + y * y); mi = fz_mini(mi, floorf(k)); ma = fz_maxi(ma, ceilf(k)); k = ((local_area.x1 - p1.x) * x + (local_area.y1 - p1.y) * y) / (x * x + y * y); mi = fz_mini(mi, floorf(k)); ma = fz_maxi(ma, ceilf(k)); dx = x1 - x0; dy = y1 - y0; if (spread == SPREAD_REPEAT) { for (i = mi; i < ma; i++) xps_draw_one_linear_gradient(ctx, doc, ctm, stops, count, 0, x0 + i * dx, y0 + i * dy, x1 + i * dx, y1 + i * dy); } else if (spread == SPREAD_REFLECT) { if ((mi % 2) != 0) mi--; for (i = mi; i < ma; i += 2) { xps_draw_one_linear_gradient(ctx, doc, ctm, stops, count, 0, x0 + i * dx, y0 + i * dy, x1 + i * dx, y1 + i * dy); xps_draw_one_linear_gradient(ctx, doc, ctm, stops, count, 0, x0 + (i + 2) * dx, y0 + (i + 2) * dy, x1 + i * dx, y1 + i * dy); } } else { xps_draw_one_linear_gradient(ctx, doc, ctm, stops, count, 1, x0, y0, x1, y1); } }
static void fz_draw_begin_tile(fz_device *devp, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) { fz_draw_device *dev = devp->user; fz_pixmap *dest = NULL; fz_pixmap *shape; fz_bbox bbox; fz_context *ctx = dev->ctx; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model = state->dest->colorspace; /* area, view, xstep, ystep are in pattern space */ /* ctm maps from pattern space to device space */ if (state->blendmode & FZ_BLEND_KNOCKOUT) fz_knockout_begin(dev); state = push_stack(dev); bbox = fz_bbox_covering_rect(fz_transform_rect(ctm, view)); /* We should never have a bbox that entirely covers our destination. * If we do, then the check for only 1 tile being visible above has * failed. Actually, this *can* fail due to the round_rect, at extreme * resolutions, so disable this assert. * assert(bbox.x0 > state->dest->x || bbox.x1 < state->dest->x + state->dest->w || * bbox.y0 > state->dest->y || bbox.y1 < state->dest->y + state->dest->h); */ dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); fz_clear_pixmap(ctx, dest); shape = state[0].shape; if (shape) { fz_var(shape); fz_try(ctx) { shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); fz_clear_pixmap(ctx, shape); } fz_catch(ctx) { fz_drop_pixmap(ctx, dest); fz_rethrow(ctx); } } state[1].blendmode |= FZ_BLEND_ISOLATED; state[1].xstep = xstep; state[1].ystep = ystep; state[1].area = area; state[1].ctm = ctm; #ifdef DUMP_GROUP_BLENDS dump_spaces(dev->top-1, "Tile begin\n"); #endif state[1].scissor = bbox; state[1].dest = dest; state[1].shape = shape; }