Skip to content

Commit

Permalink
Merge pull request #81 from dokun1/new-font-plus-open
Browse files Browse the repository at this point in the history
New font plus open
  • Loading branch information
dokun1 committed Jun 4, 2018
2 parents 9db451c + 1497329 commit 913e058
Show file tree
Hide file tree
Showing 21 changed files with 184 additions and 67 deletions.
2 changes: 1 addition & 1 deletion .swift-version
@@ -1 +1 @@
4.0
4.1.2
4 changes: 2 additions & 2 deletions .travis.yml
@@ -1,10 +1,10 @@
language: objective-c
osx_image: xcode9.1
osx_image: xcode9.3
install:
- bundle install
- brew update
- brew upgrade swiftlint
script:
- bundle exec danger
- xcodebuild -scheme Lumina -workspace Lumina.xcworkspace -destination 'platform=iOS Simulator,name=iPhone 7 Plus,OS=10.3.1'
- xcodebuild -scheme Lumina -workspace Lumina.xcworkspace -destination 'platform=iOS Simulator,name=iPhone 7 Plus,OS=11.1'
- xcodebuild -scheme Lumina -workspace Lumina.xcworkspace -destination 'platform=iOS Simulator,name=iPhone 7 Plus,OS=11.3'
8 changes: 8 additions & 0 deletions Lumina.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
22 changes: 21 additions & 1 deletion Lumina/Lumina.xcodeproj/project.pbxproj
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
5305A0C520A0DA7F0040A9A9 /* IBMPlexSans-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5305A0B520A0DA7F0040A9A9 /* IBMPlexSans-SemiBold.ttf */; };
5332084E1F9A99CA008354F7 /* LuminaDeviceUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5332084D1F9A99CA008354F7 /* LuminaDeviceUtil.swift */; };
5365BFD61F79941900B8F338 /* LuminaObjectRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5365BFD51F79941900B8F338 /* LuminaObjectRecognizer.swift */; };
5373B3C41FC386C600C197BD /* FileRecordingExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5373B3C31FC386C600C197BD /* FileRecordingExtension.swift */; };
Expand Down Expand Up @@ -41,6 +42,7 @@
53B8290F1EAAA24600E3A624 /* LuminaViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53B8290E1EAAA24600E3A624 /* LuminaViewController.swift */; };
53B9CCFB1EBF6C62008E4A43 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 53B9CCFA1EBF6C62008E4A43 /* Media.xcassets */; };
53B9CCFD1EBFD22E008E4A43 /* LuminaTextPromptView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53B9CCFC1EBFD22E008E4A43 /* LuminaTextPromptView.swift */; };
53C06F7520BF0C8F00C03BA6 /* LuminaModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C06F7420BF0C8F00C03BA6 /* LuminaModel.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -55,6 +57,7 @@

/* Begin PBXFileReference section */
509FF65F1F9D2F6300FD62CD /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
5305A0B520A0DA7F0040A9A9 /* IBMPlexSans-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "IBMPlexSans-SemiBold.ttf"; sourceTree = "<group>"; };
5332084D1F9A99CA008354F7 /* LuminaDeviceUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LuminaDeviceUtil.swift; sourceTree = "<group>"; };
5365BFD51F79941900B8F338 /* LuminaObjectRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LuminaObjectRecognizer.swift; sourceTree = "<group>"; };
5373B3C31FC386C600C197BD /* FileRecordingExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRecordingExtension.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -92,6 +95,7 @@
53B8290E1EAAA24600E3A624 /* LuminaViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LuminaViewController.swift; sourceTree = "<group>"; };
53B9CCFA1EBF6C62008E4A43 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = "<group>"; };
53B9CCFC1EBFD22E008E4A43 /* LuminaTextPromptView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LuminaTextPromptView.swift; sourceTree = "<group>"; };
53C06F7420BF0C8F00C03BA6 /* LuminaModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LuminaModel.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -114,10 +118,19 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
5305A0AA20A0DA630040A9A9 /* Fonts */ = {
isa = PBXGroup;
children = (
5305A0B520A0DA7F0040A9A9 /* IBMPlexSans-SemiBold.ttf */,
);
path = Fonts;
sourceTree = "<group>";
};
5373B3C11FC3868200C197BD /* Camera */ = {
isa = PBXGroup;
children = (
5332084D1F9A99CA008354F7 /* LuminaDeviceUtil.swift */,
53C06F7420BF0C8F00C03BA6 /* LuminaModel.swift */,
53806FA31F6618230009A0E8 /* LuminaCamera.swift */,
5373B3DE1FC3B8B600C197BD /* LuminaPhotoCapture.swift */,
5365BFD51F79941900B8F338 /* LuminaObjectRecognizer.swift */,
Expand Down Expand Up @@ -169,6 +182,7 @@
5373B3DD1FC3B7B600C197BD /* Util */ = {
isa = PBXGroup;
children = (
5305A0AA20A0DA630040A9A9 /* Fonts */,
53B2CE311FF80B4D008287E6 /* Logging */,
53B828D31EAAA07F00E3A624 /* Lumina.h */,
53B828D41EAAA07F00E3A624 /* Info.plist */,
Expand Down Expand Up @@ -312,7 +326,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0820;
LastUpgradeCheck = 0900;
LastUpgradeCheck = 0940;
ORGANIZATIONNAME = "David Okun";
TargetAttributes = {
53B828CF1EAAA07F00E3A624 = {
Expand Down Expand Up @@ -352,6 +366,7 @@
buildActionMask = 2147483647;
files = (
53B9CCFB1EBF6C62008E4A43 /* Media.xcassets in Resources */,
5305A0C520A0DA7F0040A9A9 /* IBMPlexSans-SemiBold.ttf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -397,6 +412,7 @@
5373B3ED1FC3D65500C197BD /* LuminaCameraViewSettings.swift in Sources */,
5373B3EB1FC3D5D700C197BD /* InterfaceHandlerExtension.swift in Sources */,
5373B3E21FC3D47500C197BD /* ViewControllerFocusHandlerExtension.swift in Sources */,
53C06F7520BF0C8F00C03BA6 /* LuminaModel.swift in Sources */,
5373B3CB1FC3AFF900C197BD /* VideoDataOutputSampleBufferDelegateExtension.swift in Sources */,
53806FA61F672F780009A0E8 /* LuminaButton.swift in Sources */,
53B9CCFD1EBFD22E008E4A43 /* LuminaTextPromptView.swift in Sources */,
Expand Down Expand Up @@ -450,13 +466,15 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
Expand Down Expand Up @@ -509,13 +527,15 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
Expand Down
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
LastUpgradeVersion = "0940"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand All @@ -26,7 +26,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
Expand Down Expand Up @@ -56,7 +55,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
Expand Down
Expand Up @@ -54,7 +54,7 @@ extension LuminaCamera {
func restartVideo() {
Log.verbose("restarting video feed")
if self.session.isRunning {
self.session.stopRunning()
self.stop()
updateVideo({ result in
if result == .videoSuccess {
self.start()
Expand Down
19 changes: 12 additions & 7 deletions Lumina/Lumina/Camera/LuminaCamera.swift
Expand Up @@ -165,15 +165,15 @@ final class LuminaCamera: NSObject {

var recognizer: AnyObject?

private var _streamingModels: [(AnyObject, Any.Type)]?
private var _streamingModels: [(AnyObject, String)]?
@available(iOS 11.0, *)
var streamingModels: [(MLModel, Any.Type)]? {
var streamingModels: [LuminaModel]? {
get {
if let existingModels = _streamingModels {
var models = [(MLModel, Any.Type)]()
var models = [LuminaModel]()
for potentialModel in existingModels {
if let model = potentialModel.0 as? MLModel {
models.append((model, potentialModel.1))
models.append(LuminaModel(model: model, type: potentialModel.1))
}
}
guard models.count > 0 else {
Expand All @@ -186,9 +186,12 @@ final class LuminaCamera: NSObject {
}
set {
if let tuples = newValue {
var downcastCollection = [(AnyObject, Any.Type)]()
var downcastCollection = [(AnyObject, String)]()
for tuple in tuples {
downcastCollection.append((tuple.0 as AnyObject, tuple.1))
guard let model = tuple.model, let type = tuple.type else {
continue
}
downcastCollection.append((model as AnyObject, type))
}
_streamingModels = downcastCollection
}
Expand Down Expand Up @@ -276,6 +279,8 @@ final class LuminaCamera: NSObject {

func stop() {
Log.verbose("stopping capture session")
self.session.stopRunning()
self.sessionQueue.async {
self.session.stopRunning()
}
}
}
9 changes: 7 additions & 2 deletions Lumina/Lumina/Camera/LuminaDeviceUtil.swift
Expand Up @@ -28,7 +28,7 @@ final class LuminaHapticFeedbackGenerator {
}
}

fileprivate extension UIDevice {
internal extension UIDevice {
enum DevicePlatform {
case other
case iPhone6S
Expand All @@ -38,13 +38,16 @@ fileprivate extension UIDevice {
case iPhone8
case iPhone8Plus
case iPhoneX
case simulator
}

private var platform: DevicePlatform {
static var platform: DevicePlatform {
var sysinfo = utsname()
uname(&sysinfo)
let platform = String(bytes: Data(bytes: &sysinfo.machine, count: Int(_SYS_NAMELEN)), encoding: .ascii)!.trimmingCharacters(in: .controlCharacters)
switch platform {
case "x86_64":
return .simulator
case "iPhone 10,1", "iPhone10,4":
return .iPhone8
case "iPhone 10,2", "iPhone 10,5":
Expand All @@ -65,10 +68,12 @@ fileprivate extension UIDevice {
}

var hasTapticEngine: Bool {
let platform = UIDevice.platform
return platform == .iPhone6S || platform == .iPhone6SPlus || platform == .iPhone7 || platform == .iPhone7Plus || platform == .iPhone8 || platform == .iPhone8Plus || platform == .iPhoneX
}

var hasHapticFeedback: Bool {
let platform = UIDevice.platform
return platform == .iPhone7 || platform == .iPhone7Plus || platform == .iPhone8 || platform == .iPhone8Plus || platform == .iPhoneX
}
}
24 changes: 24 additions & 0 deletions Lumina/Lumina/Camera/LuminaModel.swift
@@ -0,0 +1,24 @@
//
// LuminaModel.swift
// Lumina
//
// Created by David Okun IBM on 5/30/18.
// Copyright © 2018 David Okun. All rights reserved.
//

import Foundation
import CoreML

/// A class that creates a convenient container for loading Core ML models into Lumina
@available(iOS 11.0, *)
final public class LuminaModel {
/// The Core ML model file to perform image recognition
var model: MLModel?
/// A string that represents the class name of the model performing recognition
var type: String?

public init(model: MLModel, type: String) {
self.model = model
self.type = type
}
}
18 changes: 11 additions & 7 deletions Lumina/Lumina/Camera/LuminaObjectRecognizer.swift
Expand Up @@ -24,15 +24,15 @@ public struct LuminaPrediction {
public struct LuminaRecognitionResult {
/// The collection of predictions in a given result, as predicted by Lumina
public var predictions: [LuminaPrediction]?
/// The type of MLModel that made the predictions, best resolved as a String
public var type: Any.Type
/// The String type of MLModel that made the predictions
public var type: String
}

@available(iOS 11.0, *)
final class LuminaObjectRecognizer: NSObject {
private var modelPairs: [(MLModel, Any.Type)]
private var modelPairs: [LuminaModel]

init(modelPairs: [(MLModel, Any.Type)]) {
init(modelPairs: [LuminaModel]) {
Log.verbose("initializing object recognizer for \(modelPairs.count) CoreML models")
self.modelPairs = modelPairs
}
Expand All @@ -46,17 +46,21 @@ final class LuminaObjectRecognizer: NSObject {
let recognitionGroup = DispatchGroup()
for modelPair in modelPairs {
recognitionGroup.enter()
guard let visionModel = try? VNCoreMLModel(for: modelPair.0) else {
guard let model = modelPair.model, let modelType = modelPair.type else {
recognitionGroup.leave()
continue
}
guard let visionModel = try? VNCoreMLModel(for: model) else {
recognitionGroup.leave()
continue
}
let request = VNCoreMLRequest(model: visionModel) { request, error in
if error != nil || request.results == nil {
recognitionResults.append(LuminaRecognitionResult(predictions: nil, type: modelPair.1))
recognitionResults.append(LuminaRecognitionResult(predictions: nil, type: modelType))
recognitionGroup.leave()
} else if let results = request.results {
let mappedResults = self.mapResults(results)
recognitionResults.append(LuminaRecognitionResult(predictions: mappedResults, type: modelPair.1))
recognitionResults.append(LuminaRecognitionResult(predictions: mappedResults, type: modelType))
recognitionGroup.leave()
}
}
Expand Down
6 changes: 3 additions & 3 deletions Lumina/Lumina/UI/Extensions/InterfaceHandlerExtension.swift
Expand Up @@ -73,11 +73,11 @@ extension LuminaViewController {
}
self.shutterButton.center = CGPoint(x: self.view.frame.midX, y: maxY - 45)
}
self.switchButton.center = CGPoint(x: self.view.frame.maxX - 25, y: self.view.frame.minY + 25)
self.torchButton.center = CGPoint(x: self.view.frame.minX + 25, y: self.view.frame.minY + 25)
self.switchButton.center = CGPoint(x: self.view.frame.maxX - 25, y: self.view.frame.minY + (UIDevice.platform == .iPhoneX ? 80 : 25))
self.torchButton.center = CGPoint(x: self.view.frame.minX + 25, y: self.view.frame.minY + (UIDevice.platform == .iPhoneX ? 80 : 25))
/// Use more width, if text has been moved down below the buttons (e.g. notch on iPhone X):
let textWidth = self.view.frame.maxX - (minY > 35 ? 20 : 110)
self.textPromptView.frame.size = CGSize(width: textWidth, height: 80)
self.textPromptView.frame.size = CGSize(width: textWidth - 10, height: 80)
self.textPromptView.layoutSubviews()
self.textPromptView.center = CGPoint(x: self.view.frame.midX, y: minY + 45)
}
Expand Down
39 changes: 38 additions & 1 deletion Lumina/Lumina/UI/LuminaTextPromptView.swift
Expand Up @@ -8,6 +8,32 @@

import UIKit

enum LuminaTextError: Error {
case fontError
}

extension UIFont {
static func fontsURLs() -> [URL]? {
let bundle = Bundle(identifier: "com.okun.io.Lumina")
let fileNames = ["IBMPlexSans-SemiBold"]
let newNames = fileNames.map({ bundle?.url(forResource: $0, withExtension: "ttf") })
return newNames as? [URL]
}

static func register(from url: URL) throws {
guard let fontDataProvider = CGDataProvider(url: url as CFURL) else {
throw LuminaTextError.fontError
}
guard let font = CGFont(fontDataProvider) else {
throw LuminaTextError.fontError
}
var error: Unmanaged<CFError>?
guard CTFontManagerRegisterGraphicsFont(font, &error) else {
throw error!.takeUnretainedValue()
}
}
}

final class LuminaTextPromptView: UIView {

private var textLabel = UILabel()
Expand All @@ -19,7 +45,18 @@ final class LuminaTextPromptView: UIView {
self.textLabel.backgroundColor = UIColor.clear
self.textLabel.textColor = UIColor.white
self.textLabel.textAlignment = .center
self.textLabel.font = UIFont.systemFont(ofSize: 22, weight: .bold)
do {
if let fonts = UIFont.fontsURLs() {
try fonts.forEach { try UIFont.register(from: $0) }
}
} catch {
Log.debug("Special fonts already registered")
}
if let font = UIFont(name: "IBM Plex Sans", size: 22) {
self.textLabel.font = font
} else {
self.textLabel.font = UIFont.systemFont(ofSize: 22, weight: .bold)
}
self.textLabel.numberOfLines = 3
self.textLabel.minimumScaleFactor = 10/UIFont.labelFontSize
self.textLabel.adjustsFontSizeToFitWidth = true
Expand Down

0 comments on commit 913e058

Please sign in to comment.