summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gardiner <paul.gardiner@artifex.com>2014-04-18 15:24:11 +0100
committerPaul Gardiner <paul.gardiner@artifex.com>2014-04-18 15:26:58 +0100
commit883c430cb9b54e81e74599b990d19470bd1d9b89 (patch)
treef9887d9b6fef85f00db0adb4fbf8ee32462c7073
parent223c4e57e9e0cd2eb9193aa9ddde35686d440ea7 (diff)
downloadmupdf-883c430cb9b54e81e74599b990d19470bd1d9b89.tar.xz
iOS: use bitmap based printing
allows printing of file types other than PDF
-rw-r--r--platform/ios/Classes/MuDocumentController.m6
-rw-r--r--platform/ios/Classes/MuPageViewNormal.m26
-rw-r--r--platform/ios/Classes/MuPrintPageRenderer.h18
-rw-r--r--platform/ios/Classes/MuPrintPageRenderer.m99
-rw-r--r--platform/ios/MuPDF.xcodeproj/project.pbxproj6
-rw-r--r--platform/ios/common.h4
-rw-r--r--platform/ios/common.m29
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;
+}