summaryrefslogtreecommitdiff
path: root/ios
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2011-11-03 20:33:19 +0100
committerTor Andersson <tor.andersson@artifex.com>2011-11-03 20:33:19 +0100
commit83621651795dda31a3a10a02e1072bf976d108bc (patch)
tree7d78f79f78a31b85e2352d0a62495a3b29ebd097 /ios
parentd0dccf90e8d25b3af3b604cce930f42204716678 (diff)
downloadmupdf-83621651795dda31a3a10a02e1072bf976d108bc.tar.xz
Overlay a high resolution tile when viewing a zoomed in page.
Diffstat (limited to 'ios')
-rw-r--r--ios/main.m167
1 files changed, 157 insertions, 10 deletions
diff --git a/ios/main.m b/ios/main.m
index 1112ae1f..56c52d30 100644
--- a/ios/main.m
+++ b/ios/main.m
@@ -36,16 +36,20 @@ static fz_glyph_cache *glyphcache = NULL;
@interface MuPageView : UIScrollView <UIScrollViewDelegate>
{
- UIImageView *imageView;
- UIActivityIndicatorView *loadingView;
pdf_xref *xref;
int number;
+ UIActivityIndicatorView *loadingView;
+ UIImageView *imageView;
+ UIImageView *tileView;
+ CGRect tileFrame;
+ float tileScale;
BOOL cancel;
}
- (id) initWithFrame: (CGRect)frame xref: (pdf_xref*)aXref page: (int)aNumber;
- (void) displayImage: (UIImage*)image;
- (void) resizeImage;
- (void) loadPage;
+- (void) loadTile;
- (void) willRotate;
- (void) resetZoomAnimated: (BOOL)animated;
- (int) number;
@@ -213,6 +217,57 @@ static UIImage *renderPage(pdf_xref *xref, int number, CGSize screen)
return newImageWithPixmap(pix);
}
+static UIImage *renderTile(pdf_xref *xref, int number, CGSize screen, CGRect tile, float zoom)
+{
+ fz_error error;
+ CGSize pagesize;
+ fz_rect mediabox;
+ fz_rect tilebox;
+ fz_bbox bbox;
+ fz_matrix ctm;
+ fz_device *dev;
+ fz_pixmap *pix;
+ pdf_page *page;
+ CGSize scale;
+
+ error = pdf_load_page(&page, xref, number);
+ if (error) {
+ showAlert(@"Cannot load page");
+ return nil;
+ }
+
+ mediabox = fz_transform_rect(fz_rotate(page->rotate), page->mediabox);
+ pagesize = CGSizeMake(mediabox.x1 - mediabox.x0, mediabox.y1 - mediabox.y0);
+ scale = fitPageToScreen(pagesize, screen);
+ scale.width *= zoom;
+ scale.height *= zoom;
+
+ ctm = fz_translate(-page->mediabox.x0, page->mediabox.y0 - page->mediabox.y1);
+ ctm = fz_concat(ctm, fz_scale(scale.width, -scale.height));
+ ctm = fz_concat(ctm, fz_rotate(page->rotate));
+ mediabox = fz_transform_rect(ctm, page->mediabox);
+
+ tilebox.x0 = tile.origin.x - mediabox.x0;
+ tilebox.y0 = tile.origin.y - mediabox.y0;
+ tilebox.x1 = tilebox.x0 + tile.size.width;
+ tilebox.y1 = tilebox.y0 + tile.size.height;
+ bbox = fz_round_rect(tilebox);
+printf("render tile %d %d %d %d\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1);
+
+ pix = fz_new_pixmap_with_rect(fz_device_rgb, bbox);
+ fz_clear_pixmap_with_color(pix, 255);
+
+ dev = fz_new_draw_device(glyphcache, pix);
+ pdf_run_page(xref, page, dev, ctm);
+ fz_free_device(dev);
+
+ pdf_free_page(page);
+ pdf_age_store(xref->store, 3);
+ fz_flush_warnings();
+
+ return newImageWithPixmap(pix);
+}
+
#pragma mark -
@implementation MuLibraryController
@@ -411,6 +466,7 @@ static UIImage *renderPage(pdf_xref *xref, int number, CGSize screen)
- (void) dealloc
{
+ [tileView release];
[loadingView release];
[imageView release];
[super dealloc];
@@ -421,6 +477,22 @@ static UIImage *renderPage(pdf_xref *xref, int number, CGSize screen)
return number;
}
+- (void) resetZoomAnimated: (BOOL)animated
+{
+ // discard tile and any pending tile jobs
+ tileFrame = CGRectZero;
+ tileScale = 1;
+ if (tileView) {
+ [tileView removeFromSuperview];
+ [tileView release];
+ tileView = nil;
+ }
+
+ [self setMinimumZoomScale: 1];
+ [self setMaximumZoomScale: 5];
+ [self setZoomScale: 1 animated: animated];
+}
+
- (void) removeFromSuperview
{
cancel = YES;
@@ -445,13 +517,6 @@ static UIImage *renderPage(pdf_xref *xref, int number, CGSize screen)
});
}
-- (void) resetZoomAnimated: (BOOL)animated
-{
- [self setMinimumZoomScale: 1];
- [self setMaximumZoomScale: 3];
- [self setZoomScale: 1 animated: animated];
-}
-
- (void) displayImage: (UIImage*)image
{
if (loadingView) {
@@ -495,7 +560,6 @@ static UIImage *renderPage(pdf_xref *xref, int number, CGSize screen)
[self setContentSize: imageView.frame.size];
-// [self setNeedsLayout];
[self layoutIfNeeded];
}
}
@@ -540,6 +604,89 @@ static UIImage *renderPage(pdf_xref *xref, int number, CGSize screen)
return imageView;
}
+- (void) loadTile
+{
+ CGSize pageSize = self.bounds.size;
+
+ tileFrame.origin = self.contentOffset;
+ tileFrame.size = self.bounds.size;
+ tileFrame = CGRectIntersection(tileFrame, imageView.frame);
+ tileScale = self.zoomScale;
+
+ CGRect frame = tileFrame;
+ float scale = tileScale;
+
+ CGRect viewFrame = frame;
+ if (self.contentOffset.x < imageView.frame.origin.x)
+ viewFrame.origin.x = 0;
+ if (self.contentOffset.y < imageView.frame.origin.y)
+ viewFrame.origin.y = 0;
+
+ if (scale < 1.1)
+ return;
+
+ printf("queuing tile\n");
+
+ dispatch_async(queue, ^{
+ __block BOOL isValid;
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ isValid = CGRectEqualToRect(frame, tileFrame) && scale == tileScale;
+ });
+ if (!isValid) {
+ puts("cancel tile");
+ return;
+ }
+
+ UIImage *image = renderTile(xref, number, pageSize, viewFrame, scale);
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ isValid = CGRectEqualToRect(frame, tileFrame) && scale == tileScale;
+ if (isValid) {
+ tileFrame = CGRectZero;
+ tileScale = 1;
+ if (tileView) {
+ [tileView removeFromSuperview];
+ [tileView release];
+ tileView = nil;
+ }
+
+ tileView = [[UIImageView alloc] initWithFrame: frame];
+ [tileView setImage: image];
+ [self addSubview: tileView];
+ } else {
+ printf("discard tile\n");
+ }
+ [image release];
+ });
+ });
+}
+
+- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView { [self loadTile]; }
+- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { [self loadTile]; }
+- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { [self loadTile]; }
+- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
+{
+ if (!decelerate)
+ [self loadTile];
+}
+
+- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
+{
+ // discard tile and any pending tile jobs
+ tileFrame = CGRectZero;
+ tileScale = 1;
+ if (tileView) {
+ [tileView removeFromSuperview];
+ [tileView release];
+ tileView = nil;
+ }
+}
+
+- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
+{
+ [self loadTile];
+}
+
@end
#pragma mark -