diff options
author | Paul Gardiner <paul.gardiner@artifex.com> | 2014-04-18 15:24:11 +0100 |
---|---|---|
committer | Paul Gardiner <paul.gardiner@artifex.com> | 2014-04-18 15:26:58 +0100 |
commit | 883c430cb9b54e81e74599b990d19470bd1d9b89 (patch) | |
tree | f9887d9b6fef85f00db0adb4fbf8ee32462c7073 /platform/ios | |
parent | 223c4e57e9e0cd2eb9193aa9ddde35686d440ea7 (diff) | |
download | mupdf-883c430cb9b54e81e74599b990d19470bd1d9b89.tar.xz |
iOS: use bitmap based printing
allows printing of file types other than PDF
Diffstat (limited to 'platform/ios')
-rw-r--r-- | platform/ios/Classes/MuDocumentController.m | 6 | ||||
-rw-r--r-- | platform/ios/Classes/MuPageViewNormal.m | 26 | ||||
-rw-r--r-- | platform/ios/Classes/MuPrintPageRenderer.h | 18 | ||||
-rw-r--r-- | platform/ios/Classes/MuPrintPageRenderer.m | 99 | ||||
-rw-r--r-- | platform/ios/MuPDF.xcodeproj/project.pbxproj | 6 | ||||
-rw-r--r-- | platform/ios/common.h | 4 | ||||
-rw-r--r-- | platform/ios/common.m | 29 |
7 files changed, 160 insertions, 28 deletions
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 <UIKit/UIKit.h> +#import <MuDocRef.h> + +@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 diff --git a/platform/ios/MuPDF.xcodeproj/project.pbxproj b/platform/ios/MuPDF.xcodeproj/project.pbxproj index eb9b3fb1..0d2b2abd 100644 --- a/platform/ios/MuPDF.xcodeproj/project.pbxproj +++ b/platform/ios/MuPDF.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ 96E1CDF21779A60700FCF717 /* iTunesArtwork.png in Resources */ = {isa = PBXBuildFile; fileRef = 96E1CDEB1779A60700FCF717 /* iTunesArtwork.png */; }; 96E1CDF31779A60700FCF717 /* x_alt_blue.png in Resources */ = {isa = PBXBuildFile; fileRef = 96E1CDEC1779A60700FCF717 /* x_alt_blue.png */; }; 96E1CDF41779A60700FCF717 /* x_alt_blue@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 96E1CDED1779A60700FCF717 /* x_alt_blue@2x.png */; }; + DA0354EB18FFF48400EE31BA /* MuPrintPageRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0354EA18FFF48400EE31BA /* MuPrintPageRenderer.m */; }; DA1C68AB17E86A500061F586 /* MuLibraryController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA1C689917E85E8E0061F586 /* MuLibraryController.m */; }; DA1C68AD17E86A500061F586 /* MuOutlineController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA1C689D17E861020061F586 /* MuOutlineController.m */; }; DA1C68AF17E86A500061F586 /* MuHitView.m in Sources */ = {isa = PBXBuildFile; fileRef = DA1C689F17E861870061F586 /* MuHitView.m */; }; @@ -101,6 +102,8 @@ 96E1CDEC1779A60700FCF717 /* x_alt_blue.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = x_alt_blue.png; sourceTree = "<group>"; }; 96E1CDED1779A60700FCF717 /* x_alt_blue@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "x_alt_blue@2x.png"; sourceTree = "<group>"; }; DA012CA218803D1C00E47712 /* MuUpdater.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MuUpdater.h; path = Classes/MuUpdater.h; sourceTree = "<group>"; }; + DA0354E918FFF48400EE31BA /* MuPrintPageRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MuPrintPageRenderer.h; path = Classes/MuPrintPageRenderer.h; sourceTree = "<group>"; }; + DA0354EA18FFF48400EE31BA /* MuPrintPageRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MuPrintPageRenderer.m; path = Classes/MuPrintPageRenderer.m; sourceTree = "<group>"; }; DA1C689817E85E8E0061F586 /* MuLibraryController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MuLibraryController.h; path = Classes/MuLibraryController.h; sourceTree = "<group>"; }; DA1C689917E85E8E0061F586 /* MuLibraryController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MuLibraryController.m; path = Classes/MuLibraryController.m; sourceTree = "<group>"; }; DA1C689C17E861020061F586 /* MuOutlineController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MuOutlineController.h; path = Classes/MuOutlineController.h; sourceTree = "<group>"; }; @@ -296,6 +299,8 @@ DAF81D5918800D1800B0F028 /* TapImage.h */, DAF81D5A18800D1800B0F028 /* TapImage.m */, DA012CA218803D1C00E47712 /* MuUpdater.h */, + DA0354E918FFF48400EE31BA /* MuPrintPageRenderer.h */, + DA0354EA18FFF48400EE31BA /* MuPrintPageRenderer.m */, ); name = Classes; sourceTree = "<group>"; @@ -445,6 +450,7 @@ DA1C68AF17E86A500061F586 /* MuHitView.m in Sources */, DA1C68B117E86A500061F586 /* MuPageViewNormal.m in Sources */, DA1C68B317E86A500061F586 /* MuDocumentController.m in Sources */, + DA0354EB18FFF48400EE31BA /* MuPrintPageRenderer.m in Sources */, DA1C68B517E86A500061F586 /* MuAppDelegate.m in Sources */, 96C8ED011779A88E00A30AF4 /* main.m in Sources */, DA1C68C417E8969C0061F586 /* common.m in Sources */, diff --git a/platform/ios/common.h b/platform/ios/common.h index c62b94c1..672ea119 100644 --- a/platform/ios/common.h +++ b/platform/ios/common.h @@ -20,4 +20,8 @@ int search_page(fz_document *doc, int number, char *needle, fz_cookie *cookie); fz_rect search_result_bbox(fz_document *doc, int i); +CGDataProviderRef wrapPixmap(fz_pixmap *pix); + +CGImageRef newCGImageWithPixmap(fz_pixmap *pix, CGDataProviderRef cgdata); + #endif diff --git a/platform/ios/common.m b/platform/ios/common.m index 55c1f24c..1ef17c03 100644 --- a/platform/ios/common.m +++ b/platform/ios/common.m @@ -41,3 +41,32 @@ fz_rect search_result_bbox(fz_document *doc, int i) return hit_bbox[i]; } +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); + } +} + +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); +} + +CGImageRef newCGImageWithPixmap(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); + CGColorSpaceRelease(cgcolor); + return cgimage; +} |