Skip to content

Commit

Permalink
Merge pull request #23 from KyoheiG3/swift-4
Browse files Browse the repository at this point in the history
Support Swift 4
  • Loading branch information
KyoheiG3 authored Sep 25, 2017
2 parents 88aab91 + f26b73f commit 992e513
Show file tree
Hide file tree
Showing 14 changed files with 709 additions and 405 deletions.
44 changes: 40 additions & 4 deletions DynamicBlurView.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
objects = {

/* Begin PBXBuildFile section */
C71401761F3E894A00F41421 /* UIImage+Blur.swift in Sources */ = {isa = PBXBuildFile; fileRef = C71401751F3E894A00F41421 /* UIImage+Blur.swift */; };
C714017D1F426E8700F41421 /* BlurLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C714017C1F426E8600F41421 /* BlurLayer.swift */; };
C73390791F46721A00617D26 /* CGImage+Accelerate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C73390781F46721800617D26 /* CGImage+Accelerate.swift */; };
C733907B1F467D2B00617D26 /* CaptureQuality.swift in Sources */ = {isa = PBXBuildFile; fileRef = C733907A1F467D2B00617D26 /* CaptureQuality.swift */; };
C733907D1F467E0700617D26 /* TrackingMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = C733907C1F467E0700617D26 /* TrackingMode.swift */; };
C733907F1F467E7100617D26 /* CGContext+CGImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C733907E1F467E7100617D26 /* CGContext+CGImage.swift */; };
C7F3104F1AD572FB006D95AD /* DynamicBlurView.h in Headers */ = {isa = PBXBuildFile; fileRef = C7F3104E1AD572FB006D95AD /* DynamicBlurView.h */; settings = {ATTRIBUTES = (Public, ); }; };
C7F310551AD572FB006D95AD /* DynamicBlurView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C7F310491AD572FB006D95AD /* DynamicBlurView.framework */; };
C7F3105C1AD572FB006D95AD /* DynamicBlurViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F3105B1AD572FB006D95AD /* DynamicBlurViewTests.swift */; };
Expand All @@ -24,6 +30,12 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
C71401751F3E894A00F41421 /* UIImage+Blur.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Blur.swift"; sourceTree = "<group>"; };
C714017C1F426E8600F41421 /* BlurLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurLayer.swift; sourceTree = "<group>"; };
C73390781F46721800617D26 /* CGImage+Accelerate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGImage+Accelerate.swift"; sourceTree = "<group>"; };
C733907A1F467D2B00617D26 /* CaptureQuality.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaptureQuality.swift; sourceTree = "<group>"; };
C733907C1F467E0700617D26 /* TrackingMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackingMode.swift; sourceTree = "<group>"; };
C733907E1F467E7100617D26 /* CGContext+CGImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGContext+CGImage.swift"; sourceTree = "<group>"; };
C7F310491AD572FB006D95AD /* DynamicBlurView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DynamicBlurView.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C7F3104D1AD572FB006D95AD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C7F3104E1AD572FB006D95AD /* DynamicBlurView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DynamicBlurView.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -73,8 +85,14 @@
C7F3104B1AD572FB006D95AD /* DynamicBlurView */ = {
isa = PBXGroup;
children = (
C714017C1F426E8600F41421 /* BlurLayer.swift */,
C733907A1F467D2B00617D26 /* CaptureQuality.swift */,
C733907E1F467E7100617D26 /* CGContext+CGImage.swift */,
C73390781F46721800617D26 /* CGImage+Accelerate.swift */,
C7F3104E1AD572FB006D95AD /* DynamicBlurView.h */,
C7F310651AD573D5006D95AD /* DynamicBlurView.swift */,
C733907C1F467E0700617D26 /* TrackingMode.swift */,
C71401751F3E894A00F41421 /* UIImage+Blur.swift */,
C7F3104C1AD572FB006D95AD /* Supporting Files */,
);
path = DynamicBlurView;
Expand Down Expand Up @@ -163,12 +181,12 @@
attributes = {
LastSwiftMigration = 0700;
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0800;
LastUpgradeCheck = 0900;
ORGANIZATIONNAME = kyohei_ito;
TargetAttributes = {
C7F310481AD572FB006D95AD = {
CreatedOnToolsVersion = 6.2;
LastSwiftMigration = 0800;
LastSwiftMigration = 0900;
};
C7F310531AD572FB006D95AD = {
CreatedOnToolsVersion = 6.2;
Expand Down Expand Up @@ -216,6 +234,12 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C73390791F46721A00617D26 /* CGImage+Accelerate.swift in Sources */,
C733907D1F467E0700617D26 /* TrackingMode.swift in Sources */,
C733907B1F467D2B00617D26 /* CaptureQuality.swift in Sources */,
C733907F1F467E7100617D26 /* CGContext+CGImage.swift in Sources */,
C714017D1F426E8700F41421 /* BlurLayer.swift in Sources */,
C71401761F3E894A00F41421 /* UIImage+Blur.swift in Sources */,
C7F310661AD573D5006D95AD /* DynamicBlurView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -247,14 +271,20 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
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_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
Expand Down Expand Up @@ -297,14 +327,20 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
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_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
Expand Down Expand Up @@ -348,7 +384,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
Expand All @@ -367,7 +403,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.kyoheiito.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
SWIFT_VERSION = 4.0;
};
name = Release;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down Expand Up @@ -40,6 +40,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
Expand Down Expand Up @@ -69,6 +70,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
Expand Down
131 changes: 131 additions & 0 deletions DynamicBlurView/BlurLayer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//
// BlurLayer.swift
// DynamicBlurView
//
// Created by Kyohei Ito on 2017/08/14.
// Copyright © 2017年 kyohei_ito. All rights reserved.
//

import UIKit

private extension CGRect {
func rectangle(_ s: CGSize) -> CGRect {
let x = origin.x / s.width
let y = origin.y / s.height
let width = size.width / s.width
let height = size.height / s.height
return CGRect(x: x, y: y, width: width, height: height)
}
}

class BlurLayer: CALayer {
private static let blurRadiusKey = "blurRadius"
private static let blurLayoutKey = "blurLayout"
@NSManaged var blurRadius: CGFloat
@NSManaged private var blurLayout: CGFloat

private var fromBlurRadius: CGFloat?
var presentationRadius: CGFloat {
if let radius = fromBlurRadius {
if let layer = presentation() {
return layer.blurRadius
} else {
return radius
}
} else {
return blurRadius
}
}

override class func needsDisplay(forKey key: String) -> Bool {
if key == blurRadiusKey || key == blurLayoutKey {
return true
}
return super.needsDisplay(forKey: key)
}

open override func action(forKey event: String) -> CAAction? {
if event == BlurLayer.blurRadiusKey {
fromBlurRadius = nil

if let action = super.action(forKey: "opacity") as? CABasicAnimation {
fromBlurRadius = (presentation() ?? self).blurRadius

action.keyPath = event
action.fromValue = fromBlurRadius
return action
}
}

if event == BlurLayer.blurLayoutKey, let action = super.action(forKey: "opacity") as? CABasicAnimation {
action.keyPath = event
action.fromValue = 0
action.toValue = 1
return action
}

return super.action(forKey: event)
}
}

extension BlurLayer {
func draw(_ image: UIImage, fixes isFixes: Bool, baseLayer: CALayer?) {
contents = image.cgImage
contentsScale = image.scale

if isFixes, let blurLayer = presentation() {
contentsRect = blurLayer.convert(blurLayer.bounds, to: baseLayer).rectangle(image.size)
}
}

func refresh() {
fromBlurRadius = nil
}

func animate() {
UIView.performWithoutAnimation {
blurLayout = 0
}
blurLayout = 1
}

func render(in context: CGContext, for layer: CALayer) {
let layers = hideOverlappingLayers(layer.sublayers)
layer.render(in: context)
layers.forEach {
$0.isHidden = false
}
}

private func hideOverlappingLayers(_ layers: [CALayer]?) -> [CALayer] {
var hiddenLayers: [CALayer] = []
guard let layers = layers else {
return hiddenLayers
}

for layer in layers.reversed() {
if isHang(to: layer) {
return hiddenLayers + hideOverlappingLayers(layer.sublayers)
}
if layer.isHidden == false {
layer.isHidden = true
hiddenLayers.append(layer)
}
if layer == self {
return hiddenLayers
}
}
return hiddenLayers
}

private func isHang(to target: CALayer) -> Bool {
var layer = superlayer
while layer != nil {
if layer == target {
return true
}
layer = layer?.superlayer
}
return false
}
}
31 changes: 31 additions & 0 deletions DynamicBlurView/CGContext+CGImage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// CGContext+CGImage.swift
// DynamicBlurView
//
// Created by Kyohei Ito on 2017/08/17.
// Copyright © 2017年 kyohei_ito. All rights reserved.
//

extension CGContext {
static func imageContext(with quality: CaptureQuality, rect: CGRect, opaque: Bool) -> CGContext? {
UIGraphicsBeginImageContextWithOptions(rect.size, opaque, quality.imageScale)
guard let context = UIGraphicsGetCurrentContext() else {
return nil
}

context.translateBy(x: -rect.origin.x, y: -rect.origin.y)
context.interpolationQuality = quality.interpolationQuality

return context
}

func makeImage(with blendColor: UIColor?, blendMode: CGBlendMode, size: CGSize) -> CGImage? {
if let color = blendColor {
setFillColor(color.cgColor)
setBlendMode(blendMode)
fill(CGRect(origin: .zero, size: size))
}

return makeImage()
}
}
65 changes: 65 additions & 0 deletions DynamicBlurView/CGImage+Accelerate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// CGImage+Accelerate.swift
// DynamicBlurView
//
// Created by Kyohei Ito on 2017/08/17.
// Copyright © 2017年 kyohei_ito. All rights reserved.
//

import Accelerate

extension CGImage {
var area: Int {
return width * height
}

private var size: CGSize {
return CGSize(width: width, height: height)
}

private var bytes: Int {
return bytesPerRow * height
}

private func imageBuffer(from data: UnsafeMutableRawPointer!) -> vImage_Buffer {
return vImage_Buffer(data: data, height: vImagePixelCount(height), width: vImagePixelCount(width), rowBytes: bytesPerRow)
}

func blurred(with boxSize: UInt32, iterations: Int, blendColor: UIColor?, blendMode: CGBlendMode) -> CGImage? {
guard let provider = dataProvider else {
return nil
}

let inData = malloc(bytes)
var inBuffer = imageBuffer(from: inData)

let outData = malloc(bytes)
var outBuffer = imageBuffer(from: outData)

let tempSize = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, nil, 0, 0, boxSize, boxSize, nil, vImage_Flags(kvImageEdgeExtend + kvImageGetTempBufferSize))
let tempData = malloc(tempSize)

defer {
free(inData)
free(outData)
free(tempData)
}

let source = CFDataGetBytePtr(provider.data)
memcpy(inBuffer.data, source, bytes)

for _ in 0..<iterations {
vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, tempData, 0, 0, boxSize, boxSize, nil, vImage_Flags(kvImageEdgeExtend))

let temp = inBuffer.data
inBuffer.data = outBuffer.data
outBuffer.data = temp
}

let context = colorSpace.flatMap {
CGContext(data: inBuffer.data, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: $0, bitmapInfo: bitmapInfo.rawValue)
}

return context?.makeImage(with: blendColor, blendMode: blendMode, size: size)
}
}
Loading

0 comments on commit 992e513

Please sign in to comment.