#include "common.h" #import "MuPrintPageRenderer.h" const int MaxStripPixels = 1024*1024; @implementation MuPrintPageRenderer { MuDocRef *docRef; } -(id) initWithDocRef:(MuDocRef *)aDocRef { self = [super init]; if (self) { docRef = [aDocRef retain]; } return self; } -(void) dealloc { [docRef release]; [super dealloc]; } -(NSInteger) numberOfPages { __block NSInteger npages = 0; dispatch_sync(queue, ^{ fz_try(ctx) { npages = fz_count_pages(ctx, docRef->doc); } fz_catch(ctx) { } }); return npages; } static fz_page *getPage(fz_document *doc, NSInteger pageIndex) { __block fz_page *page = NULL; dispatch_sync(queue, ^{ fz_try(ctx) { page = fz_load_page(ctx, doc, (int)pageIndex); } fz_catch(ctx) { printf("Failed to load page\n"); } }); return page; } static CGSize getPageSize(fz_document *doc, fz_page *page) { __block CGSize size = {0.0,0.0}; dispatch_sync(queue, ^{ fz_try(ctx) { fz_rect bounds; fz_bound_page(ctx, page, &bounds); size.width = bounds.x1 - bounds.x0; size.height = bounds.y1 - bounds.y0; } fz_catch(ctx) { printf("Failed to find page bounds\n"); } }); return size; } static fz_pixmap *createPixMap(CGSize size) { __block fz_pixmap *pix = NULL; dispatch_sync(queue, ^{ fz_try(ctx) { pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), size.width, size.height); } fz_catch(ctx) { printf("Failed to create pixmap\n"); } }); return pix; } static void freePage(fz_document *doc, fz_page *page) { dispatch_sync(queue, ^{ fz_drop_page(ctx, page); }); } static void renderPage(fz_document *doc, fz_page *page, fz_pixmap *pix, fz_matrix *ctm) { dispatch_sync(queue, ^{ fz_device *dev = NULL; fz_var(dev); fz_try(ctx) { dev = fz_new_draw_device(ctx, pix); fz_clear_pixmap_with_value(ctx, pix, 0xFF); fz_run_page(ctx, page, dev, ctm, NULL); } fz_always(ctx) { fz_drop_device(ctx, dev); } fz_catch(ctx) { printf("Failed to render page\n"); } }); } -(void) drawPageAtIndex:(NSInteger)pageIndex inRect:(CGRect)printableRect { fz_page *page = NULL; fz_pixmap *pix = NULL; CGDataProviderRef dataref = NULL; CGImageRef img = NULL; CGContextRef cgctx = UIGraphicsGetCurrentContext(); float dpi = 300.0; float ppi = 72.0; if (!cgctx) return; CGSize paperSize = self.paperRect.size; page = getPage(docRef->doc, pageIndex); if (page == NULL) return; CGSize pageSize = getPageSize(docRef->doc, page); if (pageSize.width == 0.0 || pageSize.height == 0.0) goto exit; CGSize scale = fitPageToScreen(pageSize, paperSize); pageSize.width *= scale.width; pageSize.height *= scale.height; CGSize pageSizePix = {roundf(pageSize.width * dpi / ppi), roundf(pageSize.height * dpi /ppi)}; int max_strip_height = MaxStripPixels / (int)pageSizePix.width; if (pageSizePix.height > max_strip_height) pageSizePix.height = max_strip_height; CGSize stripSize = {pageSize.width, pageSizePix.height * ppi / dpi}; float cursor = 0.0; while (cursor < pageSize.height) { // Overlap strips by 1 point if (cursor > 0.0) cursor -= 1.0; pix = createPixMap(pageSizePix); if (!pix) goto exit; dataref = CreateWrappedPixmap(pix); if (dataref == NULL) goto exit; img = CreateCGImageWithPixmap(pix, dataref); if (img == NULL) goto exit; fz_matrix ctm; fz_scale(&ctm, dpi / ppi, -dpi / ppi); fz_pre_translate(&ctm, 0, -stripSize.height-cursor); fz_pre_scale(&ctm, scale.width, scale.height); renderPage(docRef->doc, page, pix, &ctm); CGRect rect = {{0.0,cursor},stripSize}; CGContextDrawImage(cgctx, rect, img); CGImageRelease(img); img = NULL; CGDataProviderRelease(dataref); // releases pix dataref = NULL; cursor += stripSize.height; } exit: freePage(docRef->doc, page); CGImageRelease(img); CGDataProviderRelease(dataref); //releases pix } @end