summaryrefslogtreecommitdiff
path: root/ios
diff options
context:
space:
mode:
Diffstat (limited to 'ios')
-rw-r--r--ios/About.pdfbin131735 -> 0 bytes
-rw-r--r--ios/About.xpsbin0 -> 76673 bytes
-rw-r--r--ios/Info.plist4
-rw-r--r--ios/MuPDF.xcodeproj/project.pbxproj73
-rw-r--r--ios/build_libs.sh10
-rw-r--r--ios/document.c128
-rw-r--r--ios/document.h6
-rw-r--r--ios/main.m492
8 files changed, 572 insertions, 141 deletions
diff --git a/ios/About.pdf b/ios/About.pdf
deleted file mode 100644
index 763c467e..00000000
--- a/ios/About.pdf
+++ /dev/null
Binary files differ
diff --git a/ios/About.xps b/ios/About.xps
new file mode 100644
index 00000000..3fcec260
--- /dev/null
+++ b/ios/About.xps
Binary files differ
diff --git a/ios/Info.plist b/ios/Info.plist
index 116bacee..85213b7c 100644
--- a/ios/Info.plist
+++ b/ios/Info.plist
@@ -11,7 +11,7 @@
<key>CFBundleIconFiles</key>
<array/>
<key>CFBundleIdentifier</key>
- <string>com.artifex.${PRODUCT_NAME:rfc1034identifier}</string>
+ <string>com.artifex.mupdf</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -19,7 +19,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>0.9</string>
+ <string>0.9.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
diff --git a/ios/MuPDF.xcodeproj/project.pbxproj b/ios/MuPDF.xcodeproj/project.pbxproj
index 61542780..73fe67c6 100644
--- a/ios/MuPDF.xcodeproj/project.pbxproj
+++ b/ios/MuPDF.xcodeproj/project.pbxproj
@@ -8,19 +8,12 @@
/* Begin PBXBuildFile section */
9644E9A0146ACEC000E5B70A /* document.c in Sources */ = {isa = PBXBuildFile; fileRef = 9644E99E146ACEC000E5B70A /* document.c */; };
- 9683F619145F4F84000E1607 /* About.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 9683F618145F4F84000E1607 /* About.pdf */; };
+ 9668C8D91476A30200D7BA52 /* About.xps in Resources */ = {isa = PBXBuildFile; fileRef = 9668C8D81476A30200D7BA52 /* About.xps */; };
968F2E9C14539C880085264E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 968F2E9B14539C880085264E /* UIKit.framework */; };
968F2E9E14539C880085264E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 968F2E9D14539C880085264E /* Foundation.framework */; };
968F2EA014539C880085264E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 968F2E9F14539C880085264E /* CoreGraphics.framework */; };
968F2EB014539CDA0085264E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 968F2E9014539BEB0085264E /* main.m */; };
- 968F2EBB14539F350085264E /* libfitz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 968F2EB314539F350085264E /* libfitz.a */; };
- 968F2EBC14539F350085264E /* libfreetype.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 968F2EB414539F350085264E /* libfreetype.a */; };
- 968F2EBD14539F350085264E /* libjbig2dec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 968F2EB514539F350085264E /* libjbig2dec.a */; };
- 968F2EBE14539F350085264E /* libjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 968F2EB614539F350085264E /* libjpeg.a */; };
- 968F2EBF14539F350085264E /* libmupdf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 968F2EB714539F350085264E /* libmupdf.a */; };
- 968F2EC014539F350085264E /* libmuxps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 968F2EB814539F350085264E /* libmuxps.a */; };
- 968F2EC114539F350085264E /* libopenjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 968F2EB914539F350085264E /* libopenjpeg.a */; };
- 968F2EC214539F350085264E /* libz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 968F2EBA14539F350085264E /* libz.a */; };
+ 96A4739B147C1C3A003D757D /* libLibraries.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 968461E214642DB00012AE09 /* libLibraries.a */; };
96BD2B38145AC485001CEBC3 /* Icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 96BD2B35145AC485001CEBC3 /* Icon-72.png */; };
96BD2B39145AC485001CEBC3 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 96BD2B36145AC485001CEBC3 /* Icon.png */; };
96F2341514603FBA004A8A22 /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 96F2341414603FBA004A8A22 /* Icon@2x.png */; };
@@ -39,7 +32,7 @@
/* Begin PBXFileReference section */
9644E99E146ACEC000E5B70A /* document.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = document.c; sourceTree = "<group>"; };
9644E99F146ACEC000E5B70A /* document.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = document.h; sourceTree = "<group>"; };
- 9683F618145F4F84000E1607 /* About.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = About.pdf; sourceTree = "<group>"; };
+ 9668C8D81476A30200D7BA52 /* About.xps */ = {isa = PBXFileReference; lastKnownFileType = file; path = About.xps; sourceTree = "<group>"; };
968461E214642DB00012AE09 /* libLibraries.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libLibraries.a; sourceTree = BUILT_PRODUCTS_DIR; };
968F2E8E14539BEB0085264E /* build_libs.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build_libs.sh; sourceTree = "<group>"; };
968F2E8F14539BEB0085264E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -48,14 +41,6 @@
968F2E9B14539C880085264E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
968F2E9D14539C880085264E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
968F2E9F14539C880085264E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
- 968F2EB314539F350085264E /* libfitz.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libfitz.a; sourceTree = BUILT_PRODUCTS_DIR; };
- 968F2EB414539F350085264E /* libfreetype.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libfreetype.a; sourceTree = BUILT_PRODUCTS_DIR; };
- 968F2EB514539F350085264E /* libjbig2dec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libjbig2dec.a; sourceTree = BUILT_PRODUCTS_DIR; };
- 968F2EB614539F350085264E /* libjpeg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libjpeg.a; sourceTree = BUILT_PRODUCTS_DIR; };
- 968F2EB714539F350085264E /* libmupdf.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libmupdf.a; sourceTree = BUILT_PRODUCTS_DIR; };
- 968F2EB814539F350085264E /* libmuxps.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libmuxps.a; sourceTree = BUILT_PRODUCTS_DIR; };
- 968F2EB914539F350085264E /* libopenjpeg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libopenjpeg.a; sourceTree = BUILT_PRODUCTS_DIR; };
- 968F2EBA14539F350085264E /* libz.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libz.a; sourceTree = BUILT_PRODUCTS_DIR; };
96BD2B35145AC485001CEBC3 /* Icon-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72.png"; sourceTree = "<group>"; };
96BD2B36145AC485001CEBC3 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = "<group>"; };
96F2341414603FBA004A8A22 /* Icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon@2x.png"; sourceTree = "<group>"; };
@@ -69,14 +54,7 @@
968F2E9C14539C880085264E /* UIKit.framework in Frameworks */,
968F2E9E14539C880085264E /* Foundation.framework in Frameworks */,
968F2EA014539C880085264E /* CoreGraphics.framework in Frameworks */,
- 968F2EBB14539F350085264E /* libfitz.a in Frameworks */,
- 968F2EBC14539F350085264E /* libfreetype.a in Frameworks */,
- 968F2EBD14539F350085264E /* libjbig2dec.a in Frameworks */,
- 968F2EBE14539F350085264E /* libjpeg.a in Frameworks */,
- 968F2EBF14539F350085264E /* libmupdf.a in Frameworks */,
- 968F2EC014539F350085264E /* libmuxps.a in Frameworks */,
- 968F2EC114539F350085264E /* libopenjpeg.a in Frameworks */,
- 968F2EC214539F350085264E /* libz.a in Frameworks */,
+ 96A4739B147C1C3A003D757D /* libLibraries.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -86,7 +64,7 @@
968F2E9214539BF10085264E /* Sources */ = {
isa = PBXGroup;
children = (
- 9683F618145F4F84000E1607 /* About.pdf */,
+ 9668C8D81476A30200D7BA52 /* About.xps */,
96BD2B36145AC485001CEBC3 /* Icon.png */,
96F2341414603FBA004A8A22 /* Icon@2x.png */,
96BD2B35145AC485001CEBC3 /* Icon-72.png */,
@@ -118,26 +96,10 @@
name = Frameworks;
sourceTree = "<group>";
};
- 968F2EB214539F230085264E /* Libraries */ = {
- isa = PBXGroup;
- children = (
- 968F2EB314539F350085264E /* libfitz.a */,
- 968F2EB414539F350085264E /* libfreetype.a */,
- 968F2EB514539F350085264E /* libjbig2dec.a */,
- 968F2EB614539F350085264E /* libjpeg.a */,
- 968F2EB714539F350085264E /* libmupdf.a */,
- 968F2EB814539F350085264E /* libmuxps.a */,
- 968F2EB914539F350085264E /* libopenjpeg.a */,
- 968F2EBA14539F350085264E /* libz.a */,
- );
- name = Libraries;
- sourceTree = "<group>";
- };
96A3B27414539BAD00D0A895 = {
isa = PBXGroup;
children = (
968F2E9214539BF10085264E /* Sources */,
- 968F2EB214539F230085264E /* Libraries */,
968F2E9A14539C880085264E /* Frameworks */,
968F2E9814539C880085264E /* Products */,
);
@@ -212,8 +174,8 @@
files = (
96BD2B38145AC485001CEBC3 /* Icon-72.png in Resources */,
96BD2B39145AC485001CEBC3 /* Icon.png in Resources */,
- 9683F619145F4F84000E1607 /* About.pdf in Resources */,
96F2341514603FBA004A8A22 /* Icon@2x.png in Resources */,
+ 9668C8D91476A30200D7BA52 /* About.xps in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -228,14 +190,7 @@
inputPaths = (
);
outputPaths = (
- "$(DERIVED_FILE_DIR)/libmupdf.a",
- "$(DERIVED_FILE_DIR)/libfitz.a",
- "$(DERIVED_FILE_DIR)/libmuxps.a",
- "$(DERIVED_FILE_DIR)/libfreetype.a",
- "$(DERIVED_FILE_DIR)/libjbig2dec.a",
- "$(DERIVED_FILE_DIR)/libjpeg.a",
- "$(DERIVED_FILE_DIR)/libopenjpeg.a",
- "$(DERIVED_FILE_DIR)/libz.a",
+ "$(DERIVED_FILE_DIR)/libLibraries.a",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -269,9 +224,9 @@
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
- IPHONEOS_DEPLOYMENT_TARGET = 4.3;
PRODUCT_NAME = Libraries;
SDKROOT = iphoneos;
+ SKIP_INSTALL = YES;
};
name = Debug;
};
@@ -279,9 +234,9 @@
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
- IPHONEOS_DEPLOYMENT_TARGET = 4.3;
PRODUCT_NAME = Libraries;
SDKROOT = iphoneos;
+ SKIP_INSTALL = YES;
};
name = Release;
};
@@ -290,7 +245,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ CODE_SIGN_IDENTITY = "iPhone Distribution";
COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -309,9 +264,10 @@
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = ..;
INFOPLIST_FILE = Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 4.3;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.0;
LIBRARY_SEARCH_PATHS = "$(inherited)";
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
@@ -323,7 +279,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ CODE_SIGN_IDENTITY = "iPhone Distribution";
COPY_PHASE_STRIP = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -335,10 +291,11 @@
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = ..;
INFOPLIST_FILE = Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 4.3;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.0;
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
diff --git a/ios/build_libs.sh b/ios/build_libs.sh
index beea9cde..72c07ce0 100644
--- a/ios/build_libs.sh
+++ b/ios/build_libs.sh
@@ -24,10 +24,10 @@ export OUT=build/$build-$OS-$ARCHS
echo Building libraries for $ARCHS.
make -C .. libs || exit 1
-echo Copying files into $BUILT_PRODUCTS_DIR.
-
-mkdir -p "$BUILT_PRODUCTS_DIR"
-cp ../$OUT/lib*.a $BUILT_PRODUCTS_DIR
-ranlib $BUILT_PRODUCTS_DIR/lib*.a
+echo Assembling final library in $TARGET_BUILD_DIR/.
+mkdir -p "$TARGET_BUILD_DIR"
+rm -f $TARGET_BUILD_DIR/libLibraries.a
+ar cru $TARGET_BUILD_DIR/libLibraries.a ../$OUT/*.o
+ranlib $TARGET_BUILD_DIR/libLibraries.a
echo Done.
diff --git a/ios/document.c b/ios/document.c
index 6d30a0bc..ffb92519 100644
--- a/ios/document.c
+++ b/ios/document.c
@@ -3,6 +3,8 @@
#include "xps/muxps.h"
#include "document.h"
+#include <ctype.h> // for tolower()
+
struct document *
open_document(char *filename)
{
@@ -12,7 +14,7 @@ open_document(char *filename)
struct document *doc = fz_malloc(sizeof *doc);
memset(doc, 0, sizeof *doc);
doc->number = -1;
- error = pdf_open_xref(&doc->pdf, filename, "");
+ error = pdf_open_xref(&doc->pdf, filename, NULL);
if (error) {
fz_free(doc);
fz_rethrow(error, "cannot open pdf document");
@@ -43,6 +45,24 @@ open_document(char *filename)
}
}
+int
+needs_password(struct document *doc)
+{
+ if (doc->pdf) {
+ return pdf_needs_password(doc->pdf);
+ }
+ return 0;
+}
+
+int
+authenticate_password(struct document *doc, char *password)
+{
+ if (doc->pdf) {
+ return pdf_authenticate_password(doc->pdf, password);
+ }
+ return 1;
+}
+
fz_outline *
load_outline(struct document *doc)
{
@@ -78,7 +98,6 @@ load_page(struct document *doc, int number)
pdf_free_page(doc->pdf_page);
}
doc->pdf_page = NULL;
-printf("load pdf page %d\n", number);
error = pdf_load_page(&doc->pdf_page, doc->pdf, number);
if (error)
fz_catch(error, "cannot load page %d", number);
@@ -87,7 +106,6 @@ printf("load pdf page %d\n", number);
if (doc->xps_page)
xps_free_page(doc->xps, doc->xps_page);
doc->xps_page = NULL;
-printf("load xps page %d\n", number);
error = xps_load_page(&doc->xps_page, doc->xps, number);
if (error)
fz_catch(error, "cannot load page %d", number);
@@ -137,6 +155,110 @@ draw_page(struct document *doc, int number, fz_device *dev, fz_matrix ctm)
fz_flush_warnings();
}
+static int
+charat(fz_text_span *span, int idx)
+{
+ int ofs = 0;
+ while (span) {
+ if (idx < ofs + span->len)
+ return span->text[idx - ofs].c;
+ if (span->eol) {
+ if (idx == ofs + span->len)
+ return ' ';
+ ofs ++;
+ }
+ ofs += span->len;
+ span = span->next;
+ }
+ return 0;
+}
+
+static fz_bbox
+bboxat(fz_text_span *span, int idx)
+{
+ int ofs = 0;
+ while (span) {
+ if (idx < ofs + span->len)
+ return span->text[idx - ofs].bbox;
+ if (span->eol) {
+ if (idx == ofs + span->len)
+ return fz_empty_bbox;
+ ofs ++;
+ }
+ ofs += span->len;
+ span = span->next;
+ }
+ return fz_empty_bbox;
+}
+
+static int
+textlen(fz_text_span *span)
+{
+ int len = 0;
+ while (span) {
+ len += span->len;
+ if (span->eol)
+ len ++;
+ span = span->next;
+ }
+ return len;
+}
+
+static int
+match(fz_text_span *span, char *s, int n)
+{
+ int start = n, c;
+ while (*s) {
+ s += chartorune(&c, s);
+ if (c == ' ' && charat(span, n) == ' ') {
+ while (charat(span, n) == ' ')
+ n++;
+ } else {
+ if (tolower(c) != tolower(charat(span, n)))
+ return 0;
+ n++;
+ }
+ }
+ return n - start;
+}
+
+int
+search_page(struct document *doc, int number, char *needle)
+{
+ int pos, len, i, n;
+
+ if (strlen(needle) == 0)
+ return 0;
+
+ fz_text_span *text = fz_new_text_span();
+ fz_device *dev = fz_new_text_device(text);
+ draw_page(doc, number, dev, fz_identity);
+ fz_free_device(dev);
+
+ doc->hit_count = 0;
+
+ len = textlen(text);
+ for (pos = 0; pos < len; pos++) {
+ n = match(text, needle, pos);
+ if (n) {
+ for (i = 0; i < n; i++) {
+ fz_bbox r = bboxat(text, pos + i);
+ if (!fz_is_empty_bbox(r) && doc->hit_count < nelem(doc->hit_bbox))
+ doc->hit_bbox[doc->hit_count++] = r;
+ }
+ }
+ }
+
+ fz_free_text_span(text);
+ return doc->hit_count;
+}
+
+fz_bbox
+search_result_bbox(struct document *doc, int i)
+{
+ return doc->hit_bbox[i];
+}
+
void
close_document(struct document *doc)
{
diff --git a/ios/document.h b/ios/document.h
index 1f59ccdd..797b1e8f 100644
--- a/ios/document.h
+++ b/ios/document.h
@@ -20,13 +20,19 @@ struct document
int number;
pdf_page *pdf_page;
xps_page *xps_page;
+ fz_bbox hit_bbox[500];
+ int hit_count;
};
struct document *open_document(char *filename);
+int needs_password(struct document *doc);
+int authenticate_password(struct document *doc, char *password);
fz_outline *load_outline(struct document *doc);
int count_pages(struct document *doc);
void measure_page(struct document *doc, int number, float *w, float *h);
void draw_page(struct document *doc, int number, fz_device *dev, fz_matrix ctm);
+int search_page(struct document *doc, int number, char *needle);
+fz_bbox search_result_bbox(struct document *doc, int i);
void close_document(struct document *doc);
#endif
diff --git a/ios/main.m b/ios/main.m
index 3a6a45f3..7b977928 100644
--- a/ios/main.m
+++ b/ios/main.m
@@ -12,6 +12,8 @@
#define GAP 20
#define INDICATOR_Y -44-24
+#define SLIDER_W (width - GAP - 24)
+#define SEARCH_W (width - GAP - 170)
static dispatch_queue_t queue;
static fz_glyph_cache *glyphcache = NULL;
@@ -21,8 +23,13 @@ static float screenScale = 1;
{
NSArray *files;
NSTimer *timer;
+ struct document *_doc; // temporaries for juggling password dialog
+ NSString *_filename;
}
- (void) openDocument: (NSString*)filename;
+- (void) askForPassword: (NSString*)prompt;
+- (void) onPasswordOkay;
+- (void) onPasswordCancel;
- (void) reload;
@end
@@ -35,6 +42,16 @@ static float screenScale = 1;
- (id) initWithTarget: (id)aTarget titles: (NSMutableArray*)aTitles pages: (NSMutableArray*)aPages;
@end
+@interface MuHitView : UIView
+{
+ CGSize pageSize;
+ int hitCount;
+ CGRect hitRects[500];
+}
+- (id) initWithSearchResults: (int)n forDocument: (struct document *)doc;
+- (void) setPageSize: (CGSize)s;
+@end
+
@interface MuPageView : UIScrollView <UIScrollViewDelegate>
{
struct document *doc;
@@ -42,6 +59,8 @@ static float screenScale = 1;
UIActivityIndicatorView *loadingView;
UIImageView *imageView;
UIImageView *tileView;
+ MuHitView *hitView;
+ CGSize pageSize;
CGRect tileFrame;
float tileScale;
BOOL cancel;
@@ -53,29 +72,37 @@ static float screenScale = 1;
- (void) loadTile;
- (void) willRotate;
- (void) resetZoomAnimated: (BOOL)animated;
+- (void) showSearchResults: (int)count;
+- (void) clearSearchResults;
- (int) number;
@end
-@interface MuDocumentController : UIViewController <UIScrollViewDelegate, UIGestureRecognizerDelegate>
+@interface MuDocumentController : UIViewController <UIScrollViewDelegate, UISearchBarDelegate>
{
struct document *doc;
NSString *key;
- NSMutableSet *visiblePages;
- NSMutableSet *recycledPages;
MuOutlineController *outline;
UIScrollView *canvas;
UILabel *indicator;
UISlider *slider;
- UIBarButtonItem *wrapper; // for slider
+ UISearchBar *searchBar;
+ UIBarButtonItem *nextButton, *prevButton, *cancelButton, *searchButton, *outlineButton;
+ UIBarButtonItem *sliderWrapper;
+ int searchPage;
+ int cancelSearch;
int width; // current screen size
int height;
int current; // currently visible page
int scroll_animating; // stop view updates during scrolling animations
}
-- (id) initWithFile: (NSString*)filename;
+- (id) initWithFilename: (NSString*)nsfilename document: (struct document *)aDoc;
- (void) createPageView: (int)number;
- (void) gotoPage: (int)number animated: (BOOL)animated;
- (void) onShowOutline: (id)sender;
+- (void) onShowSearch: (id)sender;
+- (void) onCancelSearch: (id)sender;
+- (void) resetSearch;
+- (void) showSearchResults: (int)count forPage: (int)number;
- (void) onSlide: (id)sender;
- (void) onTap: (UITapGestureRecognizer*)sender;
- (void) showNavigationBar;
@@ -147,15 +174,16 @@ static void releasePixmap(void *info, const void *data, size_t size)
static UIImage *newImageWithPixmap(fz_pixmap *pix)
{
CGDataProviderRef cgdata = CGDataProviderCreateWithData(pix, pix->samples, pix->w * 4 * pix->h, releasePixmap);
+ CGColorSpaceRef cgcolor = CGColorSpaceCreateDeviceRGB();
CGImageRef cgimage = CGImageCreate(pix->w, pix->h, 8, 32, 4 * pix->w,
- CGColorSpaceCreateDeviceRGB(),
- kCGBitmapByteOrderDefault,
+ cgcolor, kCGBitmapByteOrderDefault,
cgdata, NULL, NO, kCGRenderingIntentDefault);
UIImage *image = [[UIImage alloc]
initWithCGImage: cgimage
scale: screenScale
orientation: UIImageOrientationUp];
CGDataProviderRelease(cgdata);
+ CGColorSpaceRelease(cgcolor);
CGImageRelease(cgimage);
return image;
}
@@ -170,6 +198,13 @@ static CGSize fitPageToScreen(CGSize page, CGSize screen)
return CGSizeMake(hscale, vscale);
}
+static CGSize measurePage(struct document *doc, int number)
+{
+ CGSize pageSize;
+ measure_page(doc, number, &pageSize.width, &pageSize.height);
+ return pageSize;
+}
+
static UIImage *renderPage(struct document *doc, int number, CGSize screenSize)
{
CGSize pageSize;
@@ -317,19 +352,81 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
{
int row = [indexPath row];
if (row == 0)
- [self openDocument: @"../MuPDF.app/About.pdf"];
+ [self openDocument: @"../MuPDF.app/About.xps"];
else
[self openDocument: [files objectAtIndex: row - 1]];
}
-- (void) openDocument: (NSString*)filename
+- (void) openDocument: (NSString*)nsfilename
{
- MuDocumentController *document = [[MuDocumentController alloc] initWithFile: filename];
+ char filename[PATH_MAX];
+
+ dispatch_sync(queue, ^{});
+
+ strcpy(filename, [NSHomeDirectory() UTF8String]);
+ strcat(filename, "/Documents/");
+ strcat(filename, [nsfilename UTF8String]);
+
+ printf("open document '%s'\n", filename);
+
+ _filename = [nsfilename retain];
+ _doc = open_document(filename);
+ if (!_doc) {
+ showAlert(@"Cannot open document");
+ return;
+ }
+
+ if (needs_password(_doc))
+ [self askForPassword: @"'%@' needs a password:"];
+ else
+ [self onPasswordOkay];
+}
+
+- (void) askForPassword: (NSString*)prompt
+{
+ UIAlertView *passwordAlertView = [[UIAlertView alloc]
+ initWithTitle: @"Password Protected"
+ message: [NSString stringWithFormat: prompt, [_filename lastPathComponent]]
+ delegate: self
+ cancelButtonTitle: @"Cancel"
+ otherButtonTitles: @"Done", nil];
+ [passwordAlertView setAlertViewStyle: UIAlertViewStyleSecureTextInput];
+ [passwordAlertView show];
+ [passwordAlertView release];
+}
+
+- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
+{
+ char *password = (char*) [[[alertView textFieldAtIndex: 0] text] UTF8String];
+ [alertView dismissWithClickedButtonIndex: buttonIndex animated: TRUE];
+ if (buttonIndex == 1) {
+ if (authenticate_password(_doc, password))
+ [self onPasswordOkay];
+ else
+ [self askForPassword: @"Wrong password for '%@'. Try again:"];
+ } else {
+ [self onPasswordCancel];
+ }
+}
+
+- (void) onPasswordOkay
+{
+ MuDocumentController *document = [[MuDocumentController alloc] initWithFilename: _filename document: _doc];
if (document) {
[self setTitle: @"Library"];
[[self navigationController] pushViewController: document animated: YES];
[document release];
}
+ [_filename release];
+ _doc = NULL;
+}
+
+- (void) onPasswordCancel
+{
+ [_filename release];
+ printf("close document (password cancel)\n");
+ close_document(_doc);
+ _doc = NULL;
}
@end
@@ -404,6 +501,53 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
#pragma mark -
+@implementation MuHitView
+
+- (id) initWithSearchResults: (int)n forDocument: (struct document *)doc
+{
+ self = [super initWithFrame: CGRectMake(0,0,100,100)];
+ if (self) {
+ [self setOpaque: NO];
+
+ pageSize = CGSizeMake(100,100);
+
+ for (int i = 0; i < n && i < nelem(hitRects); i++) {
+ fz_bbox bbox = search_result_bbox(doc, i); // this is thread-safe enough
+ hitRects[i].origin.x = bbox.x0;
+ hitRects[i].origin.y = bbox.y0;
+ hitRects[i].size.width = bbox.x1 - bbox.x0;
+ hitRects[i].size.height = bbox.y1 - bbox.y0;
+ }
+ hitCount = n;
+ }
+ return self;
+}
+
+- (void) setPageSize: (CGSize)s
+{
+ pageSize = s;
+ // if page takes a long time to load we may have drawn at the initial (wrong) size
+ [self setNeedsDisplay];
+}
+
+- (void) drawRect: (CGRect)r
+{
+ CGSize scale = fitPageToScreen(pageSize, self.bounds.size);
+
+ [[UIColor colorWithRed: 0.3 green: 0.3 blue: 1 alpha: 0.5] set];
+
+ for (int i = 0; i < hitCount; i++) {
+ CGRect rect = hitRects[i];
+ rect.origin.x *= scale.width;
+ rect.origin.y *= scale.height;
+ rect.size.width *= scale.width;
+ rect.size.height *= scale.height;
+ UIRectFill(rect);
+ }
+}
+
+@end
+
@implementation MuPageView
- (id) initWithFrame: (CGRect)frame document: (struct document*)aDoc page: (int)aNumber
@@ -444,6 +588,7 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
__block id block_self = self; // don't auto-retain self!
dispatch_async(dispatch_get_main_queue(), ^{ [block_self dealloc]; });
} else {
+ [hitView release];
[tileView release];
[loadingView release];
[imageView release];
@@ -456,6 +601,30 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
return number;
}
+- (void) showSearchResults: (int)count
+{
+ if (hitView) {
+ [hitView removeFromSuperview];
+ [hitView release];
+ hitView = nil;
+ }
+ hitView = [[MuHitView alloc] initWithSearchResults: count forDocument: doc];
+ if (imageView) {
+ [hitView setFrame: [imageView frame]];
+ [hitView setPageSize: pageSize];
+ }
+ [self addSubview: hitView];
+}
+
+- (void) clearSearchResults
+{
+ if (hitView) {
+ [hitView removeFromSuperview];
+ [hitView release];
+ hitView = nil;
+ }
+}
+
- (void) resetZoomAnimated: (BOOL)animated
{
// discard tile and any pending tile jobs
@@ -485,8 +654,10 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
dispatch_async(queue, ^{
if (!cancel) {
printf("render page %d\n", number);
+ CGSize size = measurePage(doc, number);
UIImage *image = renderPage(doc, number, self.bounds.size);
dispatch_async(dispatch_get_main_queue(), ^{
+ pageSize = size;
[self displayImage: image];
[image release];
});
@@ -504,10 +675,15 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
loadingView = nil;
}
+ if (hitView)
+ [hitView setPageSize: pageSize];
+
if (!imageView) {
imageView = [[UIImageView alloc] initWithImage: image];
imageView.opaque = YES;
[self addSubview: imageView];
+ if (hitView)
+ [self bringSubviewToFront: hitView];
} else {
[imageView setImage: image];
}
@@ -530,7 +706,7 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
dispatch_async(queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
CGSize scale = fitPageToScreen(imageView.image.size, self.bounds.size);
- if (fabs(scale.width - 1) > 0.1)
+ if (fabs(scale.width - 1) > 0.01)
[self loadPage];
});
});
@@ -542,6 +718,7 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
[self layoutIfNeeded];
}
+
}
- (void) willRotate
@@ -577,6 +754,9 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
loadingView.frame = frameToCenter;
else
imageView.frame = frameToCenter;
+
+ if (hitView && imageView)
+ [hitView setFrame: [imageView frame]];
}
- (UIView*) viewForZoomingInScrollView: (UIScrollView*)scrollView
@@ -586,7 +766,7 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
- (void) loadTile
{
- CGSize pageSize = self.bounds.size;
+ CGSize screenSize = self.bounds.size;
tileFrame.origin = self.contentOffset;
tileFrame.size = self.bounds.size;
@@ -616,7 +796,7 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
}
printf("render tile\n");
- UIImage *image = renderTile(doc, number, pageSize, viewFrame, scale);
+ UIImage *image = renderTile(doc, number, screenSize, viewFrame, scale);
dispatch_async(dispatch_get_main_queue(), ^{
isValid = CGRectEqualToRect(frame, tileFrame) && scale == tileScale;
@@ -632,6 +812,8 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
tileView = [[UIImageView alloc] initWithFrame: frame];
[tileView setImage: image];
[self addSubview: tileView];
+ if (hitView)
+ [self bringSubviewToFront: hitView];
} else {
printf("discard tile\n");
}
@@ -666,53 +848,40 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
[self loadTile];
}
+- (void) scrollViewDidZoom: (UIScrollView*)scrollView
+{
+ if (hitView && imageView)
+ [hitView setFrame: [imageView frame]];
+}
+
@end
#pragma mark -
@implementation MuDocumentController
-- (id) initWithFile: (NSString*)nsfilename
+- (id) initWithFilename: (NSString*)filename document: (struct document *)aDoc
{
- char filename[PATH_MAX];
-
self = [super init];
if (!self)
return nil;
- key = [nsfilename retain];
+ key = [filename retain];
+ doc = aDoc;
dispatch_sync(queue, ^{});
- strcpy(filename, [NSHomeDirectory() UTF8String]);
- strcat(filename, "/Documents/");
- strcat(filename, [nsfilename UTF8String]);
-
- printf("open document '%s'\n", filename);
-
- doc = open_document(filename);
- if (!doc) {
- showAlert(@"Cannot open document");
- [self release];
- return nil;
- }
-
- NSMutableArray *titles = [[NSMutableArray alloc] init];
- NSMutableArray *pages = [[NSMutableArray alloc] init];
fz_outline *root = load_outline(doc);
if (root) {
+ NSMutableArray *titles = [[NSMutableArray alloc] init];
+ NSMutableArray *pages = [[NSMutableArray alloc] init];
flattenOutline(titles, pages, root, 0);
+ if ([titles count])
+ outline = [[MuOutlineController alloc] initWithTarget: self titles: titles pages: pages];
+ [titles release];
+ [pages release];
fz_free_outline(root);
}
- if ([titles count]) {
- outline = [[MuOutlineController alloc] initWithTarget: self titles: titles pages: pages];
- [[self navigationItem] setRightBarButtonItem:
- [[UIBarButtonItem alloc]
- initWithBarButtonSystemItem: UIBarButtonSystemItemBookmarks
- target:self action:@selector(onShowOutline:)]];
- }
- [titles release];
- [pages release];
return self;
}
@@ -729,9 +898,6 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
[view setAutoresizingMask: UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[view setAutoresizesSubviews: YES];
- visiblePages = [[NSMutableSet alloc] init];
- recycledPages = [[NSMutableSet alloc] init];
-
canvas = [[UIScrollView alloc] initWithFrame: CGRectMake(0,0,GAP,0)];
[canvas setAutoresizingMask: UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[canvas setPagingEnabled: YES];
@@ -752,31 +918,56 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
[indicator setBackgroundColor: [[UIColor blackColor] colorWithAlphaComponent: 0.5]];
[indicator setTextColor: [UIColor whiteColor]];
+ [view addSubview: canvas];
+ [view addSubview: indicator];
+
slider = [[UISlider alloc] initWithFrame: CGRectZero];
[slider setMinimumValue: 0];
[slider setMaximumValue: count_pages(doc) - 1];
[slider addTarget: self action: @selector(onSlide:) forControlEvents: UIControlEventValueChanged];
- [view addSubview: canvas];
- [view addSubview: indicator];
+ sliderWrapper = [[UIBarButtonItem alloc] initWithCustomView: slider];
- wrapper = [[UIBarButtonItem alloc] initWithCustomView: slider];
- [self setToolbarItems: [NSArray arrayWithObjects: wrapper, nil]];
+ [self setToolbarItems: [NSArray arrayWithObjects: sliderWrapper, nil]];
+
+ // Set up the buttons on the navigation and search bar
+
+ if (outline) {
+ outlineButton = [[UIBarButtonItem alloc]
+ initWithBarButtonSystemItem: UIBarButtonSystemItemBookmarks
+ target:self action:@selector(onShowOutline:)];
+ }
+ cancelButton = [[UIBarButtonItem alloc]
+ initWithTitle: @"Cancel" style: UIBarButtonItemStyleBordered
+ target:self action:@selector(onCancelSearch:)];
+ searchButton = [[UIBarButtonItem alloc]
+ initWithBarButtonSystemItem: UIBarButtonSystemItemSearch
+ target:self action:@selector(onShowSearch:)];
+ prevButton = [[UIBarButtonItem alloc]
+ initWithBarButtonSystemItem: UIBarButtonSystemItemRewind
+ target:self action:@selector(onSearchPrev:)];
+ nextButton = [[UIBarButtonItem alloc]
+ initWithBarButtonSystemItem: UIBarButtonSystemItemFastForward
+ target:self action:@selector(onSearchNext:)];
+
+ searchBar = [[UISearchBar alloc] initWithFrame: CGRectMake(0,0,50,32)];
+ [searchBar setPlaceholder: @"Search"];
+ [searchBar setDelegate: self];
+ // HACK to make transparent background
+ [[searchBar.subviews objectAtIndex:0] removeFromSuperview];
+
+ [prevButton setEnabled: NO];
+ [nextButton setEnabled: NO];
+
+ [[self navigationItem] setRightBarButtonItems:
+ [NSArray arrayWithObjects: searchButton, outlineButton, nil]];
+
+ // TODO: add activityindicator to search bar
[self setView: view];
[view release];
}
-- (void) viewDidUnload
-{
- [visiblePages release]; visiblePages = nil;
- [recycledPages release]; recycledPages = nil;
- [indicator release]; indicator = nil;
- [slider release]; slider = nil;
- [wrapper release]; wrapper = nil;
- [canvas release]; canvas = nil;
-}
-
- (void) dealloc
{
if (doc) {
@@ -786,6 +977,18 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
close_document(self_doc);
});
}
+
+ [indicator release]; indicator = nil;
+ [slider release]; slider = nil;
+ [sliderWrapper release]; sliderWrapper = nil;
+ [searchBar release]; searchBar = nil;
+ [outlineButton release]; outlineButton = nil;
+ [searchButton release]; searchButton = nil;
+ [cancelButton release]; cancelButton = nil;
+ [prevButton release]; prevButton = nil;
+ [nextButton release]; nextButton = nil;
+ [canvas release]; canvas = nil;
+
[outline release];
[key release];
[super dealloc];
@@ -807,7 +1010,8 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
[canvas setContentSize: CGSizeMake(count_pages(doc) * width, height)];
[canvas setContentOffset: CGPointMake(current * width, 0)];
- [wrapper setWidth: width - GAP - 24];
+ [sliderWrapper setWidth: SLIDER_W];
+ [searchBar setFrame: CGRectMake(0,0,SEARCH_W,32)];
[[self navigationController] setToolbarHidden: NO animated: animated];
}
@@ -844,6 +1048,8 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
- (void) hideNavigationBar
{
if (![[self navigationController] isNavigationBarHidden]) {
+ [searchBar resignFirstResponder];
+
[UIView beginAnimations: @"MuNavBar" context: NULL];
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector: @selector(onHideNavigationBarFinished)];
@@ -868,6 +1074,139 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
[[self navigationController] pushViewController: outline animated: YES];
}
+- (void) onShowSearch: (id)sender
+{
+ [[self navigationItem] setTitleView: searchBar];
+ [[self navigationItem] setRightBarButtonItems:
+ [NSArray arrayWithObjects: nextButton, prevButton, nil]];
+ [[self navigationItem] setLeftBarButtonItem: cancelButton];
+ [searchBar becomeFirstResponder];
+}
+
+- (void) onCancelSearch: (id)sender
+{
+ cancelSearch = YES;
+ [searchBar resignFirstResponder];
+ [[self navigationItem] setTitleView: nil];
+ [[self navigationItem] setRightBarButtonItems:
+ [NSArray arrayWithObjects: searchButton, outlineButton, nil]];
+ [[self navigationItem] setLeftBarButtonItem: nil];
+ [self resetSearch];
+}
+
+- (void) resetSearch
+{
+ searchPage = -1;
+ for (MuPageView *view in [canvas subviews])
+ [view clearSearchResults];
+}
+
+- (void) showSearchResults: (int)count forPage: (int)number
+{
+ printf("search found match on page %d\n", number);
+ searchPage = number;
+ [self gotoPage: number animated: NO];
+ for (MuPageView *view in [canvas subviews])
+ if ([view number] == number)
+ [view showSearchResults: count];
+ else
+ [view clearSearchResults];
+}
+
+- (void) searchInDirection: (int)dir
+{
+ UITextField *searchField;
+ char *needle;
+ int start;
+
+ [searchBar resignFirstResponder];
+
+ if (searchPage == current)
+ start = current + dir;
+ else
+ start = current;
+
+ needle = strdup([[searchBar text] UTF8String]);
+
+ searchField = nil;
+ for (id view in [searchBar subviews])
+ if ([view isKindOfClass: [UITextField class]])
+ searchField = view;
+
+ [prevButton setEnabled: NO];
+ [nextButton setEnabled: NO];
+ [searchField setEnabled: NO];
+
+ cancelSearch = NO;
+
+ dispatch_async(queue, ^{
+ for (int i = start; i >= 0 && i < count_pages(doc); i += dir) {
+ int n = search_page(doc, i, needle);
+ if (n) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [prevButton setEnabled: YES];
+ [nextButton setEnabled: YES];
+ [searchField setEnabled: YES];
+ [self showSearchResults: n forPage: i];
+ free(needle);
+ });
+ return;
+ }
+ if (cancelSearch) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [prevButton setEnabled: YES];
+ [nextButton setEnabled: YES];
+ [searchField setEnabled: YES];
+ free(needle);
+ });
+ return;
+ }
+ }
+ dispatch_async(dispatch_get_main_queue(), ^{
+ printf("no search results found\n");
+ [prevButton setEnabled: YES];
+ [nextButton setEnabled: YES];
+ [searchField setEnabled: YES];
+ UIAlertView *alert = [[UIAlertView alloc]
+ initWithTitle: @"No matches found for:"
+ message: [NSString stringWithUTF8String: needle]
+ delegate: nil
+ cancelButtonTitle: @"Close"
+ otherButtonTitles: nil];
+ [alert show];
+ [alert release];
+ free(needle);
+ });
+ });
+}
+
+- (void) onSearchPrev: (id)sender
+{
+ [self searchInDirection: -1];
+}
+
+- (void) onSearchNext: (id)sender
+{
+ [self searchInDirection: 1];
+}
+
+- (void) searchBarSearchButtonClicked: (UISearchBar*)sender
+{
+ [self onSearchNext: sender];
+}
+
+- (void) searchBar: (UISearchBar*)sender textDidChange: (NSString*)searchText
+{
+ [self resetSearch];
+ if ([[searchBar text] length] > 0) {
+ [prevButton setEnabled: YES];
+ [nextButton setEnabled: YES];
+ } else {
+ [prevButton setEnabled: NO];
+ [nextButton setEnabled: NO];
+ }
+}
+
- (void) onSlide: (id)sender
{
int number = [slider value];
@@ -918,22 +1257,26 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
[indicator setText: [NSString stringWithFormat: @" %d of %d ", current+1, count_pages(doc)]];
[slider setValue: current];
- // swap the page views in and out
+ // swap the distant page views out
- for (MuPageView *view in visiblePages) {
+ NSMutableSet *invisiblePages = [[NSMutableSet alloc] init];
+ for (MuPageView *view in [canvas subviews]) {
if ([view number] != current)
[view resetZoomAnimated: YES];
- if ([view number] < current - 2 || [view number] > current + 2) {
- [recycledPages addObject: view];
- [view removeFromSuperview];
- }
+ if ([view number] < current - 2 || [view number] > current + 2)
+ [invisiblePages addObject: view];
}
- [visiblePages minusSet: recycledPages];
- [recycledPages removeAllObjects]; // don't bother recycling them...
+ for (MuPageView *view in invisiblePages)
+ [view removeFromSuperview];
+ [invisiblePages release]; // don't bother recycling them...
[self createPageView: current];
[self createPageView: current - 1];
[self createPageView: current + 1];
+
+ // reset search results when page has flipped
+ if (current != searchPage)
+ [self resetSearch];
}
- (void) createPageView: (int)number
@@ -946,7 +1289,6 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
found = 1;
if (!found) {
MuPageView *view = [[MuPageView alloc] initWithFrame: CGRectMake(number * width, 0, width-GAP, height) document: doc page: number];
- [visiblePages addObject: view];
[canvas addSubview: view];
[view release];
}
@@ -958,6 +1300,8 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
number = 0;
if (number >= count_pages(doc))
number = count_pages(doc) - 1;
+ if (current == number)
+ return;
if (animated) {
// setContentOffset:animated: does not use the normal animation
// framework. It also doesn't play nice with the tap gesture
@@ -973,7 +1317,7 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector: @selector(onGotoPageFinished)];
- for (MuPageView *view in visiblePages)
+ for (MuPageView *view in [canvas subviews])
[view resetZoomAnimated: NO];
[canvas setContentOffset: CGPointMake(number * width, 0)];
@@ -982,7 +1326,7 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
[UIView commitAnimations];
} else {
- for (MuPageView *view in visiblePages)
+ for (MuPageView *view in [canvas subviews])
[view resetZoomAnimated: NO];
[canvas setContentOffset: CGPointMake(number * width, 0)];
}
@@ -1008,20 +1352,22 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
width = size.width;
height = size.height;
- [wrapper setWidth: width - GAP - 24];
+ [sliderWrapper setWidth: SLIDER_W];
+ [searchBar setFrame: CGRectMake(0,0,SEARCH_W,32)];
+
[[[self navigationController] toolbar] setNeedsLayout]; // force layout!
// use max_width so we don't clamp the content offset too early during animation
[canvas setContentSize: CGSizeMake(count_pages(doc) * max_width, height)];
[canvas setContentOffset: CGPointMake(current * width, 0)];
- for (MuPageView *view in visiblePages) {
+ for (MuPageView *view in [canvas subviews]) {
if ([view number] == current) {
[view setFrame: CGRectMake([view number] * width, 0, width-GAP, height)];
[view willRotate];
}
}
- for (MuPageView *view in visiblePages) {
+ for (MuPageView *view in [canvas subviews]) {
if ([view number] != current) {
[view setFrame: CGRectMake([view number] * width, 0, width-GAP, height)];
[view willRotate];