From 883c430cb9b54e81e74599b990d19470bd1d9b89 Mon Sep 17 00:00:00 2001 From: Paul Gardiner Date: Fri, 18 Apr 2014 15:24:11 +0100 Subject: iOS: use bitmap based printing allows printing of file types other than PDF --- platform/ios/Classes/MuDocumentController.m | 6 +- platform/ios/Classes/MuPageViewNormal.m | 26 +------- platform/ios/Classes/MuPrintPageRenderer.h | 18 ++++++ platform/ios/Classes/MuPrintPageRenderer.m | 99 +++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 28 deletions(-) create mode 100644 platform/ios/Classes/MuPrintPageRenderer.h create mode 100644 platform/ios/Classes/MuPrintPageRenderer.m (limited to 'platform/ios/Classes') diff --git a/platform/ios/Classes/MuDocumentController.m b/platform/ios/Classes/MuDocumentController.m index 490ba40e..a9bd6261 100644 --- a/platform/ios/Classes/MuDocumentController.m +++ b/platform/ios/Classes/MuDocumentController.m @@ -6,6 +6,7 @@ #import "MuDocumentController.h" #import "MuTextFieldController.h" #import "MuChoiceFieldController.h" +#import "MuPrintPageRenderer.h" #define GAP 20 #define INDICATOR_Y -44-24 @@ -485,9 +486,8 @@ static void saveDoc(char *current_path, fz_document *doc) - (void) onPrint: (id)sender { - NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:filePath]]; UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController]; - if (pic && [UIPrintInteractionController canPrintURL:url] ) { + if (pic) { UIPrintInfo *printInfo = [UIPrintInfo printInfo]; printInfo.outputType = UIPrintInfoOutputGeneral; @@ -495,7 +495,7 @@ static void saveDoc(char *current_path, fz_document *doc) printInfo.duplex = UIPrintInfoDuplexLongEdge; pic.printInfo = printInfo; pic.showsPageRange = YES; - pic.printingItem = url; + pic.printPageRenderer = [[[MuPrintPageRenderer alloc] initWithDocRef:docRef] autorelease]; void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) = ^(UIPrintInteractionController *pic, BOOL completed, NSError *error) { diff --git a/platform/ios/Classes/MuPageViewNormal.m b/platform/ios/Classes/MuPageViewNormal.m index 8c67dc4e..18183458 100644 --- a/platform/ios/Classes/MuPageViewNormal.m +++ b/platform/ios/Classes/MuPageViewNormal.m @@ -11,34 +11,10 @@ #define LINE_THICKNESS (0.07f) #define INK_THICKNESS (4.0f) -static void releasePixmap(void *info, const void *data, size_t size) -{ - if (queue) - dispatch_async(queue, ^{ - fz_drop_pixmap(ctx, info); - }); - else - { - fz_drop_pixmap(ctx, info); - } -} - -static CGDataProviderRef wrapPixmap(fz_pixmap *pix) -{ - unsigned char *samples = fz_pixmap_samples(ctx, pix); - int w = fz_pixmap_width(ctx, pix); - int h = fz_pixmap_height(ctx, pix); - return CGDataProviderCreateWithData(pix, samples, w * 4 * h, releasePixmap); -} - static UIImage *newImageWithPixmap(fz_pixmap *pix, CGDataProviderRef cgdata) { - int w = fz_pixmap_width(ctx, pix); - int h = fz_pixmap_height(ctx, pix); - CGColorSpaceRef cgcolor = CGColorSpaceCreateDeviceRGB(); - CGImageRef cgimage = CGImageCreate(w, h, 8, 32, 4 * w, cgcolor, kCGBitmapByteOrderDefault, cgdata, NULL, NO, kCGRenderingIntentDefault); + CGImageRef cgimage = newCGImageWithPixmap(pix, cgdata); UIImage *image = [[UIImage alloc] initWithCGImage: cgimage scale: screenScale orientation: UIImageOrientationUp]; - CGColorSpaceRelease(cgcolor); CGImageRelease(cgimage); return image; } diff --git a/platform/ios/Classes/MuPrintPageRenderer.h b/platform/ios/Classes/MuPrintPageRenderer.h new file mode 100644 index 00000000..44d42af0 --- /dev/null +++ b/platform/ios/Classes/MuPrintPageRenderer.h @@ -0,0 +1,18 @@ +// +// MuPrintPageRenderer.h +// MuPDF +// +// Copyright (c) 2014 Artifex Software, Inc. All rights reserved. +// + +#import +#import + +@interface MuPrintPageRenderer : UIPrintPageRenderer +{ + MuDocRef *docRef; +} + +-(id) initWithDocRef:(MuDocRef *) docRef; + +@end diff --git a/platform/ios/Classes/MuPrintPageRenderer.m b/platform/ios/Classes/MuPrintPageRenderer.m new file mode 100644 index 00000000..53e46423 --- /dev/null +++ b/platform/ios/Classes/MuPrintPageRenderer.m @@ -0,0 +1,99 @@ +// +// MuPrintPageRenderer.m +// MuPDF +// +// Copyright (c) 2014 Artifex Software, Inc. All rights reserved. +// + +#include "common.h" +#import "MuPrintPageRenderer.h" + +@implementation MuPrintPageRenderer + +-(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(docRef->doc); + } + fz_catch(ctx); + }); + return npages; +} + +-(void) drawPageAtIndex:(NSInteger)pageIndex inRect:(CGRect)printableRect +{ + CGContextRef cgctx = UIGraphicsGetCurrentContext(); + + if (!cgctx) return; + + CGSize paperSize = self.paperRect.size; + // We must perform mupdf calls within this function, but all library calls need + // to be on our background thread, so we run them synchronously on the queue + + __block fz_pixmap *pix = NULL; + __block CGSize pageSize; + dispatch_sync(queue, ^{ + fz_page *page = NULL; + fz_device *dev = NULL; + fz_var(page); + fz_var(dev); + fz_try(ctx) + { + fz_rect bounds; + fz_matrix ctm; + page = fz_load_page(docRef->doc, pageIndex); + fz_bound_page(docRef->doc, page, &bounds); + pageSize.width = bounds.x1 - bounds.x0; + pageSize.height = bounds.y1 - bounds.y0; + CGSize scale = fitPageToScreen(pageSize, paperSize); + pageSize.width = roundf(pageSize.width * scale.width); + pageSize.height = roundf(pageSize.height * scale.height); + // Need to render upside down. No idea why. + fz_scale(&ctm, scale.width, -scale.height); + fz_pre_translate(&ctm, 0, -pageSize.height); + pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), pageSize.width, pageSize.height); + fz_clear_pixmap_with_value(ctx, pix, 255); + dev = fz_new_draw_device(ctx, pix); + fz_run_page(docRef->doc, page, dev, &ctm, NULL); + } + fz_always(ctx) + { + fz_free_page(docRef->doc, page); + fz_free_device(dev); + } + fz_catch(ctx) + { + printf("Failed to print page %d\n", pageIndex+1); + } + }); + + if (!pix) return; + + CGRect rect = {{0.0,0.0},pageSize}; + CGDataProviderRef dataref = wrapPixmap(pix); + CGImageRef img = newCGImageWithPixmap(pix, dataref); + CGContextDrawImage(cgctx, rect, img); + CGImageRelease(img); + CGDataProviderRelease(dataref); //releases pix +} + +@end -- cgit v1.2.3