static void drop_page_cache(page_cache *pc) { LOGI("Drop page %d", pc->number); fz_free_display_list(ctx, pc->page_list); pc->page_list = NULL; fz_free_display_list(ctx, pc->annot_list); pc->annot_list = NULL; fz_free_page(doc, pc->page); pc->page = NULL; fz_free_page(doc, pc->hq_page); pc->hq_page = NULL; }
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 clear_hq_pages() { int i; for (i = 0; i < NUM_CACHE; i++) { fz_free_page(doc, pages[i].hq_page); pages[i].hq_page = NULL; } }
static fz_pixmap *page_to_pixmap(fz_context *context, fz_document *doc, int pagenum) { fz_page *page; fz_pixmap *image; fz_device *dev; fz_rect bounds; fz_bbox bbox; fz_matrix ctm; float scale; printf("Rendering page %d\n", pagenum); page = fz_load_page(doc, pagenum); bounds = fz_bound_page(doc, page); /* XXX: There is a small risk of lw/lh being incorrect * due to a race condition during a refresh. * This shouldn't affect any visible pages though, as it causes renders * that will be discarded by finish_page_render to be faulty. */ ims = scale = lw / bounds.x1; printf("W, H: (%f, %f)\n", lw, lh); printf("Scale: %f\n", scale); ctm = fz_scale(scale, scale); pages[pagenum].w = bounds.x1; pages[pagenum].h = bounds.y1; bounds.x1 *= scale; bounds.y1 *= scale; pages[pagenum].sw = bounds.x1; pages[pagenum].sh = bounds.y1; bbox = fz_round_rect(bounds); printf("Size: (%d, %d)\n", bbox.x1, bbox.y1); image = fz_new_pixmap_with_bbox(context, fz_device_rgb, bbox); dev = fz_new_draw_device(context, image); fz_clear_pixmap_with_value(context, image, 255); fz_run_page(doc, page, dev, ctm, NULL); fz_free_device(dev); fz_free_page(doc, page); return image; }
static void drop_page_cache(globals *glo, page_cache *pc) { fz_context *ctx = glo->ctx; fz_document *doc = glo->doc; LOGI("Drop page %d", pc->number); fz_free_display_list(ctx, pc->page_list); pc->page_list = NULL; fz_free_display_list(ctx, pc->annot_list); pc->annot_list = NULL; fz_free_page(doc, pc->page); pc->page = NULL; drop_changed_rects(ctx, &pc->changed_rects); drop_changed_rects(ctx, &pc->hq_changed_rects); }
void ViewerWidget::load(const QByteArray &data) { scene->clear(); QList<QGraphicsItem *> items; QPixmap pixmap; if (pixmap.loadFromData(data)) { items << new QGraphicsPixmapItem(pixmap); } else if (data.startsWith("%PDF")) { fz_stream *stream = fz_open_memory(context, (unsigned char *)data.constData(), data.length()); fz_document *doc = fz_open_document_with_stream(context, ".pdf", stream); fz_close(stream); int pagecount = fz_count_pages(doc); for (int i = 0; i < pagecount; i++) { fz_page *page = fz_load_page(doc, i); fz_rect bounds; fz_bound_page(doc, page, &bounds); fz_display_list *list = fz_new_display_list(context); fz_device *dev = fz_new_list_device(context, list); fz_run_page(doc, page, dev, &fz_identity, NULL); fz_free_device(dev); fz_free_page(doc, page); PageItem *item = new PageItem(context, list, bounds.x1 - bounds.x0, bounds.y1 - bounds.y0); item->setCacheMode(QGraphicsItem::DeviceCoordinateCache); items << item; } fz_close_document(doc); } else { scene->setSceneRect(0, 0, 0, 0); return; } int top = 0; QPen outline(Qt::lightGray, 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin); outline.setCosmetic(true); foreach (QGraphicsItem *item, items) { QGraphicsRectItem *rim = new QGraphicsRectItem(item->boundingRect()); item->setPos(0, top); rim->setPos(0, top); rim->setPen(outline); rim->setBrush(Qt::NoBrush); scene->addItem(rim); scene->addItem(item); top += item->boundingRect().height() + SPACING; }
static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) { fz_page *page; fz_display_list *list = NULL; fz_device *dev = NULL; int start; fz_cookie cookie = { 0 }; int needshot = 0; fz_var(list); fz_var(dev); if (showtime) { start = gettime(); } fz_try(ctx) { page = fz_load_page(doc, pagenum - 1); } fz_catch(ctx) { fz_rethrow_message(ctx, "cannot load page %d in file '%s'", pagenum, filename); } if (mujstest_file) { pdf_document *inter = pdf_specifics(doc); pdf_widget *widget = NULL; if (inter) widget = pdf_first_widget(inter, (pdf_page *)page); if (widget) { fprintf(mujstest_file, "GOTO %d\n", pagenum); needshot = 1; } for (;widget; widget = pdf_next_widget(widget)) { fz_rect rect; int w, h, len; int type = pdf_widget_get_type(widget); pdf_bound_widget(widget, &rect); w = (rect.x1 - rect.x0); h = (rect.y1 - rect.y0); ++mujstest_count; switch (type) { default: fprintf(mujstest_file, "%% UNKNOWN %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); break; case PDF_WIDGET_TYPE_PUSHBUTTON: fprintf(mujstest_file, "%% PUSHBUTTON %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); break; case PDF_WIDGET_TYPE_CHECKBOX: fprintf(mujstest_file, "%% CHECKBOX %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); break; case PDF_WIDGET_TYPE_RADIOBUTTON: fprintf(mujstest_file, "%% RADIOBUTTON %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); break; case PDF_WIDGET_TYPE_TEXT: { int maxlen = pdf_text_widget_max_len(inter, widget); int texttype = pdf_text_widget_content_type(inter, widget); /* If height is low, assume a single row, and base * the width off that. */ if (h < 10) { w = (w+h-1) / (h ? h : 1); h = 1; } /* Otherwise, if width is low, work off height */ else if (w < 10) { h = (w+h-1) / (w ? w : 1); w = 1; } else { w = (w+9)/10; h = (h+9)/10; } len = w*h; if (len < 2) len = 2; if (len > maxlen) len = maxlen; fprintf(mujstest_file, "%% TEXT %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); switch (texttype) { default: case PDF_WIDGET_CONTENT_UNRESTRAINED: fprintf(mujstest_file, "TEXT %d ", mujstest_count); escape_string(mujstest_file, len-3, lorem); fprintf(mujstest_file, "\n"); break; case PDF_WIDGET_CONTENT_NUMBER: fprintf(mujstest_file, "TEXT %d\n", mujstest_count); break; case PDF_WIDGET_CONTENT_SPECIAL: #ifdef __MINGW32__ fprintf(mujstest_file, "TEXT %I64d\n", 46702919800LL + mujstest_count); #else fprintf(mujstest_file, "TEXT %lld\n", 46702919800LL + mujstest_count); #endif break; case PDF_WIDGET_CONTENT_DATE: fprintf(mujstest_file, "TEXT Jun %d 1979\n", 1 + ((13 + mujstest_count) % 30)); break; case PDF_WIDGET_CONTENT_TIME: ++mujstest_count; fprintf(mujstest_file, "TEXT %02d:%02d\n", ((mujstest_count/60) % 24), mujstest_count % 60); break; } break; } case PDF_WIDGET_TYPE_LISTBOX: fprintf(mujstest_file, "%% LISTBOX %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); break; case PDF_WIDGET_TYPE_COMBOBOX: fprintf(mujstest_file, "%% COMBOBOX %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); break; } fprintf(mujstest_file, "CLICK %0.2f %0.2f\n", (rect.x0+rect.x1)/2, (rect.y0+rect.y1)/2); } } if (uselist) { fz_try(ctx) { list = fz_new_display_list(ctx); dev = fz_new_list_device(ctx, list); fz_run_page(doc, page, dev, &fz_identity, &cookie); } fz_always(ctx) { fz_free_device(dev); dev = NULL; } fz_catch(ctx) { fz_drop_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow_message(ctx, "cannot draw page %d in file '%s'", pagenum, filename); } } if (showxml) { fz_try(ctx) { dev = fz_new_trace_device(ctx); if (list) fz_run_display_list(list, dev, &fz_identity, &fz_infinite_rect, &cookie); else fz_run_page(doc, page, dev, &fz_identity, &cookie); } fz_always(ctx) { fz_free_device(dev); dev = NULL; } fz_catch(ctx) { fz_drop_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } } if (showtext) { fz_text_page *text = NULL; fz_var(text); fz_try(ctx) { text = fz_new_text_page(ctx); dev = fz_new_text_device(ctx, sheet, text); if (showtext == TEXT_HTML) fz_disable_device_hints(dev, FZ_IGNORE_IMAGE); if (list) fz_run_display_list(list, dev, &fz_identity, &fz_infinite_rect, &cookie); else fz_run_page(doc, page, dev, &fz_identity, &cookie); fz_free_device(dev); dev = NULL; if (showtext == TEXT_XML) { fz_print_text_page_xml(ctx, out, text); } else if (showtext == TEXT_HTML) { fz_analyze_text(ctx, sheet, text); fz_print_text_page_html(ctx, out, text); } else if (showtext == TEXT_PLAIN) { fz_print_text_page(ctx, out, text); fz_printf(out, "\f\n"); } } fz_always(ctx) { fz_free_device(dev); dev = NULL; fz_free_text_page(ctx, text); } fz_catch(ctx) { fz_drop_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } } if (showmd5 || showtime) printf("page %s %d", filename, pagenum); if (pdfout) { fz_matrix ctm; fz_rect bounds, tbounds; pdf_page *newpage; fz_bound_page(doc, page, &bounds); fz_rotate(&ctm, rotation); tbounds = bounds; fz_transform_rect(&tbounds, &ctm); newpage = pdf_create_page(pdfout, bounds, 72, 0); fz_try(ctx) { dev = pdf_page_write(pdfout, newpage); if (list) fz_run_display_list(list, dev, &ctm, &tbounds, &cookie); else fz_run_page(doc, page, dev, &ctm, &cookie); fz_free_device(dev); dev = NULL; } fz_always(ctx) { fz_free_device(dev); dev = NULL; } fz_catch(ctx) { fz_drop_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } pdf_insert_page(pdfout, newpage, INT_MAX); pdf_free_page(pdfout, newpage); } if (output && output_format == OUT_SVG) { float zoom; fz_matrix ctm; fz_rect bounds, tbounds; char buf[512]; FILE *file; fz_output *out; if (!strcmp(output, "-")) file = stdout; else { sprintf(buf, output, pagenum); file = fopen(buf, "wb"); if (file == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", buf, strerror(errno)); } out = fz_new_output_with_file(ctx, file); fz_bound_page(doc, page, &bounds); zoom = resolution / 72; fz_pre_rotate(fz_scale(&ctm, zoom, zoom), rotation); tbounds = bounds; fz_transform_rect(&tbounds, &ctm); fz_try(ctx) { dev = fz_new_svg_device(ctx, out, tbounds.x1-tbounds.x0, tbounds.y1-tbounds.y0); if (list) fz_run_display_list(list, dev, &ctm, &tbounds, &cookie); else fz_run_page(doc, page, dev, &ctm, &cookie); fz_free_device(dev); dev = NULL; } fz_always(ctx) { fz_free_device(dev); dev = NULL; fz_close_output(out); if (file != stdout) fclose(file); } fz_catch(ctx) { fz_drop_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } }
static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) { fz_page *page; fz_display_list *list = NULL; fz_device *dev = NULL; int start; fz_cookie cookie = { 0 }; fz_var(list); fz_var(dev); if (showtime) { start = gettime(); } fz_try(ctx) { page = fz_load_page(doc, pagenum - 1); } fz_catch(ctx) { fz_rethrow_message(ctx, "cannot load page %d in file '%s'", pagenum, filename); } if (uselist) { fz_try(ctx) { list = fz_new_display_list(ctx); dev = fz_new_list_device(ctx, list); fz_run_page(doc, page, dev, &fz_identity, &cookie); } fz_always(ctx) { fz_free_device(dev); dev = NULL; } fz_catch(ctx) { fz_drop_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow_message(ctx, "cannot draw page %d in file '%s'", pagenum, filename); } } if (showxml) { fz_try(ctx) { dev = fz_new_trace_device(ctx); if (list) fz_run_display_list(list, dev, &fz_identity, &fz_infinite_rect, &cookie); else fz_run_page(doc, page, dev, &fz_identity, &cookie); } fz_always(ctx) { fz_free_device(dev); dev = NULL; } fz_catch(ctx) { fz_drop_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } } if (showtext) { fz_text_page *text = NULL; fz_var(text); fz_try(ctx) { text = fz_new_text_page(ctx); dev = fz_new_text_device(ctx, sheet, text); if (showtext == TEXT_HTML) fz_disable_device_hints(dev, FZ_IGNORE_IMAGE); if (list) fz_run_display_list(list, dev, &fz_identity, &fz_infinite_rect, &cookie); else fz_run_page(doc, page, dev, &fz_identity, &cookie); fz_free_device(dev); dev = NULL; if (showtext == TEXT_XML) { fz_print_text_page_xml(ctx, out, text); } else if (showtext == TEXT_HTML) { fz_analyze_text(ctx, sheet, text); fz_print_text_page_html(ctx, out, text); } else if (showtext == TEXT_PLAIN) { fz_print_text_page(ctx, out, text); fz_printf(out, "\f\n"); } } fz_always(ctx) { fz_free_device(dev); dev = NULL; fz_free_text_page(ctx, text); } fz_catch(ctx) { fz_drop_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } } if (showmd5 || showtime || showfeatures) printf("page %s %d", filename, pagenum); if (showfeatures) { int iscolor; dev = fz_new_test_device(ctx, &iscolor, 0.02f); fz_try(ctx) { if (list) fz_run_display_list(list, dev, &fz_identity, &fz_infinite_rect, NULL); else fz_run_page(doc, page, dev, &fz_identity, &cookie); } fz_always(ctx) { fz_free_device(dev); dev = NULL; } fz_catch(ctx) { fz_rethrow(ctx); } printf(" %s", iscolor ? "color" : "grayscale"); } if (pdfout) { fz_matrix ctm; fz_rect bounds, tbounds; pdf_page *newpage; fz_bound_page(doc, page, &bounds); fz_rotate(&ctm, rotation); tbounds = bounds; fz_transform_rect(&tbounds, &ctm); newpage = pdf_create_page(pdfout, bounds, 72, 0); fz_try(ctx) { dev = pdf_page_write(pdfout, newpage); if (list) fz_run_display_list(list, dev, &ctm, &tbounds, &cookie); else fz_run_page(doc, page, dev, &ctm, &cookie); fz_free_device(dev); dev = NULL; } fz_always(ctx) { fz_free_device(dev); dev = NULL; } fz_catch(ctx) { fz_drop_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } pdf_insert_page(pdfout, newpage, INT_MAX); pdf_free_page(pdfout, newpage); } if (output && output_format == OUT_SVG) { float zoom; fz_matrix ctm; fz_rect bounds, tbounds; char buf[512]; FILE *file; fz_output *out; if (!strcmp(output, "-")) file = stdout; else { sprintf(buf, output, pagenum); file = fopen(buf, "wb"); if (file == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", buf, strerror(errno)); } out = fz_new_output_with_file(ctx, file); fz_bound_page(doc, page, &bounds); zoom = resolution / 72; fz_pre_rotate(fz_scale(&ctm, zoom, zoom), rotation); tbounds = bounds; fz_transform_rect(&tbounds, &ctm); fz_try(ctx) { dev = fz_new_svg_device(ctx, out, tbounds.x1-tbounds.x0, tbounds.y1-tbounds.y0); if (list) fz_run_display_list(list, dev, &ctm, &tbounds, &cookie); else fz_run_page(doc, page, dev, &ctm, &cookie); fz_free_device(dev); dev = NULL; } fz_always(ctx) { fz_free_device(dev); dev = NULL; fz_close_output(out); if (file != stdout) fclose(file); } fz_catch(ctx) { fz_drop_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } }
int main(int argc, char **argv) { char *filename = argv[1]; pthread_t *thread = NULL; fz_locks_context locks; pthread_mutex_t mutex[FZ_LOCK_MAX]; int i; // Initialize FZ_LOCK_MAX number of non-recursive mutexes. for (i = 0; i < FZ_LOCK_MAX; i++) { if (pthread_mutex_init(&mutex[i], NULL) < 0) fail("pthread_mutex_init()"); } // Initialize the locking structure with function pointers to // the locking functions and to the user data. In this case // the user data is a pointer to the array of mutexes so the // locking functions can find the relevant lock to change when // they are called. This way we avoid global variables. locks.user = mutex; locks.lock = lock_mutex; locks.unlock = unlock_mutex; // This is the main threads context function, so supply the // locking structure. This context will be used to parse all // the pages from the document. fz_context *ctx = fz_new_context(NULL, &locks, FZ_STORE_UNLIMITED); // Open the PDF, XPS or CBZ document. fz_document *doc = fz_open_document(ctx, filename); // Retrieve the number of pages, which translates to the // number of threads used for rendering pages. int threads = fz_count_pages(doc); fprintf(stderr, "spawning %d threads, one per page...\n", threads); thread = malloc(threads * sizeof (pthread_t)); for (i = 0; i < threads; i++) { // Load the relevant page for each thread. fz_page *page = fz_load_page(doc, i); // Compute the bounding box for each page. fz_rect rect = fz_bound_page(doc, page); fz_bbox bbox = fz_round_rect(rect); // Create a display list that will hold the drawing // commands for the page. fz_display_list *list = fz_new_display_list(ctx); // Run the loaded page through a display list device // to populate the page's display list. fz_device *dev = fz_new_list_device(ctx, list); fz_run_page(doc, page, dev, fz_identity, NULL); fz_free_device(dev); // The page is no longer needed, all drawing commands // are now in the display list. fz_free_page(doc, page); // Create a white pixmap using the correct dimensions. fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb, bbox); fz_clear_pixmap_with_value(ctx, pix, 0xff); // Populate the data structure to be sent to the // rendering thread for this page. struct data *data = malloc(sizeof (struct data)); data->pagenumber = i + 1; data->ctx = ctx; data->list = list; data->bbox = bbox; data->pix = pix; // Create the thread and pass it the data structure. if (pthread_create(&thread[i], NULL, renderer, data) < 0) fail("pthread_create()"); } // Now each thread is rendering pages, so wait for each thread // to complete its rendering. fprintf(stderr, "joining %d threads...\n", threads); for (i = threads - 1; i >= 0; i--) { char filename[42]; struct data *data; if (pthread_join(thread[i], (void **) &data) < 0) fail("pthread_join"); sprintf(filename, "out%04d.png", i); fprintf(stderr, "\tSaving %s...\n", filename); // Write the rendered image to a PNG file fz_write_png(ctx, data->pix, filename, 0); // Free the thread's pixmap and display list since // they were allocated by the main thread above. fz_drop_pixmap(ctx, data->pix); fz_free_display_list(ctx, data->list); // Free the data structured passed back and forth // between the main thread and rendering thread. free(data); } fprintf(stderr, "finally!\n"); fflush(NULL); free(thread); // Finally the document is closed and the main thread's // context is freed. fz_close_document(doc); fz_free_context(ctx); return 0; }
void render(char *filename, int pagenumber, int zoom, int rotation) { // Create a context to hold the exception stack and various caches. fz_context *ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); // Open the PDF, XPS or CBZ document. fz_document *doc = fz_open_document(ctx, filename); // Retrieve the number of pages (not used in this example). int pagecount = fz_count_pages(doc); // Load the page we want. Page numbering starts from zero. fz_page *page = fz_load_page(doc, pagenumber - 1); // Calculate a transform to use when rendering. This transform // contains the scale and rotation. Convert zoom percentage to a // scaling factor. Without scaling the resolution is 72 dpi. fz_matrix transform; fz_rotate(&transform, rotation); fz_pre_scale(&transform, zoom / 100.0f, zoom / 100.0f); // Take the page bounds and transform them by the same matrix that // we will use to render the page. fz_rect bounds; fz_bound_page(doc, page, &bounds); fz_transform_rect(&bounds, &transform); // Create a blank pixmap to hold the result of rendering. The // pixmap bounds used here are the same as the transformed page // bounds, so it will contain the entire page. The page coordinate // space has the origin at the top left corner and the x axis // extends to the right and the y axis extends down. fz_irect bbox; fz_round_rect(&bbox, &bounds); fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox); fz_clear_pixmap_with_value(ctx, pix, 0xff); // A page consists of a series of objects (text, line art, images, // gradients). These objects are passed to a device when the // interpreter runs the page. There are several devices, used for // different purposes: // // draw device -- renders objects to a target pixmap. // // text device -- extracts the text in reading order with styling // information. This text can be used to provide text search. // // list device -- records the graphic objects in a list that can // be played back through another device. This is useful if you // need to run the same page through multiple devices, without // the overhead of parsing the page each time. // Create a draw device with the pixmap as its target. // Run the page with the transform. fz_device *dev = fz_new_draw_device(ctx, pix); fz_run_page(doc, page, dev, &transform, NULL); fz_free_device(dev); // Save the pixmap to a file. fz_write_png(ctx, pix, "out.png", 0); // Clean up. fz_drop_pixmap(ctx, pix); fz_free_page(doc, page); fz_close_document(doc); fz_free_context(ctx); }
static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) { fz_page *page; fz_display_list *list = NULL; fz_device *dev = NULL; int start; fz_cookie cookie = { 0 }; fz_var(list); fz_var(dev); fz_try(ctx) { page = fz_load_page(doc, pagenum - 1); } fz_catch(ctx) { fz_throw(ctx, "cannot load page %d in file '%s'", pagenum, filename); } float zoom; fz_matrix ctm; fz_rect bounds, bounds2; fz_bbox bbox; fz_pixmap *pix = NULL; int w, h; fz_var(pix); bounds = fz_bound_page(doc, page); zoom = resolution / 72; ctm = fz_scale(zoom, zoom); ctm = fz_concat(ctm, fz_rotate(rotation)); bounds2 = fz_transform_rect(ctm, bounds); bbox = fz_round_rect(bounds2); /* Make local copies of our width/height */ w = width; h = height; /* If a resolution is specified, check to see whether w/h are * exceeded; if not, unset them. */ if (res_specified) { int t; t = bbox.x1 - bbox.x0; if (w && t <= w) w = 0; t = bbox.y1 - bbox.y0; if (h && t <= h) h = 0; } /* Now w or h will be 0 unless then need to be enforced. */ if (w || h) { float scalex = w/(bounds2.x1-bounds2.x0); float scaley = h/(bounds2.y1-bounds2.y0); if (fit) { if (w == 0) scalex = 1.0f; if (h == 0) scaley = 1.0f; } else { if (w == 0) scalex = scaley; if (h == 0) scaley = scalex; } if (!fit) { if (scalex > scaley) scalex = scaley; else scaley = scalex; } ctm = fz_concat(ctm, fz_scale(scalex, scaley)); bounds2 = fz_transform_rect(ctm, bounds); } bbox = fz_round_rect(bounds2); /* TODO: banded rendering and multi-page ppm */ fz_try(ctx) { pix = fz_new_pixmap_with_bbox(ctx, colorspace, bbox); fz_clear_pixmap_with_value(ctx, pix, 255); dev = fz_new_draw_device(ctx, pix); if (list) fz_run_display_list(list, dev, ctm, bbox, &cookie); else fz_run_page(doc, page, dev, ctm, &cookie); fz_free_device(dev); dev = NULL; int size = fz_pixmap_height(ctx, pix) * fz_pixmap_width(ctx, pix); inplace_reorder(fz_pixmap_samples(ctx, pix), size); size_t x_offset = (width - fz_pixmap_width(ctx, pix)) / 2; size_t y_offset = (height - fz_pixmap_height(ctx, pix)) / 2;; if (toggle_decors) { x_offset += decor_left_width; y_offset += decor_top_height; } for (int i = 0; i < fz_pixmap_height(ctx, pix); ++i) { memcpy(&GFX(gfx_ctx, x_offset, y_offset + i), &fz_pixmap_samples(ctx, pix)[fz_pixmap_width(ctx, pix) * i * 4], fz_pixmap_width(ctx, pix) * 4); } } fz_always(ctx) { fz_free_device(dev); dev = NULL; fz_drop_pixmap(ctx, pix); } fz_catch(ctx) { fz_free_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } if (list) fz_free_display_list(ctx, list); fz_free_page(doc, page); fz_flush_warnings(ctx); if (cookie.errors) errored = 1; }
static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) { fz_page *page; fz_display_list *list = NULL; fz_device *dev = NULL; int start; fz_cookie cookie = { 0 }; int needshot = 0; fz_var(list); fz_var(dev); if (showtime) { start = gettime(); } fz_try(ctx) { page = fz_load_page(doc, pagenum - 1); } fz_catch(ctx) { fz_throw(ctx, "cannot load page %d in file '%s'", pagenum, filename); } if (mujstest_file) { fz_interactive *inter = fz_interact(doc); fz_widget *widget = NULL; if (inter) widget = fz_first_widget(inter, page); if (widget) { fprintf(mujstest_file, "GOTO %d\n", pagenum); needshot = 1; } for (;widget; widget = fz_next_widget(inter, widget)) { fz_rect rect = fz_widget_bbox(widget); int w = (rect.x1-rect.x0); int h = (rect.y1-rect.y0); int len; int type = fz_widget_get_type(widget); ++mujstest_count; switch (type) { default: fprintf(mujstest_file, "%% UNKNOWN %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); break; case FZ_WIDGET_TYPE_PUSHBUTTON: fprintf(mujstest_file, "%% PUSHBUTTON %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); break; case FZ_WIDGET_TYPE_CHECKBOX: fprintf(mujstest_file, "%% CHECKBOX %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); break; case FZ_WIDGET_TYPE_RADIOBUTTON: fprintf(mujstest_file, "%% RADIOBUTTON %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); break; case FZ_WIDGET_TYPE_TEXT: { int maxlen = fz_text_widget_max_len(inter, widget); int texttype = fz_text_widget_content_type(inter, widget); /* If height is low, assume a single row, and base * the width off that. */ if (h < 10) { w = (w+h-1) / (h ? h : 1); h = 1; } /* Otherwise, if width is low, work off height */ else if (w < 10) { h = (w+h-1) / (w ? w : 1); w = 1; } else { w = (w+9)/10; h = (h+9)/10; } len = w*h; if (len < 2) len = 2; if (len > maxlen) len = maxlen; fprintf(mujstest_file, "%% TEXT %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); switch (texttype) { default: case FZ_WIDGET_CONTENT_UNRESTRAINED: fprintf(mujstest_file, "TEXT %d ", mujstest_count); escape_string(mujstest_file, len-3, lorem); fprintf(mujstest_file, "\n"); break; case FZ_WIDGET_CONTENT_NUMBER: fprintf(mujstest_file, "TEXT %d\n", mujstest_count); break; case FZ_WIDGET_CONTENT_SPECIAL: fprintf(mujstest_file, "TEXT %lld\n", 46702919800LL + mujstest_count); break; case FZ_WIDGET_CONTENT_DATE: fprintf(mujstest_file, "TEXT Jun %d 1979\n", 1 + ((13 + mujstest_count) % 30)); break; case FZ_WIDGET_CONTENT_TIME: ++mujstest_count; fprintf(mujstest_file, "TEXT %02d:%02d\n", ((mujstest_count/60) % 24), mujstest_count % 60); break; } break; } case FZ_WIDGET_TYPE_LISTBOX: fprintf(mujstest_file, "%% LISTBOX %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); break; case FZ_WIDGET_TYPE_COMBOBOX: fprintf(mujstest_file, "%% COMBOBOX %0.2f %0.2f %0.2f %0.2f\n", rect.x0, rect.y0, rect.x1, rect.y1); break; } fprintf(mujstest_file, "CLICK %0.2f %0.2f\n", (rect.x0+rect.x1)/2, (rect.y0+rect.y1)/2); } } if (uselist) { fz_try(ctx) { list = fz_new_display_list(ctx); dev = fz_new_list_device(ctx, list); fz_run_page(doc, page, dev, fz_identity, &cookie); } fz_always(ctx) { fz_free_device(dev); dev = NULL; } fz_catch(ctx) { fz_free_display_list(ctx, list); fz_free_page(doc, page); fz_throw(ctx, "cannot draw page %d in file '%s'", pagenum, filename); } } if (showxml) { fz_try(ctx) { dev = fz_new_trace_device(ctx); fz_printf(out, "<page number=\"%d\">\n", pagenum); if (list) fz_run_display_list(list, dev, fz_identity, fz_infinite_rect, &cookie); else fz_run_page(doc, page, dev, fz_identity, &cookie); fz_printf(out, "</page>\n"); } fz_always(ctx) { fz_free_device(dev); dev = NULL; } fz_catch(ctx) { fz_free_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } } if (showtext) { fz_text_page *text = NULL; fz_var(text); fz_try(ctx) { text = fz_new_text_page(ctx, fz_bound_page(doc, page)); dev = fz_new_text_device(ctx, sheet, text); if (list) fz_run_display_list(list, dev, fz_identity, fz_infinite_rect, &cookie); else fz_run_page(doc, page, dev, fz_identity, &cookie); fz_free_device(dev); dev = NULL; if (showtext == TEXT_XML) { fz_print_text_page_xml(ctx, out, text); } else if (showtext == TEXT_HTML) { fz_print_text_page_html(ctx, out, text); } else if (showtext == TEXT_PLAIN) { fz_print_text_page(ctx, out, text); fz_printf(out, "\f\n"); } } fz_always(ctx) { fz_free_device(dev); dev = NULL; fz_free_text_page(ctx, text); } fz_catch(ctx) { fz_free_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } } if (showmd5 || showtime) printf("page %s %d", filename, pagenum); #ifdef GDI_PLUS_BMP_RENDERER // hack: use -G0 to "enable GDI+" when saving as TGA if (output && (strstr(output, ".bmp") || strstr(output, ".tga") && !gamma_value)) drawbmp(ctx, doc, page, list, pagenum); else #endif if (output || showmd5 || showtime) { float zoom; fz_matrix ctm; fz_rect bounds, tbounds; fz_bbox ibounds; fz_pixmap *pix = NULL; int w, h; fz_var(pix); bounds = fz_bound_page(doc, page); zoom = resolution / 72; ctm = fz_scale(zoom, zoom); ctm = fz_concat(ctm, fz_rotate(rotation)); tbounds = fz_transform_rect(ctm, bounds); ibounds = fz_round_rect(tbounds); /* convert to integers */ /* Make local copies of our width/height */ w = width; h = height; /* If a resolution is specified, check to see whether w/h are * exceeded; if not, unset them. */ if (res_specified) { int t; t = ibounds.x1 - ibounds.x0; if (w && t <= w) w = 0; t = ibounds.y1 - ibounds.y0; if (h && t <= h) h = 0; } /* Now w or h will be 0 unless they need to be enforced. */ if (w || h) { float scalex = w / (tbounds.x1 - tbounds.x0); float scaley = h / (tbounds.y1 - tbounds.y0); if (fit) { if (w == 0) scalex = 1.0f; if (h == 0) scaley = 1.0f; } else { if (w == 0) scalex = scaley; if (h == 0) scaley = scalex; } if (!fit) { if (scalex > scaley) scalex = scaley; else scaley = scalex; } ctm = fz_concat(ctm, fz_scale(scalex, scaley)); tbounds = fz_transform_rect(ctm, bounds); } ibounds = fz_round_rect(tbounds); /* TODO: banded rendering and multi-page ppm */ fz_try(ctx) { pix = fz_new_pixmap_with_bbox(ctx, colorspace, ibounds); if (savealpha) fz_clear_pixmap(ctx, pix); else fz_clear_pixmap_with_value(ctx, pix, 255); dev = fz_new_draw_device(ctx, pix); if (list) fz_run_display_list(list, dev, ctm, tbounds, &cookie); else fz_run_page(doc, page, dev, ctm, &cookie); fz_free_device(dev); dev = NULL; if (invert) fz_invert_pixmap(ctx, pix); if (gamma_value != 1) fz_gamma_pixmap(ctx, pix, gamma_value); if (savealpha) fz_unmultiply_pixmap(ctx, pix); if (output) { char buf[512]; sprintf(buf, output, pagenum); if (strstr(output, ".pgm") || strstr(output, ".ppm") || strstr(output, ".pnm")) fz_write_pnm(ctx, pix, buf); else if (strstr(output, ".pam")) fz_write_pam(ctx, pix, buf, savealpha); else if (strstr(output, ".png")) fz_write_png(ctx, pix, buf, savealpha); else if (strstr(output, ".pbm")) { fz_bitmap *bit = fz_halftone_pixmap(ctx, pix, NULL); fz_write_pbm(ctx, bit, buf); fz_drop_bitmap(ctx, bit); } /* SumatraPDF: support TGA as output format */ else if (strstr(output, ".tga")) fz_write_tga(ctx, pix, buf, savealpha); } if (showmd5) { unsigned char digest[16]; int i; fz_md5_pixmap(pix, digest); printf(" "); for (i = 0; i < 16; i++) printf("%02x", digest[i]); } } fz_always(ctx) { fz_free_device(dev); dev = NULL; fz_drop_pixmap(ctx, pix); } fz_catch(ctx) { fz_free_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } }
DrPage * DrPDFExtractor::ExtractPage(unsigned int pageno) { fz_page * page = fz_load_page(m_doc, pageno); if (page == NULL) { return NULL; } DrPage * dpage = new DrPage; dpage->SetPageNo(pageno); std::list<DrChar *> charlist; std::list<DrPhrase *> phraselist; std::list<DrLine *> linelist; std::list<DrZone *> &zonelist = dpage->m_zonelist; fz_matrix transform; fz_rotate(&transform,0); fz_pre_scale(&transform, 1.0f, 1.0f); fz_rect bounds; fz_bound_page(m_doc, page, &bounds); fz_transform_rect(&bounds, &transform); fz_irect bbox; fz_round_rect(&bbox, &bounds); fz_matrix ttransform = transform; fz_pixmap *pix = fz_new_pixmap_with_bbox(m_ctx, fz_device_rgb(m_ctx), &bbox); fz_clear_pixmap_with_value(m_ctx, pix, 0xff); fz_device * dev = fz_new_draw_device(m_ctx,pix); fz_run_page(m_doc, page, dev, &transform, NULL); fz_free_device(dev); fz_text_sheet * sheet = fz_new_text_sheet(m_ctx); fz_text_page * tpage = fz_new_text_page(m_ctx); fz_device * cdev = fz_new_text_device(m_ctx, sheet, tpage); fz_run_page(m_doc, page, cdev, &ttransform, NULL); ExtractChars(charlist,tpage); fz_free_device(cdev); // DrThumbnail * thumb = new DrThumbnail(m_ctx,pix,pageno); // dpage->m_thumbnail = thumb; DrTextGrouper::TextGroup(phraselist, charlist); std::list<DrPhrase *>::iterator itphrase = phraselist.begin(); while (itphrase != phraselist.end()) { if ((*itphrase)->IsSpacePhrase()) { delete *itphrase; itphrase = phraselist.erase(itphrase); } else itphrase++; } DrTextGrouper::TextGroup(linelist, phraselist); DrTextGrouper::TextGroup(zonelist, linelist); dpage->CalculatePageBox(); // fz_free_text_sheet(m_ctx, tsheet); // fz_free_text_page(m_ctx, tpage); fz_free_page(m_doc, page); return dpage; }
static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) { fz_page *page; fz_link *links; fz_display_list *list = NULL; fz_device *dev = NULL; int start; fz_var(list); fz_var(dev); if (showtime) { start = gettime(); } fz_try(ctx) { page = fz_load_page(doc, pagenum - 1); } fz_catch(ctx) { fz_throw(ctx, "cannot load page %d in file '%s'", pagenum, filename); } fz_try(ctx) { links = fz_load_links(doc, page); } fz_catch(ctx) { fz_throw(ctx, "cannot load links for page %d in file '%s'", pagenum, filename); } if (uselist) { fz_try(ctx) { list = fz_new_display_list(ctx); dev = fz_new_list_device(ctx, list); fz_run_page(doc, page, dev, fz_identity, NULL); } fz_catch(ctx) { fz_free_device(dev); fz_free_display_list(ctx, list); fz_free_page(doc, page); fz_throw(ctx, "cannot draw page %d in file '%s'", pagenum, filename); } fz_free_device(dev); dev = NULL; } if (showjson) { fz_text_page *text = NULL; fz_var(text); fz_try(ctx) { text = fz_new_text_page(ctx, fz_bound_page(doc, page)); dev = fz_new_text_device(ctx, sheet, text); if (list) fz_run_display_list(list, dev, fz_identity, fz_infinite_bbox, NULL); else fz_run_page(doc, page, dev, fz_identity, NULL); fz_free_device(dev); dev = NULL; fz_print_text_page_json(ctx, stdout, text, links); printf("\f\n"); } fz_catch(ctx) { fz_free_device(dev); fz_free_text_page(ctx, text); fz_free_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } fz_free_text_page(ctx, text); } if (showmd5 || showtime) printf("page %s %d", filename, pagenum); if (output || showmd5 || showtime) { float zoom; fz_matrix ctm; fz_rect bounds, bounds2; fz_bbox bbox; fz_pixmap *pix = NULL; int w, h; fz_var(pix); bounds = fz_bound_page(doc, page); zoom = resolution / 72; ctm = fz_scale(zoom, zoom); ctm = fz_concat(ctm, fz_rotate(rotation)); bounds2 = fz_transform_rect(ctm, bounds); bbox = fz_round_rect(bounds2); /* Make local copies of our width/height */ w = width; h = height; /* If a resolution is specified, check to see whether w/h are * exceeded; if not, unset them. */ if (res_specified) { int t; t = bbox.x1 - bbox.x0; if (w && t <= w) w = 0; t = bbox.y1 - bbox.y0; if (h && t <= h) h = 0; } /* Now w or h will be 0 unless then need to be enforced. */ if (w || h) { float scalex = w/(bounds2.x1-bounds2.x0); float scaley = h/(bounds2.y1-bounds2.y0); if (fit) { if (w == 0) scalex = 1.0f; if (h == 0) scaley = 1.0f; } else { if (w == 0) scalex = scaley; if (h == 0) scaley = scalex; } if (!fit) { if (scalex > scaley) scalex = scaley; else scaley = scalex; } ctm = fz_concat(ctm, fz_scale(scalex, scaley)); bounds2 = fz_transform_rect(ctm, bounds); } bbox = fz_round_rect(bounds2); /* TODO: banded rendering and multi-page ppm */ fz_try(ctx) { pix = fz_new_pixmap_with_bbox(ctx, colorspace, bbox); if (savealpha) fz_clear_pixmap(ctx, pix); else fz_clear_pixmap_with_value(ctx, pix, 255); dev = fz_new_draw_device(ctx, pix); if (list) fz_run_display_list(list, dev, ctm, bbox, NULL); else fz_run_page(doc, page, dev, ctm, NULL); fz_free_device(dev); dev = NULL; if (invert) fz_invert_pixmap(ctx, pix); if (gamma_value != 1) fz_gamma_pixmap(ctx, pix, gamma_value); if (savealpha) fz_unmultiply_pixmap(ctx, pix); if (output) { char buf[512]; sprintf(buf, output, pagenum); if (strstr(output, ".pgm") || strstr(output, ".ppm") || strstr(output, ".pnm")) fz_write_pnm(ctx, pix, buf); else if (strstr(output, ".pam")) fz_write_pam(ctx, pix, buf, savealpha); else if (strstr(output, ".png")) fz_write_png(ctx, pix, buf, savealpha); else if (strstr(output, ".pbm")) { fz_bitmap *bit = fz_halftone_pixmap(ctx, pix, NULL); fz_write_pbm(ctx, bit, buf); fz_drop_bitmap(ctx, bit); } } if (showmd5) { unsigned char digest[16]; int i; fz_md5_pixmap(pix, digest); printf(" "); for (i = 0; i < 16; i++) printf("%02x", digest[i]); } fz_drop_pixmap(ctx, pix); } fz_catch(ctx) { fz_free_device(dev); fz_drop_pixmap(ctx, pix); fz_free_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } }
int bmpmupdf_pdffile_to_bmp(WILLUSBITMAP *bmp,char *filename,int pageno,double dpi, int bpp) { fz_context *ctx; fz_colorspace *colorspace; fz_document *doc; fz_page *page; fz_display_list *list; fz_device *dev; fz_pixmap *pix; double dpp; fz_rect bounds,bounds2; fz_matrix ctm; fz_irect bbox; // fz_glyph_cache *glyphcache; // fz_error error; int np,status; dev=NULL; list=NULL; page=NULL; doc=NULL; status=0; if (pageno<1) return(-99); ctx = fz_new_context(NULL,NULL,FZ_STORE_DEFAULT); if (!ctx) return(-1); fz_try(ctx) { fz_register_document_handlers(ctx); fz_set_aa_level(ctx,8); /* Sumatra version of MuPDF v1.4 -- use locally installed fonts */ pdf_install_load_system_font_funcs(ctx); // fz_accelerate(); // glyphcache=fz_new_glyph_cache(); colorspace=(bpp==8 ? fz_device_gray(ctx) : fz_device_rgb(ctx)); fz_try(ctx) { doc=fz_open_document(ctx,filename); } fz_catch(ctx) { fz_free_context(ctx); return(-1); } /* if (fz_needs_password(doc) && !fz_authenticate_password(doc,password)) return(-2); */ // error=pdf_load_page_tree(xref); // if (error) // { // pdf_free_xref(xref); // return(-2); // } np=fz_count_pages(doc); if (pageno>np) return(-99); fz_try(ctx) { page = fz_load_page(doc,pageno-1); } fz_catch(ctx) { fz_close_document(doc); fz_free_context(ctx); return(-3); } fz_try(ctx) { list=fz_new_display_list(ctx); dev=fz_new_list_device(ctx,list); fz_run_page(doc,page,dev,&fz_identity,NULL); } fz_catch(ctx) { fz_free_device(dev); fz_drop_display_list(ctx,list); fz_free_page(doc,page); fz_close_document(doc); fz_free_context(ctx); return(-4); } fz_free_device(dev); dev=NULL; dpp=dpi/72.; pix=NULL; fz_var(pix); fz_bound_page(doc,page,&bounds); ctm=fz_identity; fz_scale(&ctm,dpp,dpp); // ctm=fz_concat(ctm,fz_rotate(rotation)); bounds2=bounds; fz_transform_rect(&bounds2,&ctm); fz_round_rect(&bbox,&bounds2); // ctm=fz_translate(0,-page->mediabox.y1); // ctm=fz_concat(ctm,fz_scale(dpp,-dpp)); // ctm=fz_concat(ctm,fz_rotate(page->rotate)); // ctm=fz_concat(ctm,fz_rotate(0)); // bbox=fz_round_rect(fz_transform_rect(ctm,page->mediabox)); // pix=fz_new_pixmap_with_rect(colorspace,bbox); fz_try(ctx) { pix=fz_new_pixmap_with_bbox(ctx,colorspace,&bbox); fz_clear_pixmap_with_value(ctx,pix,255); dev=fz_new_draw_device(ctx,pix); if (list) fz_run_display_list(list,dev,&ctm,&bounds2,NULL); else fz_run_page(doc,page,dev,&ctm,NULL); fz_free_device(dev); dev=NULL; status=bmpmupdf_pixmap_to_bmp(bmp,ctx,pix); fz_drop_pixmap(ctx,pix); } fz_catch(ctx) { fz_free_device(dev); fz_drop_pixmap(ctx,pix); fz_drop_display_list(ctx,list); fz_free_page(doc,page); fz_close_document(doc); fz_free_context(ctx); return(-5); } if (list) fz_drop_display_list(ctx,list); fz_free_page(doc,page); // pdf_free_xref(xref); fz_close_document(doc); fz_flush_warnings(ctx); } /* fz_catch before registering handlers */ fz_catch(ctx) /* Error registering */ { status = -10; } fz_free_context(ctx); // fz_free_glyph_cache(glyphcache); // fz_flush_warnings(); if (status<0) return(status-10); return(0); }
/* ** Returns 0 if got dimensions. */ int bmpmupdf_pdffile_width_and_height(char *filename,int pageno,double *width_in,double *height_in) { fz_context *ctx; fz_document *doc; fz_page *page; fz_display_list *list; fz_device *dev; fz_rect bounds; int np; dev=NULL; list=NULL; page=NULL; doc=NULL; if (pageno<1) return(-99); ctx = fz_new_context(NULL,NULL,FZ_STORE_DEFAULT); if (!ctx) return(-1); fz_try(ctx) { fz_register_document_handlers(ctx); fz_set_aa_level(ctx,8); /* Sumatra version of MuPDF v1.4 -- use locally installed fonts */ pdf_install_load_system_font_funcs(ctx); fz_try(ctx) { doc=fz_open_document(ctx,filename); } fz_catch(ctx) { fz_free_context(ctx); return(-1); } np=fz_count_pages(doc); if (pageno>np) return(-99); fz_try(ctx) { page = fz_load_page(doc,pageno-1); } fz_catch(ctx) { fz_close_document(doc); fz_free_context(ctx); return(-3); } fz_try(ctx) { list=fz_new_display_list(ctx); dev=fz_new_list_device(ctx,list); fz_run_page(doc,page,dev,&fz_identity,NULL); } fz_catch(ctx) { fz_free_device(dev); fz_drop_display_list(ctx,list); fz_free_page(doc,page); fz_close_document(doc); fz_free_context(ctx); return(-4); } fz_free_device(dev); dev=NULL; fz_bound_page(doc,page,&bounds); if (width_in!=NULL) (*width_in)=fabs(bounds.x1-bounds.x0)/72.; if (height_in!=NULL) (*height_in)=fabs(bounds.y1-bounds.y0)/72.; fz_drop_display_list(ctx,list); fz_free_page(doc,page); fz_close_document(doc); } fz_catch(ctx) /* Error registering */ { fz_free_context(ctx); return(-20); } fz_free_context(ctx); return(0); }