├── .gitignore ├── .travis.yml ├── Classes ├── RoboAppDelegate.h ├── RoboAppDelegate.m ├── RoboDemoController.h └── RoboDemoController.m ├── Default-568h@2x.png ├── Graphics ├── AppIcon72.png ├── icon_1024.png ├── icon_144.png ├── icon_29.png ├── icon_50.png ├── icon_512.png └── icon_72.png ├── LICENSE ├── README.md ├── Resources ├── RoboReader-Info.plist ├── RoboReader-Prefix.pch ├── f5_newspaper.pdf └── main.m ├── RoboReader.podspec ├── RoboReader.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ ├── MacBook.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ ├── mac.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings │ │ └── vaivaikitay.xcuserdatad │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ ├── MacBook.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints.xcbkptlist │ └── xcschemes │ │ ├── RoboReader.xcscheme │ │ └── xcschememanagement.plist │ ├── mac.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints.xcbkptlist │ └── xcschemes │ │ ├── Reader.xcscheme │ │ └── xcschememanagement.plist │ └── vaivaikitay.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── RoboReader.xcscheme │ └── xcschememanagement.plist └── RoboReader ├── Classes ├── CGPDFDocument.h ├── CGPDFDocument.m ├── PDFPageConverter.h ├── PDFPageConverter.m ├── PDFPageRenderer.h ├── PDFPageRenderer.m ├── RoboConstants.h ├── RoboConstants.m ├── RoboContentView.h ├── RoboContentView.m ├── RoboDocument.h ├── RoboDocument.m ├── RoboMainPagebar.h ├── RoboMainPagebar.m ├── RoboMainToolbar.h ├── RoboMainToolbar.m ├── RoboPDFController.h ├── RoboPDFController.m ├── RoboPDFModel.h ├── RoboPDFModel.m ├── RoboReader.h ├── RoboViewController.h └── RoboViewController.m └── Graphics ├── Stroke2px.png ├── Stroke2px@2x.png ├── Stroke2px_single.png ├── Stroke2px_single@2x.png ├── X.png ├── X@2x.png ├── back_button.png ├── back_button@2x.png ├── nav_bar_plashka.png ├── nav_bar_plashka@2x.png ├── page-bg.png ├── page-bg@2x.png ├── page_left.png ├── page_left@2x.png ├── page_right.png ├── page_right@2x.png ├── progress_bar.png └── progress_bar@2x.png /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | */build/* 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | .idea/ 20 | *.hmap 21 | *.xccheckout 22 | 23 | # CocoaPods 24 | Pods 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c -------------------------------------------------------------------------------- /Classes/RoboAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "RoboDemoController.h" 23 | 24 | @interface RoboAppDelegate : NSObject { 25 | @private 26 | 27 | UIWindow *mainWindow; 28 | 29 | UINavigationController *navigationController; 30 | 31 | RoboDemoController *roboDemoController; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Classes/RoboAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "RoboAppDelegate.h" 23 | 24 | @implementation RoboAppDelegate 25 | 26 | 27 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 28 | 29 | 30 | mainWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 31 | 32 | mainWindow.backgroundColor = [UIColor blackColor]; // Window background color 33 | 34 | roboDemoController = [[RoboDemoController alloc] initWithNibName:nil bundle:nil]; 35 | 36 | navigationController = [[UINavigationController alloc] initWithRootViewController:roboDemoController]; 37 | 38 | navigationController.navigationBar.hidden = YES; 39 | 40 | mainWindow.rootViewController = navigationController; 41 | 42 | [mainWindow makeKeyAndVisible]; 43 | 44 | return YES; 45 | } 46 | 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Classes/RoboDemoController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "RoboReader.h" 23 | 24 | @interface RoboDemoController : UIViewController 25 | @end 26 | -------------------------------------------------------------------------------- /Classes/RoboDemoController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "RoboDemoController.h" 23 | 24 | @implementation RoboDemoController 25 | { 26 | RoboViewController *roboViewController; 27 | } 28 | 29 | - (void)viewDidLoad { 30 | 31 | [super viewDidLoad]; 32 | 33 | self.view.backgroundColor = [UIColor blackColor]; 34 | 35 | UILabel *tapLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 220.0f, 100.0f)]; 36 | 37 | tapLabel.text = @"PRESS..."; 38 | tapLabel.textColor = [UIColor whiteColor]; 39 | tapLabel.textAlignment = NSTextAlignmentCenter; 40 | tapLabel.backgroundColor = [UIColor clearColor]; 41 | tapLabel.font = [UIFont systemFontOfSize:48.0f]; 42 | tapLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin; 43 | tapLabel.autoresizingMask |= UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; 44 | tapLabel.center = self.view.center; 45 | [self.view addSubview:tapLabel]; 46 | 47 | UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; 48 | [self.view addGestureRecognizer:singleTap]; 49 | } 50 | 51 | 52 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 53 | 54 | return YES; 55 | 56 | } 57 | 58 | 59 | - (void)handleSingleTap:(UITapGestureRecognizer *)recognizer { 60 | 61 | NSString *password = @""; 62 | 63 | NSString *filePath = [[NSBundle mainBundle] pathForResource:@"f5_newspaper" ofType:@"pdf"]; 64 | 65 | assert(filePath != nil); 66 | 67 | RoboDocument *document = [RoboDocument withDocumentFilePath:filePath password:password]; 68 | 69 | if (document != nil) { 70 | roboViewController = [[RoboViewController alloc] initWithRoboDocument:document]; 71 | 72 | roboViewController.delegate = self; 73 | 74 | [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide]; 75 | 76 | [self.navigationController pushViewController:roboViewController animated:YES]; 77 | 78 | 79 | } 80 | } 81 | 82 | 83 | - (void)dismissRoboViewController:(RoboViewController *)viewController { 84 | 85 | [self.navigationController popViewControllerAnimated:YES]; 86 | 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/Default-568h@2x.png -------------------------------------------------------------------------------- /Graphics/AppIcon72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/Graphics/AppIcon72.png -------------------------------------------------------------------------------- /Graphics/icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/Graphics/icon_1024.png -------------------------------------------------------------------------------- /Graphics/icon_144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/Graphics/icon_144.png -------------------------------------------------------------------------------- /Graphics/icon_29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/Graphics/icon_29.png -------------------------------------------------------------------------------- /Graphics/icon_50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/Graphics/icon_50.png -------------------------------------------------------------------------------- /Graphics/icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/Graphics/icon_512.png -------------------------------------------------------------------------------- /Graphics/icon_72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/Graphics/icon_72.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 AFNetworking (http://afnetworking.com/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Build Status](https://travis-ci.org/vaivaikitay/RoboReader.png?branch=master)](https://travis-ci.org/vaivaikitay/RoboReader) 3 | 4 | With a couple of lines of code you can create a PDF view controller. This framework is very fast and easy to use. 5 | 6 | 7 | ## Sample usage 8 | 9 | ``` objective-c 10 | 11 | // Add RoboReader files to your project; import "RoboViewController.h" 12 | 13 | // Create a RoboDocument instance for the PDF file you want to display. 14 | 15 | NSString *path = [[NSBundle mainBundle] PathForResource:@"YourPdf" withExtension:@"pdf"]; 16 | 17 | RoboDocument *document = [[RoboDocument alloc] initWithFilePath:url password:@"YourPdfPassword_or_nil"] 18 | 19 | 20 | //Create a RoboViewController instance and present it as a child view controller. 21 | 22 | RoboViewController *r = [[RoboViewController alloc] initWithDocument:document]; 23 | 24 | ``` 25 | 26 | 27 | ## Installation via CocoaPods 28 | 29 | Add this line to your Podfile 30 | ``` 31 | pod 'RoboReaderPDF' 32 | ``` 33 | 34 | 35 | ## Credits 36 | 37 | RoboReader was created by [Mikhail Viceman](https://github.com/vaivaikitay) in the development of [Digital Edition platform] (http://digitaled.ru) [Copyright (c) REDMADROBOT] (http://redmadrobot.ru). 38 | 39 | 40 | ## Creators 41 | 42 | [Mikhail Viceman](https://github.com/vaivaikitay) 43 | [@vaivaikitay](https://twitter.com/vaivaikitay) 44 | 45 | 46 | ## License 47 | 48 | RoboReader is available under the MIT license. See the LICENSE file for more info. 49 | -------------------------------------------------------------------------------- /Resources/RoboReader-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFiles 12 | 13 | icon_29.png 14 | icon_50.png 15 | icon_72.png 16 | icon_144.png 17 | icon_512.png 18 | icon_1024.png 19 | 20 | CFBundleIdentifier 21 | com.redmadrobot.kiosk-reader 22 | CFBundleInfoDictionaryVersion 23 | 6.0 24 | CFBundleName 25 | ${PRODUCT_NAME} 26 | CFBundlePackageType 27 | APPL 28 | CFBundleShortVersionString 29 | 2.0.1 30 | CFBundleSignature 31 | ???? 32 | CFBundleVersion 33 | 78 34 | LSRequiresIPhoneOS 35 | 36 | UIPrerenderedIcon 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationPortraitUpsideDown 42 | UIInterfaceOrientationLandscapeRight 43 | UIInterfaceOrientationLandscapeLeft 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Resources/RoboReader-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #ifdef __OBJC__ 23 | 24 | #import 25 | #import 26 | #import 27 | #import 28 | #import 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /Resources/f5_newspaper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/Resources/f5_newspaper.pdf -------------------------------------------------------------------------------- /Resources/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | int main(int argc, char *argv[]) { 23 | 24 | 25 | @autoreleasepool { 26 | int retVal = UIApplicationMain(argc, argv, nil, @"RoboAppDelegate"); 27 | 28 | 29 | 30 | return retVal; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /RoboReader.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "RoboReader" 3 | s.version = "0.9" 4 | s.summary = "A cool pdf reader framework." 5 | 6 | s.description = <<-DESC 7 | With a couple of lines of code you can create a PDF view controller. This framework is very fast and easy to use. 8 | DESC 9 | 10 | s.homepage = "https://github.com/vaivaikitay/RoboReader" 11 | s.license = { :type => 'MIT', :file => 'LICENSE' } 12 | s.authors = { "Mikhail Viceman" => "mikhail.viceman@gmail.com"} 13 | s.platform = :ios, '5.0' 14 | s.source = { :git => "https://github.com/vaivaikitay/RoboReader" } 15 | s.source_files = 'RoboReader/Classes/*.{h,m}' 16 | #s.exclude_files = 'Classes/Exclude' 17 | s.resources = "RoboReader/Graphics/*.png" 18 | s.requires_arc = true 19 | end 20 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 044B432A17034644002ADE90 /* icon_29.png in Resources */ = {isa = PBXBuildFile; fileRef = 044B432417034644002ADE90 /* icon_29.png */; }; 11 | 044B432B17034644002ADE90 /* icon_50.png in Resources */ = {isa = PBXBuildFile; fileRef = 044B432517034644002ADE90 /* icon_50.png */; }; 12 | 044B432C17034644002ADE90 /* icon_72.png in Resources */ = {isa = PBXBuildFile; fileRef = 044B432617034644002ADE90 /* icon_72.png */; }; 13 | 044B432D17034644002ADE90 /* icon_144.png in Resources */ = {isa = PBXBuildFile; fileRef = 044B432717034644002ADE90 /* icon_144.png */; }; 14 | 044B432E17034644002ADE90 /* icon_512.png in Resources */ = {isa = PBXBuildFile; fileRef = 044B432817034644002ADE90 /* icon_512.png */; }; 15 | 044B432F17034644002ADE90 /* icon_1024.png in Resources */ = {isa = PBXBuildFile; fileRef = 044B432917034644002ADE90 /* icon_1024.png */; }; 16 | 04B304561609C0E60000CDDA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 04B304531609C0E60000CDDA /* main.m */; }; 17 | 04C55FA4173A7295007791DE /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 04C55FA3173A7295007791DE /* README.md */; }; 18 | 04CBD3C317396D1200A5E440 /* CGPDFDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CBD39A17396D1200A5E440 /* CGPDFDocument.m */; }; 19 | 04CBD3C417396D1200A5E440 /* PDFPageConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CBD39C17396D1200A5E440 /* PDFPageConverter.m */; }; 20 | 04CBD3C517396D1200A5E440 /* PDFPageRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CBD39E17396D1200A5E440 /* PDFPageRenderer.m */; }; 21 | 04CBD3C617396D1200A5E440 /* RoboConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CBD3A017396D1200A5E440 /* RoboConstants.m */; }; 22 | 04CBD3C717396D1200A5E440 /* RoboContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CBD3A217396D1200A5E440 /* RoboContentView.m */; }; 23 | 04CBD3C817396D1200A5E440 /* RoboDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CBD3A417396D1200A5E440 /* RoboDocument.m */; }; 24 | 04CBD3C917396D1200A5E440 /* RoboMainPagebar.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CBD3A617396D1200A5E440 /* RoboMainPagebar.m */; }; 25 | 04CBD3CA17396D1200A5E440 /* RoboMainToolbar.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CBD3A817396D1200A5E440 /* RoboMainToolbar.m */; }; 26 | 04CBD3CB17396D1200A5E440 /* RoboPDFController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CBD3AA17396D1200A5E440 /* RoboPDFController.m */; }; 27 | 04CBD3CC17396D1200A5E440 /* RoboPDFModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CBD3AC17396D1200A5E440 /* RoboPDFModel.m */; }; 28 | 04CBD3CD17396D1200A5E440 /* RoboViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04CBD3AF17396D1200A5E440 /* RoboViewController.m */; }; 29 | 04CBD3CE17396D1200A5E440 /* back_button.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3B117396D1200A5E440 /* back_button.png */; }; 30 | 04CBD3CF17396D1200A5E440 /* back_button@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3B217396D1200A5E440 /* back_button@2x.png */; }; 31 | 04CBD3D017396D1200A5E440 /* nav_bar_plashka.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3B317396D1200A5E440 /* nav_bar_plashka.png */; }; 32 | 04CBD3D117396D1200A5E440 /* nav_bar_plashka@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3B417396D1200A5E440 /* nav_bar_plashka@2x.png */; }; 33 | 04CBD3D217396D1200A5E440 /* page-bg.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3B517396D1200A5E440 /* page-bg.png */; }; 34 | 04CBD3D317396D1200A5E440 /* page-bg@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3B617396D1200A5E440 /* page-bg@2x.png */; }; 35 | 04CBD3D417396D1200A5E440 /* page_left.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3B717396D1200A5E440 /* page_left.png */; }; 36 | 04CBD3D517396D1200A5E440 /* page_left@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3B817396D1200A5E440 /* page_left@2x.png */; }; 37 | 04CBD3D617396D1200A5E440 /* page_right.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3B917396D1200A5E440 /* page_right.png */; }; 38 | 04CBD3D717396D1200A5E440 /* page_right@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3BA17396D1200A5E440 /* page_right@2x.png */; }; 39 | 04CBD3D817396D1200A5E440 /* progress_bar.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3BB17396D1200A5E440 /* progress_bar.png */; }; 40 | 04CBD3D917396D1200A5E440 /* progress_bar@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3BC17396D1200A5E440 /* progress_bar@2x.png */; }; 41 | 04CBD3DA17396D1200A5E440 /* Stroke2px.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3BD17396D1200A5E440 /* Stroke2px.png */; }; 42 | 04CBD3DB17396D1200A5E440 /* Stroke2px@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3BE17396D1200A5E440 /* Stroke2px@2x.png */; }; 43 | 04CBD3DC17396D1200A5E440 /* Stroke2px_single.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3BF17396D1200A5E440 /* Stroke2px_single.png */; }; 44 | 04CBD3DD17396D1200A5E440 /* Stroke2px_single@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3C017396D1200A5E440 /* Stroke2px_single@2x.png */; }; 45 | 04CBD3DE17396D1200A5E440 /* X.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3C117396D1200A5E440 /* X.png */; }; 46 | 04CBD3DF17396D1200A5E440 /* X@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 04CBD3C217396D1200A5E440 /* X@2x.png */; }; 47 | 04EB51F7170AF91A0095CA89 /* f5_newspaper.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 04EB51F6170AF9190095CA89 /* f5_newspaper.pdf */; }; 48 | 04F138C41701AEC00051C0E0 /* RoboAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 04F138BF1701AEC00051C0E0 /* RoboAppDelegate.m */; }; 49 | 04F138C61701AEC00051C0E0 /* RoboDemoController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04F138C31701AEC00051C0E0 /* RoboDemoController.m */; }; 50 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 51 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 52 | 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; 53 | 450A670411D27B9D00014BF5 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 450A670311D27B9D00014BF5 /* QuartzCore.framework */; }; 54 | 458DDFD7140D45FA00C5DA94 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 458DDFD6140D45FA00C5DA94 /* ImageIO.framework */; }; 55 | 45BD5AFE13AE721A00D6FE97 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 45BD5AFD13AE721A00D6FE97 /* MessageUI.framework */; }; 56 | 67441C48182A60F7007A68B9 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 67441C47182A60F7007A68B9 /* Default-568h@2x.png */; }; 57 | /* End PBXBuildFile section */ 58 | 59 | /* Begin PBXFileReference section */ 60 | 044B432417034644002ADE90 /* icon_29.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = icon_29.png; path = Graphics/icon_29.png; sourceTree = ""; }; 61 | 044B432517034644002ADE90 /* icon_50.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = icon_50.png; path = Graphics/icon_50.png; sourceTree = ""; }; 62 | 044B432617034644002ADE90 /* icon_72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = icon_72.png; path = Graphics/icon_72.png; sourceTree = ""; }; 63 | 044B432717034644002ADE90 /* icon_144.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = icon_144.png; path = Graphics/icon_144.png; sourceTree = ""; }; 64 | 044B432817034644002ADE90 /* icon_512.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = icon_512.png; path = Graphics/icon_512.png; sourceTree = ""; }; 65 | 044B432917034644002ADE90 /* icon_1024.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = icon_1024.png; path = Graphics/icon_1024.png; sourceTree = ""; }; 66 | 04B304511609C0E60000CDDA /* RoboReader-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "RoboReader-Info.plist"; path = "Resources/RoboReader-Info.plist"; sourceTree = ""; }; 67 | 04B304521609C0E60000CDDA /* RoboReader-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "RoboReader-Prefix.pch"; path = "Resources/RoboReader-Prefix.pch"; sourceTree = ""; }; 68 | 04B304531609C0E60000CDDA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Resources/main.m; sourceTree = ""; }; 69 | 04C55FA3173A7295007791DE /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.md; sourceTree = SOURCE_ROOT; }; 70 | 04CBD39917396D1200A5E440 /* CGPDFDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGPDFDocument.h; sourceTree = ""; }; 71 | 04CBD39A17396D1200A5E440 /* CGPDFDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CGPDFDocument.m; sourceTree = ""; }; 72 | 04CBD39B17396D1200A5E440 /* PDFPageConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDFPageConverter.h; sourceTree = ""; }; 73 | 04CBD39C17396D1200A5E440 /* PDFPageConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDFPageConverter.m; sourceTree = ""; }; 74 | 04CBD39D17396D1200A5E440 /* PDFPageRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDFPageRenderer.h; sourceTree = ""; }; 75 | 04CBD39E17396D1200A5E440 /* PDFPageRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDFPageRenderer.m; sourceTree = ""; }; 76 | 04CBD39F17396D1200A5E440 /* RoboConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoboConstants.h; sourceTree = ""; }; 77 | 04CBD3A017396D1200A5E440 /* RoboConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoboConstants.m; sourceTree = ""; }; 78 | 04CBD3A117396D1200A5E440 /* RoboContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoboContentView.h; sourceTree = ""; }; 79 | 04CBD3A217396D1200A5E440 /* RoboContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoboContentView.m; sourceTree = ""; }; 80 | 04CBD3A317396D1200A5E440 /* RoboDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoboDocument.h; sourceTree = ""; }; 81 | 04CBD3A417396D1200A5E440 /* RoboDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoboDocument.m; sourceTree = ""; }; 82 | 04CBD3A517396D1200A5E440 /* RoboMainPagebar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoboMainPagebar.h; sourceTree = ""; }; 83 | 04CBD3A617396D1200A5E440 /* RoboMainPagebar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoboMainPagebar.m; sourceTree = ""; }; 84 | 04CBD3A717396D1200A5E440 /* RoboMainToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoboMainToolbar.h; sourceTree = ""; }; 85 | 04CBD3A817396D1200A5E440 /* RoboMainToolbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoboMainToolbar.m; sourceTree = ""; }; 86 | 04CBD3A917396D1200A5E440 /* RoboPDFController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoboPDFController.h; sourceTree = ""; }; 87 | 04CBD3AA17396D1200A5E440 /* RoboPDFController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoboPDFController.m; sourceTree = ""; }; 88 | 04CBD3AB17396D1200A5E440 /* RoboPDFModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoboPDFModel.h; sourceTree = ""; }; 89 | 04CBD3AC17396D1200A5E440 /* RoboPDFModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoboPDFModel.m; sourceTree = ""; }; 90 | 04CBD3AD17396D1200A5E440 /* RoboReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoboReader.h; sourceTree = ""; }; 91 | 04CBD3AE17396D1200A5E440 /* RoboViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoboViewController.h; sourceTree = ""; }; 92 | 04CBD3AF17396D1200A5E440 /* RoboViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoboViewController.m; sourceTree = ""; }; 93 | 04CBD3B117396D1200A5E440 /* back_button.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = back_button.png; sourceTree = ""; }; 94 | 04CBD3B217396D1200A5E440 /* back_button@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "back_button@2x.png"; sourceTree = ""; }; 95 | 04CBD3B317396D1200A5E440 /* nav_bar_plashka.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = nav_bar_plashka.png; sourceTree = ""; }; 96 | 04CBD3B417396D1200A5E440 /* nav_bar_plashka@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "nav_bar_plashka@2x.png"; sourceTree = ""; }; 97 | 04CBD3B517396D1200A5E440 /* page-bg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "page-bg.png"; sourceTree = ""; }; 98 | 04CBD3B617396D1200A5E440 /* page-bg@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "page-bg@2x.png"; sourceTree = ""; }; 99 | 04CBD3B717396D1200A5E440 /* page_left.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = page_left.png; sourceTree = ""; }; 100 | 04CBD3B817396D1200A5E440 /* page_left@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "page_left@2x.png"; sourceTree = ""; }; 101 | 04CBD3B917396D1200A5E440 /* page_right.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = page_right.png; sourceTree = ""; }; 102 | 04CBD3BA17396D1200A5E440 /* page_right@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "page_right@2x.png"; sourceTree = ""; }; 103 | 04CBD3BB17396D1200A5E440 /* progress_bar.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = progress_bar.png; sourceTree = ""; }; 104 | 04CBD3BC17396D1200A5E440 /* progress_bar@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "progress_bar@2x.png"; sourceTree = ""; }; 105 | 04CBD3BD17396D1200A5E440 /* Stroke2px.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Stroke2px.png; sourceTree = ""; }; 106 | 04CBD3BE17396D1200A5E440 /* Stroke2px@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Stroke2px@2x.png"; sourceTree = ""; }; 107 | 04CBD3BF17396D1200A5E440 /* Stroke2px_single.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Stroke2px_single.png; sourceTree = ""; }; 108 | 04CBD3C017396D1200A5E440 /* Stroke2px_single@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Stroke2px_single@2x.png"; sourceTree = ""; }; 109 | 04CBD3C117396D1200A5E440 /* X.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = X.png; sourceTree = ""; }; 110 | 04CBD3C217396D1200A5E440 /* X@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "X@2x.png"; sourceTree = ""; }; 111 | 04EB51F6170AF9190095CA89 /* f5_newspaper.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = f5_newspaper.pdf; path = Resources/f5_newspaper.pdf; sourceTree = ""; }; 112 | 04F138BE1701AEC00051C0E0 /* RoboAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoboAppDelegate.h; sourceTree = ""; }; 113 | 04F138BF1701AEC00051C0E0 /* RoboAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoboAppDelegate.m; sourceTree = ""; }; 114 | 04F138C21701AEC00051C0E0 /* RoboDemoController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoboDemoController.h; sourceTree = ""; }; 115 | 04F138C31701AEC00051C0E0 /* RoboDemoController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoboDemoController.m; sourceTree = ""; }; 116 | 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 117 | 1D6058910D05DD3D006BFB54 /* RoboReader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RoboReader.app; sourceTree = BUILT_PRODUCTS_DIR; }; 118 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 119 | 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 120 | 450A670311D27B9D00014BF5 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 121 | 458DDFD6140D45FA00C5DA94 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; 122 | 45BD5AFD13AE721A00D6FE97 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; }; 123 | 67441C47182A60F7007A68B9 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 124 | /* End PBXFileReference section */ 125 | 126 | /* Begin PBXFrameworksBuildPhase section */ 127 | 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { 128 | isa = PBXFrameworksBuildPhase; 129 | buildActionMask = 2147483647; 130 | files = ( 131 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 132 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 133 | 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */, 134 | 450A670411D27B9D00014BF5 /* QuartzCore.framework in Frameworks */, 135 | 45BD5AFE13AE721A00D6FE97 /* MessageUI.framework in Frameworks */, 136 | 458DDFD7140D45FA00C5DA94 /* ImageIO.framework in Frameworks */, 137 | ); 138 | runOnlyForDeploymentPostprocessing = 0; 139 | }; 140 | /* End PBXFrameworksBuildPhase section */ 141 | 142 | /* Begin PBXGroup section */ 143 | 044B427617032473002ADE90 /* Demo */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 080E96DDFE201D6D7F000001 /* Classes */, 147 | 29B97317FDCFA39411CA2CEA /* Resources */, 148 | 450A66D911D27B5800014BF5 /* Graphics */, 149 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 150 | 19C28FACFE9D520D11CA2CBB /* Products */, 151 | ); 152 | name = Demo; 153 | sourceTree = ""; 154 | }; 155 | 04CBD39717396D1200A5E440 /* RoboReader */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 04CBD39817396D1200A5E440 /* Classes */, 159 | 04CBD3B017396D1200A5E440 /* Graphics */, 160 | ); 161 | path = RoboReader; 162 | sourceTree = ""; 163 | }; 164 | 04CBD39817396D1200A5E440 /* Classes */ = { 165 | isa = PBXGroup; 166 | children = ( 167 | 04CBD39917396D1200A5E440 /* CGPDFDocument.h */, 168 | 04CBD39A17396D1200A5E440 /* CGPDFDocument.m */, 169 | 04CBD39B17396D1200A5E440 /* PDFPageConverter.h */, 170 | 04CBD39C17396D1200A5E440 /* PDFPageConverter.m */, 171 | 04CBD39D17396D1200A5E440 /* PDFPageRenderer.h */, 172 | 04CBD39E17396D1200A5E440 /* PDFPageRenderer.m */, 173 | 04CBD39F17396D1200A5E440 /* RoboConstants.h */, 174 | 04CBD3A017396D1200A5E440 /* RoboConstants.m */, 175 | 04CBD3A117396D1200A5E440 /* RoboContentView.h */, 176 | 04CBD3A217396D1200A5E440 /* RoboContentView.m */, 177 | 04CBD3A317396D1200A5E440 /* RoboDocument.h */, 178 | 04CBD3A417396D1200A5E440 /* RoboDocument.m */, 179 | 04CBD3A517396D1200A5E440 /* RoboMainPagebar.h */, 180 | 04CBD3A617396D1200A5E440 /* RoboMainPagebar.m */, 181 | 04CBD3A717396D1200A5E440 /* RoboMainToolbar.h */, 182 | 04CBD3A817396D1200A5E440 /* RoboMainToolbar.m */, 183 | 04CBD3A917396D1200A5E440 /* RoboPDFController.h */, 184 | 04CBD3AA17396D1200A5E440 /* RoboPDFController.m */, 185 | 04CBD3AB17396D1200A5E440 /* RoboPDFModel.h */, 186 | 04CBD3AC17396D1200A5E440 /* RoboPDFModel.m */, 187 | 04CBD3AD17396D1200A5E440 /* RoboReader.h */, 188 | 04CBD3AE17396D1200A5E440 /* RoboViewController.h */, 189 | 04CBD3AF17396D1200A5E440 /* RoboViewController.m */, 190 | ); 191 | path = Classes; 192 | sourceTree = ""; 193 | }; 194 | 04CBD3B017396D1200A5E440 /* Graphics */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | 04CBD3B117396D1200A5E440 /* back_button.png */, 198 | 04CBD3B217396D1200A5E440 /* back_button@2x.png */, 199 | 04CBD3B317396D1200A5E440 /* nav_bar_plashka.png */, 200 | 04CBD3B417396D1200A5E440 /* nav_bar_plashka@2x.png */, 201 | 04CBD3B517396D1200A5E440 /* page-bg.png */, 202 | 04CBD3B617396D1200A5E440 /* page-bg@2x.png */, 203 | 04CBD3B717396D1200A5E440 /* page_left.png */, 204 | 04CBD3B817396D1200A5E440 /* page_left@2x.png */, 205 | 04CBD3B917396D1200A5E440 /* page_right.png */, 206 | 04CBD3BA17396D1200A5E440 /* page_right@2x.png */, 207 | 04CBD3BB17396D1200A5E440 /* progress_bar.png */, 208 | 04CBD3BC17396D1200A5E440 /* progress_bar@2x.png */, 209 | 04CBD3BD17396D1200A5E440 /* Stroke2px.png */, 210 | 04CBD3BE17396D1200A5E440 /* Stroke2px@2x.png */, 211 | 04CBD3BF17396D1200A5E440 /* Stroke2px_single.png */, 212 | 04CBD3C017396D1200A5E440 /* Stroke2px_single@2x.png */, 213 | 04CBD3C117396D1200A5E440 /* X.png */, 214 | 04CBD3C217396D1200A5E440 /* X@2x.png */, 215 | ); 216 | path = Graphics; 217 | sourceTree = ""; 218 | }; 219 | 080E96DDFE201D6D7F000001 /* Classes */ = { 220 | isa = PBXGroup; 221 | children = ( 222 | 04F138BE1701AEC00051C0E0 /* RoboAppDelegate.h */, 223 | 04F138BF1701AEC00051C0E0 /* RoboAppDelegate.m */, 224 | 04F138C21701AEC00051C0E0 /* RoboDemoController.h */, 225 | 04F138C31701AEC00051C0E0 /* RoboDemoController.m */, 226 | ); 227 | path = Classes; 228 | sourceTree = ""; 229 | }; 230 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 231 | isa = PBXGroup; 232 | children = ( 233 | 1D6058910D05DD3D006BFB54 /* RoboReader.app */, 234 | ); 235 | name = Products; 236 | sourceTree = ""; 237 | }; 238 | 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { 239 | isa = PBXGroup; 240 | children = ( 241 | 67441C47182A60F7007A68B9 /* Default-568h@2x.png */, 242 | 044B427617032473002ADE90 /* Demo */, 243 | 04CBD39717396D1200A5E440 /* RoboReader */, 244 | 04C55FA3173A7295007791DE /* README.md */, 245 | ); 246 | name = CustomTemplate; 247 | sourceTree = ""; 248 | }; 249 | 29B97317FDCFA39411CA2CEA /* Resources */ = { 250 | isa = PBXGroup; 251 | children = ( 252 | 04EB51F6170AF9190095CA89 /* f5_newspaper.pdf */, 253 | 04B304511609C0E60000CDDA /* RoboReader-Info.plist */, 254 | 04B304521609C0E60000CDDA /* RoboReader-Prefix.pch */, 255 | 04B304531609C0E60000CDDA /* main.m */, 256 | ); 257 | name = Resources; 258 | sourceTree = ""; 259 | }; 260 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 261 | isa = PBXGroup; 262 | children = ( 263 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 264 | 1D30AB110D05D00D00671497 /* Foundation.framework */, 265 | 288765FC0DF74451002DB57D /* CoreGraphics.framework */, 266 | 450A670311D27B9D00014BF5 /* QuartzCore.framework */, 267 | 45BD5AFD13AE721A00D6FE97 /* MessageUI.framework */, 268 | 458DDFD6140D45FA00C5DA94 /* ImageIO.framework */, 269 | ); 270 | name = Frameworks; 271 | sourceTree = ""; 272 | }; 273 | 450A66D911D27B5800014BF5 /* Graphics */ = { 274 | isa = PBXGroup; 275 | children = ( 276 | 044B432417034644002ADE90 /* icon_29.png */, 277 | 044B432517034644002ADE90 /* icon_50.png */, 278 | 044B432617034644002ADE90 /* icon_72.png */, 279 | 044B432717034644002ADE90 /* icon_144.png */, 280 | 044B432817034644002ADE90 /* icon_512.png */, 281 | 044B432917034644002ADE90 /* icon_1024.png */, 282 | ); 283 | name = Graphics; 284 | sourceTree = ""; 285 | }; 286 | /* End PBXGroup section */ 287 | 288 | /* Begin PBXNativeTarget section */ 289 | 1D6058900D05DD3D006BFB54 /* RoboReader */ = { 290 | isa = PBXNativeTarget; 291 | buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "RoboReader" */; 292 | buildPhases = ( 293 | 1D60588D0D05DD3D006BFB54 /* Resources */, 294 | 1D60588E0D05DD3D006BFB54 /* Sources */, 295 | 1D60588F0D05DD3D006BFB54 /* Frameworks */, 296 | ); 297 | buildRules = ( 298 | ); 299 | dependencies = ( 300 | ); 301 | name = RoboReader; 302 | productName = Reader; 303 | productReference = 1D6058910D05DD3D006BFB54 /* RoboReader.app */; 304 | productType = "com.apple.product-type.application"; 305 | }; 306 | /* End PBXNativeTarget section */ 307 | 308 | /* Begin PBXProject section */ 309 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 310 | isa = PBXProject; 311 | attributes = { 312 | LastUpgradeCheck = 0500; 313 | }; 314 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "RoboReader" */; 315 | compatibilityVersion = "Xcode 3.2"; 316 | developmentRegion = en; 317 | hasScannedForEncodings = 1; 318 | knownRegions = ( 319 | en, 320 | jp, 321 | fr, 322 | de, 323 | ); 324 | mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; 325 | projectDirPath = ""; 326 | projectRoot = ""; 327 | targets = ( 328 | 1D6058900D05DD3D006BFB54 /* RoboReader */, 329 | ); 330 | }; 331 | /* End PBXProject section */ 332 | 333 | /* Begin PBXResourcesBuildPhase section */ 334 | 1D60588D0D05DD3D006BFB54 /* Resources */ = { 335 | isa = PBXResourcesBuildPhase; 336 | buildActionMask = 2147483647; 337 | files = ( 338 | 044B432A17034644002ADE90 /* icon_29.png in Resources */, 339 | 044B432B17034644002ADE90 /* icon_50.png in Resources */, 340 | 044B432C17034644002ADE90 /* icon_72.png in Resources */, 341 | 044B432D17034644002ADE90 /* icon_144.png in Resources */, 342 | 044B432E17034644002ADE90 /* icon_512.png in Resources */, 343 | 044B432F17034644002ADE90 /* icon_1024.png in Resources */, 344 | 04EB51F7170AF91A0095CA89 /* f5_newspaper.pdf in Resources */, 345 | 04CBD3CE17396D1200A5E440 /* back_button.png in Resources */, 346 | 04CBD3CF17396D1200A5E440 /* back_button@2x.png in Resources */, 347 | 04CBD3D017396D1200A5E440 /* nav_bar_plashka.png in Resources */, 348 | 04CBD3D117396D1200A5E440 /* nav_bar_plashka@2x.png in Resources */, 349 | 67441C48182A60F7007A68B9 /* Default-568h@2x.png in Resources */, 350 | 04CBD3D217396D1200A5E440 /* page-bg.png in Resources */, 351 | 04CBD3D317396D1200A5E440 /* page-bg@2x.png in Resources */, 352 | 04CBD3D417396D1200A5E440 /* page_left.png in Resources */, 353 | 04CBD3D517396D1200A5E440 /* page_left@2x.png in Resources */, 354 | 04CBD3D617396D1200A5E440 /* page_right.png in Resources */, 355 | 04CBD3D717396D1200A5E440 /* page_right@2x.png in Resources */, 356 | 04CBD3D817396D1200A5E440 /* progress_bar.png in Resources */, 357 | 04CBD3D917396D1200A5E440 /* progress_bar@2x.png in Resources */, 358 | 04CBD3DA17396D1200A5E440 /* Stroke2px.png in Resources */, 359 | 04CBD3DB17396D1200A5E440 /* Stroke2px@2x.png in Resources */, 360 | 04CBD3DC17396D1200A5E440 /* Stroke2px_single.png in Resources */, 361 | 04CBD3DD17396D1200A5E440 /* Stroke2px_single@2x.png in Resources */, 362 | 04CBD3DE17396D1200A5E440 /* X.png in Resources */, 363 | 04CBD3DF17396D1200A5E440 /* X@2x.png in Resources */, 364 | 04C55FA4173A7295007791DE /* README.md in Resources */, 365 | ); 366 | runOnlyForDeploymentPostprocessing = 0; 367 | }; 368 | /* End PBXResourcesBuildPhase section */ 369 | 370 | /* Begin PBXSourcesBuildPhase section */ 371 | 1D60588E0D05DD3D006BFB54 /* Sources */ = { 372 | isa = PBXSourcesBuildPhase; 373 | buildActionMask = 2147483647; 374 | files = ( 375 | 04B304561609C0E60000CDDA /* main.m in Sources */, 376 | 04F138C41701AEC00051C0E0 /* RoboAppDelegate.m in Sources */, 377 | 04F138C61701AEC00051C0E0 /* RoboDemoController.m in Sources */, 378 | 04CBD3C317396D1200A5E440 /* CGPDFDocument.m in Sources */, 379 | 04CBD3C417396D1200A5E440 /* PDFPageConverter.m in Sources */, 380 | 04CBD3C517396D1200A5E440 /* PDFPageRenderer.m in Sources */, 381 | 04CBD3C617396D1200A5E440 /* RoboConstants.m in Sources */, 382 | 04CBD3C717396D1200A5E440 /* RoboContentView.m in Sources */, 383 | 04CBD3C817396D1200A5E440 /* RoboDocument.m in Sources */, 384 | 04CBD3C917396D1200A5E440 /* RoboMainPagebar.m in Sources */, 385 | 04CBD3CA17396D1200A5E440 /* RoboMainToolbar.m in Sources */, 386 | 04CBD3CB17396D1200A5E440 /* RoboPDFController.m in Sources */, 387 | 04CBD3CC17396D1200A5E440 /* RoboPDFModel.m in Sources */, 388 | 04CBD3CD17396D1200A5E440 /* RoboViewController.m in Sources */, 389 | ); 390 | runOnlyForDeploymentPostprocessing = 0; 391 | }; 392 | /* End PBXSourcesBuildPhase section */ 393 | 394 | /* Begin XCBuildConfiguration section */ 395 | 1D6058940D05DD3E006BFB54 /* Debug */ = { 396 | isa = XCBuildConfiguration; 397 | buildSettings = { 398 | ALWAYS_SEARCH_USER_PATHS = NO; 399 | CLANG_ENABLE_OBJC_ARC = YES; 400 | CODE_SIGN_IDENTITY = "iPhone Developer"; 401 | COPY_PHASE_STRIP = NO; 402 | FRAMEWORK_SEARCH_PATHS = ( 403 | "$(inherited)", 404 | "\"$(SRCROOT)\"", 405 | ); 406 | GCC_DYNAMIC_NO_PIC = NO; 407 | GCC_OPTIMIZATION_LEVEL = 0; 408 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 409 | GCC_PREFIX_HEADER = "Resources/RoboReader-Prefix.pch"; 410 | INFOPLIST_FILE = "Resources/RoboReader-Info.plist"; 411 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 412 | PRODUCT_NAME = RoboReader; 413 | PROVISIONING_PROFILE = ""; 414 | TARGETED_DEVICE_FAMILY = "1,2"; 415 | }; 416 | name = Debug; 417 | }; 418 | 1D6058950D05DD3E006BFB54 /* Release */ = { 419 | isa = XCBuildConfiguration; 420 | buildSettings = { 421 | ALWAYS_SEARCH_USER_PATHS = NO; 422 | CLANG_ENABLE_OBJC_ARC = YES; 423 | CODE_SIGN_IDENTITY = "iPhone Developer"; 424 | COPY_PHASE_STRIP = YES; 425 | FRAMEWORK_SEARCH_PATHS = ( 426 | "$(inherited)", 427 | "\"$(SRCROOT)\"", 428 | ); 429 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 430 | GCC_PREFIX_HEADER = "Resources/RoboReader-Prefix.pch"; 431 | INFOPLIST_FILE = "Resources/RoboReader-Info.plist"; 432 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 433 | PRODUCT_NAME = RoboReader; 434 | PROVISIONING_PROFILE = ""; 435 | TARGETED_DEVICE_FAMILY = "1,2"; 436 | VALIDATE_PRODUCT = YES; 437 | }; 438 | name = Release; 439 | }; 440 | 458529CE13DDE2DF00EDC79D /* Testing */ = { 441 | isa = XCBuildConfiguration; 442 | buildSettings = { 443 | CLANG_WARN_BOOL_CONVERSION = YES; 444 | CLANG_WARN_CONSTANT_CONVERSION = YES; 445 | CLANG_WARN_EMPTY_BODY = YES; 446 | CLANG_WARN_ENUM_CONVERSION = YES; 447 | CLANG_WARN_INT_CONVERSION = YES; 448 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 449 | CODE_SIGN_IDENTITY = "iPhone Developer: Aydar Mukhametyanov (28LJ99WCN7)"; 450 | GCC_C_LANGUAGE_STANDARD = c99; 451 | GCC_MODEL_TUNING = ""; 452 | GCC_PREPROCESSOR_DEFINITIONS = NDEBUG; 453 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 454 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 455 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 456 | GCC_WARN_UNDECLARED_SELECTOR = YES; 457 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 458 | GCC_WARN_UNUSED_FUNCTION = YES; 459 | GCC_WARN_UNUSED_VARIABLE = YES; 460 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; 461 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 462 | PROVISIONING_PROFILE = "674107E8-51FB-42F5-82E0-A7C3F69E237F"; 463 | SDKROOT = iphoneos; 464 | TARGETED_DEVICE_FAMILY = "1,2"; 465 | }; 466 | name = Testing; 467 | }; 468 | 458529CF13DDE2DF00EDC79D /* Testing */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | ALWAYS_SEARCH_USER_PATHS = NO; 472 | CLANG_ENABLE_OBJC_ARC = YES; 473 | CODE_SIGN_IDENTITY = "iPhone Developer"; 474 | COPY_PHASE_STRIP = YES; 475 | FRAMEWORK_SEARCH_PATHS = ( 476 | "$(inherited)", 477 | "\"$(SRCROOT)\"", 478 | ); 479 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 480 | GCC_PREFIX_HEADER = "Resources/RoboReader-Prefix.pch"; 481 | INFOPLIST_FILE = "Resources/RoboReader-Info.plist"; 482 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 483 | PRODUCT_NAME = RoboReader; 484 | PROVISIONING_PROFILE = ""; 485 | TARGETED_DEVICE_FAMILY = "1,2"; 486 | }; 487 | name = Testing; 488 | }; 489 | C01FCF4F08A954540054247B /* Debug */ = { 490 | isa = XCBuildConfiguration; 491 | buildSettings = { 492 | CLANG_WARN_BOOL_CONVERSION = YES; 493 | CLANG_WARN_CONSTANT_CONVERSION = YES; 494 | CLANG_WARN_EMPTY_BODY = YES; 495 | CLANG_WARN_ENUM_CONVERSION = YES; 496 | CLANG_WARN_INT_CONVERSION = YES; 497 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 498 | CODE_SIGN_IDENTITY = "iPhone Developer: Aydar Mukhametyanov (28LJ99WCN7)"; 499 | GCC_C_LANGUAGE_STANDARD = c99; 500 | GCC_MODEL_TUNING = ""; 501 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG; 502 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 503 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 504 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 505 | GCC_WARN_UNDECLARED_SELECTOR = YES; 506 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 507 | GCC_WARN_UNUSED_FUNCTION = YES; 508 | GCC_WARN_UNUSED_VARIABLE = YES; 509 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; 510 | ONLY_ACTIVE_ARCH = YES; 511 | PROVISIONING_PROFILE = "674107E8-51FB-42F5-82E0-A7C3F69E237F"; 512 | SDKROOT = iphoneos; 513 | TARGETED_DEVICE_FAMILY = "1,2"; 514 | }; 515 | name = Debug; 516 | }; 517 | C01FCF5008A954540054247B /* Release */ = { 518 | isa = XCBuildConfiguration; 519 | buildSettings = { 520 | CLANG_WARN_BOOL_CONVERSION = YES; 521 | CLANG_WARN_CONSTANT_CONVERSION = YES; 522 | CLANG_WARN_EMPTY_BODY = YES; 523 | CLANG_WARN_ENUM_CONVERSION = YES; 524 | CLANG_WARN_INT_CONVERSION = YES; 525 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 526 | CODE_SIGN_IDENTITY = "iPhone Developer: Aydar Mukhametyanov (28LJ99WCN7)"; 527 | GCC_C_LANGUAGE_STANDARD = c99; 528 | GCC_MODEL_TUNING = ""; 529 | GCC_PREPROCESSOR_DEFINITIONS = NDEBUG; 530 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 531 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 532 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 533 | GCC_WARN_UNDECLARED_SELECTOR = YES; 534 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 535 | GCC_WARN_UNUSED_FUNCTION = YES; 536 | GCC_WARN_UNUSED_VARIABLE = YES; 537 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; 538 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 539 | PROVISIONING_PROFILE = "674107E8-51FB-42F5-82E0-A7C3F69E237F"; 540 | SDKROOT = iphoneos; 541 | TARGETED_DEVICE_FAMILY = "1,2"; 542 | }; 543 | name = Release; 544 | }; 545 | /* End XCBuildConfiguration section */ 546 | 547 | /* Begin XCConfigurationList section */ 548 | 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "RoboReader" */ = { 549 | isa = XCConfigurationList; 550 | buildConfigurations = ( 551 | 1D6058940D05DD3E006BFB54 /* Debug */, 552 | 458529CF13DDE2DF00EDC79D /* Testing */, 553 | 1D6058950D05DD3E006BFB54 /* Release */, 554 | ); 555 | defaultConfigurationIsVisible = 0; 556 | defaultConfigurationName = Release; 557 | }; 558 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "RoboReader" */ = { 559 | isa = XCConfigurationList; 560 | buildConfigurations = ( 561 | C01FCF4F08A954540054247B /* Debug */, 562 | 458529CE13DDE2DF00EDC79D /* Testing */, 563 | C01FCF5008A954540054247B /* Release */, 564 | ); 565 | defaultConfigurationIsVisible = 0; 566 | defaultConfigurationName = Release; 567 | }; 568 | /* End XCConfigurationList section */ 569 | }; 570 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 571 | } 572 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/project.xcworkspace/xcuserdata/MacBook.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader.xcodeproj/project.xcworkspace/xcuserdata/MacBook.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /RoboReader.xcodeproj/project.xcworkspace/xcuserdata/mac.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader.xcodeproj/project.xcworkspace/xcuserdata/mac.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /RoboReader.xcodeproj/project.xcworkspace/xcuserdata/mac.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/project.xcworkspace/xcuserdata/vaivaikitay.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/xcuserdata/MacBook.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 18 | 19 | 31 | 32 | 44 | 45 | 57 | 58 | 70 | 71 | 83 | 84 | 96 | 97 | 109 | 110 | 122 | 123 | 135 | 136 | 148 | 149 | 161 | 162 | 174 | 175 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/xcuserdata/MacBook.xcuserdatad/xcschemes/RoboReader.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/xcuserdata/MacBook.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | RoboReader.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1D6058900D05DD3D006BFB54 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/xcuserdata/mac.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 18 | 19 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/Reader.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Reader.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1D6058900D05DD3D006BFB54 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/xcuserdata/vaivaikitay.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/xcuserdata/vaivaikitay.xcuserdatad/xcschemes/RoboReader.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /RoboReader.xcodeproj/xcuserdata/vaivaikitay.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | RoboReader.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1D6058900D05DD3D006BFB54 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /RoboReader/Classes/CGPDFDocument.h: -------------------------------------------------------------------------------- 1 | // 2 | // CGPDFDocument.h 3 | // Robo v2.5.4 4 | // 5 | // Created by Julius Oklamcak on 2011-07-01. 6 | // Copyright © 2011-2012 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | #import 28 | 29 | // 30 | // Custom CGPDFDocument[...] functions 31 | // 32 | 33 | CGPDFDocumentRef CGPDFDocumentCreateX(CFURLRef theURL, NSString *password); 34 | 35 | BOOL CGPDFDocumentNeedsPassword(CFURLRef theURL, NSString *password); 36 | -------------------------------------------------------------------------------- /RoboReader/Classes/CGPDFDocument.m: -------------------------------------------------------------------------------- 1 | // 2 | // CGPDFDocument.m 3 | // Robo v2.5.4 4 | // 5 | // Created by Julius Oklamcak on 2011-07-01. 6 | // Copyright © 2011-2012 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "CGPDFDocument.h" 27 | 28 | // 29 | // CGPDFDocumentRef CGPDFDocumentCreateX(CFURLRef, NSString *) function 30 | // 31 | 32 | CGPDFDocumentRef CGPDFDocumentCreateX(CFURLRef theURL, NSString *password) { 33 | 34 | CGPDFDocumentRef thePDFDocRef = NULL; 35 | 36 | if (theURL != NULL) // Check for non-NULL CFURLRef 37 | { 38 | thePDFDocRef = CGPDFDocumentCreateWithURL(theURL); 39 | 40 | if (thePDFDocRef != NULL) // Check for non-NULL CGPDFDocumentRef 41 | { 42 | if (CGPDFDocumentIsEncrypted(thePDFDocRef) == TRUE) // Encrypted 43 | { 44 | // Try a blank password first, per Apple's Quartz PDF example 45 | 46 | if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, "") == FALSE) { 47 | // Nope, now let's try the provided password to unlock the PDF 48 | 49 | if ((password != nil) && ([password length] > 0)) // Not blank? 50 | { 51 | char text[128]; // char array buffer for the string conversion 52 | 53 | [password getCString:text maxLength:126 encoding:NSUTF8StringEncoding]; 54 | 55 | if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, text) == FALSE) // Log failure 56 | { 57 | #ifdef DEBUG 58 | NSLog(@"CGPDFDocumentCreateX: Unable to unlock [%@] with [%@]", theURL, password); 59 | #endif 60 | } 61 | } 62 | } 63 | 64 | if (CGPDFDocumentIsUnlocked(thePDFDocRef) == FALSE) // Cleanup unlock failure 65 | { 66 | CGPDFDocumentRelease(thePDFDocRef), thePDFDocRef = NULL; 67 | } 68 | } 69 | } 70 | } 71 | else // Log an error diagnostic 72 | { 73 | #ifdef DEBUG 74 | NSLog(@"CGPDFDocumentCreateX: theURL == NULL"); 75 | #endif 76 | } 77 | 78 | return thePDFDocRef; 79 | } 80 | 81 | // 82 | // BOOL CGPDFDocumentNeedsPassword(CFURLRef, NSString *) function 83 | // 84 | 85 | BOOL CGPDFDocumentNeedsPassword(CFURLRef theURL, NSString *password) { 86 | 87 | 88 | BOOL needPassword = NO; // Default flag 89 | 90 | if (theURL != NULL) // Check for non-NULL CFURLRef 91 | { 92 | CGPDFDocumentRef thePDFDocRef = CGPDFDocumentCreateWithURL(theURL); 93 | 94 | if (thePDFDocRef != NULL) // Check for non-NULL CGPDFDocumentRef 95 | { 96 | if (CGPDFDocumentIsEncrypted(thePDFDocRef) == TRUE) // Encrypted 97 | { 98 | // Try a blank password first, per Apple's Quartz PDF example 99 | 100 | if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, "") == FALSE) { 101 | // Nope, now let's try the provided password to unlock the PDF 102 | 103 | if ((password != nil) && ([password length] > 0)) // Not blank? 104 | { 105 | char text[128]; // char array buffer for the string conversion 106 | 107 | [password getCString:text maxLength:126 encoding:NSUTF8StringEncoding]; 108 | 109 | if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, text) == FALSE) { 110 | needPassword = YES; 111 | } 112 | } 113 | else 114 | needPassword = YES; 115 | } 116 | } 117 | 118 | CGPDFDocumentRelease(thePDFDocRef); // Cleanup CGPDFDocumentRef 119 | } 120 | } 121 | else // Log an error diagnostic 122 | { 123 | #ifdef DEBUG 124 | NSLog(@"CGPDFDocumentNeedsPassword: theURL == NULL"); 125 | #endif 126 | } 127 | 128 | return needPassword; 129 | } 130 | 131 | // EOF 132 | -------------------------------------------------------------------------------- /RoboReader/Classes/PDFPageConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // PDFPageConverter.h 3 | // 4 | // Created by Sorin Nistor on 3/23/11. 5 | // Copyright 2011 iPDFdev.com. All rights reserved. 6 | // 7 | // Copyright (c) 2011 Sorin Nistor. All rights reserved. This software is provided 'as-is', 8 | // without any express or implied warranty. In no event will the authors be held liable for 9 | // any damages arising from the use of this software. Permission is granted to anyone to 10 | // use this software for any purpose, including commercial applications, and to alter it 11 | // and redistribute it freely, subject to the following restrictions: 12 | // 1. The origin of this software must not be misrepresented; you must not claim that you 13 | // wrote the original software. If you use this software in a product, an acknowledgment 14 | // in the product documentation would be appreciated but is not required. 15 | // 2. Altered source versions must be plainly marked as such, and must not be misrepresented 16 | // as being the original software. 17 | // 3. This notice may not be removed or altered from any source distribution. 18 | 19 | #import 20 | 21 | 22 | @interface PDFPageConverter : NSObject { 23 | 24 | } 25 | 26 | + (UIImage *)convertPDFPageToImage:(CGPDFPageRef)page withResolution:(float)resolution; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /RoboReader/Classes/PDFPageConverter.m: -------------------------------------------------------------------------------- 1 | // 2 | // PDFPageConverter.m 3 | // 4 | // Created by Sorin Nistor on 3/23/11. 5 | // Copyright 2011 iPDFdev.com. All rights reserved. 6 | // 7 | 8 | #import "PDFPageConverter.h" 9 | #import "PDFPageRenderer.h" 10 | 11 | @implementation PDFPageConverter 12 | 13 | + (UIImage *)convertPDFPageToImage:(CGPDFPageRef)page withResolution:(float)resolution { 14 | #ifdef HARDCORX 15 | NSLog(@"%s", __FUNCTION__); 16 | #endif 17 | CGRect cropBox = CGPDFPageGetBoxRect(page, kCGPDFCropBox); 18 | int pageRotation = CGPDFPageGetRotationAngle(page); 19 | 20 | if ((pageRotation == 0) || (pageRotation == 180) || (pageRotation == -180)) { 21 | UIGraphicsBeginImageContextWithOptions(cropBox.size, NO, resolution / 72); 22 | } 23 | else { 24 | 25 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(cropBox.size.height, cropBox.size.width), NO, 0.0); 26 | 27 | } 28 | 29 | CGContextRef imageContext = UIGraphicsGetCurrentContext(); 30 | 31 | [PDFPageRenderer renderPage:page inContext:imageContext]; 32 | 33 | UIImage *pageImage = UIGraphicsGetImageFromCurrentImageContext(); 34 | 35 | UIGraphicsEndImageContext(); 36 | return pageImage; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /RoboReader/Classes/PDFPageRenderer.h: -------------------------------------------------------------------------------- 1 | // 2 | // PDFPageRenderer.h 3 | // 4 | // Created by Sorin Nistor on 3/21/11. 5 | // Copyright 2011 iPDFdev.com. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | 11 | @interface PDFPageRenderer : NSObject { 12 | 13 | } 14 | 15 | + (void)renderPage:(CGPDFPageRef)page inContext:(CGContextRef)context; 16 | 17 | + (void)renderPage:(CGPDFPageRef)page inContext:(CGContextRef)context atPoint:(CGPoint)point; 18 | 19 | + (void)renderPage:(CGPDFPageRef)page inContext:(CGContextRef)context atPoint:(CGPoint)point withZoom:(float)zoom; 20 | 21 | + (void)renderPage:(CGPDFPageRef)page inContext:(CGContextRef)context inRectangle:(CGRect)rectangle; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /RoboReader/Classes/PDFPageRenderer.m: -------------------------------------------------------------------------------- 1 | // 2 | // PDFPageRenderer.m 3 | // 4 | // Created by Sorin Nistor on 3/21/11. 5 | // Copyright 2011 iPDFdev.com. All rights reserved. 6 | // 7 | 8 | #import "PDFPageRenderer.h" 9 | 10 | 11 | @implementation PDFPageRenderer 12 | 13 | + (void)renderPage:(CGPDFPageRef)page inContext:(CGContextRef)context { 14 | #ifdef HARDCORX 15 | NSLog(@"%s", __FUNCTION__); 16 | #endif 17 | [PDFPageRenderer renderPage:page inContext:context atPoint:CGPointMake(0, 0)]; 18 | } 19 | 20 | + (void)renderPage:(CGPDFPageRef)page inContext:(CGContextRef)context atPoint:(CGPoint)point { 21 | #ifdef HARDCORX 22 | NSLog(@"%s", __FUNCTION__); 23 | #endif 24 | [PDFPageRenderer renderPage:page inContext:context atPoint:point withZoom:100]; 25 | } 26 | 27 | + (void)renderPage:(CGPDFPageRef)page inContext:(CGContextRef)context atPoint:(CGPoint)point withZoom:(float)zoom { 28 | #ifdef HARDCORX 29 | NSLog(@"%s", __FUNCTION__); 30 | #endif 31 | 32 | CGRect cropBox = CGPDFPageGetBoxRect(page, kCGPDFCropBox); 33 | int rotate = CGPDFPageGetRotationAngle(page); 34 | 35 | CGContextSaveGState(context); 36 | 37 | // Setup the coordinate system. 38 | // Top left corner of the displayed page must be located at the point specified by the 'point' parameter. 39 | CGContextTranslateCTM(context, point.x, point.y); 40 | 41 | // Scale the page to desired zoom level. 42 | CGContextScaleCTM(context, zoom / 100, zoom / 100); 43 | 44 | // The coordinate system must be set to match the PDF coordinate system. 45 | switch (rotate) { 46 | case 0: 47 | CGContextTranslateCTM(context, 0, cropBox.size.height); 48 | CGContextScaleCTM(context, 1, -1); 49 | break; 50 | case 90: 51 | CGContextScaleCTM(context, 1, -1); 52 | CGContextRotateCTM(context, -M_PI / 2); 53 | break; 54 | case 180: 55 | case -180: 56 | CGContextScaleCTM(context, 1, -1); 57 | CGContextTranslateCTM(context, cropBox.size.width, 0); 58 | CGContextRotateCTM(context, M_PI); 59 | break; 60 | case 270: 61 | case -90: 62 | CGContextTranslateCTM(context, cropBox.size.height, cropBox.size.width); 63 | CGContextRotateCTM(context, M_PI / 2); 64 | CGContextScaleCTM(context, -1, 1); 65 | break; 66 | default: 67 | break; 68 | } 69 | 70 | // The CropBox defines the page visible area, clip everything outside it. 71 | CGRect clipRect = CGRectMake(0, 0, cropBox.size.width, cropBox.size.height); 72 | CGContextAddRect(context, clipRect); 73 | CGContextClip(context); 74 | 75 | CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0); 76 | CGContextFillRect(context, clipRect); 77 | 78 | CGContextTranslateCTM(context, -cropBox.origin.x, -cropBox.origin.y); 79 | 80 | //new 81 | CGContextSetInterpolationQuality(context, kCGInterpolationHigh); 82 | CGContextSetRenderingIntent(context, kCGRenderingIntentDefault); 83 | //end of new 84 | 85 | CGContextDrawPDFPage(context, page); 86 | 87 | CGContextRestoreGState(context); 88 | } 89 | 90 | + (void)renderPage:(CGPDFPageRef)page inContext:(CGContextRef)context inRectangle:(CGRect)displayRectangle { 91 | #ifdef HARDCORX 92 | NSLog(@"%s", __FUNCTION__); 93 | #endif 94 | if ((displayRectangle.size.width == 0) || (displayRectangle.size.height == 0)) { 95 | return; 96 | } 97 | 98 | CGRect cropBox = CGPDFPageGetBoxRect(page, kCGPDFCropBox); 99 | int pageRotation = CGPDFPageGetRotationAngle(page); 100 | 101 | CGSize pageVisibleSize = CGSizeMake(cropBox.size.width, cropBox.size.height); 102 | if ((pageRotation == 90) || (pageRotation == 270) || (pageRotation == -90)) { 103 | pageVisibleSize = CGSizeMake(cropBox.size.height, cropBox.size.width); 104 | } 105 | 106 | float scaleX = displayRectangle.size.width / pageVisibleSize.width; 107 | float scaleY = displayRectangle.size.height / pageVisibleSize.height; 108 | float scale = scaleX < scaleY ? scaleX : scaleY; 109 | 110 | // Offset relative to top left corner of rectangle where the page will be displayed 111 | float offsetX = 0; 112 | float offsetY = 0; 113 | 114 | float rectangleAspectRatio = displayRectangle.size.width / displayRectangle.size.height; 115 | float pageAspectRatio = pageVisibleSize.width / pageVisibleSize.height; 116 | 117 | if (pageAspectRatio < rectangleAspectRatio) { 118 | // The page is narrower than the rectangle, we place it at center on the horizontal 119 | offsetX = (displayRectangle.size.width - pageVisibleSize.width * scale) / 2; 120 | } 121 | else { 122 | // The page is wider than the rectangle, we place it at center on the vertical 123 | offsetY = (displayRectangle.size.height - pageVisibleSize.height * scale) / 2; 124 | } 125 | 126 | CGPoint topLeftPage = CGPointMake(displayRectangle.origin.x + offsetX, displayRectangle.origin.y + offsetY); 127 | 128 | [PDFPageRenderer renderPage:page inContext:context atPoint:topLeftPage withZoom:scale * 100]; 129 | } 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | 24 | 25 | 26 | #define READER_TOOLBAR_HEIGHT 44.0f 27 | 28 | #define PAGEBAR_HEIGHT_PAD 190.0f 29 | #define PAGEBAR_HEIGHT_PHONE 110.0f 30 | 31 | // following values are for iPads. For iPhones half of them are used. 32 | #define THUMB_SMALL_GAP 13.0f 33 | #define THUMB_SMALL_HEIGHT 120.0f 34 | 35 | #define PAGE_NUMBER_WIDTH 74.0f 36 | #define PAGE_NUMBER_HEIGHT 22.0f 37 | 38 | #define SLIDER_HEIGHT 40.0f 39 | #define SCROLL_SLIDER_GAP 4.0f 40 | #define TOP_SCROLL_GAP 16.0f 41 | 42 | #define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] 43 | #define UIColorFromRGBWithAlpha(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:0.99] 44 | #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) 45 | 46 | 47 | #import 48 | 49 | @interface RoboConstants : NSObject 50 | 51 | @property(nonatomic) BOOL retinaDisplay; 52 | 53 | + (RoboConstants *)instance; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboConstants.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "RoboConstants.h" 23 | 24 | @implementation RoboConstants 25 | @synthesize retinaDisplay = _retinaDisplay; 26 | 27 | + (RoboConstants *)instance { 28 | 29 | #ifdef DEBUGX 30 | NSLog(@"%s", __FUNCTION__); 31 | #endif 32 | 33 | static RoboConstants *instance = nil; 34 | static dispatch_once_t onceToken; 35 | dispatch_once(&onceToken, ^{ 36 | instance = [[self alloc] init]; 37 | }); 38 | return instance; 39 | } 40 | 41 | 42 | - (id)init { 43 | 44 | if (self = [super init]) { 45 | 46 | _retinaDisplay = [self isRetinaDisplay]; 47 | } 48 | return self; 49 | } 50 | 51 | 52 | - (BOOL)isRetinaDisplay { 53 | 54 | if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && 55 | ([UIScreen mainScreen].scale == 2.0)) { 56 | return YES; 57 | } else { 58 | return NO; 59 | } 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboContentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | 24 | @protocol RoboContentViewDelegate 25 | 26 | @optional 27 | 28 | - (void)getZoomedPages:(int)pageNum isLands:(BOOL)isLands zoomIn:(BOOL)zoomIn; 29 | 30 | @end 31 | 32 | @interface RoboContentView : UIView { 33 | @private 34 | 35 | UIScrollView *theScrollView; 36 | BOOL _isLandscape; 37 | 38 | UIImageView *theContentViewImagePDF; 39 | UIImageView *theContentViewImage2PDF; 40 | 41 | UITextField *pageNumberTextField; 42 | UITextField *pageNumberTextField2; 43 | 44 | UIView *theContainerView; 45 | BOOL noTiledLayer; 46 | int pageNumber; 47 | 48 | BOOL flag1Loaded; 49 | BOOL flag2Loaded; 50 | 51 | } 52 | 53 | 54 | - (id)initWithFrame:(CGRect)frame page:(NSUInteger)page orientation:(BOOL)isLandscape; 55 | 56 | - (void)pageContentLoadingComplete:(UIImage *)pageBarImage rightSide:(BOOL)rightSide zoomed:(BOOL)zoomed; 57 | 58 | @property(nonatomic, unsafe_unretained, readwrite) id delegate; 59 | 60 | 61 | @end 62 | 63 | 64 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboContentView.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | #import "RoboContentView.h" 24 | #import "CGPDFDocument.h" 25 | #import "RoboConstants.h" 26 | #import "RoboPDFModel.h" 27 | #import "RoboPDFController.h" 28 | 29 | #define ZOOM_LEVELS 3 30 | 31 | @implementation RoboContentView { 32 | BOOL flag1ZoomedLoaded; 33 | BOOL flag2ZoomedLoaded; 34 | } 35 | 36 | 37 | - (void)updateMinimumMaximumZoom { 38 | 39 | theScrollView.minimumZoomScale = 1.0f; 40 | 41 | theScrollView.maximumZoomScale = ZOOM_LEVELS; 42 | } 43 | 44 | 45 | - (id)initWithFrame:(CGRect)frame page:(NSUInteger)page orientation:(BOOL)isLandscape { 46 | 47 | 48 | if ((self = [super initWithFrame:frame])) 49 | { 50 | 51 | noTiledLayer = YES; 52 | pageNumber = page; 53 | _isLandscape = isLandscape; 54 | 55 | if (page == 0) 56 | page = 1; 57 | 58 | self.autoresizesSubviews = YES; 59 | self.userInteractionEnabled = YES; 60 | self.contentMode = UIViewContentModeRedraw; 61 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 62 | self.backgroundColor = [UIColor blackColor]; 63 | 64 | theScrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; 65 | 66 | theScrollView.scrollsToTop = NO; 67 | theScrollView.delaysContentTouches = NO; 68 | theScrollView.showsVerticalScrollIndicator = NO; 69 | theScrollView.showsHorizontalScrollIndicator = NO; 70 | theScrollView.backgroundColor = [UIColor blackColor]; 71 | theScrollView.userInteractionEnabled = YES; 72 | theScrollView.autoresizesSubviews = NO; 73 | theScrollView.bouncesZoom = YES; 74 | theScrollView.delegate = self; 75 | theScrollView.directionalLockEnabled = YES; 76 | 77 | theContainerView = [[UIView alloc] initWithFrame:self.bounds]; 78 | theContainerView.autoresizesSubviews = NO; 79 | theContainerView.userInteractionEnabled = NO; 80 | theContainerView.contentMode = UIViewContentModeRedraw; 81 | theContainerView.autoresizingMask = UIViewAutoresizingNone; 82 | theContainerView.backgroundColor = [UIColor blackColor]; 83 | 84 | 85 | 86 | //portrait 87 | if (!isLandscape) { 88 | 89 | theContentViewImagePDF = [[UIImageView alloc] init]; 90 | 91 | 92 | pageNumberTextField = [[UITextField alloc] initWithFrame:self.bounds]; 93 | if (page <= [RoboPDFModel instance].numberOfPages) { 94 | [pageNumberTextField setText:[NSString stringWithFormat:@"%i", page]]; 95 | } 96 | [pageNumberTextField setTextColor:[UIColor whiteColor]]; 97 | [pageNumberTextField setTextAlignment:NSTextAlignmentCenter]; 98 | [pageNumberTextField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter]; 99 | [pageNumberTextField setFont:[UIFont fontWithName:@"Helvetica-Bold" size:75]]; 100 | [theContainerView addSubview:pageNumberTextField]; 101 | 102 | } 103 | //landscape 104 | else { 105 | 106 | if (page <= 1) { 107 | 108 | theContentViewImagePDF = [[UIImageView alloc] init]; 109 | [theContentViewImagePDF setBackgroundColor:[UIColor blackColor]]; 110 | 111 | CGRect landsFrame = CGRectMake(CGRectGetWidth(frame) / 2, 0, CGRectGetWidth(frame) / 2, CGRectGetHeight(frame)); 112 | 113 | theContentViewImage2PDF = [[UIImageView alloc] init]; 114 | pageNumberTextField2 = [[UITextField alloc] initWithFrame:landsFrame]; 115 | if (page <= [RoboPDFModel instance].numberOfPages) { 116 | [pageNumberTextField2 setText:[NSString stringWithFormat:@"%i", page]]; 117 | } 118 | [pageNumberTextField2 setTextColor:[UIColor whiteColor]]; 119 | [pageNumberTextField2 setTextAlignment:NSTextAlignmentCenter]; 120 | [pageNumberTextField2 setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter]; 121 | [pageNumberTextField2 setFont:[UIFont fontWithName:@"Helvetica-Bold" size:75]]; 122 | [theContainerView addSubview:pageNumberTextField2]; 123 | 124 | } 125 | else { 126 | 127 | CGRect landsFrame = CGRectMake(0, 0, CGRectGetWidth(frame) / 2, CGRectGetHeight(frame)); 128 | 129 | theContentViewImagePDF = [[UIImageView alloc] init]; 130 | 131 | pageNumberTextField = [[UITextField alloc] initWithFrame:landsFrame]; 132 | if (page <= [RoboPDFModel instance].numberOfPages) { 133 | [pageNumberTextField setText:[NSString stringWithFormat:@"%i", page]]; 134 | } 135 | [pageNumberTextField setTextColor:[UIColor whiteColor]]; 136 | [pageNumberTextField setTextAlignment:NSTextAlignmentCenter]; 137 | [pageNumberTextField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter]; 138 | [pageNumberTextField setFont:[UIFont fontWithName:@"Helvetica-Bold" size:75]]; 139 | [theContainerView addSubview:pageNumberTextField]; 140 | 141 | 142 | theContentViewImage2PDF = [[UIImageView alloc] init]; 143 | if (page < [RoboPDFModel instance].numberOfPages) { 144 | 145 | landsFrame.origin.x = CGRectGetWidth(self.frame) / 2; 146 | pageNumberTextField2 = [[UITextField alloc] initWithFrame:landsFrame]; 147 | [pageNumberTextField2 setText:[NSString stringWithFormat:@"%i", page + 1]]; 148 | [pageNumberTextField2 setTextColor:[UIColor whiteColor]]; 149 | [pageNumberTextField2 setTextAlignment:NSTextAlignmentCenter]; 150 | [pageNumberTextField2 setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter]; 151 | [pageNumberTextField2 setFont:[UIFont fontWithName:@"Helvetica-Bold" size:75]]; 152 | [theContainerView addSubview:pageNumberTextField2]; 153 | 154 | } 155 | } 156 | } 157 | 158 | if (theContentViewImagePDF != nil) { 159 | 160 | 161 | [theContainerView addSubview:theContentViewImagePDF]; 162 | 163 | if(( isLandscape) && (theContentViewImage2PDF != NULL)){ // Landscape 164 | 165 | [theContainerView addSubview:theContentViewImage2PDF]; 166 | 167 | } 168 | 169 | theScrollView.contentSize = theContainerView.bounds.size; 170 | [theScrollView setFrame:theContainerView.frame]; 171 | 172 | [theScrollView addSubview:theContainerView]; 173 | 174 | [self updateMinimumMaximumZoom]; 175 | 176 | theScrollView.zoomScale = theScrollView.minimumZoomScale; 177 | } 178 | 179 | [self addSubview:theScrollView]; 180 | 181 | [theScrollView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:NULL]; 182 | 183 | self.tag = page; 184 | 185 | flag1Loaded = NO; 186 | flag1ZoomedLoaded = NO; 187 | flag2Loaded = NO; 188 | flag2ZoomedLoaded = NO; 189 | 190 | } 191 | 192 | 193 | return self; 194 | } 195 | 196 | 197 | - (void)pageContentLoadingComplete:(UIImage *)pageBarImage rightSide:(BOOL)rightSide zoomed:(BOOL)zoomed{ 198 | 199 | dispatch_async(dispatch_get_main_queue(), ^{ 200 | 201 | 202 | if (rightSide) { 203 | 204 | 205 | if (!flag2Loaded || !flag2ZoomedLoaded) { 206 | 207 | if (!flag2Loaded) 208 | theContentViewImage2PDF.alpha = 0; 209 | 210 | if (zoomed) 211 | flag2ZoomedLoaded = YES; 212 | 213 | flag2Loaded = YES; 214 | 215 | [pageNumberTextField2 removeFromSuperview]; 216 | pageNumberTextField2 = nil; 217 | 218 | CGRect pdfSize2 = [RoboPDFModel getPdfRectsWithSize:pageBarImage.size isLands:_isLandscape]; pdfSize2.origin.x = CGRectGetWidth(self.frame) / 2; 219 | [theContentViewImage2PDF setFrame:pdfSize2]; 220 | [theContentViewImage2PDF setImage:pageBarImage]; 221 | 222 | [UIView animateWithDuration:0.3 delay:0.0 223 | options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction 224 | animations:^(void) 225 | { 226 | theContentViewImage2PDF.alpha = 1.0f; 227 | } 228 | completion:nil 229 | ]; 230 | } 231 | 232 | } 233 | else { 234 | 235 | if (!flag1Loaded || !flag1ZoomedLoaded) { 236 | 237 | if (!flag1Loaded) 238 | theContentViewImagePDF.alpha = 0; 239 | 240 | if (zoomed) 241 | flag1ZoomedLoaded = YES; 242 | 243 | flag1Loaded = YES; 244 | 245 | [pageNumberTextField removeFromSuperview]; 246 | pageNumberTextField = nil; 247 | 248 | [theContentViewImagePDF setFrame:[RoboPDFModel getPdfRectsWithSize:pageBarImage.size isLands:_isLandscape]]; 249 | [theContentViewImagePDF setImage:pageBarImage]; 250 | 251 | [UIView animateWithDuration:0.3 delay:0.0 252 | options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction 253 | animations:^(void) 254 | { 255 | theContentViewImagePDF.alpha = 1.0f; 256 | 257 | } 258 | completion:nil 259 | ]; 260 | } 261 | 262 | } 263 | }); 264 | 265 | 266 | } 267 | 268 | - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { 269 | 270 | 271 | return theContainerView; 272 | } 273 | 274 | - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view { 275 | 276 | if (noTiledLayer) { 277 | noTiledLayer = NO; 278 | [_delegate getZoomedPages:pageNumber isLands:_isLandscape zoomIn:YES]; 279 | 280 | } 281 | 282 | } 283 | 284 | - (void)dealloc { 285 | 286 | [theScrollView removeObserver:self forKeyPath:@"frame"]; 287 | 288 | theScrollView = nil; 289 | 290 | theContainerView = nil; 291 | 292 | theContentViewImagePDF = nil; 293 | 294 | theContentViewImage2PDF = nil; 295 | 296 | } 297 | 298 | @end 299 | 300 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboDocument.h: -------------------------------------------------------------------------------- 1 | // 2 | // RoboDocument.h 3 | // Robo v2.5.4 4 | // 5 | // Copyright © 2011-2012 Julius Oklamcak. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights to 10 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | // of the Software, and to permit persons to whom the Software is furnished to 12 | // do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | // 24 | 25 | #import 26 | 27 | @interface RoboDocument : NSObject { 28 | @private // Instance variables 29 | 30 | NSString *_guid; 31 | 32 | NSDate *_fileDate; 33 | 34 | NSDate *_lastOpen; 35 | 36 | NSNumber *_fileSize; 37 | 38 | NSNumber *_pageCount; 39 | 40 | 41 | NSMutableIndexSet *_bookmarks; 42 | 43 | NSString *_fileName; 44 | 45 | NSString *_password; 46 | 47 | NSURL *_fileURL; 48 | } 49 | 50 | @property(nonatomic, strong, readonly) NSString *guid; 51 | @property(nonatomic, strong, readonly) NSDate *fileDate; 52 | @property(nonatomic, strong, readwrite) NSDate *lastOpen; 53 | @property(nonatomic, strong, readonly) NSNumber *fileSize; 54 | @property(nonatomic, strong, readonly) NSNumber *pageCount; 55 | @property(nonatomic, strong, readwrite) NSNumber *currentPage; 56 | @property(nonatomic, strong, readonly) NSMutableIndexSet *bookmarks; 57 | @property(nonatomic, strong, readonly) NSString *fileName; 58 | @property(nonatomic, strong, readonly) NSString *password; 59 | @property(nonatomic, strong, readonly) NSURL *fileURL; 60 | 61 | + (RoboDocument *)withDocumentFilePath:(NSString *)filename password:(NSString *)phrase; 62 | 63 | + (RoboDocument *)unarchiveFromFileName:(NSString *)filename password:(NSString *)phrase; 64 | 65 | - (id)initWithFilePath:(NSString *)fullFilePath password:(NSString *)phrase; 66 | 67 | - (void)saveRoboDocument; 68 | 69 | - (void)updateProperties; 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboDocument.m: -------------------------------------------------------------------------------- 1 | // 2 | // RoboDocument.m 3 | // Robo v2.5.4 4 | // 5 | // Copyright © 2011-2012 Julius Oklamcak. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights to 10 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | // of the Software, and to permit persons to whom the Software is furnished to 12 | // do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | // 24 | 25 | #import "RoboDocument.h" 26 | #import "CGPDFDocument.h" 27 | 28 | @implementation RoboDocument 29 | 30 | @synthesize guid = _guid; 31 | @synthesize fileDate = _fileDate; 32 | @synthesize fileSize = _fileSize; 33 | @synthesize pageCount = _pageCount; 34 | @synthesize currentPage = _currentPage; 35 | @synthesize bookmarks = _bookmarks; 36 | @synthesize lastOpen = _lastOpen; 37 | @synthesize password = _password; 38 | @dynamic fileName, fileURL; 39 | 40 | 41 | + (NSString *)GUID { 42 | 43 | 44 | CFUUIDRef theUUID; 45 | CFStringRef theString; 46 | 47 | theUUID = CFUUIDCreate(NULL); 48 | 49 | theString = CFUUIDCreateString(NULL, theUUID); 50 | 51 | NSString *unique = [NSString stringWithString:(__bridge id) theString]; 52 | 53 | CFRelease(theString); 54 | CFRelease(theUUID); // Cleanup 55 | 56 | return unique; 57 | } 58 | 59 | + (NSString *)applicationPath { 60 | 61 | 62 | NSArray *documentsPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 63 | 64 | return [documentsPaths[0] stringByDeletingLastPathComponent]; // Strip "Documents" component 65 | } 66 | 67 | + (NSString *)applicationSupportPath { 68 | 69 | 70 | NSFileManager *fileManager = [NSFileManager new]; // File manager instance 71 | 72 | NSURL *pathURL = [fileManager URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:NULL]; 73 | 74 | return [pathURL path]; // Path to the application's "~/Library/Application Support" directory 75 | } 76 | 77 | + (NSString *)relativeFilePath:(NSString *)fullFilePath { 78 | 79 | 80 | assert(fullFilePath != nil); // Ensure that the full file path is not nil 81 | 82 | NSString *applicationPath = [RoboDocument applicationPath]; // Get the application path 83 | 84 | NSRange range = [fullFilePath rangeOfString:applicationPath]; // Look for the application path 85 | 86 | assert(range.location != NSNotFound); // Ensure that the application path is in the full file path 87 | 88 | return [fullFilePath stringByReplacingCharactersInRange:range withString:@""]; // Strip it out 89 | } 90 | 91 | + (NSString *)archiveFilePath:(NSString *)filename { 92 | 93 | 94 | assert(filename != nil); // Ensure that the archive file name is not nil 95 | 96 | //NSString *archivePath = [RoboDocument documentsPath]; // Application's "~/Documents" path 97 | 98 | NSString *archivePath = [RoboDocument applicationSupportPath]; // Application's "~/Library/Application Support" path 99 | 100 | NSString *archiveName = [[filename stringByDeletingPathExtension] stringByAppendingPathExtension:@"plist"]; 101 | 102 | return [archivePath stringByAppendingPathComponent:archiveName]; // "{archivePath}/'filename'.plist" 103 | } 104 | 105 | + (RoboDocument *)unarchiveFromFileName:(NSString *)filename password:(NSString *)phrase { 106 | 107 | 108 | RoboDocument *document = nil; // RoboDocument object 109 | 110 | NSString *withName = [filename lastPathComponent]; // File name only 111 | 112 | NSString *archiveFilePath = [RoboDocument archiveFilePath:withName]; 113 | 114 | @try // Unarchive an archived RoboDocument object from its property list 115 | { 116 | document = [NSKeyedUnarchiver unarchiveObjectWithFile:archiveFilePath]; 117 | 118 | if ((document != nil) && (phrase != nil)) // Set the document password 119 | { 120 | [document setValue:[phrase copy] forKey:@"password"]; 121 | } 122 | } 123 | @catch (NSException *exception) // Exception handling (just in case O_o) 124 | { 125 | #ifdef DEBUG 126 | NSLog(@"%s Caught %@: %@", __FUNCTION__, [exception name], [exception reason]); 127 | #endif 128 | } 129 | 130 | return document; 131 | } 132 | 133 | + (RoboDocument *)withDocumentFilePath:(NSString *)filePath password:(NSString *)phrase { 134 | 135 | 136 | RoboDocument *document = nil; // RoboDocument object 137 | 138 | document = [RoboDocument unarchiveFromFileName:filePath password:phrase]; 139 | 140 | if (document == nil) // Unarchive failed so we create a new RoboDocument object 141 | { 142 | document = [[RoboDocument alloc] initWithFilePath:filePath password:phrase]; 143 | } 144 | 145 | return document; 146 | } 147 | 148 | + (BOOL)isPDF:(NSString *)filePath { 149 | 150 | 151 | BOOL state = NO; 152 | 153 | if (filePath != nil) // Must have a file path 154 | { 155 | const char *path = [filePath fileSystemRepresentation]; 156 | 157 | int fd = open(path, O_RDONLY); // Open the file 158 | 159 | if (fd > 0) // We have a valid file descriptor 160 | { 161 | const unsigned char sig[4]; // File signature 162 | 163 | ssize_t len = read(fd, (void *) &sig, sizeof(sig)); 164 | 165 | if (len == 4) if (sig[0] == '%') if (sig[1] == 'P') if (sig[2] == 'D') if (sig[3] == 'F') 166 | state = YES; 167 | 168 | close(fd); // Close the file 169 | } 170 | } 171 | 172 | return state; 173 | } 174 | 175 | 176 | - (id)initWithFilePath:(NSString *)fullFilePath password:(NSString *)phrase { 177 | 178 | 179 | id object = nil; // RoboDocument object 180 | 181 | if ([RoboDocument isPDF:fullFilePath] == YES) // File must exist 182 | { 183 | if ((self = [super init])) // Initialize the superclass object first 184 | { 185 | _guid = [RoboDocument GUID]; // Create a document GUID 186 | 187 | _password = [phrase copy]; // Keep a copy of any document password 188 | 189 | _bookmarks = [NSMutableIndexSet new]; // Bookmarked pages index set 190 | 191 | _currentPage = @1; // Start page 1 192 | 193 | _fileName = [RoboDocument relativeFilePath:fullFilePath]; 194 | 195 | CFURLRef docURLRef = (__bridge CFURLRef) [self fileURL]; // CFURLRef from NSURL 196 | 197 | CGPDFDocumentRef thePDFDocRef = CGPDFDocumentCreateX(docURLRef, _password); 198 | 199 | if (thePDFDocRef != NULL) // Get the number of pages in a document 200 | { 201 | int pageCount = CGPDFDocumentGetNumberOfPages(thePDFDocRef); 202 | 203 | _pageCount = @(pageCount); 204 | 205 | CGPDFDocumentRelease(thePDFDocRef); // Cleanup 206 | } 207 | else // Cupertino, we have a problem with the document 208 | { 209 | NSAssert(NO, @"CGPDFDocumentRef == NULL"); 210 | } 211 | 212 | NSFileManager *fileManager = [NSFileManager new]; // File manager 213 | 214 | _lastOpen = [NSDate dateWithTimeIntervalSinceReferenceDate:0.0]; // Last opened 215 | 216 | NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:fullFilePath error:NULL]; 217 | 218 | _fileDate = fileAttributes[NSFileModificationDate]; // File date 219 | 220 | _fileSize = fileAttributes[NSFileSize]; // File size (bytes) 221 | 222 | [self saveRoboDocument]; // Save RoboDocument object 223 | 224 | object = self; // Return initialized RoboDocument object 225 | } 226 | } 227 | 228 | return object; 229 | } 230 | 231 | - (void)dealloc { 232 | 233 | 234 | _fileURL = nil; 235 | 236 | 237 | _fileName = nil; 238 | 239 | 240 | } 241 | 242 | - (NSString *)fileName { 243 | 244 | 245 | return [_fileName lastPathComponent]; 246 | } 247 | 248 | - (NSURL *)fileURL { 249 | 250 | 251 | if (_fileURL == nil) // Create and keep the file URL the first time it is requested 252 | { 253 | NSString *fullFilePath = [[RoboDocument applicationPath] stringByAppendingPathComponent:_fileName]; 254 | 255 | _fileURL = [[NSURL alloc] initFileURLWithPath:fullFilePath isDirectory:NO]; // File URL from full file path 256 | } 257 | 258 | return _fileURL; 259 | } 260 | 261 | - (BOOL)archiveWithFileName:(NSString *)filename { 262 | 263 | 264 | NSString *archiveFilePath = [RoboDocument archiveFilePath:filename]; 265 | 266 | return [NSKeyedArchiver archiveRootObject:self toFile:archiveFilePath]; 267 | } 268 | 269 | - (void)saveRoboDocument { 270 | 271 | 272 | [self archiveWithFileName:[self fileName]]; 273 | } 274 | 275 | - (void)updateProperties { 276 | 277 | } 278 | 279 | 280 | - (void)encodeWithCoder:(NSCoder *)encoder { 281 | 282 | 283 | [encoder encodeObject:_guid forKey:@"FileGUID"]; 284 | 285 | [encoder encodeObject:_fileName forKey:@"FileName"]; 286 | 287 | [encoder encodeObject:_fileDate forKey:@"FileDate"]; 288 | 289 | [encoder encodeObject:_pageCount forKey:@"PageCount"]; 290 | 291 | [encoder encodeObject:_currentPage forKey:@"PageNumber"]; 292 | 293 | [encoder encodeObject:_bookmarks forKey:@"Bookmarks"]; 294 | 295 | [encoder encodeObject:_fileSize forKey:@"FileSize"]; 296 | 297 | [encoder encodeObject:_lastOpen forKey:@"LastOpen"]; 298 | } 299 | 300 | - (id)initWithCoder:(NSCoder *)decoder { 301 | 302 | 303 | if ((self = [super init])) // Superclass init 304 | { 305 | _guid = [decoder decodeObjectForKey:@"FileGUID"]; 306 | 307 | _fileName = [decoder decodeObjectForKey:@"FileName"]; 308 | 309 | _fileDate = [decoder decodeObjectForKey:@"FileDate"]; 310 | 311 | _pageCount = [decoder decodeObjectForKey:@"PageCount"]; 312 | 313 | _currentPage = [decoder decodeObjectForKey:@"PageNumber"]; 314 | 315 | _bookmarks = [[decoder decodeObjectForKey:@"Bookmarks"] mutableCopy]; 316 | 317 | _fileSize = [decoder decodeObjectForKey:@"FileSize"]; 318 | 319 | _lastOpen = [decoder decodeObjectForKey:@"LastOpen"]; 320 | 321 | if (_bookmarks == nil) _bookmarks = [NSMutableIndexSet new]; 322 | 323 | if (_guid == nil) _guid = [RoboDocument GUID]; 324 | } 325 | 326 | return self; 327 | } 328 | 329 | @end 330 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboMainPagebar.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | #import "RoboPDFController.h" 24 | 25 | 26 | @class RoboMainPagebar; 27 | @class RoboTrackControl; 28 | @class RoboDocument; 29 | 30 | @protocol RoboMainPagebarDelegate 31 | 32 | @required // Delegate protocols 33 | 34 | - (void)openPage:(int)page; 35 | 36 | @end 37 | 38 | @interface ImagesFlags : NSObject 39 | 40 | @property(atomic) BOOL onPageBar; 41 | @property(atomic) BOOL isRendered; 42 | 43 | @end 44 | 45 | @interface RoboMainPagebar : UIView { 46 | @private // Instance variables 47 | CGSize barContentSize; 48 | 49 | 50 | RoboDocument *document; 51 | 52 | RoboTrackControl *trackControl; 53 | 54 | UILabel *pageLabel; 55 | 56 | UIView *pageLabelView; 57 | 58 | UISlider *pagebarSlider; 59 | 60 | BOOL sliderValueChanged; 61 | 62 | NSTimer *trackTimer; 63 | 64 | RoboPDFController *pdfController; 65 | 66 | float previewPageWidth; 67 | int beginPage; 68 | int endPage; 69 | NSMutableArray *imagesFlags; 70 | float offsetCounter; 71 | float maxOffsetForUpdate; 72 | float prevOffset; 73 | int currentWindowSize; 74 | 75 | BOOL inited; 76 | } 77 | @property(atomic, retain) NSMutableDictionary *pagesDict; 78 | @property(atomic, retain) NSMutableDictionary *renderedPages; 79 | 80 | @property(nonatomic, unsafe_unretained, readwrite) id delegate; 81 | 82 | - (id)initWithFrame:(CGRect)frame document:(RoboDocument *)object pdfController:(RoboPDFController *)pdfController; 83 | 84 | - (void)pagebarImageLoadingComplete:(UIImage *)pageBarImage page:(int)page; 85 | 86 | - (void)hidePagebar; 87 | 88 | - (void)showPagebar; 89 | 90 | - (void)didReceiveMemoryWarning; 91 | 92 | - (void)reset; 93 | 94 | - (void)start; 95 | 96 | @end 97 | 98 | 99 | // 100 | // RoboTrackControl class interface 101 | // 102 | 103 | @interface RoboTrackControl : UIScrollView { 104 | @private // Instance variables 105 | 106 | CGFloat _value; 107 | float previewPageWidth; 108 | int lastPage; 109 | UIImageView *strokeTrackImage; 110 | 111 | } 112 | 113 | @property(nonatomic, assign, readonly) CGFloat value; 114 | 115 | - (id)initWithFrame:(CGRect)frame page:(int)page previewPageWidth:(float)previewPageWidth lastPage:(int)lPage; 116 | 117 | - (void)setStrokePage:(int)page; 118 | @end -------------------------------------------------------------------------------- /RoboReader/Classes/RoboMainPagebar.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | 23 | #import "RoboMainPagebar.h" 24 | #import "RoboConstants.h" 25 | #import "RoboPDFModel.h" 26 | 27 | @implementation ImagesFlags 28 | 29 | @synthesize isRendered; 30 | @synthesize onPageBar; 31 | 32 | - (NSString *)description { 33 | return [NSString stringWithFormat:@"onPageBar = %d, isRendered = %d", onPageBar, isRendered]; 34 | } 35 | 36 | @end 37 | 38 | /** 39 | * UI size values from constants are encapsulated. 40 | * This class adjusts the given constant sizes for the current device 41 | * If the device is an iPhone, all sizes will be half. Otherwise 42 | * the they will be untouched. 43 | */ 44 | @interface RoboMainPagebarSizes : NSObject 45 | 46 | @property (nonatomic) float thumbSmallGap; 47 | @property (nonatomic) float thumbSmallHeight; 48 | @property (nonatomic) float pageNumberWidth; 49 | @property (nonatomic) float pageNumberHeight; 50 | @property (nonatomic) float sliderHeight; 51 | @property (nonatomic) float scrollSliderGap; 52 | @property (nonatomic) float topScrollGap; 53 | 54 | @end 55 | 56 | @implementation RoboMainPagebarSizes 57 | @synthesize thumbSmallGap, thumbSmallHeight, pageNumberWidth, pageNumberHeight, sliderHeight, scrollSliderGap, topScrollGap; 58 | 59 | - (id)init 60 | { 61 | self = [super init]; 62 | if (self) { 63 | thumbSmallGap = THUMB_SMALL_GAP; 64 | thumbSmallHeight = THUMB_SMALL_HEIGHT; 65 | pageNumberWidth = PAGE_NUMBER_WIDTH; 66 | pageNumberHeight = PAGE_NUMBER_HEIGHT; 67 | sliderHeight = SLIDER_HEIGHT; 68 | scrollSliderGap = SCROLL_SLIDER_GAP; 69 | topScrollGap = TOP_SCROLL_GAP; 70 | 71 | // half of their size will be used for ipads 72 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { 73 | thumbSmallGap /= 2; 74 | thumbSmallHeight /= 2; 75 | pageNumberWidth /= 2; 76 | sliderHeight /= 2; 77 | scrollSliderGap /= 2; 78 | topScrollGap /= 2; 79 | } 80 | } 81 | return self; 82 | } 83 | 84 | @end 85 | 86 | 87 | @interface RoboMainPagebar () 88 | 89 | 90 | 91 | @end 92 | 93 | @implementation RoboMainPagebar 94 | { 95 | RoboMainPagebarSizes *sizes; 96 | } 97 | @synthesize pagesDict; 98 | @synthesize renderedPages; 99 | 100 | 101 | - (id)initWithFrame:(CGRect)frame 102 | document:(RoboDocument *)object pdfController:(RoboPDFController *)ipdfController {// firstPage: (UIImage*) firstImage{ 103 | 104 | 105 | if ((self = [super initWithFrame:frame])) { 106 | inited = NO; 107 | pdfController = ipdfController; 108 | pdfController.pagebarDelegate = self; 109 | 110 | sizes = [[RoboMainPagebarSizes alloc] init]; 111 | 112 | maxOffsetForUpdate = 200; 113 | offsetCounter = 0; 114 | prevOffset = 0; 115 | currentWindowSize = 6; 116 | // firstPageImage = firstImage; 117 | // _pdfController = ipdfController; 118 | // _pdfController.pagebarDelegate = self; 119 | 120 | document = object; // Retain the document object for our use 121 | 122 | CGRect firstPageSize = [pdfController getFirstPdfPageRect]; 123 | previewPageWidth = sizes.thumbSmallHeight * firstPageSize.size.width / firstPageSize.size.height; 124 | 125 | int pages = [document.pageCount intValue]; 126 | 127 | barContentSize = CGSizeMake(pages * (previewPageWidth + sizes.thumbSmallGap) - sizes.thumbSmallGap * (-2 + pages / 2 + pages % 2), sizes.thumbSmallHeight + 2 * sizes.scrollSliderGap); 128 | 129 | self.autoresizesSubviews = YES; 130 | self.userInteractionEnabled = YES; 131 | self.contentMode = UIViewContentModeRedraw; 132 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; 133 | //self.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.6f]; 134 | [self setBackgroundColor:UIColorFromRGBWithAlpha(0x333333)]; 135 | 136 | 137 | trackControl = [[RoboTrackControl alloc] initWithFrame:CGRectMake(0, sizes.topScrollGap - sizes.scrollSliderGap, self.frame.size.width, self.frame.size.height) page:pages previewPageWidth:previewPageWidth lastPage:pages]; // Track control view 138 | [trackControl setContentSize:barContentSize]; 139 | trackControl.showsVerticalScrollIndicator = NO; 140 | trackControl.showsHorizontalScrollIndicator = NO; 141 | [trackControl addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:NULL]; 142 | UITapGestureRecognizer *trackTouchUpInside = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(trackViewTouchUpInside:)]; 143 | trackTouchUpInside.numberOfTapsRequired = 1; 144 | [trackControl addGestureRecognizer:trackTouchUpInside]; 145 | [self addSubview:trackControl]; // Add the track control and thumbs view 146 | pagebarSlider.value = [document.currentPage floatValue]; 147 | // [self sliderValueChanged:pagebarSlider]; 148 | [trackControl setStrokePage:[document.currentPage intValue]]; 149 | [trackControl setDelegate:self]; 150 | 151 | 152 | CGRect pagebarFrame = frame; 153 | pagebarFrame.origin.x = 0.0; 154 | pagebarFrame.origin.y = self.frame.size.height - sizes.sliderHeight; 155 | pagebarFrame.size.height = sizes.sliderHeight; 156 | pagebarSlider = [[UISlider alloc] initWithFrame:pagebarFrame]; 157 | [pagebarSlider setThumbImage:[UIImage imageNamed:@"page-bg.png"] forState:UIControlStateNormal]; 158 | [pagebarSlider setMinimumTrackImage:[UIImage imageNamed:@"progress_bar.png"] forState:UIControlStateNormal]; 159 | [pagebarSlider setMaximumTrackImage:[UIImage imageNamed:@"progress_bar.png"] forState:UIControlStateNormal]; 160 | [pagebarSlider setMinimumValue:1.0f]; 161 | [pagebarSlider setMaximumValue:pages]; 162 | [pagebarSlider setValue:[document.currentPage floatValue]]; 163 | [pagebarSlider setContinuous:YES]; 164 | [pagebarSlider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged]; 165 | [self addSubview:pagebarSlider]; 166 | 167 | 168 | CGRect numberRect = CGRectMake(0, self.frame.size.height - sizes.sliderHeight + (pagebarSlider.frame.size.height - sizes.pageNumberHeight) / 2, sizes.pageNumberWidth, sizes.pageNumberHeight); 169 | pageLabelView = [[UIView alloc] initWithFrame:numberRect]; // Page numbers view 170 | pageLabelView.autoresizesSubviews = NO; 171 | pageLabelView.userInteractionEnabled = NO; 172 | pageLabelView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; 173 | pageLabelView.backgroundColor = [UIColor clearColor]; 174 | [self addSubview:pageLabelView]; 175 | 176 | 177 | CGRect textRect = CGRectMake(0, 0, sizes.pageNumberWidth, sizes.pageNumberHeight); 178 | pageLabel = [[UILabel alloc] initWithFrame:textRect]; // Page numbers label 179 | pageLabel.autoresizesSubviews = NO; 180 | pageLabel.autoresizingMask = UIViewAutoresizingNone; 181 | pageLabel.textAlignment = NSTextAlignmentCenter; 182 | pageLabel.backgroundColor = [UIColor clearColor]; 183 | pageLabel.textColor = UIColorFromRGB(0xBEBEBE); 184 | [pageLabel setFont:[UIFont fontWithName:@"Helvetica" size:16.0f]]; 185 | //[pageLabelView addSubview:pageLabel]; // Add label view 186 | 187 | 188 | 189 | CGRect barContentRect = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, barContentSize.width, barContentSize.height); 190 | CGRect controlRect = CGRectInset(barContentRect, 4.0f, 0.0f); 191 | 192 | CGFloat previewPageWidthWithGap = (previewPageWidth + sizes.thumbSmallGap); 193 | 194 | CGFloat heightDelta = (controlRect.size.height - sizes.thumbSmallHeight); 195 | 196 | float thumbY = (heightDelta / 2.0f); 197 | float thumbX = 0; // Initial X, Y 198 | 199 | CGRect thumbRect = CGRectMake(thumbX, thumbY, previewPageWidth, sizes.thumbSmallHeight + 11); 200 | // pagebarImages = [[NSMutableArray alloc] init]; 201 | 202 | thumbRect.origin.x += sizes.thumbSmallGap; 203 | // first page 204 | 205 | // middle pages 206 | 207 | pagesDict = [[NSMutableDictionary alloc] init]; 208 | renderedPages = [[NSMutableDictionary alloc] init]; 209 | imagesFlags = [[NSMutableArray alloc] init]; 210 | beginPage = -1; 211 | for (int page = 1; page <= pages; page++) // Iterate through needed thumbs 212 | { 213 | if (page > pages) page = pages; // Page 214 | 215 | // We need to create a new small thumb view for the page number 216 | 217 | // UIImageView *smallThumbView = [[UIImageView alloc] initWithFrame:thumbRect]; 218 | CGRect textFieldRect = thumbRect; 219 | textFieldRect.origin.y += textFieldRect.size.height; 220 | textFieldRect.size.height = 10.0f; 221 | UITextField *currentPageTextField = [[UITextField alloc] initWithFrame:textFieldRect]; 222 | [currentPageTextField setTextColor:UIColorFromRGB(0xCCCCCC)]; 223 | [currentPageTextField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter]; 224 | [currentPageTextField setFont:[UIFont fontWithName:@"Helvetica" size:10]]; 225 | 226 | //UITextField *smallThumbTextLeft; 227 | //UITextField *smallThumbTextRight; 228 | //[smallThumbView setBackgroundColor:[UIColor purpleColor]]; 229 | 230 | if (page % 2) { 231 | // [smallThumbView setImage: [UIImage imageNamed:@"page_right.png"]]; 232 | thumbRect.origin.x += previewPageWidthWithGap; 233 | [currentPageTextField setTextAlignment:NSTextAlignmentLeft]; 234 | [currentPageTextField setText:[NSString stringWithFormat:@" %i", page]]; 235 | } 236 | else { 237 | // [smallThumbView setImage: [UIImage imageNamed:@"page_left.png"]]; 238 | thumbRect.origin.x += previewPageWidthWithGap - sizes.thumbSmallGap; 239 | [currentPageTextField setTextAlignment:NSTextAlignmentRight]; 240 | [currentPageTextField setText:[NSString stringWithFormat:@"%i ", page]]; 241 | } 242 | //[smallThumbView addSubview:smallThumbTextLeft]; 243 | // [trackControl addSubview:smallThumbView]; 244 | [trackControl addSubview:currentPageTextField]; 245 | //[pagebarImages addObject:smallThumbView]; 246 | // Next thumb X position 247 | // [pagesDict setValue:smallThumbView forKey:[NSString stringWithFormat:@"%d", page]]; 248 | 249 | endPage = page; 250 | ImagesFlags *imageFlags = [[ImagesFlags alloc] init]; 251 | [imagesFlags addObject:imageFlags]; 252 | } 253 | 254 | [self sliderValueChanged:pagebarSlider]; 255 | 256 | CGRect newFrame = self.frame; 257 | newFrame.origin.y += newFrame.size.height; 258 | [self setFrame:newFrame]; 259 | self.alpha = 0.0f; 260 | 261 | [self start]; 262 | /* [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];*/ 263 | } 264 | 265 | 266 | return self; 267 | } 268 | 269 | 270 | - (void)pagebarImageLoadingComplete:(UIImage *)pageBarImage page:(int)page { 271 | if (inited) { 272 | dispatch_async(dispatch_get_main_queue(), ^{ 273 | NSString *key = [NSString stringWithFormat:@"%d", page]; 274 | if ([renderedPages valueForKey:key] == nil) { 275 | 276 | CGRect barContentRect = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, barContentSize.width, barContentSize.height); 277 | CGRect controlRect = CGRectInset(barContentRect, 4.0f, 0.0f); 278 | CGFloat heightDelta = (controlRect.size.height - sizes.thumbSmallHeight); 279 | 280 | float thumbY = (heightDelta / 2.0f); 281 | float thumbX = (page - 1) * (previewPageWidth + sizes.thumbSmallGap) - sizes.thumbSmallGap * (-2 + page / 2 + page % 2);// Initial X, Y 282 | 283 | CGRect thumbRect = CGRectMake(thumbX, thumbY, previewPageWidth, sizes.thumbSmallHeight); 284 | 285 | UIImageView *thumbView = [[UIImageView alloc] initWithFrame:thumbRect]; 286 | 287 | [thumbView setImage:pageBarImage]; 288 | 289 | [renderedPages setObject:thumbView forKey:key]; 290 | ((ImagesFlags *) imagesFlags[page - 1]).isRendered = YES; 291 | 292 | UIView *previousThumbView = [pagesDict objectForKey:key]; 293 | if (previousThumbView != nil) { 294 | [pagesDict removeObjectForKey:key]; 295 | [pagesDict setObject:thumbView forKey:key]; 296 | 297 | if ([previousThumbView superview] != nil) { 298 | if ([self onScreen:page]) { 299 | thumbView.alpha = 0; 300 | [trackControl addSubview:thumbView]; 301 | [UIView animateWithDuration:0.3 delay:0.0 302 | options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction 303 | animations:^(void) { 304 | thumbView.alpha = 1.0f; 305 | } 306 | completion:^(BOOL f) { 307 | thumbView.alpha = 1.0f; 308 | [previousThumbView removeFromSuperview]; 309 | } 310 | ]; 311 | } else { 312 | [trackControl addSubview:thumbView]; 313 | } 314 | } 315 | } 316 | } 317 | 318 | }); 319 | } 320 | } 321 | 322 | 323 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 324 | 325 | 326 | if ([keyPath isEqualToString:@"contentOffset"] && !sliderValueChanged) { 327 | UIScrollView *trackScroll = (UIScrollView *) object; 328 | 329 | float ratio = 0.0; 330 | if (barContentSize.width != self.bounds.size.width) 331 | ratio = trackScroll.contentOffset.x / (barContentSize.width - self.bounds.size.width); 332 | 333 | float pagebarOffset; 334 | if (ratio > 0.0 && ratio < 1.0) 335 | pagebarOffset = ([document.pageCount floatValue]) * ratio; 336 | else if (ratio >= 1.0) 337 | pagebarOffset = [document.pageCount floatValue]; 338 | else if (ratio <= 0.0) 339 | pagebarOffset = 1.0f; 340 | else pagebarOffset = 0; 341 | 342 | 343 | //set slider text and position 344 | float currentPage = 1.0f; 345 | if (pagebarSlider.maximumValue != pagebarSlider.minimumValue) 346 | currentPage = pagebarOffset * (pagebarSlider.maximumValue / (pagebarSlider.maximumValue - pagebarSlider.minimumValue)); 347 | if (currentPage > [document.pageCount floatValue]) 348 | currentPage = [document.pageCount floatValue]; 349 | //currentSliderPage = currentPage; 350 | 351 | float sliderRatio = 0; 352 | if (pagebarSlider.maximumValue != pagebarSlider.minimumValue) 353 | sliderRatio = (pagebarOffset - pagebarSlider.minimumValue) / (pagebarSlider.maximumValue - pagebarSlider.minimumValue); 354 | if (sliderRatio < 0) 355 | sliderRatio = 0; 356 | if (sliderRatio > 1) 357 | sliderRatio = 1; 358 | 359 | CGRect pageLabelViewRect = CGRectMake((self.bounds.size.width - sizes.pageNumberWidth) * sliderRatio, self.frame.size.height - sizes.sliderHeight + (pagebarSlider.frame.size.height - sizes.pageNumberHeight) / 2, sizes.pageNumberWidth, sizes.pageNumberHeight); 360 | [pageLabelView setFrame:pageLabelViewRect]; 361 | 362 | int labelPage = currentPage; 363 | if (labelPage < 1) 364 | labelPage = 1; 365 | 366 | [pageLabel setText:[NSString stringWithFormat:@"%i / %i", labelPage, [document.pageCount intValue]]]; 367 | 368 | [pagebarSlider setValue:pagebarOffset animated:NO]; 369 | 370 | 371 | } 372 | } 373 | 374 | 375 | - (void)sliderValueChanged:(UISlider *)sender { 376 | 377 | sliderValueChanged = YES; 378 | 379 | CGPoint offset = trackControl.contentOffset; 380 | [trackControl setContentOffset:offset animated:NO]; 381 | 382 | float documentPage = [document.pageCount floatValue]; 383 | 384 | int page = sender.value; 385 | if (page < 1) 386 | page = 1; 387 | if (page > documentPage) 388 | page = documentPage; 389 | 390 | double ratio = 0; 391 | if (sender.maximumValue != sender.minimumValue) 392 | ratio = (sender.value - sender.minimumValue) / (sender.maximumValue - sender.minimumValue); 393 | 394 | if (ratio < 0) 395 | ratio = 0; 396 | if (ratio > 1) 397 | ratio = 1; 398 | 399 | CGRect pageLabelViewRect = CGRectMake((self.bounds.size.width - sizes.pageNumberWidth) * ratio, self.frame.size.height - sizes.sliderHeight + (pagebarSlider.frame.size.height - sizes.pageNumberHeight) / 2, sizes.pageNumberWidth, sizes.pageNumberHeight); 400 | [pageLabelView setFrame:pageLabelViewRect]; 401 | 402 | [pageLabel setText:[NSString stringWithFormat:@"%i / %i", page, [document.pageCount intValue]]]; 403 | 404 | [trackControl setContentOffset:CGPointMake((barContentSize.width - self.bounds.size.width) * ratio, 0)]; 405 | 406 | sliderValueChanged = NO; 407 | } 408 | 409 | 410 | - (void)dealloc { 411 | 412 | //pdfController.stop = YES; 413 | _delegate = nil; 414 | 415 | 416 | [trackTimer invalidate]; 417 | 418 | trackTimer = nil; 419 | 420 | pagebarSlider = nil; 421 | 422 | [trackControl removeObserver:self forKeyPath:@"contentOffset"]; 423 | trackControl = nil; 424 | 425 | pageLabel = nil; 426 | 427 | pageLabelView = nil; 428 | 429 | document = nil; 430 | 431 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 432 | [pagesDict removeAllObjects]; 433 | pagesDict = nil; 434 | 435 | } 436 | 437 | - (void)layoutSubviews { 438 | 439 | CGRect trackRect = trackControl.frame; 440 | trackRect.size.width = self.bounds.size.width; 441 | [trackControl setFrame:trackRect]; 442 | 443 | CGRect sliderFrame = pagebarSlider.frame; 444 | sliderFrame.size.width = self.bounds.size.width; 445 | [pagebarSlider setFrame:sliderFrame]; 446 | 447 | } 448 | 449 | 450 | - (void)hidePagebar { 451 | 452 | [UIView animateWithDuration:0.1 delay:0.0 453 | options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction 454 | animations:^(void) { 455 | CGRect newFrame = self.frame; 456 | newFrame.origin.y += newFrame.size.height; 457 | [self setFrame:newFrame]; 458 | self.alpha = 0.0f; 459 | } 460 | completion:^(BOOL finished) { 461 | } 462 | ]; 463 | 464 | } 465 | 466 | 467 | - (void)showPagebar { 468 | offsetCounter = maxOffsetForUpdate; 469 | pagebarSlider.value = [document.currentPage floatValue]; 470 | [self sliderValueChanged:pagebarSlider]; 471 | [trackControl setStrokePage:[document.currentPage intValue]]; 472 | [UIView animateWithDuration:0.1 delay:0.0 473 | options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction 474 | animations:^(void) { 475 | self.alpha = 1.0f; 476 | CGRect newFrame = self.frame; 477 | newFrame.origin.y -= newFrame.size.height; 478 | [self setFrame:newFrame]; 479 | } 480 | completion:NULL 481 | ]; 482 | 483 | } 484 | 485 | 486 | - (void)trackViewTouchUpInside:(UITapGestureRecognizer *)recognizer { 487 | 488 | if (recognizer.state == UIGestureRecognizerStateRecognized) { 489 | CGPoint point = [recognizer locationInView:recognizer.view]; 490 | 491 | int page = 0; 492 | 493 | while (point.x > (page * (previewPageWidth + sizes.thumbSmallGap) - sizes.thumbSmallGap * (-1 + page / 2 + page % 2))) 494 | page++; 495 | 496 | if (page < 1) 497 | page = 1; 498 | 499 | if (page > [document.pageCount intValue]) 500 | page = [document.pageCount intValue]; 501 | 502 | [_delegate openPage:page]; 503 | 504 | [trackControl setStrokePage:page]; 505 | } 506 | } 507 | 508 | 509 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 510 | offsetCounter += fabsf(scrollView.contentOffset.x - prevOffset); 511 | prevOffset = scrollView.contentOffset.x; 512 | if (offsetCounter > maxOffsetForUpdate) { 513 | [self updateFirstAndLastPagesOnScreen2:scrollView.contentOffset.x withRemoving:NO]; 514 | offsetCounter = 0; 515 | } 516 | } 517 | 518 | 519 | - (void)updateFirstAndLastPagesOnScreen2:(float)offset withRemoving:(BOOL)withRemoving { 520 | if (inited) { 521 | #warning fix the number 1024 1 522 | int newBeginPage = floor((offset - previewPageWidth) / (sizes.thumbSmallGap / 2 + previewPageWidth)) + 1; 523 | int newEndPage = floor((offset + CGRectGetWidth(self.frame)) / (sizes.thumbSmallGap / 2 + previewPageWidth)) + 2; 524 | 525 | newBeginPage -= currentWindowSize; 526 | newEndPage += currentWindowSize; 527 | 528 | if (newBeginPage < 1) newBeginPage = 1; 529 | if (newBeginPage > [document.pageCount intValue]) newBeginPage = [document.pageCount intValue]; 530 | if (newEndPage < 1) newEndPage = 1; 531 | if (newEndPage > [document.pageCount intValue]) newEndPage = [document.pageCount intValue]; 532 | 533 | if (beginPage != newBeginPage || endPage != newEndPage || withRemoving) { 534 | beginPage = newBeginPage; 535 | endPage = newEndPage; 536 | int i; 537 | 538 | // if (withRemoving) { 539 | for (i = 1; i < beginPage; i++) { 540 | //disappear 541 | [self deleteSmallPageView:i]; 542 | } 543 | for (i = endPage + 1; i <= [document.pageCount intValue]; i++) { 544 | [self deleteSmallPageView:i]; 545 | } 546 | // } 547 | for (i = beginPage; i <= endPage; i++) { 548 | [self initSmallPageView:i]; 549 | } 550 | } 551 | } 552 | 553 | } 554 | 555 | - (void)initSmallPageView:(int)page { 556 | NSString *key = [NSString stringWithFormat:@"%d", page]; 557 | 558 | UIImageView *smallThumbView = [pagesDict valueForKey:key]; 559 | if (smallThumbView == nil) { 560 | if ([renderedPages objectForKey:key] != nil) { 561 | smallThumbView = [renderedPages objectForKey:key]; 562 | ((ImagesFlags *) imagesFlags[page - 1]).onPageBar = YES; 563 | } else { 564 | CGRect barContentRect = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, barContentSize.width, barContentSize.height); 565 | CGRect controlRect = CGRectInset(barContentRect, 4.0f, 0.0f); 566 | CGFloat heightDelta = (controlRect.size.height - sizes.thumbSmallHeight); 567 | 568 | float thumbY = (heightDelta / 2.0f); 569 | float thumbX = (page - 1) * (previewPageWidth + sizes.thumbSmallGap) - sizes.thumbSmallGap * (-2 + page / 2 + page % 2);// Initial X, Y 570 | 571 | CGRect thumbRect = CGRectMake(thumbX, thumbY, previewPageWidth, sizes.thumbSmallHeight + 11); 572 | 573 | // We need to create a new small thumb view for the page number 574 | 575 | smallThumbView = [[UIImageView alloc] initWithFrame:thumbRect]; 576 | if (page % 2) { 577 | //smallThumbText = [[UITextField alloc] initWithFrame:CGRectMake(thumbRect.origin.x, thumbSmallHeight, 20, 20)]; 578 | [smallThumbView setImage:[UIImage imageNamed:@"page_right"]]; 579 | } 580 | else { 581 | [smallThumbView setImage:[UIImage imageNamed:@"page_left"]]; 582 | } 583 | [pdfController addGettingPageBarImageToQueue:page]; 584 | } 585 | [pagesDict setValue:smallThumbView forKey:key]; 586 | ((ImagesFlags *) imagesFlags[page - 1]).onPageBar = YES; 587 | } else { 588 | if ([renderedPages objectForKey:key] == nil) { 589 | [pdfController addGettingPageBarImageToQueue:page]; 590 | } 591 | } 592 | if ([smallThumbView superview] == nil) 593 | [trackControl addSubview:smallThumbView]; 594 | } 595 | 596 | - (void)deleteSmallPageView:(int)i { 597 | NSString *key = [NSString stringWithFormat:@"%d", i]; 598 | UIView *previousThumbView = [pagesDict objectForKey:key]; 599 | if (previousThumbView != nil) { 600 | ((ImagesFlags *) imagesFlags[i - 1]).onPageBar = NO; 601 | [previousThumbView removeFromSuperview]; 602 | [pagesDict removeObjectForKey:key]; 603 | } 604 | UIImageView *renderedView = [renderedPages objectForKey:key]; 605 | if (renderedView != nil) { 606 | ((ImagesFlags *) imagesFlags[i - 1]).isRendered = NO; 607 | [renderedView removeFromSuperview]; 608 | [renderedPages removeObjectForKey:key]; 609 | } 610 | } 611 | 612 | - (void)clearImageCache { 613 | [self updateFirstAndLastPagesOnScreen2:trackControl.contentOffset.x withRemoving:YES]; 614 | for (int i = 1; i < beginPage; i++) { 615 | NSString *key = [NSString stringWithFormat:@"%d", i]; 616 | UIImageView *previousThumbView = [pagesDict objectForKey:key]; 617 | if (previousThumbView != nil) { 618 | ((ImagesFlags *) imagesFlags[i - 1]).onPageBar = NO; 619 | [previousThumbView removeFromSuperview]; 620 | [pagesDict removeObjectForKey:key]; 621 | } 622 | UIImageView *renderedView = [renderedPages objectForKey:key]; 623 | if (renderedView != nil) { 624 | ((ImagesFlags *) imagesFlags[i - 1]).isRendered = NO; 625 | [renderedView removeFromSuperview]; 626 | [renderedPages removeObjectForKey:key]; 627 | } 628 | } 629 | for (int i = endPage + 1; i <= [document.pageCount intValue]; i++) { 630 | NSString *key = [NSString stringWithFormat:@"%d", i]; 631 | UIView *previousThumbView = [pagesDict objectForKey:key]; 632 | if (previousThumbView != nil) { 633 | ((ImagesFlags *) imagesFlags[i - 1]).onPageBar = NO; 634 | [previousThumbView removeFromSuperview]; 635 | [pagesDict removeObjectForKey:key]; 636 | } 637 | UIImageView *renderedView = [renderedPages objectForKey:key]; 638 | if (renderedView != nil) { 639 | ((ImagesFlags *) imagesFlags[i - 1]).isRendered = NO; 640 | [renderedView removeFromSuperview]; 641 | [renderedPages removeObjectForKey:key]; 642 | } 643 | } 644 | } 645 | 646 | - (BOOL)isNeedLoad:(int)i { 647 | /* NSString* key = [NSString stringWithFormat:@"%d", i]; 648 | 649 | if ([[renderedPages allKeys] containsObject:key]) return NO;// already rendered 650 | if ([[pagesDict allKeys] containsObject:key]) return YES;// not rendered and on pagebar 651 | if ([self allPagesOnScreenRendered]) return YES;// not rendered and not on pagebar, but all important pages loaded*/ 652 | 653 | if (((ImagesFlags *) imagesFlags[i - 1]).isRendered) return NO;// already rendered 654 | if (((ImagesFlags *) imagesFlags[i - 1]).onPageBar) return YES;// not rendered and on pagebar 655 | 656 | return NO; 657 | // if ([self allPagesOnScreenRendered] && flagMemoryIsOK) return YES;// not rendered and not on pagebar, all important pages loaded, and memOK 658 | 659 | // return NO;// not rendered and not on pagebar and low memory 660 | } 661 | 662 | - (BOOL)allPagesOnScreenRendered { 663 | 664 | for (int i = MAX(beginPage, 1); i <= endPage; i++) { 665 | if (!((ImagesFlags *) imagesFlags[i - 1]).isRendered) return NO; 666 | } 667 | 668 | return YES; 669 | } 670 | 671 | - (void)didReceiveMemoryWarning { 672 | [self clearImageCache]; 673 | } 674 | 675 | - (BOOL)onScreen:(int)i { 676 | 677 | int onScreenBeginPage = floor((trackControl.contentOffset.x - previewPageWidth) / (sizes.thumbSmallGap / 2 + previewPageWidth)) + 1; 678 | int onScreenEndPage = floor((trackControl.contentOffset.x + CGRectGetWidth(self.frame)) / (sizes.thumbSmallGap / 2 + previewPageWidth)) + 2; 679 | 680 | if (onScreenBeginPage <= i <= onScreenEndPage) return YES; 681 | else return NO; 682 | } 683 | 684 | - (void)reset { 685 | inited = NO; 686 | beginPage = 0; 687 | endPage = 0; 688 | for (int i = 1; i <= [document.pageCount intValue]; i++) { 689 | NSString *key = [NSString stringWithFormat:@"%d", i]; 690 | UIImageView *renderedView = [renderedPages objectForKey:key]; 691 | if (renderedView != nil) { 692 | ((ImagesFlags *) imagesFlags[i - 1]).isRendered = NO; 693 | [renderedView removeFromSuperview]; 694 | [renderedPages removeObjectForKey:key]; 695 | } 696 | [self deleteSmallPageView:i]; 697 | } 698 | } 699 | 700 | - (void)start { 701 | inited = YES; 702 | [self updateFirstAndLastPagesOnScreen2:trackControl.contentOffset.x withRemoving:YES]; 703 | } 704 | 705 | @end 706 | 707 | 708 | @implementation RoboTrackControl 709 | { 710 | RoboMainPagebarSizes *sizes; 711 | } 712 | @synthesize value = _value; 713 | 714 | 715 | - (id)initWithFrame:(CGRect)frame page:(int)page previewPageWidth:(float)previewWidth lastPage:(int)lPage { 716 | 717 | 718 | if ((self = [super initWithFrame:frame])) { 719 | self.autoresizesSubviews = NO; 720 | self.userInteractionEnabled = YES; 721 | self.contentMode = UIViewContentModeRedraw; 722 | self.autoresizingMask = UIViewAutoresizingNone; 723 | self.backgroundColor = [UIColor clearColor]; 724 | 725 | sizes = [[RoboMainPagebarSizes alloc] init]; 726 | 727 | previewPageWidth = previewWidth; 728 | lastPage = lPage; 729 | 730 | strokeTrackImage = [[UIImageView alloc] init]; 731 | [self addSubview:strokeTrackImage]; 732 | [strokeTrackImage setImage:[UIImage imageNamed:@"Stroke2px.png"]]; 733 | 734 | } 735 | 736 | return self; 737 | } 738 | 739 | 740 | - (void)setStrokePage:(int)page { 741 | 742 | if (page == 0) 743 | page = 1; 744 | 745 | float pageOffset; 746 | CGRect orangeOffset; 747 | if (page == 1 || (page == lastPage && !(lastPage % 2))) { 748 | pageOffset = page * (previewPageWidth + sizes.thumbSmallGap) - sizes.thumbSmallGap * (-1 + page / 2 + page % 2); 749 | // first or last page and odd number of pages in pdf 750 | if (page == 1) 751 | orangeOffset = CGRectMake(sizes.thumbSmallGap - 6, 0, previewPageWidth + 12, sizes.thumbSmallHeight + 8); 752 | else 753 | orangeOffset = CGRectMake(pageOffset - previewPageWidth - 6, 0, previewPageWidth + 12, sizes.thumbSmallHeight + 8); 754 | [strokeTrackImage setImage:[UIImage imageNamed:@"Stroke2px_single.png"]]; 755 | [strokeTrackImage setFrame:orangeOffset]; 756 | 757 | } 758 | else { 759 | // not first and not last 760 | if (page % 2) { 761 | pageOffset = page * (previewPageWidth + sizes.thumbSmallGap) - sizes.thumbSmallGap * (-1 + page / 2 + page % 2); 762 | orangeOffset = CGRectMake(pageOffset - 2 * previewPageWidth - 6, 0, previewPageWidth * 2 + 12, sizes.thumbSmallHeight + 8); 763 | [strokeTrackImage setImage:[UIImage imageNamed:@"Stroke2px.png"]]; 764 | [strokeTrackImage setFrame:orangeOffset]; 765 | } 766 | else [self setStrokePage:(page + 1)]; 767 | 768 | } 769 | } 770 | 771 | - (void)dealloc { 772 | 773 | 774 | } 775 | 776 | 777 | @end -------------------------------------------------------------------------------- /RoboReader/Classes/RoboMainToolbar.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | 23 | #import 24 | 25 | 26 | @class RoboMainToolbar; 27 | 28 | @protocol RoboMainToolbarDelegate 29 | 30 | @required // Delegate protocols 31 | 32 | - (void)dismissButtonTapped; 33 | 34 | @end 35 | 36 | @interface RoboMainToolbar : UIView { 37 | @private // Instance variables 38 | 39 | UILabel *theTitleLabel; 40 | } 41 | 42 | @property(nonatomic, unsafe_unretained, readwrite) id delegate; 43 | 44 | - (id)initWithFrame:(CGRect)frame title:(NSString *)title; 45 | 46 | 47 | - (void)hideToolbar; 48 | 49 | - (void)showToolbar; 50 | 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboMainToolbar.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | 23 | #import "RoboMainToolbar.h" 24 | #import "RoboConstants.h" 25 | 26 | @implementation RoboMainToolbar 27 | 28 | 29 | #define TITLE_Y 8.0f 30 | #define TITLE_X 12.0f 31 | #define TITLE_HEIGHT 28.0f 32 | 33 | 34 | 35 | #define BUTTON_X 0.0f 36 | #define BUTTON_Y 0.0f 37 | #define DONE_BUTTON_WIDTH 44.0f 38 | 39 | 40 | @synthesize delegate; 41 | 42 | 43 | - (id)initWithFrame:(CGRect)frame { 44 | 45 | 46 | return [self initWithFrame:frame title:nil]; 47 | } 48 | 49 | - (id)initWithFrame:(CGRect)frame title:(NSString *)title { 50 | 51 | 52 | if ((self = [super initWithFrame:frame])) { 53 | 54 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth; 55 | 56 | CGFloat titleX = TITLE_X; 57 | CGFloat titleWidth = (self.bounds.size.width - (titleX * 2.0f)); 58 | #warning fix the number 1024, reset toolbar img frame on orientation change 59 | UIImageView *toolbarImg = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024.0f, frame.size.height)]; 60 | [toolbarImg setImage:[UIImage imageNamed:@"nav_bar_plashka.png"]]; 61 | [self addSubview:toolbarImg]; 62 | 63 | // shift buttons a little to avoid overlapping with ios7 status bar 64 | float ios7padding = (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) ? 7.0f : 0.0f; 65 | 66 | CGRect titleRect = CGRectMake(titleX, TITLE_Y + ios7padding, titleWidth, TITLE_HEIGHT); 67 | 68 | theTitleLabel = [[UILabel alloc] initWithFrame:titleRect]; 69 | 70 | theTitleLabel.text = title; // Toolbar title 71 | theTitleLabel.textAlignment = NSTextAlignmentCenter; 72 | theTitleLabel.font = [UIFont systemFontOfSize:20.0f]; 73 | theTitleLabel.textColor = [UIColor colorWithWhite:1.0f alpha:1.0f]; 74 | theTitleLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; 75 | theTitleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; 76 | theTitleLabel.backgroundColor = [UIColor clearColor]; 77 | theTitleLabel.adjustsFontSizeToFitWidth = YES; 78 | [self addSubview:theTitleLabel]; 79 | 80 | UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom]; 81 | 82 | doneButton.frame = CGRectMake(BUTTON_X, BUTTON_Y, DONE_BUTTON_WIDTH, READER_TOOLBAR_HEIGHT); 83 | 84 | [doneButton addTarget:self action:@selector(doneButtonTapped:) forControlEvents:UIControlEventTouchDown]; 85 | 86 | UIImageView *backImage = [[UIImageView alloc] initWithFrame:CGRectMake((READER_TOOLBAR_HEIGHT - 18) / 2, (READER_TOOLBAR_HEIGHT - 18) / 2 + ios7padding, 13, 18)]; 87 | [backImage setImage:[UIImage imageNamed:@"back_button.png"]]; 88 | [doneButton addSubview:backImage]; 89 | 90 | doneButton.autoresizingMask = UIViewAutoresizingNone; 91 | 92 | [self addSubview:doneButton]; 93 | 94 | CGRect newFrame = self.frame; 95 | newFrame.origin.y -= newFrame.size.height; 96 | [self setFrame:newFrame]; 97 | self.alpha = 0.0f; 98 | self.hidden = YES; 99 | 100 | } 101 | 102 | return self; 103 | } 104 | 105 | - (void)dealloc { 106 | 107 | 108 | theTitleLabel = nil; 109 | 110 | } 111 | 112 | 113 | - (void)hideToolbar { 114 | 115 | if (self.hidden == NO) { 116 | [UIView animateWithDuration:0.1 delay:0.0 117 | options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction 118 | animations:^(void) { 119 | CGRect newFrame = self.frame; 120 | newFrame.origin.y -= newFrame.size.height; 121 | [self setFrame:newFrame]; 122 | self.alpha = 0.0f; 123 | } 124 | completion:^(BOOL finished) { 125 | self.hidden = YES; 126 | } 127 | ]; 128 | } 129 | } 130 | 131 | - (void)showToolbar { 132 | 133 | 134 | if (self.hidden == YES) { 135 | [UIView animateWithDuration:0.1 delay:0.0 136 | options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction 137 | animations:^(void) { 138 | self.hidden = NO; 139 | self.alpha = 1.0f; 140 | CGRect newFrame = self.frame; 141 | newFrame.origin.y += newFrame.size.height; 142 | [self setFrame:newFrame]; 143 | } 144 | completion:NULL 145 | ]; 146 | } 147 | } 148 | 149 | 150 | - (void)doneButtonTapped:(UIBarButtonItem *)button { 151 | 152 | 153 | [delegate dismissButtonTapped]; 154 | } 155 | 156 | 157 | @end 158 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboPDFController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | 23 | #import 24 | #import "RoboDocument.h" 25 | 26 | @protocol PDFControllerDelegateToPagebar 27 | @required 28 | - (void)pagebarImageLoadingComplete:(UIImage *)pageBarImage page:(int)page; 29 | 30 | - (BOOL)isNeedLoad:(int)i; 31 | @end 32 | 33 | @protocol PDFControllerDelegateToView 34 | @required 35 | - (void)pageContentLoadingComplete:(int)page pageBarImage:(UIImage *)pageBarImage rightSide:(BOOL)rightSide zoomed:(BOOL)zoomed; 36 | @end 37 | 38 | 39 | @interface RoboPDFController : NSObject { 40 | @private 41 | 42 | NSOperationQueue *viewQueue; 43 | NSOperationQueue *pagesQueue; 44 | NSOperationQueue *pagebarQueue; 45 | 46 | 47 | BOOL isRetina; 48 | 49 | CGPDFPageRef onePDFPageRef; 50 | 51 | NSMutableDictionary *opDict; 52 | NSMutableSet *loadedPages; 53 | 54 | BOOL running; 55 | 56 | CGPDFDocumentRef thePDFDocRef; 57 | 58 | NSString *pdfPassword; 59 | NSURL *pdfFileURL; 60 | 61 | } 62 | - (id)initWithDocument:(RoboDocument *)document; 63 | 64 | - (void)stopMashina; 65 | 66 | - (CGRect)getFirstPdfPageRect; 67 | 68 | - (void)getZoomedPageContent:(int)page isLands:(int)isLands; 69 | 70 | - (void)getPagesContentFromPage:(int)minValue toPage:(int)maxValue isLands:(BOOL)isLands; 71 | 72 | - (void)addGettingPageBarImageToQueue:(int)i; 73 | 74 | @property(nonatomic, unsafe_unretained) id pagebarDelegate; 75 | @property(nonatomic, unsafe_unretained) id viewDelegate; 76 | @property(nonatomic) int currentPage; 77 | @property(nonatomic) BOOL resetPdfDoc; 78 | @property(nonatomic) BOOL didRotate; 79 | @property(nonatomic, strong) NSString *password; 80 | @property(nonatomic, strong) NSURL *fileURL; 81 | @property(nonatomic) BOOL isSmall; 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboPDFController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "RoboPDFController.h" 23 | #import "PDFPageConverter.h" 24 | #import "CGPDFDocument.h" 25 | #import "RoboConstants.h" 26 | 27 | 28 | #define MAX_DPI 300.0f 29 | 30 | @implementation RoboPDFController 31 | 32 | - (id)initWithDocument:(RoboDocument *)document { 33 | 34 | #ifdef HARDCORX 35 | NSLog(@"%s", __FUNCTION__); 36 | #endif 37 | if (self = [super init]) { 38 | 39 | thePDFDocRef = CGPDFDocumentCreateX((__bridge CFURLRef) document.fileURL, document.password); 40 | 41 | pdfFileURL = document.fileURL; 42 | pdfPassword = document.password; 43 | 44 | _resetPdfDoc = NO; 45 | isRetina = [RoboConstants instance].retinaDisplay; 46 | 47 | viewQueue = [[NSOperationQueue alloc] init]; 48 | [viewQueue setMaxConcurrentOperationCount:8]; 49 | 50 | opDict = [[NSMutableDictionary alloc] init]; 51 | pagesQueue = [[NSOperationQueue alloc] init]; 52 | [pagesQueue setMaxConcurrentOperationCount:2]; 53 | pagebarQueue = [[NSOperationQueue alloc] init]; 54 | [pagebarQueue setMaxConcurrentOperationCount:2]; 55 | 56 | loadedPages = [[NSMutableSet alloc] init]; 57 | _didRotate = NO; 58 | running = YES; 59 | 60 | } 61 | return self; 62 | } 63 | 64 | - (void)setPdfPage:(CGPDFPageRef)newPage { 65 | if (onePDFPageRef != newPage) { 66 | CGPDFPageRelease(onePDFPageRef); 67 | onePDFPageRef = CGPDFPageRetain(newPage); 68 | } 69 | } 70 | 71 | - (CGRect)getFirstPdfPageRect { 72 | 73 | @synchronized (self) { 74 | if (running) { 75 | if (_resetPdfDoc) { 76 | CGPDFDocumentRelease(thePDFDocRef); 77 | thePDFDocRef = CGPDFDocumentCreateX((__bridge CFURLRef) (pdfFileURL), pdfPassword); 78 | _resetPdfDoc = NO; 79 | } 80 | [self setPdfPage:CGPDFDocumentGetPage(thePDFDocRef, 1)]; 81 | if (onePDFPageRef != NULL) { 82 | 83 | CGRect pageRect = CGPDFPageGetBoxRect(onePDFPageRef, kCGPDFCropBox); 84 | 85 | return pageRect; 86 | } 87 | else { 88 | 89 | NSLog(@"Error while loading pdf page number: %i", 1); 90 | 91 | } 92 | } 93 | } 94 | 95 | 96 | return CGRectZero; 97 | 98 | } 99 | 100 | 101 | - (void)addGettingPageBarImageToQueue:(int)i { 102 | NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{ 103 | [self getPageBarImageIfNeeded:i]; 104 | }]; 105 | [op setQueuePriority:NSOperationQueuePriorityVeryLow]; 106 | [pagebarQueue addOperation:op]; 107 | 108 | } 109 | 110 | - (void)getPageBarImageIfNeeded:(int)i { 111 | #ifdef HARDCORX 112 | NSLog(@"%s", __FUNCTION__); 113 | #endif 114 | 115 | if ([self.pagebarDelegate isNeedLoad:i]) { 116 | @synchronized (self) { 117 | if (running) { 118 | if (_resetPdfDoc) { 119 | CGPDFDocumentRelease(thePDFDocRef); 120 | thePDFDocRef = CGPDFDocumentCreateX((__bridge CFURLRef) (pdfFileURL), pdfPassword); 121 | _resetPdfDoc = NO; 122 | } 123 | [self setPdfPage:CGPDFDocumentGetPage(thePDFDocRef, i)]; 124 | if (onePDFPageRef != NULL) { 125 | 126 | UIImage *pagebarImage; 127 | if (_isSmall) { 128 | if (isRetina) 129 | pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:150.0f]; 130 | else 131 | pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:150.0f]; 132 | } else { 133 | if (isRetina) 134 | pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:20.0f]; 135 | else 136 | pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:14.0f]; 137 | } 138 | if (running) 139 | [_pagebarDelegate pagebarImageLoadingComplete:pagebarImage page:i]; 140 | } 141 | else { 142 | 143 | NSLog(@"Error while loading pdf page number: %i", i); 144 | 145 | } 146 | } 147 | } 148 | } 149 | } 150 | 151 | - (void)stopMashina { 152 | 153 | running = NO; 154 | 155 | [viewQueue cancelAllOperations]; 156 | [viewQueue waitUntilAllOperationsAreFinished]; 157 | 158 | [pagesQueue cancelAllOperations]; 159 | [pagesQueue waitUntilAllOperationsAreFinished]; 160 | 161 | [pagebarQueue cancelAllOperations]; 162 | [pagebarQueue waitUntilAllOperationsAreFinished]; 163 | 164 | CGPDFPageRelease(onePDFPageRef); 165 | CGPDFDocumentRelease(thePDFDocRef); 166 | 167 | onePDFPageRef = nil; 168 | thePDFDocRef = nil; 169 | 170 | } 171 | 172 | 173 | - (void)getPagesContentFromPage:(int)minValue toPage:(int)maxVal isLands:(BOOL)isLands { 174 | 175 | [pagesQueue cancelAllOperations]; 176 | 177 | NSOperation *pagesOp = [NSBlockOperation blockOperationWithBlock:^{ 178 | 179 | 180 | if (_didRotate) { 181 | _didRotate = NO; 182 | [viewQueue cancelAllOperations]; 183 | [loadedPages removeAllObjects]; 184 | } 185 | 186 | int maxValue = maxVal; 187 | 188 | if (isLands) { 189 | for (NSNumber *key in [loadedPages allObjects]) { 190 | 191 | 192 | NSOperation *renderOperation = opDict[key]; 193 | 194 | if ([key intValue] == _currentPage || [key intValue] == _currentPage + 1) { 195 | 196 | [renderOperation setQueuePriority:NSOperationQueuePriorityVeryHigh]; 197 | 198 | } 199 | else if ((_currentPage - [key intValue] >= 3) || ([key intValue] - _currentPage >= 4)) { 200 | 201 | [renderOperation cancel]; 202 | [loadedPages removeObject:key]; 203 | 204 | } 205 | else { 206 | [renderOperation setQueuePriority:NSOperationQueuePriorityNormal]; 207 | } 208 | } 209 | } 210 | else { 211 | for (NSNumber *key in [loadedPages allObjects]) { 212 | NSOperation *renderOperation = opDict[key]; 213 | if ([key intValue] == _currentPage) { 214 | [renderOperation setQueuePriority:NSOperationQueuePriorityVeryHigh]; 215 | } 216 | else if (abs([key intValue] - _currentPage) >= 2) { 217 | [loadedPages removeObject:key]; 218 | [renderOperation cancel]; 219 | } 220 | else { 221 | [renderOperation setQueuePriority:NSOperationQueuePriorityNormal]; 222 | } 223 | } 224 | } 225 | if (isLands) 226 | maxValue++; 227 | for (int page = minValue; page <= maxValue; page++) { 228 | 229 | NSString *key = [NSString stringWithFormat:@"%i", page]; 230 | if (![loadedPages containsObject:key]) { 231 | [loadedPages addObject:key]; 232 | NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{ 233 | [self getOnePageContent:page isLands:isLands]; 234 | }]; 235 | if ((isLands && page == _currentPage + 1) || page == _currentPage) 236 | [op setQueuePriority:NSOperationQueuePriorityVeryHigh]; 237 | else 238 | [op setQueuePriority:NSOperationQueuePriorityNormal]; 239 | [viewQueue addOperation:op]; 240 | opDict[key] = op; 241 | } 242 | } 243 | }]; 244 | [pagesOp setQueuePriority:NSOperationQueuePriorityHigh]; 245 | [pagesQueue addOperation:pagesOp]; 246 | 247 | } 248 | 249 | - (void)getOnePageContent:(int)page isLands:(int)isLands { 250 | #ifdef HARDCORX 251 | NSLog(@"%s", __FUNCTION__); 252 | #endif 253 | 254 | @synchronized (self) { 255 | if (running) { 256 | 257 | BOOL rightSide; 258 | if (isLands) { 259 | if (page >= 1) 260 | rightSide = page % 2; 261 | else 262 | rightSide = NO; 263 | } 264 | else { 265 | rightSide = NO; 266 | } 267 | 268 | if (_resetPdfDoc) { 269 | CGPDFDocumentRelease(thePDFDocRef); 270 | thePDFDocRef = CGPDFDocumentCreateX((__bridge CFURLRef) (pdfFileURL), pdfPassword); 271 | _resetPdfDoc = NO; 272 | 273 | } 274 | [self setPdfPage:CGPDFDocumentGetPage(thePDFDocRef, page)]; // Get page 275 | if (onePDFPageRef != NULL) { // Check for non-NULL CGPDFPageRef 276 | UIImage *pagebarImage; 277 | if (isLands) { 278 | if (isRetina) { 279 | pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:MAX_DPI * 0.5]; 280 | } 281 | else { 282 | pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:MAX_DPI * 0.25]; 283 | } 284 | } 285 | else { 286 | if (isRetina) { 287 | pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:MAX_DPI * 0.6]; 288 | } 289 | else { 290 | pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:MAX_DPI * 0.3]; 291 | } 292 | } 293 | 294 | if (running) 295 | [_viewDelegate pageContentLoadingComplete:page pageBarImage:pagebarImage rightSide:rightSide zoomed:NO]; 296 | 297 | } 298 | else { 299 | NSLog(@"Error while loading pdf page number: %i", page); 300 | // return nil; 301 | } 302 | } 303 | } 304 | } 305 | 306 | - (void)getZoomedPageContent:(int)page isLands:(int)isLands { 307 | #ifdef HARDCORX 308 | NSLog(@"%s", __FUNCTION__); 309 | #endif 310 | 311 | 312 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 313 | 314 | BOOL rightSide; 315 | if (isLands) { 316 | if (page >= 1) 317 | rightSide = page % 2; 318 | else 319 | rightSide = NO; 320 | } 321 | else { 322 | rightSide = NO; 323 | } 324 | 325 | if ((isLands && ((page - _currentPage) <= 3 || (_currentPage - page) >= 2)) || (!isLands && abs(page - _currentPage) <= 1)) { 326 | @synchronized (self) { 327 | if (_resetPdfDoc) { 328 | CGPDFDocumentRelease(thePDFDocRef); 329 | thePDFDocRef = CGPDFDocumentCreateX((__bridge CFURLRef) (pdfFileURL), pdfPassword); 330 | _resetPdfDoc = NO; 331 | 332 | } 333 | 334 | [self setPdfPage:CGPDFDocumentGetPage(thePDFDocRef, page)]; 335 | if (onePDFPageRef != NULL) { 336 | 337 | UIImage *pagebarImage; 338 | 339 | if (isLands) { 340 | if (isRetina) { 341 | pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:MAX_DPI * 0.8]; 342 | } 343 | else { 344 | pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:MAX_DPI * 0.5]; 345 | } 346 | } 347 | else { 348 | if (isRetina) { 349 | pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:MAX_DPI]; 350 | } 351 | else { 352 | pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:MAX_DPI * 0.6]; 353 | } 354 | } 355 | 356 | if ((isLands && ((page - _currentPage) <= 3 || (_currentPage - page) >= 2)) || (!isLands && abs(page - _currentPage) <= 1)) if (running) 357 | [_viewDelegate pageContentLoadingComplete:page pageBarImage:pagebarImage rightSide:rightSide zoomed:YES]; 358 | 359 | } 360 | else { 361 | NSLog(@"Error while loading pdf page number: %i", page); 362 | // return nil; 363 | } 364 | 365 | } 366 | } 367 | }); 368 | 369 | } 370 | 371 | /* 372 | - (void)renderPage:(int)page withScale:(float)scale { 373 | #ifdef HARDCORX 374 | NSLog(@"%s", __FUNCTION__); 375 | #endif 376 | CGPDFPageRef onePDFPageRef = CGPDFDocumentGetPage([RoboPDFDocRef instance:nil].thePDFDocRef, page); 377 | [PDFPageRenderer renderPage:onePDFPageRef inContext:UIGraphicsGetCurrentContext() atPoint:CGPointMake(0, 0) withZoom:scale*100.0f]; 378 | } 379 | 380 | 381 | - (UIImage *)getPageContentImmediately:(int)page { 382 | #ifdef HARDCORX 383 | NSLog(@"%s", __FUNCTION__); 384 | #endif 385 | CGPDFPageRef onePDFPageRef = CGPDFDocumentGetPage([RoboPDFDocRef instance:nil].thePDFDocRef, page); // Get page 386 | if (onePDFPageRef != NULL) { // Check for non-NULL CGPDFPageRef 387 | UIImage *pagebarImage = [PDFPageConverter convertPDFPageToImage:onePDFPageRef withResolution:500]; 388 | 389 | 390 | return pagebarImage; 391 | } 392 | else { 393 | NSLog(@"Error while loading pdf page number: %i", page); 394 | return nil; 395 | } 396 | 397 | } 398 | 399 | 400 | - (RoboContentPage *)getTiledPage:(int)page { 401 | #ifdef HARDCORX 402 | NSLog(@"%s", __FUNCTION__); 403 | #endif 404 | CGPDFPageRef onePDFPageRef = CGPDFDocumentGetPage([RoboPDFDocRef instance:nil].thePDFDocRef, page); 405 | return [[RoboContentPage alloc] initWithPageRef:onePDFPageRef viewRect:[RoboPDFInfo instance].pdfRect]; 406 | } 407 | */ 408 | 409 | - (void)dealloc { 410 | 411 | //dispatch_release(backgroundQueueViews); 412 | } 413 | 414 | 415 | @end 416 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboPDFModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | 23 | #import 24 | #import "CGPDFDocument.h" 25 | 26 | @interface RoboPDFModel : NSObject 27 | 28 | + (RoboPDFModel *)instance; 29 | 30 | @property int numberOfPages; 31 | 32 | + (CGRect)getPdfRectsWithSize:(CGSize)onePageSize isLands:(BOOL)isLands; 33 | 34 | @end 35 | 36 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboPDFModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | 23 | #import "RoboPDFModel.h" 24 | 25 | @implementation RoboPDFModel 26 | 27 | + (RoboPDFModel *)instance { 28 | 29 | #ifdef DEBUGX 30 | NSLog(@"%s", __FUNCTION__); 31 | #endif 32 | 33 | static RoboPDFModel *instance = nil; 34 | static dispatch_once_t onceToken; 35 | dispatch_once(&onceToken, ^{ 36 | 37 | instance = [[self alloc] init]; 38 | 39 | }); 40 | return instance; 41 | 42 | } 43 | 44 | + (CGRect)getPdfRectsWithSize:(CGSize)onePageSize isLands:(BOOL)isLands { 45 | 46 | CGRect bounds = [[UIScreen mainScreen] bounds]; 47 | if (!isLands) { 48 | // set sizes for portrait pdf - it will save processor time - 49 | // but each pdf page must be the same size 50 | CGFloat widthPortrNew; CGFloat heightPortrNew; 51 | CGFloat originPortrX; CGFloat originPortrY; 52 | heightPortrNew = CGRectGetHeight(bounds); 53 | widthPortrNew = CGRectGetHeight(bounds) * onePageSize.width / onePageSize.height; 54 | if (widthPortrNew > CGRectGetWidth(bounds)) { 55 | widthPortrNew = CGRectGetWidth(bounds); 56 | heightPortrNew = CGRectGetWidth(bounds) * onePageSize.height / onePageSize.width; 57 | originPortrX = 0; 58 | originPortrY = (CGRectGetHeight(bounds) - heightPortrNew) / 2.0f; 59 | } 60 | else { 61 | originPortrX = (CGRectGetWidth(bounds) - widthPortrNew) / 2.0f; 62 | originPortrY = 0; 63 | } 64 | return CGRectMake(originPortrX, originPortrY, widthPortrNew, heightPortrNew); 65 | } 66 | else { 67 | // set sizes for landscapes pdf 68 | CGFloat widthLandsNew; CGFloat heightLandsNew; 69 | CGFloat originLandsX; CGFloat originLandsY; 70 | widthLandsNew = CGRectGetHeight(bounds) / 2; 71 | heightLandsNew = CGRectGetHeight(bounds) / 2 * onePageSize.height / onePageSize.width; 72 | if (heightLandsNew > CGRectGetWidth(bounds)) { 73 | 74 | heightLandsNew = CGRectGetWidth(bounds); 75 | widthLandsNew = CGRectGetWidth(bounds) * onePageSize.width / onePageSize.height; 76 | originLandsX = CGRectGetHeight(bounds) / 2 - widthLandsNew; 77 | originLandsY = 0; 78 | } 79 | else { 80 | originLandsX = 0; 81 | originLandsY = (CGRectGetWidth(bounds) - heightLandsNew) / 2.0f; 82 | } 83 | return CGRectMake(originLandsX, originLandsY, widthLandsNew, heightLandsNew); 84 | } 85 | } 86 | 87 | 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboReader.h: -------------------------------------------------------------------------------- 1 | // 2 | // RoboReader.h 3 | // RoboReader 4 | // 5 | // Created by Mikhail Viceman on 26.03.13. 6 | // Copyright (c) 2012 REDMADROBOT. All rights reserved. 7 | // 8 | 9 | #ifndef RoboReader_RoboReader_h 10 | #define RoboReader_RoboReader_h 11 | 12 | #import "RoboViewController.h" 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | 23 | #import 24 | #import 25 | 26 | #import "RoboDocument.h" 27 | #import "RoboContentView.h" 28 | #import "RoboMainToolbar.h" 29 | #import "RoboMainPagebar.h" 30 | #import "RoboConstants.h" 31 | 32 | 33 | @class RoboViewController; 34 | @class RoboMainToolbar; 35 | 36 | @protocol RoboViewControllerDelegate 37 | 38 | @optional 39 | 40 | - (void)dismissRoboViewController:(RoboViewController *)viewController; 41 | 42 | @end 43 | 44 | @interface RoboViewController : UIViewController { 46 | @private 47 | 48 | RoboDocument *document; 49 | 50 | UIScrollView *theScrollView; 51 | RoboPDFController *pdfController; 52 | RoboPDFController *smallPdfController; 53 | 54 | 55 | RoboMainPagebar *mainPagebar; 56 | RoboMainToolbar *mainToolbar; 57 | 58 | NSMutableDictionary *contentViews; 59 | NSMutableSet *loadedPages; 60 | 61 | int startPageNumber; 62 | 63 | BOOL isLandscape; 64 | BOOL didRotate; 65 | BOOL barsHiddenFlag; 66 | 67 | UIButton *leftButton; 68 | UIButton *rightButton; 69 | 70 | } 71 | 72 | @property(nonatomic, unsafe_unretained, readwrite) id delegate; 73 | 74 | - (id)initWithRoboDocument:(RoboDocument *)object; 75 | //- (id)initWithRoboDocument:(RoboDocument *)object small_document:(RoboDocument *)small_object; 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /RoboReader/Classes/RoboViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 RoboReader ( http://brainfaq.ru/roboreader ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "RoboViewController.h" 23 | #import "RoboPDFModel.h" 24 | 25 | @implementation RoboViewController 26 | 27 | 28 | @synthesize delegate; 29 | 30 | - (void)showDocument { 31 | 32 | 33 | [self updateScrollViewContentSize]; 34 | 35 | startPageNumber = [document.currentPage intValue]; 36 | // if (startPageNumber <= 1) 37 | // startPageNumber = 2; 38 | 39 | // [self showDocumentPage:1 fastScroll:NO]; 40 | 41 | 42 | // [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ 43 | // [self.view setAlpha:0.0]; 44 | // } completion:^(BOOL finished) { 45 | // [self showDocumentPage:startPageNumber fastScroll:NO]; 46 | // [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ 47 | // [self.view setAlpha:1.0]; 48 | // } completion:nil]; 49 | // 50 | // }]; 51 | 52 | [self showDocumentPage:startPageNumber fastScroll:NO]; 53 | 54 | document.lastOpen = [NSDate date]; 55 | 56 | } 57 | 58 | - (void)updateScrollViewContentSize { 59 | 60 | 61 | int count = [document.pageCount intValue]; 62 | if (count == 0) 63 | count = 1; 64 | 65 | CGFloat contentHeight = theScrollView.bounds.size.height; 66 | 67 | CGFloat contentWidth; 68 | 69 | if (isLandscape) 70 | contentWidth = CGRectGetWidth(self.view.frame) * (count / 2 + 1); 71 | else 72 | contentWidth = CGRectGetWidth(self.view.frame) * count; 73 | 74 | theScrollView.contentSize = CGSizeMake(contentWidth, contentHeight); 75 | 76 | } 77 | 78 | 79 | - (void)pageContentLoadingComplete:(int)page pageBarImage:(UIImage *)pageBarImage rightSide:(BOOL)rightSide zoomed:(BOOL)zoomed { 80 | 81 | int fullPageNum = page; 82 | if (rightSide) { 83 | if (fullPageNum % 2) 84 | fullPageNum -= 1; 85 | } 86 | NSString *key; 87 | if (rightSide && fullPageNum == 0) 88 | key = @"1"; 89 | else 90 | key = [NSString stringWithFormat:@"%i", fullPageNum]; 91 | RoboContentView *contentView = contentViews[key]; 92 | if (contentView) { 93 | [contentView pageContentLoadingComplete:pageBarImage rightSide:rightSide zoomed:zoomed]; 94 | } 95 | } 96 | 97 | - (void)getZoomedPages:(int)pageNum isLands:(BOOL)isLands zoomIn:(BOOL)zoomIn; { 98 | 99 | [pdfController getZoomedPageContent:pageNum isLands:isLands]; 100 | if (isLands && pageNum != 1) 101 | [pdfController getZoomedPageContent:pageNum + 1 isLands:isLands]; 102 | } 103 | 104 | 105 | - (void)showDocumentPage:(int)page fastScroll:(BOOL)fastScroll { 106 | 107 | if ((page < 1) || (page > [document.pageCount intValue])) 108 | return; 109 | 110 | int minValue; 111 | int maxValue; 112 | 113 | if (isLandscape) { 114 | 115 | if (page != 1 && page % 2) 116 | page -= 1; 117 | 118 | minValue = (page - 2); 119 | maxValue = (page + 2); 120 | 121 | 122 | if (page == 1) { 123 | 124 | minValue = 0; 125 | maxValue = 2; 126 | 127 | } 128 | if (page == 2) { 129 | 130 | minValue = 0; 131 | maxValue = 4; 132 | } 133 | 134 | } 135 | else { 136 | 137 | minValue = (page - 1); 138 | maxValue = (page + 1); 139 | 140 | if (page == 1) { 141 | 142 | minValue = 1; 143 | maxValue = 2; 144 | } 145 | 146 | } 147 | 148 | pdfController.currentPage = page; 149 | CGRect viewRect = CGRectZero; 150 | viewRect.size = theScrollView.bounds.size; 151 | if (isLandscape) 152 | viewRect.origin.x = viewRect.size.width * minValue / 2; 153 | else 154 | viewRect.origin.x = viewRect.size.width * (minValue - 1); 155 | 156 | // if rotated => kill all content 157 | // else - free memory of unnecessary content 158 | 159 | if (didRotate) { 160 | 161 | didRotate = NO; 162 | 163 | for (NSString *key in loadedPages) { 164 | RoboContentView *contentView = contentViews[key]; 165 | [contentView removeFromSuperview]; 166 | [contentViews removeObjectForKey:key]; 167 | 168 | } 169 | [loadedPages removeAllObjects]; 170 | [self updateScrollViewContentSize]; 171 | 172 | } 173 | else { 174 | 175 | if (isLandscape) { 176 | for (NSString *key in [loadedPages allObjects]) { 177 | if ((page - [key intValue] > 2) || ([key intValue] - page > 3)) { 178 | RoboContentView *contentView = contentViews[key]; 179 | [contentView removeFromSuperview]; 180 | [contentViews removeObjectForKey:key]; 181 | [loadedPages removeObject:key]; 182 | 183 | } 184 | } 185 | } 186 | else { 187 | for (NSString *key in [loadedPages allObjects]) { 188 | if (abs([key intValue] - page) > 1) { 189 | RoboContentView *contentView = contentViews[key]; 190 | [contentView removeFromSuperview]; 191 | [contentViews removeObjectForKey:key]; 192 | [loadedPages removeObject:key]; 193 | 194 | } 195 | } 196 | } 197 | 198 | } 199 | 200 | for (int number = minValue; number <= maxValue; number++) { 201 | 202 | NSString *key; 203 | if (isLandscape && number == 0) 204 | key = @"1"; 205 | else 206 | key = [NSString stringWithFormat:@"%i", number]; 207 | 208 | RoboContentView *contentView = contentViews[key]; 209 | if (!contentView) { 210 | 211 | contentView = [[RoboContentView alloc] initWithFrame:viewRect page:number orientation:isLandscape]; 212 | 213 | contentView.delegate = self; 214 | 215 | [theScrollView addSubview:contentView]; 216 | contentViews[key] = contentView; 217 | 218 | [loadedPages addObject:key]; 219 | } 220 | 221 | viewRect.origin.x += viewRect.size.width; 222 | if (isLandscape) 223 | number++; 224 | 225 | } 226 | 227 | [pdfController getPagesContentFromPage:minValue toPage:maxValue isLands:isLandscape]; 228 | 229 | if (!fastScroll) { 230 | if (isLandscape) 231 | theScrollView.contentOffset = CGPointMake(viewRect.size.width * (page / 2), 0); 232 | else 233 | theScrollView.contentOffset = CGPointMake(viewRect.size.width * (page - 1), 0); 234 | } 235 | 236 | 237 | if ([document.currentPage intValue] != page) { 238 | document.currentPage = @(page); 239 | } 240 | 241 | } 242 | 243 | 244 | - (id)initWithRoboDocument:(RoboDocument *)object { 245 | 246 | 247 | id robo = nil; // RoboViewController object 248 | 249 | if ((object != nil) && ([object isKindOfClass:[RoboDocument class]])) { 250 | if ((self = [super initWithNibName:nil bundle:nil])) // Designated initializer 251 | { 252 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 253 | 254 | [notificationCenter addObserver:self selector:@selector(applicationWill:) name:UIApplicationWillTerminateNotification object:nil]; 255 | 256 | [notificationCenter addObserver:self selector:@selector(applicationWill:) name:UIApplicationWillResignActiveNotification object:nil]; 257 | 258 | [object updateProperties]; 259 | 260 | document = object; 261 | 262 | 263 | robo = self; 264 | 265 | // get the current device orientation to determine initial isLandscape variable 266 | UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; 267 | isLandscape = interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight; 268 | } 269 | } 270 | 271 | return robo; 272 | } 273 | 274 | 275 | - (void)hideBars { 276 | if (!barsHiddenFlag) { 277 | [UIView animateWithDuration:0.1 delay:0.0 278 | options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction 279 | animations:^(void) { 280 | [[UIApplication sharedApplication] setStatusBarHidden:YES]; 281 | } 282 | completion:nil 283 | ]; 284 | [mainToolbar hideToolbar]; 285 | [mainPagebar hidePagebar]; 286 | barsHiddenFlag = YES; 287 | } 288 | 289 | } 290 | 291 | - (void)showBars { 292 | if (barsHiddenFlag) { 293 | [UIView animateWithDuration:0.1 delay:0.0 294 | options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction 295 | animations:^(void) { 296 | [[UIApplication sharedApplication] setStatusBarHidden:NO]; 297 | } 298 | completion:nil 299 | ]; 300 | [mainToolbar showToolbar]; 301 | [mainPagebar showPagebar]; 302 | barsHiddenFlag = NO; 303 | } 304 | } 305 | 306 | - (void)nextPage:(id)sender { 307 | [self hideBars]; 308 | CGPoint newContOffset = theScrollView.contentOffset; 309 | newContOffset.x += CGRectGetWidth(self.view.frame); 310 | if (newContOffset.x < theScrollView.contentSize.width) { 311 | [UIView animateWithDuration:0.5f delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 312 | [theScrollView setContentOffset:newContOffset]; 313 | } completion:^(BOOL finished) { 314 | }]; 315 | 316 | } 317 | } 318 | 319 | - (void)prevPage:(id)sender { 320 | 321 | [self hideBars]; 322 | CGPoint newContOffset = theScrollView.contentOffset; 323 | newContOffset.x -= CGRectGetWidth(self.view.frame); 324 | if (newContOffset.x >= 0) { 325 | [UIView animateWithDuration:0.5f delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 326 | [theScrollView setContentOffset:newContOffset]; 327 | } completion:^(BOOL finished) { 328 | }]; 329 | } 330 | } 331 | 332 | - (void)viewDidLoad { 333 | #ifdef DEBUGX 334 | NSLog(@"%s %@", __FUNCTION__, NSStringFromCGRect(self.view.bounds)); 335 | #endif 336 | 337 | [super viewDidLoad]; 338 | 339 | NSAssert(!(document == nil), @"RoboDocument == nil"); 340 | 341 | if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) { 342 | self.automaticallyAdjustsScrollViewInsets = NO; 343 | } 344 | else { 345 | [self setWantsFullScreenLayout:YES]; 346 | 347 | } 348 | 349 | CGRect viewRect = self.view.bounds; 350 | 351 | 352 | self.view.backgroundColor = [UIColor blackColor]; 353 | 354 | [RoboPDFModel instance].numberOfPages = [document.pageCount intValue]; 355 | 356 | pdfController = [[RoboPDFController alloc] initWithDocument:document]; 357 | pdfController.viewDelegate = self; 358 | pdfController.fileURL = document.fileURL; 359 | pdfController.password = document.password; 360 | // 361 | // if (small_document != nil) { 362 | // smallPdfController = [[RoboPDFController alloc] initWithDocument:small_document]; 363 | // smallPdfController.viewDelegate = self; 364 | // smallPdfController.isSmall = YES; 365 | // } 366 | 367 | [[UIApplication sharedApplication] setStatusBarHidden:YES]; 368 | 369 | 370 | contentViews = [[NSMutableDictionary alloc] init]; 371 | loadedPages = [[NSMutableSet alloc] init]; 372 | 373 | 374 | theScrollView = [[UIScrollView alloc] initWithFrame:viewRect]; // All 375 | 376 | theScrollView.scrollsToTop = NO; 377 | theScrollView.pagingEnabled = YES; 378 | //theScrollView.delaysContentTouches = NO; 379 | theScrollView.showsVerticalScrollIndicator = NO; 380 | theScrollView.showsHorizontalScrollIndicator = NO; 381 | theScrollView.contentMode = UIViewContentModeRedraw; 382 | theScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 383 | theScrollView.backgroundColor = [UIColor clearColor]; 384 | theScrollView.userInteractionEnabled = YES; 385 | theScrollView.autoresizesSubviews = NO; 386 | theScrollView.delegate = self; 387 | 388 | [self.view addSubview:theScrollView]; 389 | 390 | CGRect toolbarRect = viewRect; 391 | toolbarRect.size.height = READER_TOOLBAR_HEIGHT; 392 | 393 | // if it is ios7+, just use all the status bar space 394 | toolbarRect.origin.y = (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) ? 0.0f : 20.0f; 395 | NSString *toolbarTitle = (self.title == nil) ? [document.fileName stringByDeletingPathExtension] : self.title; 396 | 397 | mainToolbar = [[RoboMainToolbar alloc] initWithFrame:toolbarRect title:toolbarTitle]; 398 | 399 | mainToolbar.delegate = self; 400 | 401 | [self.view addSubview:mainToolbar]; 402 | 403 | CGRect pagebarRect = viewRect; 404 | pagebarRect.size.height = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? PAGEBAR_HEIGHT_PAD : PAGEBAR_HEIGHT_PHONE; 405 | pagebarRect.origin.y = (viewRect.size.height - pagebarRect.size.height); 406 | 407 | if (smallPdfController != nil) { 408 | mainPagebar = [[RoboMainPagebar alloc] initWithFrame:pagebarRect document:document pdfController:smallPdfController]; 409 | } else { 410 | mainPagebar = [[RoboMainPagebar alloc] initWithFrame:pagebarRect document:document pdfController:pdfController]; 411 | } 412 | mainPagebar.delegate = self; 413 | [self.view addSubview:mainPagebar]; 414 | 415 | UITapGestureRecognizer *singleTapOne = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; 416 | singleTapOne.numberOfTouchesRequired = 1; 417 | singleTapOne.numberOfTapsRequired = 1; 418 | singleTapOne.delegate = self; 419 | 420 | 421 | [self.view addGestureRecognizer:singleTapOne]; 422 | 423 | 424 | leftButton = [[UIButton alloc] init]; 425 | [leftButton addTarget:self action:@selector(prevPage:) forControlEvents:UIControlEventTouchDown]; 426 | [self.view insertSubview:leftButton aboveSubview:theScrollView]; 427 | 428 | rightButton = [[UIButton alloc] init]; 429 | [rightButton addTarget:self action:@selector(nextPage:) forControlEvents:UIControlEventTouchDown]; 430 | [self.view insertSubview:rightButton aboveSubview:theScrollView]; 431 | 432 | [self willAnimateRotationToInterfaceOrientation:self.interfaceOrientation duration:0]; 433 | 434 | barsHiddenFlag = YES; 435 | 436 | } 437 | 438 | 439 | - (void)viewDidAppear:(BOOL)animated { 440 | #ifdef DEBUGX 441 | NSLog(@"%s %@", __FUNCTION__, NSStringFromCGRect(self.view.bounds)); 442 | #endif 443 | 444 | [super viewDidAppear:animated]; 445 | 446 | if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) 447 | isLandscape = YES; 448 | else 449 | isLandscape = NO; 450 | 451 | [self showDocument]; 452 | 453 | } 454 | 455 | - (void)viewWillDisappear:(BOOL)animated { 456 | #ifdef DEBUGX 457 | NSLog(@"%s %@", __FUNCTION__, NSStringFromCGRect(self.view.bounds)); 458 | #endif 459 | 460 | [super viewWillDisappear:animated]; 461 | 462 | [[UIApplication sharedApplication] setStatusBarHidden:NO]; 463 | 464 | } 465 | 466 | 467 | - (void)viewDidUnload { 468 | 469 | mainToolbar = nil; 470 | 471 | mainPagebar = nil; 472 | 473 | theScrollView = nil; 474 | 475 | 476 | [super viewDidUnload]; 477 | 478 | } 479 | 480 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 481 | #ifdef DEBUGX 482 | NSLog(@"%s (%d)", __FUNCTION__, interfaceOrientation); 483 | #endif 484 | 485 | return YES; 486 | } 487 | 488 | - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 489 | #ifdef DEBUGX 490 | NSLog(@"%s %@ (%d)", __FUNCTION__, NSStringFromCGRect(self.view.bounds), toInterfaceOrientation); 491 | #endif 492 | 493 | if (UIDeviceOrientationIsLandscape(toInterfaceOrientation)) 494 | isLandscape = YES; 495 | else 496 | isLandscape = NO; 497 | 498 | didRotate = YES; 499 | pdfController.didRotate = YES; 500 | 501 | } 502 | 503 | - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration { 504 | #ifdef DEBUGX 505 | NSLog(@"%s %@ (%d)", __FUNCTION__, NSStringFromCGRect(self.view.bounds), interfaceOrientation); 506 | #endif 507 | if (UIDeviceOrientationIsLandscape(interfaceOrientation)) { 508 | 509 | if (![[UIApplication sharedApplication] isStatusBarHidden]) { 510 | 511 | if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) { 512 | [self.view setBounds:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))]; 513 | [self.view setFrame:CGRectMake(0, 0.0f, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))]; 514 | } else { 515 | [self.view setBounds:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))]; 516 | [self.view setFrame:CGRectMake(0, -20.0f, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))]; 517 | } 518 | 519 | } 520 | 521 | [leftButton setFrame:CGRectMake(0, 0, 66.0f, CGRectGetHeight(self.view.frame))]; 522 | [rightButton setFrame:CGRectMake(958.0f, 0, 66.0f, CGRectGetHeight(self.view.frame))]; 523 | 524 | } 525 | else { 526 | if (![[UIApplication sharedApplication] isStatusBarHidden]) { 527 | 528 | if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) { 529 | [self.view setBounds:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))]; 530 | [self.view setFrame:CGRectMake(0, 0.0f, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))]; 531 | } else { 532 | [self.view setBounds:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))]; 533 | [self.view setFrame:CGRectMake(0, -20.0f, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))]; 534 | } 535 | 536 | } 537 | [leftButton setFrame:CGRectMake(0, 0, 66.0f, CGRectGetHeight(self.view.frame))]; 538 | [rightButton setFrame:CGRectMake(702.0f, 0, 66.0f, CGRectGetHeight(self.view.frame))]; 539 | 540 | } 541 | 542 | } 543 | 544 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 545 | #ifdef DEBUGX 546 | NSLog(@"%s %@ (%d to %d)", __FUNCTION__, NSStringFromCGRect(self.view.bounds), fromInterfaceOrientation, self.interfaceOrientation); 547 | #endif 548 | 549 | [self showDocumentPage:[document.currentPage intValue] fastScroll:NO]; 550 | 551 | } 552 | 553 | - (void)didReceiveMemoryWarning { 554 | 555 | 556 | [super didReceiveMemoryWarning]; 557 | 558 | pdfController.resetPdfDoc = YES; 559 | 560 | if (smallPdfController) { 561 | smallPdfController.resetPdfDoc = YES; 562 | } 563 | 564 | } 565 | 566 | - (void)dealloc { 567 | 568 | [pdfController stopMashina]; 569 | 570 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 571 | 572 | mainToolbar = nil; 573 | mainPagebar = nil; 574 | 575 | theScrollView = nil; 576 | 577 | document = nil; 578 | 579 | 580 | } 581 | 582 | 583 | - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView { 584 | 585 | [self hideBars]; 586 | } 587 | 588 | 589 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 590 | 591 | if (!didRotate) { 592 | 593 | CGFloat pageWidth; 594 | int currentPage = [document.currentPage intValue]; 595 | int page; 596 | if (isLandscape) { 597 | pageWidth = CGRectGetWidth(self.view.frame) / 2; 598 | page = floor((theScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1; 599 | if (currentPage != page && currentPage != page + 1 && currentPage != page - 1) 600 | [self showDocumentPage:page fastScroll:YES]; 601 | } 602 | else { 603 | pageWidth = CGRectGetWidth(self.view.frame); 604 | page = floor((theScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 2; 605 | if (currentPage != page) 606 | [self showDocumentPage:page fastScroll:YES]; 607 | } 608 | 609 | } 610 | } 611 | 612 | 613 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch { 614 | 615 | if ([touch.view isKindOfClass:[UIScrollView class]]) return YES; 616 | 617 | return NO; 618 | } 619 | 620 | 621 | - (void)handleSingleTap:(UITapGestureRecognizer *)recognizer { 622 | 623 | 624 | if (barsHiddenFlag) { 625 | [self showBars]; 626 | } 627 | else { 628 | [self hideBars]; 629 | } 630 | 631 | } 632 | 633 | 634 | - (void)dismissButtonTapped { 635 | 636 | 637 | [document saveRoboDocument]; 638 | 639 | if ([delegate respondsToSelector:@selector(dismissRoboViewController:)] == YES) { 640 | [delegate dismissRoboViewController:self]; 641 | } 642 | else { 643 | NSAssert(NO, @"Delegate must respond to -dismissRoboViewController:"); 644 | } 645 | 646 | } 647 | 648 | 649 | - (void)openPage:(int)page { 650 | 651 | 652 | [self showDocumentPage:page fastScroll:NO]; 653 | } 654 | 655 | 656 | - (void)applicationWill:(NSNotification *)notification { 657 | 658 | 659 | [document saveRoboDocument]; // Save any RoboDocument object changes 660 | 661 | } 662 | 663 | @end 664 | -------------------------------------------------------------------------------- /RoboReader/Graphics/Stroke2px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/Stroke2px.png -------------------------------------------------------------------------------- /RoboReader/Graphics/Stroke2px@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/Stroke2px@2x.png -------------------------------------------------------------------------------- /RoboReader/Graphics/Stroke2px_single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/Stroke2px_single.png -------------------------------------------------------------------------------- /RoboReader/Graphics/Stroke2px_single@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/Stroke2px_single@2x.png -------------------------------------------------------------------------------- /RoboReader/Graphics/X.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/X.png -------------------------------------------------------------------------------- /RoboReader/Graphics/X@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/X@2x.png -------------------------------------------------------------------------------- /RoboReader/Graphics/back_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/back_button.png -------------------------------------------------------------------------------- /RoboReader/Graphics/back_button@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/back_button@2x.png -------------------------------------------------------------------------------- /RoboReader/Graphics/nav_bar_plashka.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/nav_bar_plashka.png -------------------------------------------------------------------------------- /RoboReader/Graphics/nav_bar_plashka@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/nav_bar_plashka@2x.png -------------------------------------------------------------------------------- /RoboReader/Graphics/page-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/page-bg.png -------------------------------------------------------------------------------- /RoboReader/Graphics/page-bg@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/page-bg@2x.png -------------------------------------------------------------------------------- /RoboReader/Graphics/page_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/page_left.png -------------------------------------------------------------------------------- /RoboReader/Graphics/page_left@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/page_left@2x.png -------------------------------------------------------------------------------- /RoboReader/Graphics/page_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/page_right.png -------------------------------------------------------------------------------- /RoboReader/Graphics/page_right@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/page_right@2x.png -------------------------------------------------------------------------------- /RoboReader/Graphics/progress_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/progress_bar.png -------------------------------------------------------------------------------- /RoboReader/Graphics/progress_bar@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikwiseman/RoboReader/cd3484e2b910275f508a3539ad13e82a7f0c1aff/RoboReader/Graphics/progress_bar@2x.png --------------------------------------------------------------------------------