From a832100bef8b3b2d3cb4a1f9575ab7fe12fb413d Mon Sep 17 00:00:00 2001 From: Heberti Almeida Date: Tue, 20 Sep 2016 01:03:00 -0300 Subject: [PATCH 1/2] Swift 2.3 and Xcode 8 migration --- Example/Example.xcodeproj/project.pbxproj | 44 +++- .../xcshareddata/xcschemes/Example.xcscheme | 2 +- Example/Podfile | 6 +- Example/Podfile.lock | 21 +- FolioReaderKit.podspec | 1 - Source/EPUBCore/FREpubParser.swift | 4 +- Source/FolioReaderContainer.swift | 1 - Source/FolioReaderKit.swift | 14 +- Source/FolioReaderPage.swift | 10 +- Source/FolioReaderPageIndicator.swift | 19 +- Vendor/FontBlaster/FontBlaster.swift | 228 ++++++++++++++++++ Vendor/HAControls/HADiscreteSlider.swift | 20 +- 12 files changed, 316 insertions(+), 54 deletions(-) create mode 100644 Vendor/FontBlaster/FontBlaster.swift diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj index 3f05cf902..b10eb193b 100644 --- a/Example/Example.xcodeproj/project.pbxproj +++ b/Example/Example.xcodeproj/project.pbxproj @@ -273,11 +273,14 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = FolioReader; TargetAttributes = { 1A42C2881C0E3882000F2137 = { CreatedOnToolsVersion = 7.1.1; + DevelopmentTeam = 32F2T8EJ6G; + LastSwiftMigration = 0800; + ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.BackgroundModes = { enabled = 1; @@ -286,10 +289,15 @@ }; CA10C1301C572A4B0049165D = { CreatedOnToolsVersion = 7.3; + DevelopmentTeam = 32F2T8EJ6G; + LastSwiftMigration = 0800; + ProvisioningStyle = Automatic; TestTargetID = 1A42C2881C0E3882000F2137; }; D12066621D65FABD006E1D18 = { CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = 32F2T8EJ6G; + ProvisioningStyle = Automatic; }; }; }; @@ -307,8 +315,8 @@ projectRoot = ""; targets = ( 1A42C2881C0E3882000F2137 /* Example */, - CA10C1301C572A4B0049165D /* FolioReaderTests */, D12066621D65FABD006E1D18 /* StoryboardExample */, + CA10C1301C572A4B0049165D /* FolioReaderTests */, ); }; /* End PBXProject section */ @@ -665,8 +673,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -710,8 +720,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -730,7 +742,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.1; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -740,11 +752,15 @@ isa = XCBuildConfiguration; baseConfigurationReference = 5C8EADB52E1D834750CD7D23 /* Pods-Example.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = 32F2T8EJ6G; INFOPLIST_FILE = Example/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.folioreader.Example; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 2.3; }; name = Debug; }; @@ -752,11 +768,15 @@ isa = XCBuildConfiguration; baseConfigurationReference = F4CBB0C2C0FDFA3E1648DB43 /* Pods-Example.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = 32F2T8EJ6G; INFOPLIST_FILE = Example/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.folioreader.Example; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 2.3; }; name = Release; }; @@ -764,12 +784,16 @@ isa = XCBuildConfiguration; baseConfigurationReference = 3CE90B4095B5C7E6237EEBDD /* Pods-FolioReaderTests.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = 32F2T8EJ6G; INFOPLIST_FILE = FolioReaderTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.folioreader.FolioReaderTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 2.3; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example"; }; name = Debug; @@ -778,12 +802,16 @@ isa = XCBuildConfiguration; baseConfigurationReference = 8E1BE6465444C567F5D1B8E6 /* Pods-FolioReaderTests.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = 32F2T8EJ6G; INFOPLIST_FILE = FolioReaderTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.folioreader.FolioReaderTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 2.3; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example"; }; name = Release; @@ -792,12 +820,15 @@ isa = XCBuildConfiguration; baseConfigurationReference = D7C82C879F323C6E960F882B /* Pods-StoryboardExample.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = 32F2T8EJ6G; INFOPLIST_FILE = StoryboardExample/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.panajotis.maroungas.StoryboardExample; + PRODUCT_BUNDLE_IDENTIFIER = com.folioreader.StoryboardExample; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -806,12 +837,15 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1D4790507F22E69298DC06E1 /* Pods-StoryboardExample.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = 32F2T8EJ6G; INFOPLIST_FILE = StoryboardExample/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.panajotis.maroungas.StoryboardExample; + PRODUCT_BUNDLE_IDENTIFIER = com.folioreader.StoryboardExample; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; diff --git a/Example/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme b/Example/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme index 42724eee5..d78b6713e 100644 --- a/Example/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme +++ b/Example/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme @@ -1,6 +1,6 @@ 3.0) - RealmSwift (~> 1.0) - SSZipArchive (= 1.5) - UIMenuItem-CXAImageSupport (~> 0.0) - ZFDragableModalTransition (~> 0.6) - - FontBlaster (2.1.4) - JSQWebViewController (3.0.0) - Nimble (4.1.0) - Quick (0.9.2) - - Realm (1.0.2): - - Realm/Headers (= 1.0.2) - - Realm/Headers (1.0.2) - - RealmSwift (1.0.2): - - Realm (= 1.0.2) + - Realm (1.1.0): + - Realm/Headers (= 1.1.0) + - Realm/Headers (1.1.0) + - RealmSwift (1.1.0): + - Realm (= 1.1.0) - SSZipArchive (1.5) - UIMenuItem-CXAImageSupport (0.0.1) - ZFDragableModalTransition (0.6) @@ -32,17 +30,16 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: AEXML: 716fb0a8decba4a3517324a71fee3685b30233d2 - FolioReaderKit: 0d8e44d7ed0ed4bfd9724dae7ef049b1fb5a4552 - FontBlaster: b780f709b8f705638d0c80a1ecdfb23b3077d0a6 + FolioReaderKit: 0803a79ab8b4909bee39274b2e19d1c3d4dbeea4 JSQWebViewController: eaa6bd68d9e1426ae25ade99c9bbde4c6cdd4120 Nimble: 97a0a4cae5124c117115634b2d055d8c97d0af19 Quick: 18d057bc66451eedd5d1c8dc99ba2a5db6e60226 - Realm: 9d5c46a4d7d27958530a8dfc58f63a99e5c2cba3 - RealmSwift: 82f3ac5e24530143dddfde2033acc0d308f27d96 + Realm: ceecf1a4540c4ce9efe196fe73fa9855bce05bd8 + RealmSwift: 838058b2db95b12cb86bd0cf209df642c33fb60a SSZipArchive: 29daace2bccb90a47de2837744da397728ff9207 UIMenuItem-CXAImageSupport: 2945e2af4487414caad801ed8ff6ac8db274e986 ZFDragableModalTransition: 0d294eaaba6edfcb9839595de765f9ca06a4b524 -PODFILE CHECKSUM: 019ed1399429245758bdf9b0c090c4b685a25030 +PODFILE CHECKSUM: 2084e898fe18713ba33a9b26753d36d93d892bd8 COCOAPODS: 1.0.1 diff --git a/FolioReaderKit.podspec b/FolioReaderKit.podspec index 09cdc7a1b..69781e8fd 100644 --- a/FolioReaderKit.podspec +++ b/FolioReaderKit.podspec @@ -35,7 +35,6 @@ Pod::Spec.new do |s| s.dependency 'UIMenuItem-CXAImageSupport', '~> 0.0' s.dependency 'ZFDragableModalTransition', '~> 0.6' s.dependency 'AEXML', '3.0' - s.dependency 'FontBlaster', '2.1.4' s.dependency 'JSQWebViewController', '~> 3.0' s.dependency 'RealmSwift', '~> 1.0' # s.dependency 'SMSegmentView' diff --git a/Source/EPUBCore/FREpubParser.swift b/Source/EPUBCore/FREpubParser.swift index 6cc0e43c5..b8b04e63e 100755 --- a/Source/EPUBCore/FREpubParser.swift +++ b/Source/EPUBCore/FREpubParser.swift @@ -236,9 +236,9 @@ class FREpubParser: NSObject, SSZipArchiveDelegate { let tocData = try NSData(contentsOfFile: tocPath, options: .DataReadingMappedAlways) let xmlDoc = try AEXMLDocument(xmlData: tocData) - if let nav = xmlDoc.root["body"]["nav"].first, itemsList = nav["ol"]["li"].all { + if let nav = xmlDoc.root["body"]["nav"].first, let itemsList = nav["ol"]["li"].all { tocItems = itemsList - } else if let nav = findNavTag(xmlDoc.root["body"]), itemsList = nav["ol"]["li"].all { + } else if let nav = findNavTag(xmlDoc.root["body"]), let itemsList = nav["ol"]["li"].all { tocItems = itemsList } } diff --git a/Source/FolioReaderContainer.swift b/Source/FolioReaderContainer.swift index 151f6dfc1..d55944f7f 100755 --- a/Source/FolioReaderContainer.swift +++ b/Source/FolioReaderContainer.swift @@ -7,7 +7,6 @@ // import UIKit -import FontBlaster var readerConfig: FolioReaderConfig! var book: FRBook! diff --git a/Source/FolioReaderKit.swift b/Source/FolioReaderKit.swift index 87b3f0cd2..11311ee7d 100755 --- a/Source/FolioReaderKit.swift +++ b/Source/FolioReaderKit.swift @@ -179,7 +179,7 @@ public class FolioReader: NSObject { // MARK: - Get Cover Image /** - Read Cover Image and Return an IUImage + Read Cover Image and Return an `UIImage` */ public class func getCoverImage(epubPath: String) -> UIImage? { return FREpubParser().parseCoverImage(epubPath) @@ -606,11 +606,11 @@ internal extension UIImage { CGContextSetBlendMode(context, CGBlendMode.Normal) let rect = CGRectMake(0, 0, self.size.width, self.size.height) as CGRect - CGContextClipToMask(context, rect, self.CGImage) + CGContextClipToMask(context, rect, self.CGImage!) tintColor.setFill() CGContextFillRect(context, rect) - let newImage = UIGraphicsGetImageFromCurrentImageContext() as UIImage + let newImage = UIGraphicsGetImageFromCurrentImageContext()! as UIImage UIGraphicsEndImageContext() return newImage @@ -633,11 +633,11 @@ internal extension UIImage { UIColor.whiteColor().setFill() } - CGContextFillRect(context, rect) + CGContextFillRect(context!, rect) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() - return image + return image! } /** @@ -651,7 +651,7 @@ internal extension UIImage { layer.renderInContext(UIGraphicsGetCurrentContext()!) let img = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() - return img + return img! } /** @@ -665,7 +665,7 @@ internal extension UIImage { view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true) let img = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() - return img + return img! } } diff --git a/Source/FolioReaderPage.swift b/Source/FolioReaderPage.swift index eb566ee18..b8123d263 100755 --- a/Source/FolioReaderPage.swift +++ b/Source/FolioReaderPage.swift @@ -166,7 +166,7 @@ public class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGesture shouldShowBar = false - let decoded = url.absoluteString.stringByRemovingPercentEncoding as String! + let decoded = url.absoluteString!.stringByRemovingPercentEncoding as String! let rect = CGRectFromString(decoded.substringFromIndex(decoded.startIndex.advancedBy(12))) webView.createMenu(options: true) @@ -176,7 +176,7 @@ public class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGesture return false } else if url.scheme == "play-audio" { - let decoded = url.absoluteString.stringByRemovingPercentEncoding as String! + let decoded = url.absoluteString!.stringByRemovingPercentEncoding as String! let playID = decoded.substringFromIndex(decoded.startIndex.advancedBy(13)) let chapter = FolioReader.sharedInstance.readerCenter?.getCurrentChapter() let href = chapter != nil ? chapter!.href : ""; @@ -224,7 +224,7 @@ public class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGesture } else if url.scheme == "mailto" { print("Email") return true - } else if url.absoluteString != "about:blank" && url.scheme.containsString("http") && navigationType == .LinkClicked { + } else if url.absoluteString != "about:blank" && url.scheme!.containsString("http") && navigationType == .LinkClicked { if #available(iOS 9.0, *) { let safariVC = SFSafariViewController(URL: request.URL!) @@ -242,7 +242,7 @@ public class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGesture var isClassBasedOnClickListenerScheme = false for listener in readerConfig.classBasedOnClickListeners { if url.scheme == listener.schemeName { - let attributeContentString = (request.URL?.absoluteString.stringByReplacingOccurrencesOfString("\(url.scheme)://", withString: "").stringByRemovingPercentEncoding) + let attributeContentString = (request.URL?.absoluteString!.stringByReplacingOccurrencesOfString("\(url.scheme)://", withString: "").stringByRemovingPercentEncoding) listener.onClickAction(attributeContent: attributeContentString) isClassBasedOnClickListenerScheme = true } @@ -477,7 +477,7 @@ extension UIWebView { || (action == #selector(UIWebView.define(_:)) && isOneWord) || (action == #selector(UIWebView.play(_:)) && (book.hasAudio() || readerConfig.enableTTS)) || (action == #selector(UIWebView.share(_:)) && readerConfig.allowSharing) - || (action == #selector(NSObject.copy(_:)) && readerConfig.allowSharing) { + || (action == #selector(UIWebView.copy(_:)) && readerConfig.allowSharing) { return true } return false diff --git a/Source/FolioReaderPageIndicator.swift b/Source/FolioReaderPageIndicator.swift index d3876087c..0c2c8e5e0 100644 --- a/Source/FolioReaderPageIndicator.swift +++ b/Source/FolioReaderPageIndicator.swift @@ -80,15 +80,6 @@ class FolioReaderPageIndicator: UIView { pagesLabel.textColor = isNight(UIColor(white: 5, alpha: 0.6), UIColor(white: 0, alpha: 0.9)) } - override func animationDidStop(anim: CAAnimation, finished flag: Bool) { - // Set the shadow color to the final value of the animation is done - print("animationDidStop animation: \(anim)") - if let _keyPath = anim.valueForKeyPath("keyPath") as? String where _keyPath == "shadowColor" { - let color = isNight(readerConfig.nightModeBackground, UIColor.whiteColor()) - layer.shadowColor = color.CGColor - } - } - private func reloadViewWithPage(page: Int) { let pagesRemaining = FolioReader.needsRTLChange ? totalPages-(totalPages-page+1) : totalPages-page @@ -111,3 +102,13 @@ class FolioReaderPageIndicator: UIView { reloadView(updateShadow: false) } } + +extension FolioReaderPageIndicator: CAAnimationDelegate { + func animationDidStop(anim: CAAnimation, finished flag: Bool) { + // Set the shadow color to the final value of the animation is done + if let keyPath = anim.valueForKeyPath("keyPath") as? String where keyPath == "shadowColor" { + let color = isNight(readerConfig.nightModeBackground, UIColor.whiteColor()) + layer.shadowColor = color.CGColor + } + } +} diff --git a/Vendor/FontBlaster/FontBlaster.swift b/Vendor/FontBlaster/FontBlaster.swift new file mode 100644 index 000000000..86fc78ce7 --- /dev/null +++ b/Vendor/FontBlaster/FontBlaster.swift @@ -0,0 +1,228 @@ +// +// FontBlaster.swift +// FontBlaster +// +// Created by Arthur Sabintsev on 5/5/15. +// Copyright (c) 2015 Arthur Ariel Sabintsev. All rights reserved. +// + +import Foundation +import CoreGraphics +import CoreText + + +// MARK: - Enums + +/** + Limits the type of fonts that can be loaded into an application + + There are two options: + - TrueTypeFont + - OpenTypeFont + */ +private enum SupportedFontExtensions: String { + case TrueTypeFont = ".ttf" + case OpenTypeFont = ".otf" +} + + +// MARK: - FontBlaster + +/** + The FontBlaster Class. + + Only one class method can be accessed + - blast(_:) + Only one class variable can be accessed and modified + - debugEnabled + */ +final public class FontBlaster { + + private typealias FontPath = String + private typealias FontName = String + private typealias FontExtension = String + private typealias Font = (path: FontPath, name: FontName, ext: FontExtension) + + /** + Used to toggle debug println() statements + */ + public static var debugEnabled = false + + /** + A list of the loaded fonts + */ + public static var loadedFonts: [String] = [] + + /** + Load all fonts found in a specific bundle. If no value is entered, it defaults to NSBundle.mainBundle(). + */ + public class func blast(bundle: NSBundle = NSBundle.mainBundle()) { + blast(bundle, completion: nil) + } + + /** + Load all fonts found in a specific bundle. If no value is entered, it defaults to NSBundle.mainBundle(). + + - returns: An array of strings constaining the names of the fonts that were loaded. + */ + public class func blast(bundle: NSBundle = NSBundle.mainBundle(), completion handler: ([String]->Void)?) { + let path = bundle.bundlePath + loadFontsForBundleWithPath(path) + loadFontsFromBundlesFoundInBundle(path) + handler?(loadedFonts) + } +} + + +// MARK: - Helpers (Font Loading) + +private extension FontBlaster { + /** + Loads all fonts found in a bundle. + + - parameter path: The absolute path to the bundle. + */ + class func loadFontsForBundleWithPath(path: String) { + do { + let contents = try NSFileManager.defaultManager().contentsOfDirectoryAtPath(path) + let fonts = fontsFromPath(path: path, contents: contents) + if !fonts.isEmpty { + for font in fonts { + loadFont(font) + } + } else { + printStatus(status: "No fonts were found in the bundle path: \(path).") + } + } catch let error as NSError { + printStatus(status: "There was an error loading fonts from the bundle. \nPath: \(path).\nError: \(error)") + } + } + + /** + Loads all fonts found in a bundle that is loaded within another bundle. + + - parameter path: The absolute path to the bundle. + */ + class func loadFontsFromBundlesFoundInBundle(path: String) { + + do { + + let contents = try NSFileManager.defaultManager().contentsOfDirectoryAtPath(path) + + for item in contents { + + if let url = NSURL(string: path) where item.containsString(".bundle"), + let urlPath = url.URLByAppendingPathComponent(item), + urlPathString = urlPath.absoluteString { + + loadFontsForBundleWithPath(urlPathString) + + } + + } + + } catch let error as NSError { + printStatus(status: "There was an error accessing bundle with path. \nPath: \(path).\nError: \(error)") + } + + } + + /** + Loads a specific font. + + - parameter font: The font to load. + */ + class func loadFont(font: Font) { + let fontPath: FontPath = font.path + let fontName: FontName = font.name + let fontExtension: FontExtension = font.ext + + guard let fontFileURL = NSBundle(path: fontPath)?.URLForResource(fontName, withExtension: fontExtension) else { + printStatus(status: "Could not unwrap the file URL for the resource with name: \(fontName) and extension \(fontExtension)") + return + } + + var fontError: Unmanaged? + + if let fontData = NSData(contentsOfURL: fontFileURL), + dataProvider = CGDataProviderCreateWithCFData(fontData) { + + let fontRef = CGFontCreateWithDataProvider(dataProvider) + + if CTFontManagerRegisterGraphicsFont(fontRef, &fontError) { + + if let postScriptName = CGFontCopyPostScriptName(fontRef) { + printStatus(status: "Successfully loaded font: '\(postScriptName)'.") + loadedFonts.append(String(postScriptName)) + } + + } else if let fontError = fontError?.takeRetainedValue() { + let errorDescription = CFErrorCopyDescription(fontError) + printStatus(status: "Failed to load font '\(fontName)': \(errorDescription)") + } + + } else { + + guard let fontError = fontError?.takeRetainedValue() else { + printStatus(status: "Failed to load font '\(fontName)'.") + return + } + + let errorDescription = CFErrorCopyDescription(fontError) + printStatus(status: "Failed to load font '\(fontName)': \(errorDescription)") + } + + } +} + + +// MARK: - Helpers (Miscellaneous) + +private extension FontBlaster { + /** + Parses a font into its name and extension components. + + - parameter path: The absolute path to the font file. + - parameter contents: The contents of an NSBundle as an array of String objects. + - returns: A tuple with the font's name and extension. + */ + class func fontsFromPath(path path: String, contents: [NSString]) -> [Font] { + var fonts = [Font]() + for fontName in contents { + var parsedFont: (FontName, FontExtension)? + + if fontName.containsString(SupportedFontExtensions.TrueTypeFont.rawValue) || fontName.containsString(SupportedFontExtensions.OpenTypeFont.rawValue) { + parsedFont = fontFromName(fontName as String) + } + + if let parsedFont = parsedFont { + let font: Font = (path, parsedFont.0, parsedFont.1) + fonts.append(font) + } + } + + return fonts + } + + /** + Parses a font into its name and extension components. + + - parameter The: name of the font. + - returns: A tuple with the font's name and extension. + */ + class func fontFromName(name: String) -> (FontName, FontExtension) { + let components = name.characters.split{$0 == "."}.map { String($0) } + return (components[0], components[1]) + } + + /** + Prints debug messages to the console if debugEnabled is set to true. + + - parameter The: status to print to the console. + */ + class func printStatus(status status: String) { + if debugEnabled == true { + print("[FontBlaster]: \(status)") + } + } +} diff --git a/Vendor/HAControls/HADiscreteSlider.swift b/Vendor/HAControls/HADiscreteSlider.swift index 42f069d28..709e7c26b 100644 --- a/Vendor/HAControls/HADiscreteSlider.swift +++ b/Vendor/HAControls/HADiscreteSlider.swift @@ -191,7 +191,7 @@ class HADiscreteSlider : UIControl { // Track switch self.trackStyle { case .Rectangular: - CGContextAddRect(ctx, self.trackRectangle) + CGContextAddRect(ctx!, self.trackRectangle) break case .Image: @@ -199,13 +199,13 @@ class HADiscreteSlider : UIControl { if let imageName = self.trackImage { let image = UIImage(named:imageName)! let centered = CGRectMake((self.frame.size.width/2)-(image.size.width/2), (self.frame.size.height/2)-(image.size.height/2), image.size.width, image.size.height) - CGContextDrawImage(ctx, centered, image.CGImage) + CGContextDrawImage(ctx!, centered, image.CGImage!) } break case .Invisible, .Rounded, .IOS: let path: UIBezierPath = UIBezierPath(roundedRect: self.trackRectangle, cornerRadius: self.trackRectangle.size.height/2) - CGContextAddPath(ctx, path.CGPath) + CGContextAddPath(ctx!, path.CGPath) break } @@ -217,10 +217,10 @@ class HADiscreteSlider : UIControl { switch self.tickStyle { case .Rounded: let path = UIBezierPath(roundedRect: rectangle, cornerRadius: rectangle.size.height/2) - CGContextAddPath(ctx, path.CGPath) + CGContextAddPath(ctx!, path.CGPath) break case .Rectangular: - CGContextAddRect(ctx, rectangle) + CGContextAddRect(ctx!, rectangle) break case .Image: // Draw image if exists @@ -228,7 +228,7 @@ class HADiscreteSlider : UIControl { if let imageName = self.tickImage { let image = UIImage(named: imageName)! let centered = CGRectMake(rectangle.origin.x+(rectangle.size.width/2)-(image.size.width/2), rectangle.origin.y+(rectangle.size.height/2)-(image.size.height/2), image.size.width, image.size.height) - CGContextDrawImage(ctx, centered, image.CGImage) + CGContextDrawImage(ctx!, centered, image.CGImage!) } break @@ -239,8 +239,8 @@ class HADiscreteSlider : UIControl { } // iOS UISlider aka .IOS does not have ticks - CGContextSetFillColorWithColor(ctx, self.tintColor.CGColor) - CGContextFillPath(ctx) + CGContextSetFillColorWithColor(ctx!, self.tintColor.CGColor) + CGContextFillPath(ctx!) // For colored track, we overlay a CALayer, which will animate along with the cursor if .IOS == self.trackStyle { var frame = self.trackRectangle @@ -388,8 +388,8 @@ class HADiscreteSlider : UIControl { self.touchUp(touches) } - override func touchesCancelled(touches: Set?, withEvent event: UIEvent?) { - self.touchUp(touches!) + override func touchesCancelled(touches: Set, withEvent event: UIEvent?) { + self.touchUp(touches) } func touchDown(touches: NSSet, duration: NSTimeInterval) { From eae0d7bed1a3c12fb5b6ac7bc6361d265c0e77b2 Mon Sep 17 00:00:00 2001 From: Heberti Almeida Date: Tue, 20 Sep 2016 01:05:08 -0300 Subject: [PATCH 2/2] =?UTF-8?q?Prevent=20to=20always=20unzip=20the=20ePub,?= =?UTF-8?q?=20performance=20improvement=20=F0=9F=93=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Source/EPUBCore/FREpubParser.swift | 45 ++++++++++++++++-------------- Source/FolioReaderContainer.swift | 12 ++------ 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/Source/EPUBCore/FREpubParser.swift b/Source/EPUBCore/FREpubParser.swift index b8b04e63e..c9d431240 100755 --- a/Source/EPUBCore/FREpubParser.swift +++ b/Source/EPUBCore/FREpubParser.swift @@ -26,14 +26,12 @@ class FREpubParser: NSObject, SSZipArchiveDelegate { Returns an UIImage. */ func parseCoverImage(epubPath: String) -> UIImage? { - let book = readEpub(epubPath: epubPath, removeEpub: false) - - // Read the cover image - if let coverImage = book.coverImage { - return UIImage(contentsOfFile: coverImage.fullHref) + guard let book = readEpub(epubPath: epubPath, removeEpub: false), + let coverImage = book.coverImage else { + return nil } - return nil + return UIImage(contentsOfFile: coverImage.fullHref) } /** @@ -41,14 +39,31 @@ class FREpubParser: NSObject, SSZipArchiveDelegate { Returns a FRBook. */ - func readEpub(epubPath withEpubPath: String, removeEpub: Bool = true) -> FRBook { + func readEpub(epubPath withEpubPath: String, removeEpub: Bool = true) -> FRBook? { epubPathToRemove = withEpubPath shouldRemoveEpub = removeEpub - // Unzip + var isDir: ObjCBool = false + let fileManager = NSFileManager.defaultManager() let bookName = (withEpubPath as NSString).lastPathComponent bookBasePath = (kApplicationDocumentsDirectory as NSString).stringByAppendingPathComponent(bookName) - SSZipArchive.unzipFileAtPath(withEpubPath, toDestination: bookBasePath, delegate: self) + + guard fileManager.fileExistsAtPath(withEpubPath) else { + print("Epub file does not exist.") + return nil + } + + // Unzip if necessary + var needsUnzip = false + if fileManager.fileExistsAtPath(bookBasePath, isDirectory:&isDir) { + if !isDir { needsUnzip = true } + } else { + needsUnzip = true + } + + if needsUnzip { + SSZipArchive.unzipFileAtPath(withEpubPath, toDestination: bookBasePath, delegate: self) + } // Skip from backup this folder addSkipBackupAttributeToItemAtURL(NSURL(fileURLWithPath: bookBasePath, isDirectory: true)) @@ -59,18 +74,6 @@ class FREpubParser: NSObject, SSZipArchiveDelegate { return book } - /** - Read an unziped epub file. - Returns a FRBook. - */ - func readEpub(filePath withFilePath: String) -> FRBook { - bookBasePath = withFilePath - kBookId = (withFilePath as NSString).lastPathComponent - readContainer() - readOpf() - return book - } - /** Read and parse container.xml file. */ diff --git a/Source/FolioReaderContainer.swift b/Source/FolioReaderContainer.swift index d55944f7f..e110482f8 100755 --- a/Source/FolioReaderContainer.swift +++ b/Source/FolioReaderContainer.swift @@ -124,17 +124,9 @@ public class FolioReaderContainer: UIViewController { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), { () -> Void in - var isDir: ObjCBool = false - let fileManager = NSFileManager.defaultManager() - - if fileManager.fileExistsAtPath(self.epubPath, isDirectory:&isDir) { - if isDir { - book = FREpubParser().readEpub(filePath: self.epubPath) - } - - book = FREpubParser().readEpub(epubPath: self.epubPath, removeEpub: self.shouldRemoveEpub) + if let parsedBook = FREpubParser().readEpub(epubPath: self.epubPath, removeEpub: self.shouldRemoveEpub) { + book = parsedBook } else { - print("Epub file does not exist.") self.errorOnLoad = true }