1
1
mirror of https://github.com/exyte/Macaw.git synced 2024-11-13 13:14:20 +03:00

Merge pull request #207 from exyte/task/swiftlint

Integrate SwiftLint in project
This commit is contained in:
Victor Sukochev 2017-10-19 15:44:31 +07:00 committed by GitHub
commit ff7c3e2df7
119 changed files with 6218 additions and 6089 deletions

115
.swiftlint.yml Normal file
View File

@ -0,0 +1,115 @@
included:
- Source
- Tests
excluded:
- Dependencies
disabled_rules:
- unused_optional_binding
- file_header
- no_extension_access_modifier
- number_separator
- object_literal
- pattern_matching_keywords
- private_over_fileprivate
- strict_fileprivate
- sorted_imports
- identifier_name # Disabled due to a lot of one symbol identifiers
# Temporary disabled
- explicit_type_interface
- line_length
- file_length
- type_body_length
- function_body_length
- cyclomatic_complexity
- function_parameter_count
- type_name
- force_unwrapping
- explicit_top_level_acl
- legacy_constructor
- todo
- implicitly_unwrapped_optional
- attributes
- force_cast
- extension_access_modifier
- large_tuple
- no_grouping_extension
opt_in_rules:
- block_based_kvo
- class_delegate_protocol
- closing_brace
- closure_end_indentation
- closure_parameter_position
- closure_spacing
- colon
- comma
- compiler_protocol_init
- conditional_returns_on_newline
- control_statement
- discarded_notification_center_observer
- discouraged_direct_init
- dynamic_inline
- empty_count
- empty_enum_arguments
- empty_parameters
- empty_parentheses_with_trailing_closure
- explicit_enum_raw_value
- explicit_init
- fatal_error_message
- first_where
- for_where
- force_try
- generic_type_name
- identifier_name
- implicit_getter
- implicit_return
- is_disjoint
- joined_default_parameter
- leading_whitespace
- legacy_cggeometry_functions
- legacy_constant
- legacy_nsgeometry_functions
- let_var_whitespace
- mark
- multiline_parameters
- multiple_closures_with_trailing_closure
- nesting
- nimble_operator
- notification_center_detachment
- opening_brace
- operator_usage_whitespace
- operator_whitespace
- overridden_super_call
- private_outlet
- private_unit_test
- prohibited_super_call
- protocol_property_accessors_order
- quick_discouraged_call
- redundant_discardable_let
- redundant_nil_coalescing
- redundant_optional_initialization
- redundant_string_enum_value
- redundant_void_return
- return_arrow_whitespace
- shorthand_operator
- single_test_class
- statement_position
- superfluous_disable_command
- switch_case_on_newline
- syntactic_sugar
- trailing_closure
- trailing_comma
- trailing_newline
- trailing_semicolon
- trailing_whitespace
- unneeded_parentheses_in_closure_argument
- unused_closure_parameter
- unused_enumerated
- valid_ibinspectable
- vertical_parameter_alignment
- vertical_whitespace
- void_return
- weak_delegate
- xctfail_message
force_cast: warning
shorthand_operator: warning
empty_count: warning

View File

@ -911,6 +911,7 @@
57614B731F83D15600875933 /* Headers */,
57614B741F83D15600875933 /* Resources */,
57614B751F83D15600875933 /* CopyFiles */,
665742FC1F988D93006612C6 /* ShellScript */,
);
buildRules = (
);
@ -930,6 +931,7 @@
57FCD2691D76EA4600CC0FB6 /* Headers */,
57FCD26A1D76EA4600CC0FB6 /* Resources */,
57D202181D78047000A90D4F /* CopyFiles */,
669D360B1F8F9B4C0048EF8B /* ShellScript */,
);
buildRules = (
);
@ -1040,6 +1042,35 @@
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
665742FC1F988D93006612C6 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if which swiftlint >/dev/null; then\n swiftlint autocorrect --format\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
};
669D360B1F8F9B4C0048EF8B /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if which swiftlint >/dev/null; then\n swiftlint autocorrect --format\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
57614AFC1F83D15600875933 /* Sources */ = {
isa = PBXSourcesBuildPhase;

View File

@ -35,7 +35,7 @@ public class Animation {
return self
}
public func cycle() -> Animation{
public func cycle() -> Animation {
return self
}
@ -47,7 +47,7 @@ public class Animation {
return self
}
@discardableResult public func onComplete(_: @escaping (() -> ())) -> Animation {
@discardableResult public func onComplete(_: @escaping (() -> Void)) -> Animation {
return self
}
}

View File

@ -26,7 +26,7 @@ class BasicAnimation: Animation {
var type = AnimationType.unknown
let ID: String
var next: BasicAnimation?
var removeFunc: (() -> ())?
var removeFunc: (() -> Void)?
var delayed = false
var manualStop = false
var paused = false
@ -36,9 +36,9 @@ class BasicAnimation: Animation {
var cycled = false
var delay = 0.0
var autoreverses = false
var onProgressUpdate: ((Double) -> ())?
var onProgressUpdate: ((Double) -> Void)?
var easing = Easing.ease
var completion: (() -> ())?
var completion: (() -> Void)?
override init() {
ID = UUID().uuidString
@ -72,7 +72,7 @@ class BasicAnimation: Animation {
return self
}
override open func onComplete(_ f: @escaping (() -> ())) -> Animation {
override open func onComplete(_ f: @escaping (() -> Void)) -> Animation {
self.completion = f
return self
}
@ -136,7 +136,7 @@ extension BasicAnimation: Hashable {
return ID.hashValue
}
public static func ==(lhs: BasicAnimation, rhs: BasicAnimation) -> Bool {
public static func == (lhs: BasicAnimation, rhs: BasicAnimation) -> Bool {
return lhs.ID == rhs.ID
}
}
@ -148,7 +148,6 @@ extension BasicAnimation {
}
}
// Animated property list https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/AnimatableProperties/AnimatableProperties.html
internal class AnimationImpl<T: Interpolable>: BasicAnimation {
@ -248,7 +247,7 @@ internal class AnimationImpl<T: Interpolable>: BasicAnimation {
// For sequence completion
class EmptyAnimation: BasicAnimation {
required init(completion: @escaping (() -> ())) {
required init(completion: @escaping (() -> Void)) {
super.init()
self.completion = completion
@ -259,9 +258,11 @@ class EmptyAnimation: BasicAnimation {
// MARK: - Animation Description
open class AnimationDescription <T> {
open let valueFunc: (Double) -> T
open var duration = 0.0
open var delay = 0.0
public init(valueFunc: @escaping (Double) -> T, duration: Double = 1.0, delay: Double = 0.0) {
self.valueFunc = valueFunc
self.duration = duration

View File

@ -10,7 +10,6 @@ let animationProducer = AnimationProducer()
class AnimationProducer {
var storedAnimations = [Node: BasicAnimation]()
var delayedAnimations = [BasicAnimation: Timer]()
var displayLink: MDisplayLinkProtocol?
@ -21,7 +20,7 @@ class AnimationProducer {
weak var cache: AnimationCache?
let startDate: Date
let finishDate: Date
let completion: (()->())?
let completion: (() -> Void)?
}
var contentsAnimations = [ContentAnimationDesc]()
@ -31,11 +30,11 @@ class AnimationProducer {
// Delay - launching timer
if animation.delay > 0.0 && !withoutDelay {
let timer = Timer.schedule(delay: animation.delay, handler: { [weak self] _ in
let timer = Timer.schedule(delay: animation.delay) { [weak self] _ in
self?.addAnimation(animation, withoutDelay: true)
_ = self?.delayedAnimations.removeValue(forKey: animation)
animation.delayed = false
})
}
animation.delayed = true
delayedAnimations[animation] = timer
@ -66,7 +65,6 @@ class AnimationProducer {
}
}
// General case
guard let nodeId = animation.nodeId, let node = Node.nodeBy(id: nodeId) else {
return
@ -81,11 +79,11 @@ class AnimationProducer {
return
}
guard let cache = macawView.animationCache else {
return
}
// swiftlint:disable superfluous_disable_command switch_case_alignment
switch animation.type {
case .unknown:
return
@ -107,26 +105,27 @@ class AnimationProducer {
case .combine:
addCombineAnimation(animation)
case .contents:
addContentsAnimation(animation, cache: cache, completion: {
addContentsAnimation(animation, cache: cache) {
if let next = animation.next {
self.addAnimation(next)
}
})
}
case .morphing:
addMorphingAnimation(animation, sceneLayer: layer, animationCache: cache, completion: {
addMorphingAnimation(animation, sceneLayer: layer, animationCache: cache) {
if let next = animation.next {
self.addAnimation(next)
}
})
}
case .shape:
addShapeAnimation(animation, sceneLayer: layer, animationCache: cache, completion: {
addShapeAnimation(animation, sceneLayer: layer, animationCache: cache) {
if let next = animation.next {
self.addAnimation(next)
}
})
}
case .empty:
executeCompletion(animation)
}
// swiftlint:enable superfluous_disable_command switch_case_alignment
}
func removeDelayed(animation: BasicAnimation) {
@ -279,7 +278,7 @@ class AnimationProducer {
// MARK: - Contents animation
func addContentsAnimation(_ animation: BasicAnimation, cache: AnimationCache?, completion: @escaping (() -> ())) {
func addContentsAnimation(_ animation: BasicAnimation, cache: AnimationCache?, completion: @escaping (() -> Void)) {
guard let contentsAnimation = animation as? ContentsAnimation else {
return
}
@ -339,7 +338,7 @@ class AnimationProducer {
}
@objc func updateContentAnimations() {
if contentsAnimations.count == 0 {
if contentsAnimations.isEmpty {
displayLink?.invalidate()
displayLink = .none
}

View File

@ -35,6 +35,7 @@ class AnimationUtils {
}
private static var indexCache = [Node: Int]()
class func absoluteIndex(_ node: Node, useCache: Bool = false) -> Int {
if useCache {
if let cachedIndex = indexCache[node] {
@ -44,8 +45,7 @@ class AnimationUtils {
indexCache.removeAll()
}
func childrenTotalCount(_ node: Node) -> Int{
func childrenTotalCount(_ node: Node) -> Int {
guard let group = node as? Group else {
return 1
}

View File

@ -1,5 +1,6 @@
import Foundation
// swiftlint:disable trailing_closure
public func >> (a: Double, b: Double) -> OpacityAnimationDescription {
return OpacityAnimationDescription(valueFunc: { t in
return a.interpolate(b, progress: t)
@ -22,3 +23,4 @@ public func >> (a: Locus, b: Locus) -> MorphingAnimationDescription {
return b
})
}
// swiftlint:enable trailing_closure

View File

@ -1,4 +1,3 @@
public protocol TransformInterpolation: Interpolable {
}

View File

@ -1,19 +1,18 @@
func solveEquation(a: Double, b: Double, c: Double) -> (s1: Double?, s2: Double?) {
let epsilon: Double = 0.000000001
if (abs(a) < epsilon) {
if (abs(b) < epsilon) {
if abs(a) < epsilon {
if abs(b) < epsilon {
return (.none, .none)
}
let s = -c / b
if (0.0 < s && s < 1.0) {
if 0.0 < s && s < 1.0 {
return (s, .none)
}
return (.none, .none)
}
let b2ac = b * b - 4.0 * c * a
if (b2ac < 0.0) {
if b2ac < 0.0 {
return (.none, .none)
}
let sqrtb2ac = b2ac.squareRoot()
@ -24,7 +23,7 @@ func solveEquation(a: Double, b: Double, c: Double) -> (s1: Double?, s2: Double?
}
let s2 = (-b - sqrtb2ac) / (2.0 * a)
var r2: Double? = .none
if ((epsilon < s2) && (1-s2 > epsilon)) {
if (epsilon < s2) && (1-s2 > epsilon) {
r2 = s2
}
return (r1, r2)
@ -42,10 +41,10 @@ func boundsWithDerivative(p0: Point, p1: Point, p2: Point, p3: Point) -> Rect? {
let sy = solveEquation(a: ay, b: by, c: cy)
let solutions = [sx.s1, sx.s2, sy.s1, sy.s2].flatMap { $0 }
var minX:Double? = .none
var minY:Double? = .none
var maxX:Double? = .none
var maxY:Double? = .none
var minX: Double? = .none
var minY: Double? = .none
var maxX: Double? = .none
var maxY: Double? = .none
for s in solutions {
let p = BezierFunc2D(s, p0: p0, p1: p1, p2: p2, p3: p3)
if let mx = minX {

View File

@ -1,4 +1,3 @@
func pathBounds(_ path: Path) -> Rect? {
guard let firstSegment = path.segments.first else {
@ -67,7 +66,7 @@ func pathSegmenInfo(_ segment: PathSegment, currentPoint: Point?, currentBezierP
Point(x: p2.x, y: p2.y))
case .H:
if let p = currentPoint {
if (data[0] > p.x) {
if data[0] > p.x {
return (Rect(x: p.x, y: p.y, w: data[0] - p.x, h: 0.0), Point(x: data[0], y: p.y), .none)
} else {
return (Rect(x: data[0], y: p.y, w: p.x - data[0], h: 0.0), Point(x: data[0], y: p.y), .none)
@ -78,7 +77,7 @@ func pathSegmenInfo(_ segment: PathSegment, currentPoint: Point?, currentBezierP
return (Rect(x: 0.0, y: 0.0, w: data[0], h: 0.0), Point(x: data[0], y: 0.0), .none)
case .V:
if let p = currentPoint {
if (data[0] > p.y) {
if data[0] > p.y {
return (Rect(x: p.x, y: p.y, w: 0.0, h: data[0] - p.y), Point(x: p.x, y: data[0]), .none)
} else {
return (Rect(x: p.x, y: data[0], w: 0.0, h: p.y - data[0]), Point(x: p.x, y: data[0]), .none)
@ -100,7 +99,7 @@ private func cubicBounds(_ data: [Double], currentPoint: Point?) -> Rect {
let p2 = Point(x: data[2], y: data[3])
let p3 = Point(x: data[4], y: data[5])
return boundsWithDerivative(p0: p0, p1: p1, p2: p2, p3: p3) ?? Rect(x: 0, y: 0, w: 0, h:0)
return boundsWithDerivative(p0: p0, p1: p1, p2: p2, p3: p3) ?? Rect(x: 0, y: 0, w: 0, h: 0)
}
private func sCubicBounds(_ data: [Double], currentPoint: Point, currentBezierPoint: Point?) -> Rect {
@ -115,5 +114,5 @@ private func sCubicBounds(_ data: [Double], currentPoint: Point, currentBezierPo
y: 2.0 * currentPoint.y - bezierPoint.y)
}
return boundsWithDerivative(p0: p0, p1: p1, p2: p2, p3: p3) ?? Rect(x: 0, y: 0, w: 0, h:0)
return boundsWithDerivative(p0: p0, p1: p1, p2: p2, p3: p3) ?? Rect(x: 0, y: 0, w: 0, h: 0)
}

View File

@ -1,4 +1,3 @@
import Foundation
internal class AnimationSequence: BasicAnimation {
@ -16,7 +15,7 @@ internal class AnimationSequence: BasicAnimation {
}
override func getDuration() -> Double {
let originalDuration = animations.map({ $0.getDuration() }).reduce(0, { $0 + $1 })
let originalDuration = animations.map { $0.getDuration() } .reduce(0) { $0 + $1 }
if autoreverses {
return originalDuration * 2.0

View File

@ -1,4 +1,3 @@
import Foundation
internal class CombineAnimation: BasicAnimation {

View File

@ -1,4 +1,3 @@
internal class ContentsAnimation: AnimationImpl<[Node]> {
init(animatedGroup: Group, valueFunc: @escaping (Double) -> [Node], animationDuration: Double, delay: Double = 0.0, autostart: Bool = false, fps: UInt = 30) {
@ -22,7 +21,6 @@ internal class ContentsAnimation: AnimationImpl<[Node]> {
}
}
open override func reverse() -> Animation {
let factory = { () -> (Double) -> [Node] in
let original = self.timeFactory()
@ -55,11 +53,11 @@ public extension AnimatableVariable where T: ContentsInterpolation {
public func animate(_ f: @escaping (Double) -> [Node]) {
let group = node! as! Group
let _ = ContentsAnimation(animatedGroup: group, valueFunc: f, animationDuration: 1.0, delay: 0.0, autostart: true)
_ = ContentsAnimation(animatedGroup: group, valueFunc: f, animationDuration: 1.0, delay: 0.0, autostart: true)
}
public func animate(_ f: @escaping ((Double) -> [Node]), during: Double = 1.0, delay: Double = 0.0) {
let group = node! as! Group
let _ = ContentsAnimation(animatedGroup: group, valueFunc: f, animationDuration: during, delay: delay, autostart: true)
_ = ContentsAnimation(animatedGroup: group, valueFunc: f, animationDuration: during, delay: delay, autostart: true)
}
}

View File

@ -1,4 +1,3 @@
class MorphingAnimation: AnimationImpl<Locus> {
convenience init(animatedNode: Shape, startValue: Locus, finalValue: Locus, animationDuration: Double, delay: Double = 0.0, autostart: Bool = false, fps: UInt = 30) {
@ -40,15 +39,14 @@ public typealias MorphingAnimationDescription = AnimationDescription<Locus>
public extension AnimatableVariable where T: LocusInterpolation {
public func animate(_ desc: MorphingAnimationDescription) {
let _ = MorphingAnimation(animatedNode: node as! Shape, valueFunc: desc.valueFunc, animationDuration: desc.duration, delay: desc.delay, autostart: true)
_ = MorphingAnimation(animatedNode: node as! Shape, valueFunc: desc.valueFunc, animationDuration: desc.duration, delay: desc.delay, autostart: true)
}
public func animation(_ desc: MorphingAnimationDescription) -> Animation {
return MorphingAnimation(animatedNode: node as! Shape, valueFunc: desc.valueFunc, animationDuration: desc.duration, delay: desc.delay, autostart: false)
}
public func animate(from: Locus? =
nil, to: Locus, during: Double = 1.0, delay: Double = 0.0) {
public func animate(from: Locus? = nil, to: Locus, during: Double = 1.0, delay: Double = 0.0) {
self.animate(((from ?? (node as! Shape).form) >> to).t(during, delay: delay))
}
@ -86,8 +84,8 @@ public extension AnimatableVariable where T: ContentsInterpolation {
}
// Shapes on same hierarhy level
let fromShapes = fromNode.contents.flatMap{$0 as? Shape}
let toShapes = to.flatMap{$0 as? Shape}
let fromShapes = fromNode.contents.flatMap { $0 as? Shape }
let toShapes = to.flatMap { $0 as? Shape }
let minPathsNumber = min(fromShapes.count, toShapes.count)
var animations = [Animation]()
@ -102,7 +100,7 @@ public extension AnimatableVariable where T: ContentsInterpolation {
if fromShapes.count > minPathsNumber {
for i in minPathsNumber..<fromShapes.count {
let shapeToHide = fromShapes[i]
let animation = shapeToHide.opacityVar.animation(to: 0.0, during:during, delay: delay)
let animation = shapeToHide.opacityVar.animation(to: 0.0, during: during, delay: delay)
animations.append(animation)
}
}
@ -113,14 +111,14 @@ public extension AnimatableVariable where T: ContentsInterpolation {
shapeToShow.opacity = 0.0
fromNode.contents.append(shapeToShow)
let animation = shapeToShow.opacityVar.animation(to: 1.0, during:during, delay: delay)
let animation = shapeToShow.opacityVar.animation(to: 1.0, during: during, delay: delay)
animations.append(animation)
}
}
// Groups on same hierahy level
let fromGroups = fromNode.contents.flatMap{$0 as? Group}
let toGroups = to.flatMap{$0 as? Group}
let fromGroups = fromNode.contents.flatMap { $0 as? Group }
let toGroups = to.flatMap { $0 as? Group }
let minGroupsNumber = min(fromGroups.count, toGroups.count)
for i in 0..<minGroupsNumber {
let fromGroup = fromGroups[i]
@ -131,7 +129,7 @@ public extension AnimatableVariable where T: ContentsInterpolation {
for i in minGroupsNumber..<fromGroups.count {
let groupToHide = fromGroups[i]
let animation = groupToHide.opacityVar.animation(to: 0.0, during:during, delay: delay)
let animation = groupToHide.opacityVar.animation(to: 0.0, during: during, delay: delay)
animations.append(animation)
}
@ -140,22 +138,21 @@ public extension AnimatableVariable where T: ContentsInterpolation {
groupToShow.opacity = 0.0
fromNode.contents.append(groupToShow)
let animation = groupToShow.opacityVar.animation(to: 1.0, during:during, delay: delay)
let animation = groupToShow.opacityVar.animation(to: 1.0, during: during, delay: delay)
animations.append(animation)
}
// Rest nodes
let fromNodes = fromNode.contents.filter {
return !($0 is Group || $0 is Shape)
!($0 is Group || $0 is Shape)
}
let toNodes = to.filter {
return !($0 is Group || $0 is Shape)
!($0 is Group || $0 is Shape)
}
fromNodes.forEach { node in
let animation = node.opacityVar.animation(to: 0.0, during:during, delay: delay)
let animation = node.opacityVar.animation(to: 0.0, during: during, delay: delay)
animations.append(animation)
}
@ -163,7 +160,7 @@ public extension AnimatableVariable where T: ContentsInterpolation {
node.opacity = 0.0
fromNode.contents.append(node)
let animation = node.opacityVar.animation(to: 1.0, during:during, delay: delay)
let animation = node.opacityVar.animation(to: 1.0, during: during, delay: delay)
animations.append(animation)
}

View File

@ -1,4 +1,3 @@
internal class OpacityAnimation: AnimationImpl<Double> {
convenience init(animatedNode: Node, startValue: Double, finalValue: Double, animationDuration: Double, delay: Double = 0.0, autostart: Bool = false, fps: UInt = 30) {
@ -52,7 +51,7 @@ public typealias OpacityAnimationDescription = AnimationDescription<Double>
public extension AnimatableVariable where T: DoubleInterpolation {
public func animate(_ desc: OpacityAnimationDescription) {
let _ = OpacityAnimation(animatedNode: node!, valueFunc: desc.valueFunc, animationDuration: desc.duration, delay: desc.delay, autostart: true)
_ = OpacityAnimation(animatedNode: node!, valueFunc: desc.valueFunc, animationDuration: desc.duration, delay: desc.delay, autostart: true)
}
public func animation(_ desc: OpacityAnimationDescription) -> Animation {

View File

@ -59,7 +59,7 @@ class ShapeAnimation: AnimationImpl<Shape> {
}
public extension AnimatableVariable {
public func animate<T:Stroke>(from: T? = nil, to: T, during: Double = 1.0, delay: Double = 0.0) {
public func animate<T: Stroke>(from: T? = nil, to: T, during: Double = 1.0, delay: Double = 0.0) {
let shape = node as! Shape
var safeFrom = from
@ -76,10 +76,10 @@ public extension AnimatableVariable {
let finalShape = SceneUtils.shapeCopy(from: shape)
finalShape.stroke = to
let _ = ShapeAnimation(animatedNode: shape, finalValue: finalShape, animationDuration: during, delay: delay, autostart: true)
_ = ShapeAnimation(animatedNode: shape, finalValue: finalShape, animationDuration: during, delay: delay, autostart: true)
}
public func animation<T:Stroke>(from: T? = nil, to: T, during: Double = 1.0, delay: Double = 0.0) -> Animation {
public func animation<T: Stroke>(from: T? = nil, to: T, during: Double = 1.0, delay: Double = 0.0) -> Animation {
let shape = node as! Shape
var safeFrom = from
@ -101,7 +101,7 @@ public extension AnimatableVariable {
}
public extension AnimatableVariable {
public func animate<T:Fill>(from: T? = nil, to: T, during: Double = 1.0, delay: Double = 0.0) {
public func animate<T: Fill>(from: T? = nil, to: T, during: Double = 1.0, delay: Double = 0.0) {
let shape = node as! Shape
var safeFrom = from
@ -118,10 +118,10 @@ public extension AnimatableVariable {
let finalShape = SceneUtils.shapeCopy(from: shape)
finalShape.fill = to
let _ = ShapeAnimation(animatedNode: shape, finalValue: finalShape, animationDuration: during, delay: delay, autostart: true)
_ = ShapeAnimation(animatedNode: shape, finalValue: finalShape, animationDuration: during, delay: delay, autostart: true)
}
public func animation<T:Fill>(from: T? = nil, to: T, during: Double = 1.0, delay: Double = 0.0) -> Animation {
public func animation<T: Fill>(from: T? = nil, to: T, during: Double = 1.0, delay: Double = 0.0) -> Animation {
let shape = node as! Shape
var safeFrom = from

View File

@ -54,7 +54,7 @@ public typealias TransformAnimationDescription = AnimationDescription<Transform>
public extension AnimatableVariable where T: TransformInterpolation {
public func animate(_ desc: TransformAnimationDescription) {
let _ = TransformAnimation(animatedNode: node!, valueFunc: desc.valueFunc, animationDuration: desc.duration, delay: desc.delay, autostart: true)
_ = TransformAnimation(animatedNode: node!, valueFunc: desc.valueFunc, animationDuration: desc.duration, delay: desc.delay, autostart: true)
}
public func animation(_ desc: TransformAnimationDescription) -> Animation {
@ -70,7 +70,6 @@ public extension AnimatableVariable where T: TransformInterpolation {
animation.play()
}
public func animation(from: Transform? = nil, to: Transform, during: Double = 1.0, delay: Double = 0.0) -> Animation {
if let safeFrom = from {
return self.animation((safeFrom >> to).t(during, delay: delay))

View File

@ -68,8 +68,6 @@ class AnimationCache {
}
}
layer.opacity = Float(node.opacity)
layer.node = node
@ -121,7 +119,7 @@ class AnimationCache {
maxArea = currentArea
}
t = t + step
t += step
}
return defaultScale * CGFloat(sqrt(maxArea))
@ -182,7 +180,7 @@ class AnimationCache {
func animations() -> [Animation] {
return layerCache.map ({ $0.1.animation })
return layerCache.map { $0.1.animation }
}
func replace(original: Node, replacement: Node) {

View File

@ -1,8 +1,11 @@
import Foundation
let animationRestorer = AnimationRestorer()
open class AnimationRestorer {
typealias RestoreClosure = () -> ()
typealias RestoreClosure = () -> Void
var restoreClosures = [RestoreClosure]()
func addRestoreClosure(_ closure: @escaping RestoreClosure) {

View File

@ -1,4 +1,3 @@
// TODO: Implement better hash
extension Node: Hashable {

View File

@ -1,4 +1,3 @@
extension Transform: Hashable {
public var hashValue: Int {
return m11.hashValue ^

View File

@ -14,8 +14,7 @@ import Foundation
import AppKit
#endif
func addMorphingAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animationCache: AnimationCache?, completion: @escaping (() -> ())) {
func addMorphingAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animationCache: AnimationCache?, completion: @escaping (() -> Void)) {
guard let morphingAnimation = animation as? MorphingAnimation else {
return
}
@ -39,8 +38,8 @@ func addMorphingAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, anim
// Creating proper animation
let generatedAnim = pathAnimation(
from:fromLocus,
to:toLocus,
from: fromLocus,
to: toLocus,
duration: duration,
renderTransform: layer.renderTransform!)
@ -95,7 +94,7 @@ func addMorphingAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, anim
layer.lineWidth = CGFloat(stroke.width)
layer.lineCap = RenderUtils.mapLineCapToString(stroke.cap)
layer.lineJoin = RenderUtils.mapLineJoinToString(stroke.join)
layer.lineDashPattern = stroke.dashes.map{ NSNumber(value: $0)}
layer.lineDashPattern = stroke.dashes.map { NSNumber(value: $0) }
} else {
layer.strokeColor = MColor.black.cgColor
layer.lineWidth = 1.0
@ -114,7 +113,7 @@ func addMorphingAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, anim
}
}
fileprivate func pathAnimation(from:Locus, to: Locus, duration: Double, renderTransform: CGAffineTransform) -> CAAnimation {
fileprivate func pathAnimation(from: Locus, to: Locus, duration: Double, renderTransform: CGAffineTransform) -> CAAnimation {
var transform = renderTransform
let fromPath = RenderUtils.toCGPath(from).copy(using: &transform)

View File

@ -6,7 +6,7 @@ import Foundation
import AppKit
#endif
func addOpacityAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animationCache: AnimationCache?, completion: @escaping (() -> ())) {
func addOpacityAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animationCache: AnimationCache?, completion: @escaping (() -> Void)) {
guard let opacityAnimation = animation as? OpacityAnimation else {
return
}
@ -28,7 +28,7 @@ func addOpacityAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, anima
animationCache?.freeLayer(node)
if animation.paused {
animation.pausedProgress = animation.pausedProgress + animation.progress
animation.pausedProgress += animation.progress
node.opacityVar.value = opacityAnimation.getVFunc()(animation.pausedProgress)
} else if animation.manualStop {
animation.pausedProgress = 0.0

View File

@ -14,7 +14,7 @@ import Foundation
import AppKit
#endif
func addShapeAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animationCache: AnimationCache?, completion: @escaping (() -> ())) {
func addShapeAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animationCache: AnimationCache?, completion: @escaping (() -> Void)) {
guard let shapeAnimation = animation as? ShapeAnimation else {
return
}
@ -35,11 +35,10 @@ func addShapeAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animati
return
}
// Creating proper animation
let generatedAnim = generateShapeAnimation(
from:fromShape,
to:toShape,
from: fromShape,
to: toShape,
duration: duration,
renderTransform: layer.renderTransform!)
@ -106,7 +105,7 @@ func addShapeAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animati
layer.lineWidth = CGFloat(stroke.width)
layer.lineCap = RenderUtils.mapLineCapToString(stroke.cap)
layer.lineJoin = RenderUtils.mapLineJoinToString(stroke.join)
layer.lineDashPattern = stroke.dashes.map{ NSNumber(value: $0)}
layer.lineDashPattern = stroke.dashes.map { NSNumber(value: $0) }
} else if shape.fill == nil {
layer.strokeColor = MColor.black.cgColor
layer.lineWidth = 1.0
@ -125,7 +124,7 @@ func addShapeAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animati
}
}
fileprivate func generateShapeAnimation(from:Shape, to: Shape, duration: Double, renderTransform: CGAffineTransform) -> CAAnimation {
fileprivate func generateShapeAnimation(from: Shape, to: Shape, duration: Double, renderTransform: CGAffineTransform) -> CAAnimation {
let group = CAAnimationGroup()
@ -155,7 +154,6 @@ fileprivate func generateShapeAnimation(from:Shape, to: Shape, duration: Double,
group.animations?.append(fillAnimation)
}
// Stroke
let fromStroke = from.stroke ?? Stroke(fill: Color.black, width: 1.0)
let toStroke = to.stroke ?? Stroke(fill: Color.black, width: 1.0)

View File

@ -6,7 +6,7 @@ import Foundation
import AppKit
#endif
func addTransformAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animationCache: AnimationCache?, completion: @escaping (() -> ())) {
func addTransformAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animationCache: AnimationCache?, completion: @escaping (() -> Void)) {
guard let transformAnimation = animation as? TransformAnimation else {
return
}
@ -34,7 +34,7 @@ func addTransformAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, ani
generatedAnim.completion = { finished in
if animation.paused {
animation.pausedProgress = animation.pausedProgress + animation.progress
animation.pausedProgress += animation.progress
node.placeVar.value = transformAnimation.getVFunc()(animation.pausedProgress)
} else if animation.manualStop {
animation.pausedProgress = 0.0

View File

@ -10,9 +10,9 @@ import Foundation
open class Disposable {
let handler: (()->())
let handler: (() -> Void)
init (_ disposeHandler: @escaping (()->()) ) {
init (_ disposeHandler: @escaping (() -> Void) ) {
handler = disposeHandler
}

View File

@ -9,13 +9,13 @@
import Foundation
class ChangeHandler<T>: Equatable {
let handle: ((T)->())
let handle: ((T) -> Void)
init(_ f: @escaping ((T)->()) ) {
init(_ f: @escaping ((T) -> Void) ) {
handle = f
}
static func ==(lhs: ChangeHandler<T>, rhs: ChangeHandler<T>) -> Bool {
static func == (lhs: ChangeHandler<T>, rhs: ChangeHandler<T>) -> Bool {
return lhs === rhs
}
}
@ -33,15 +33,15 @@ open class Variable<T> {
value = v
}
@discardableResult open func onChange(_ f: @escaping ((T)->())) -> Disposable {
@discardableResult open func onChange(_ f: @escaping ((T) -> Void)) -> Disposable {
let handler = ChangeHandler<T>(f)
handlers.append(handler)
return Disposable({ [weak self] in
return Disposable { [weak self] in
guard let index = self?.handlers.index(of: handler) else {
return
}
self?.handlers.remove(at: index)
})
}
}
}

View File

@ -1,4 +1,4 @@
open class PanEvent : Event {
open class PanEvent: Event {
open let dx: Double
open let dy: Double

View File

@ -1,4 +1,4 @@
open class PinchEvent : Event {
open class PinchEvent: Event {
open let scale: Double

View File

@ -1,4 +1,4 @@
open class RotateEvent : Event {
open class RotateEvent: Event {
open let angle: Double

View File

@ -1,4 +1,4 @@
open class TapEvent : Event {
open class TapEvent: Event {
open let location: Point

View File

@ -6,13 +6,12 @@
//
//
public struct TouchPoint {
public let id: Int
public let location: Point
}
public class TouchEvent : Event {
public class TouchEvent: Event {
public let points: [TouchPoint]

View File

@ -70,7 +70,7 @@ open class Color: Fill, Equatable {
return rgbt( r: r, g: g, b: b, t: 0 )
}
public static func ==(lhs: Color, rhs: Color) -> Bool {
public static func == (lhs: Color, rhs: Color) -> Bool {
return lhs.val == rhs.val
}
}

View File

@ -17,7 +17,7 @@ open class GeomUtils {
let cy = arc.ellipse.cy
var delta = arc.extent
if (arc.shift == 0.0 && abs(arc.extent - Double.pi * 2.0) < 0.00001) {
if arc.shift == 0.0 && abs(arc.extent - Double.pi * 2.0) < 0.00001 {
delta = Double.pi * 2.0 - 0.001
}
let theta1 = arc.shift
@ -42,7 +42,7 @@ open class GeomUtils {
fileprivate class func pointsToPath(_ points: [Double], close: Bool = false) -> Path {
var pb = PathBuilder(segment: PathSegment(type: .M, data: [points[0], points[1]]))
if (points.count > 2) {
if points.count > 2 {
let parts = stride(from: 2, to: points.count, by: 2).map { Array(points[$0 ..< $0 + 2]) }
for part in parts {
pb = pb.lineTo(x: part[0], y: part[1])

View File

@ -147,9 +147,9 @@ open class PathBuilder {
// GENERATED NOT
open func build() -> Path {
var segments : [PathSegment] = []
var builder : PathBuilder? = self
while(builder != nil) {
var segments: [PathSegment] = []
var builder: PathBuilder? = self
while builder != nil {
segments.append(builder!.segment)
builder = builder!.rest
}
@ -158,6 +158,6 @@ open class PathBuilder {
// GENERATED NOT
fileprivate func boolsToNum(_ largeArc: Bool, sweep: Bool) -> Double {
return (largeArc ? 1 : 0) + (sweep ? 1 : 0) * 2;
return (largeArc ? 1 : 0) + (sweep ? 1 : 0) * 2
}
}

View File

@ -9,7 +9,9 @@ open class Polygon: Locus {
}
override open func bounds() -> Rect {
guard !points.isEmpty else { return Rect.zero() }
guard !points.isEmpty else {
return Rect.zero()
}
var minX = Double(INT16_MAX)
var minY = Double(INT16_MAX)

View File

@ -9,7 +9,9 @@ open class Polyline: Locus {
}
override open func bounds() -> Rect {
guard !points.isEmpty else { return Rect.zero() }
guard !points.isEmpty else {
return Rect.zero()
}
var minX = Double(INT16_MAX)
var minY = Double(INT16_MAX)

View File

@ -59,7 +59,7 @@ open class Rect: Locus {
}
extension Rect {
public static func ==(lhs: Rect, rhs: Rect) -> Bool {
public static func == (lhs: Rect, rhs: Rect) -> Bool {
return lhs.x == rhs.x
&& lhs.y == rhs.y
&& lhs.w == rhs.w

View File

@ -78,7 +78,7 @@ public final class Transform {
// GENERATED NOT
public func invert() -> Transform? {
let det = self.m11 * self.m22 - self.m12 * self.m21
if (det == 0) {
if det == 0 {
return nil
}
return Transform(m11: m22 / det, m12: -m12 / det, m21: -m21 / det, m22: m11 / det,

View File

@ -20,7 +20,6 @@ open class Group: Node {
}
}
public init(contents: [Node] = [], place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) {
self.contentsVar = AnimatableVariable<[Node]>(contents)
super.init(

View File

@ -69,11 +69,9 @@ open class Image: Node {
public init(image: MImage, xAlign: Align = .min, yAlign: Align = .min, aspectRatio: AspectRatio = .none, w: Int = 0, h: Int = 0, place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) {
var oldId: String?
for key in imagesMap.keys {
if image === imagesMap[key] {
for key in imagesMap.keys where image === imagesMap[key] {
oldId = key
}
}
let id = oldId ?? UUID().uuidString
imagesMap[id] = image
@ -117,9 +115,9 @@ open class Image: Node {
case PNG
}
internal func base64encoded(type:ImageRepresentationType) -> String? {
internal func base64encoded(type: ImageRepresentationType) -> String? {
if let image = self.image() {
switch (type) {
switch type {
case .JPEG:
if let data = MImageJPEGRepresentation(image) {
return data.base64EncodedString()

View File

@ -46,7 +46,6 @@ open class Node: Drawable {
return Node.map.object(forKey: id as NSString)
}
// MARK: - Searching
public func nodeBy(tag: String) -> Node? {
if self.tag.contains(tag) {
@ -71,95 +70,95 @@ open class Node: Drawable {
var rotateHandlers = [ChangeHandler<RotateEvent>]()
var pinchHandlers = [ChangeHandler<PinchEvent>]()
@discardableResult public func onTouchPressed (_ f: @escaping (TouchEvent) -> ()) -> Disposable {
@discardableResult public func onTouchPressed (_ f: @escaping (TouchEvent) -> Void) -> Disposable {
let handler = ChangeHandler<TouchEvent>(f)
touchPressedHandlers.append(handler)
return Disposable({ [weak self] in
return Disposable { [weak self] in
guard let index = self?.touchPressedHandlers.index(of: handler) else {
return
}
self?.touchPressedHandlers.remove(at: index)
})
}
}
@discardableResult public func onTouchMoved (_ f: @escaping (TouchEvent) -> ()) -> Disposable {
@discardableResult public func onTouchMoved (_ f: @escaping (TouchEvent) -> Void) -> Disposable {
let handler = ChangeHandler<TouchEvent>(f)
touchMovedHandlers.append(handler)
return Disposable({ [weak self] in
return Disposable { [weak self] in
guard let index = self?.touchMovedHandlers.index(of: handler) else {
return
}
self?.touchMovedHandlers.remove(at: index)
})
}
}
@discardableResult public func onTouchReleased(_ f: @escaping (TouchEvent) -> ()) -> Disposable {
@discardableResult public func onTouchReleased(_ f: @escaping (TouchEvent) -> Void) -> Disposable {
let handler = ChangeHandler<TouchEvent>(f)
touchReleasedHandlers.append(handler)
return Disposable({ [weak self] in
return Disposable { [weak self] in
guard let index = self?.touchReleasedHandlers.index(of: handler) else {
return
}
self?.touchReleasedHandlers.remove(at: index)
})
}
}
@discardableResult public func onTap(_ f: @escaping (TapEvent) -> ()) -> Disposable {
@discardableResult public func onTap(_ f: @escaping (TapEvent) -> Void) -> Disposable {
let handler = ChangeHandler<TapEvent>(f)
tapHandlers.append(handler)
return Disposable({ [weak self] in
return Disposable { [weak self] in
guard let index = self?.tapHandlers.index(of: handler) else {
return
}
self?.tapHandlers.remove(at: index)
})
}
}
@discardableResult public func onPan(_ f: @escaping (PanEvent) -> ()) -> Disposable {
@discardableResult public func onPan(_ f: @escaping (PanEvent) -> Void) -> Disposable {
let handler = ChangeHandler<PanEvent>(f)
panHandlers.append(handler)
return Disposable({ [weak self] in
return Disposable { [weak self] in
guard let index = self?.panHandlers.index(of: handler) else {
return
}
self?.panHandlers.remove(at: index)
})
}
}
@discardableResult public func onRotate(_ f: @escaping (RotateEvent) -> ()) -> Disposable {
@discardableResult public func onRotate(_ f: @escaping (RotateEvent) -> Void) -> Disposable {
let handler = ChangeHandler<RotateEvent>(f)
rotateHandlers.append(handler)
return Disposable({ [weak self] in
return Disposable { [weak self] in
guard let index = self?.rotateHandlers.index(of: handler) else {
return
}
self?.rotateHandlers.remove(at: index)
})
}
}
@discardableResult public func onPinch(_ f: @escaping (PinchEvent) -> ()) -> Disposable {
@discardableResult public func onPinch(_ f: @escaping (PinchEvent) -> Void) -> Disposable {
let handler = ChangeHandler<PinchEvent>(f)
pinchHandlers.append(handler)
return Disposable({ [weak self] in
return Disposable { [weak self] in
guard let index = self?.pinchHandlers.index(of: handler) else {
return
}
self?.pinchHandlers.remove(at: index)
})
}
}
// Helpers
@ -193,34 +192,31 @@ open class Node: Drawable {
}
func shouldCheckForPressed() -> Bool {
return touchPressedHandlers.count > 0
return !touchPressedHandlers.isEmpty
}
func shouldCheckForMoved() -> Bool {
return touchMovedHandlers.count > 0
return !touchMovedHandlers.isEmpty
}
func shouldCheckForReleased() -> Bool {
return touchReleasedHandlers.count > 0
return !touchReleasedHandlers.isEmpty
}
func shouldCheckForTap() -> Bool {
return tapHandlers.count > 0
return !tapHandlers.isEmpty
}
func shouldCheckForPan() -> Bool {
return panHandlers.count > 0
return !panHandlers.isEmpty
}
func shouldCheckForRotate() -> Bool {
return rotateHandlers.count > 0
return !rotateHandlers.isEmpty
}
func shouldCheckForPinch() -> Bool {
return pinchHandlers.count > 0
return !pinchHandlers.isEmpty
}
public init(place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) {

View File

@ -6,7 +6,6 @@ import Foundation
import AppKit
#endif
open class Text: Node {
open let textVar: Variable<String>
@ -68,7 +67,7 @@ open class Text: Node {
let font: MFont
if let f = self.font {
if let customFont = RenderUtils.loadFont(name: f.name, size:f.size) {
if let customFont = RenderUtils.loadFont(name: f.name, size: f.size) {
font = customFont
} else {
font = MFont.systemFont(ofSize: CGFloat(f.size))

View File

@ -85,4 +85,3 @@ import Foundation
}
#endif

View File

@ -18,7 +18,7 @@
displayLink?.invalidate()
}
//MARK: - MDisplayLinkProtocol
// MARK: - MDisplayLinkProtocol
func startUpdates(_ onUpdate: @escaping () -> Void) {
self.onUpdate = onUpdate

View File

@ -94,4 +94,3 @@ import Foundation
}
#endif

View File

@ -115,7 +115,7 @@ import Foundation
extension NSString {
@nonobjc
func size(attributes attrs: [NSAttributedStringKey : Any]? = nil) -> NSSize {
func size(attributes attrs: [NSAttributedStringKey: Any]? = nil) -> NSSize {
return size(withAttributes: attrs)
}
}
@ -124,7 +124,4 @@ import Foundation
return MScreen.main
}
#endif

View File

@ -43,7 +43,6 @@ import Foundation
return rep?.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [NSBitmapImageRep.PropertyKey.compressionFactor: quality])
}
func MGraphicsBeginImageContextWithOptions(_ size: CGSize, _ opaque: Bool, _ scale: CGFloat) {
var scale = scale
@ -59,7 +58,7 @@ import Foundation
let colorSpace = CGColorSpaceCreateDeviceRGB()
guard let ctx = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: 4*width, space: colorSpace, bitmapInfo: (opaque ? CGImageAlphaInfo.noneSkipFirst.rawValue : CGImageAlphaInfo.premultipliedFirst.rawValue)) else {
guard let ctx = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: 4 * width, space: colorSpace, bitmapInfo: (opaque ? CGImageAlphaInfo.noneSkipFirst.rawValue : CGImageAlphaInfo.premultipliedFirst.rawValue)) else {
return
}

View File

@ -31,7 +31,7 @@ import Foundation
extension MBezierPath {
public var cgPath: CGPath {
get { let path = CGMutablePath()
let path = CGMutablePath()
var points = [CGPoint](repeating: .zero, count: 3)
for i in 0 ..< self.elementCount {
@ -57,7 +57,6 @@ import Foundation
return path
}
}
public convenience init(arcCenter center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool) {
self.init()
@ -70,9 +69,9 @@ import Foundation
let kappa: CGFloat = 1.0 - 0.552228474
let topLeft = rect.origin
let topRight = NSPoint(x: rect.maxX, y: rect.minY);
let bottomRight = NSPoint(x: rect.maxX, y: rect.maxY);
let bottomLeft = NSPoint(x: rect.minX, y: rect.maxY);
let topRight = NSPoint(x: rect.maxX, y: rect.minY)
let bottomRight = NSPoint(x: rect.maxX, y: rect.maxY)
let bottomLeft = NSPoint(x: rect.minX, y: rect.maxY)
if corners.contains(.topLeft) {
move(to: CGPoint(x: topLeft.x + cornerRadii.width, y: topLeft.y))
@ -88,7 +87,6 @@ import Foundation
controlPoint1: CGPoint(x: topRight.x - cornerRadii.width * kappa, y: topRight.y),
controlPoint2: CGPoint(x: topRight.x, y: topRight.y + cornerRadii.height * kappa))
} else {
line(to: topRight)
}

View File

@ -12,19 +12,19 @@ import Foundation
import AppKit
public enum MViewContentMode: Int {
case scaleToFill
case scaleAspectFit
case scaleAspectFill
case redraw
case center
case top
case bottom
case left
case right
case topLeft
case topRight
case bottomLeft
case bottomRight
case scaleToFill = 0
case scaleAspectFit = 1
case scaleAspectFill = 2
case redraw = 3
case center = 4
case top = 5
case bottom = 6
case left = 7
case right = 8
case topLeft = 9
case topRight = 10
case bottomLeft = 11
case bottomRight = 12
}
open class MView: NSView, Touchable {
@ -142,33 +142,30 @@ import Foundation
}
private func subscribeForMouseDown() {
NSEvent.addLocalMonitorForEvents(matching: .leftMouseDown, handler: { [weak self] event -> NSEvent? in
self?.handleInput(event: event, handler: { touches in
NSEvent.addLocalMonitorForEvents(matching: .leftMouseDown) { [weak self] event -> NSEvent? in
self?.handleInput(event: event) { touches in
self?.mTouchesBegan(touches)
})
}
return event
})
}
}
private func subscribeForMouseUp() {
NSEvent.addLocalMonitorForEvents(matching: .leftMouseUp, handler: { [weak self] event -> NSEvent? in
self?.handleInput(event: event, handler: { touches in
NSEvent.addLocalMonitorForEvents(matching: .leftMouseUp) { [weak self] event -> NSEvent? in
self?.handleInput(event: event) { touches in
self?.mTouchesEnded(touches)
})
}
return event
})
}
}
private func subscribeForMouseDragged() {
NSEvent.addLocalMonitorForEvents(matching: .leftMouseDragged, handler: { [weak self] event -> NSEvent? in
self?.handleInput(event: event, handler: { touches in
NSEvent.addLocalMonitorForEvents(matching: .leftMouseDragged) { [weak self] event -> NSEvent? in
self?.handleInput(event: event) { touches in
self?.mTouchesMoved(touches)
})
}
return event
})
}
}
private func handleInput(event: NSEvent, handler: (_ touches: [MTouchEvent]) -> Void ) {

View File

@ -57,10 +57,10 @@ class GroupRenderer: NodeRenderer {
}
private func updateRenderers() {
renderers.forEach{ $0.dispose() }
renderers.forEach { $0.dispose() }
renderers.removeAll()
if let updatedRenderers = group?.contents.flatMap ({ (child) -> NodeRenderer? in
if let updatedRenderers = group?.contents.flatMap ({ child -> NodeRenderer? in
guard let interval = renderingInterval else {
return RenderUtils.createNodeRenderer(child, context: ctx, animationCache: animationCache)
}

View File

@ -72,7 +72,7 @@ class ImageRenderer: NodeRenderer {
if let mImage = osImage {
let rect = getRect(mImage)
if (rect.contains(location)) {
if rect.contains(location) {
return node()
}
}
@ -87,15 +87,15 @@ class ImageRenderer: NodeRenderer {
let imageSize = mImage.size
var w = CGFloat(image.w)
var h = CGFloat(image.h)
if ((w == 0 || w == imageSize.width) && (h == 0 || h == imageSize.height)) {
if (w == 0 || w == imageSize.width) && (h == 0 || h == imageSize.height) {
return CGRect(x: 0, y: 0, width: imageSize.width, height: imageSize.height)
} else {
if (w == 0) {
if w == 0 {
w = imageSize.width * h / imageSize.height
} else if (h == 0) {
} else if h == 0 {
h = imageSize.height * w / imageSize.width
}
switch (image.aspectRatio) {
switch image.aspectRatio {
case AspectRatio.meet:
return calculateMeetAspectRatio(image, size: imageSize)
case AspectRatio.slice:
@ -117,7 +117,7 @@ class ImageRenderer: NodeRenderer {
var resultH = h
var destX = CGFloat(0)
var destY = CGFloat(0)
if (destAR < srcAR) {
if destAR < srcAR {
// fill all available width and scale height
resultH = size.height * w / size.width
} else {
@ -125,7 +125,7 @@ class ImageRenderer: NodeRenderer {
resultW = size.width * h / size.height
}
let xalign = image.xAlign
switch (xalign) {
switch xalign {
case Align.min:
destX = 0
case Align.mid:
@ -134,7 +134,7 @@ class ImageRenderer: NodeRenderer {
destX = w - resultW
}
let yalign = image.yAlign
switch (yalign) {
switch yalign {
case Align.min:
destY = 0
case Align.mid:
@ -155,11 +155,11 @@ class ImageRenderer: NodeRenderer {
// destination and source aspect ratios
let destAR = w / h
let srcAR = size.width / size.height
if (destAR > srcAR) {
if destAR > srcAR {
// fill all available width and scale height
totalH = size.height * w / size.width
totalW = w
switch (image.yAlign) {
switch image.yAlign {
case Align.min:
srcY = 0
case Align.mid:
@ -171,7 +171,7 @@ class ImageRenderer: NodeRenderer {
// fill all available height and scale width
totalW = size.width * h / size.height
totalH = h
switch (image.xAlign) {
switch image.xAlign {
case Align.min:
srcX = 0
case Align.mid:

View File

@ -4,7 +4,6 @@ import Foundation
import UIKit
#endif
struct RenderingInterval {
let from: Int
let to: Int
@ -14,7 +13,7 @@ class NodeRenderer {
let ctx: RenderContext
fileprivate let onNodeChange: ()->()
fileprivate let onNodeChange: () -> Void
fileprivate let disposables = GroupDisposable()
fileprivate var active = false
weak var animationCache: AnimationCache?
@ -92,7 +91,7 @@ class NodeRenderer {
if let isAnimating = animationCache?.isAnimating(node), isAnimating {
self.removeObservers()
if (!force) {
if !force {
return
}
} else {
@ -110,7 +109,7 @@ class NodeRenderer {
return .none
}
if (node.opaque) {
if node.opaque {
let place = node.place
if let inverted = place.invert() {
ctx.saveGState()
@ -155,14 +154,14 @@ class NodeRenderer {
}
private func addObservers() {
if (!active) {
if !active {
active = true
doAddObservers()
}
}
fileprivate func removeObservers() {
if (active) {
if active {
active = false
disposables.dispose()
}

View File

@ -22,38 +22,50 @@ class RenderUtils {
class func mapLineJoin(_ join: LineJoin?) -> CGLineJoin {
switch join {
case LineJoin.round?: return CGLineJoin.round
case LineJoin.bevel?: return CGLineJoin.bevel
default: return CGLineJoin.miter
case LineJoin.round?:
return CGLineJoin.round
case LineJoin.bevel?:
return CGLineJoin.bevel
default:
return CGLineJoin.miter
}
}
class func mapLineJoinToString(_ join: LineJoin?) -> String {
switch join {
case LineJoin.round?: return kCALineJoinRound
case LineJoin.bevel?: return kCALineJoinBevel
default: return kCALineJoinMiter
case LineJoin.round?:
return kCALineJoinRound
case LineJoin.bevel?:
return kCALineJoinBevel
default:
return kCALineJoinMiter
}
}
class func mapLineCap(_ cap: LineCap?) -> CGLineCap {
switch cap {
case LineCap.round?: return CGLineCap.round
case LineCap.square?: return CGLineCap.square
default: return CGLineCap.butt
case LineCap.round?:
return CGLineCap.round
case LineCap.square?:
return CGLineCap.square
default:
return CGLineCap.butt
}
}
class func mapLineCapToString(_ cap: LineCap?) -> String {
switch cap {
case LineCap.round?: return kCALineCapRound
case LineCap.square?: return kCALineCapSquare
default: return kCALineCapButt
case LineCap.round?:
return kCALineCapRound
case LineCap.square?:
return kCALineCapSquare
default:
return kCALineCapButt
}
}
class func mapDash(_ dashes: [Double]) -> UnsafeMutablePointer<CGFloat> {
let p = UnsafeMutablePointer<CGFloat>.allocate(capacity:dashes.count * MemoryLayout<CGFloat>.size)
let p = UnsafeMutablePointer<CGFloat>.allocate(capacity: dashes.count * MemoryLayout<CGFloat>.size)
for (index, item) in dashes.enumerated() {
p[index] = CGFloat(item)
}
@ -75,11 +87,11 @@ class RenderUtils {
} else if let image = node as? Image {
return ImageRenderer(image: image, ctx: context, animationCache: animationCache)
}
fatalError("Unsupported node: \(node)");
fatalError("Unsupported node: \(node)")
}
class func loadFont(name: String, size: Int) -> MFont? {
let separationSet = CharacterSet(charactersIn:",")
let separationSet = CharacterSet(charactersIn: ",")
let names = name.components(separatedBy: separationSet)
var customFont: MFont? = .none
names.forEach { fontName in
@ -88,7 +100,7 @@ class RenderUtils {
}
if fontName.characters.first == " " {
let index = fontName.index(fontName.startIndex, offsetBy:1)
let index = fontName.index(fontName.startIndex, offsetBy: 1)
let fixedName = String(fontName.suffix(from: index))
customFont = MFont(name: fixedName, size: CGFloat(size))
return
@ -173,7 +185,7 @@ class RenderUtils {
var first = true
for part in parts {
let point = CGPoint(x: CGFloat(part[0]), y: CGFloat(part[1]))
if (first) {
if first {
path.move(to: point)
first = false
} else {
@ -310,35 +322,35 @@ class RenderUtils {
// find arc center coordinates and points angles as per
// http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
let x1_ = cos(angle) * (x1 - x) / 2 + sin(angle) * (y1 - y) / 2;
let y1_ = -1 * sin(angle) * (x1 - x) / 2 + cos(angle) * (y1 - y) / 2;
let x1_ = cos(angle) * (x1 - x) / 2 + sin(angle) * (y1 - y) / 2
let y1_ = -1 * sin(angle) * (x1 - x) / 2 + cos(angle) * (y1 - y) / 2
// make sure the value under the root is positive
let underroot = (rx * rx * ry * ry - rx * rx * y1_ * y1_ - ry * ry * x1_ * x1_)
/ (rx * rx * y1_ * y1_ + ry * ry * x1_ * x1_);
var bigRoot = (underroot > 0) ? sqrt(underroot) : 0;
/ (rx * rx * y1_ * y1_ + ry * ry * x1_ * x1_)
var bigRoot = (underroot > 0) ? sqrt(underroot) : 0
// TODO: Replace concrete number with 1e-2
bigRoot = (bigRoot <= 0.01) ? 0 : bigRoot;
let coef: Double = (sweep != largeArc) ? 1 : -1;
let cx_ = coef * bigRoot * rx * y1_ / ry;
let cy_ = -1 * coef * bigRoot * ry * x1_ / rx;
let cx = (cos(angle) * cx_ - sin(angle) * cy_ + (x1 + x) / 2);
let cy = (sin(angle) * cx_ + cos(angle) * cy_ + (y1 + y) / 2);
let t1 = -1 * atan2(y1 - cy, x1 - cx);
let t2 = atan2(y - cy, x - cx);
var delta = -(t1 + t2);
bigRoot = (bigRoot <= 0.01) ? 0 : bigRoot
let coef: Double = (sweep != largeArc) ? 1 : -1
let cx_ = coef * bigRoot * rx * y1_ / ry
let cy_ = -1 * coef * bigRoot * ry * x1_ / rx
let cx = (cos(angle) * cx_ - sin(angle) * cy_ + (x1 + x) / 2)
let cy = (sin(angle) * cx_ + cos(angle) * cy_ + (y1 + y) / 2)
let t1 = -1 * atan2(y1 - cy, x1 - cx)
let t2 = atan2(y - cy, x - cx)
var delta = -(t1 + t2)
// recalculate delta depending on arc. Preserve rotation direction
if (largeArc) {
let sg = copysign(1.0, delta);
if (abs(delta) < Double.pi) {
delta = -1 * (sg * M_2_PI - delta);
if largeArc {
let sg = copysign(1.0, delta)
if abs(delta) < Double.pi {
delta = -1 * (sg * M_2_PI - delta)
}
} else {
let sg = copysign(1.0, delta);
if (abs(delta) > Double.pi) {
delta = -1 * (sg * M_2_PI - delta);
let sg = copysign(1.0, delta)
if abs(delta) > Double.pi {
delta = -1 * (sg * M_2_PI - delta)
}
}
E(cx - rx, y: cy - ry, w: 2 * rx, h: 2 * ry, startAngle: t1, arcAngle: delta);
E(cx - rx, y: cy - ry, w: 2 * rx, h: 2 * ry, startAngle: t1, arcAngle: delta)
setPoint(CGPoint(x: CGFloat(x), y: CGFloat(y)))
}
}
@ -458,8 +470,8 @@ class RenderUtils {
}
class func numToBools(_ num: Double) -> [Bool] {
let val: Int = Int(num);
return [(val & 1) > 0, (val & 2) > 0];
let val: Int = Int(num)
return [(val & 1) > 0, (val & 2) > 0]
}
fileprivate class func newCGRect(_ rect: Rect) -> CGRect {

View File

@ -118,7 +118,7 @@ class ShapeRenderer: NodeRenderer {
var first = true
for part in parts {
let point = CGPoint(x: CGFloat(part[0]), y: CGFloat(part[1]))
if (first) {
if first {
path.move(to: point)
first = false
} else {
@ -255,35 +255,35 @@ class ShapeRenderer: NodeRenderer {
// find arc center coordinates and points angles as per
// http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
let x1_ = cos(angle) * (x1 - x) / 2 + sin(angle) * (y1 - y) / 2;
let y1_ = -1 * sin(angle) * (x1 - x) / 2 + cos(angle) * (y1 - y) / 2;
let x1_ = cos(angle) * (x1 - x) / 2 + sin(angle) * (y1 - y) / 2
let y1_ = -1 * sin(angle) * (x1 - x) / 2 + cos(angle) * (y1 - y) / 2
// make sure the value under the root is positive
let underroot = (rx * rx * ry * ry - rx * rx * y1_ * y1_ - ry * ry * x1_ * x1_)
/ (rx * rx * y1_ * y1_ + ry * ry * x1_ * x1_);
var bigRoot = (underroot > 0) ? sqrt(underroot) : 0;
/ (rx * rx * y1_ * y1_ + ry * ry * x1_ * x1_)
var bigRoot = (underroot > 0) ? sqrt(underroot) : 0
// TODO: Replace concrete number with 1e-2
bigRoot = (bigRoot <= 0.01) ? 0 : bigRoot;
let coef: Double = (sweep != largeArc) ? 1 : -1;
let cx_ = coef * bigRoot * rx * y1_ / ry;
let cy_ = -1 * coef * bigRoot * ry * x1_ / rx;
let cx = (cos(angle) * cx_ - sin(angle) * cy_ + (x1 + x) / 2);
let cy = (sin(angle) * cx_ + cos(angle) * cy_ + (y1 + y) / 2);
let t1 = -1 * atan2(y1 - cy, x1 - cx);
let t2 = atan2(y - cy, x - cx);
var delta = -(t1 + t2);
bigRoot = (bigRoot <= 0.01) ? 0 : bigRoot
let coef: Double = (sweep != largeArc) ? 1 : -1
let cx_ = coef * bigRoot * rx * y1_ / ry
let cy_ = -1 * coef * bigRoot * ry * x1_ / rx
let cx = (cos(angle) * cx_ - sin(angle) * cy_ + (x1 + x) / 2)
let cy = (sin(angle) * cx_ + cos(angle) * cy_ + (y1 + y) / 2)
let t1 = -1 * atan2(y1 - cy, x1 - cx)
let t2 = atan2(y - cy, x - cx)
var delta = -(t1 + t2)
// recalculate delta depending on arc. Preserve rotation direction
if (largeArc) {
let sg = copysign(1.0, delta);
if (abs(delta) < Double.pi) {
delta = -1 * (sg * M_2_PI - delta);
if largeArc {
let sg = copysign(1.0, delta)
if abs(delta) < Double.pi {
delta = -1 * (sg * M_2_PI - delta)
}
} else {
let sg = copysign(1.0, delta);
if (abs(delta) > Double.pi) {
delta = -1 * (sg * M_2_PI - delta);
let sg = copysign(1.0, delta)
if abs(delta) > Double.pi {
delta = -1 * (sg * M_2_PI - delta)
}
}
E(cx - rx, y: cy - ry, w: 2 * rx, h: 2 * ry, startAngle: t1, arcAngle: delta);
E(cx - rx, y: cy - ry, w: 2 * rx, h: 2 * ry, startAngle: t1, arcAngle: delta)
setPoint(CGPoint(x: CGFloat(x), y: CGFloat(y)))
}
}
@ -403,8 +403,8 @@ class ShapeRenderer: NodeRenderer {
}
fileprivate func numToBools(_ num: Double) -> [Bool] {
let val: Int = Int(num);
return [(val & 1) > 0, (val & 2) > 0];
let val: Int = Int(num)
return [(val & 1) > 0, (val & 2) > 0]
}
fileprivate func newCGRect(_ rect: Rect) -> CGRect {
@ -458,7 +458,7 @@ class ShapeRenderer: NodeRenderer {
}
fileprivate func drawWithStroke(_ stroke: Stroke, ctx: CGContext?, opacity: Double, shouldStrokePath: Bool = false, path: CGPath? = nil, mode: CGPathDrawingMode) {
if let path = path , shouldStrokePath {
if let path = path, shouldStrokePath {
ctx!.addPath(path)
}
setStrokeAttributes(stroke, ctx: ctx)

View File

@ -89,12 +89,17 @@ class TextRenderer: NodeRenderer {
}
fileprivate func getWeight(_ weight: String) -> MFont.Weight? {
switch (weight) {
case "normal": return MFont.Weight.regular
case "bold": return MFont.Weight.bold
case "bolder": return MFont.Weight.semibold
case "lighter": return MFont.Weight.light
default: return .none
switch weight {
case "normal":
return MFont.Weight.regular
case "bold":
return MFont.Weight.bold
case "bolder":
return MFont.Weight.semibold
case "lighter":
return MFont.Weight.light
default:
return .none
}
}

View File

@ -294,7 +294,7 @@ open class SVGConstants {
]
open static func valueToColor(_ color: Int) -> String? {
return SVGConstants.colorList.filter { (k, v) -> Bool in v == color }.map { (k, v) -> String in k }.first
return SVGConstants.colorList.filter { (_, v) -> Bool in v == color }.map { (k, _) -> String in k }.first
}
open static let defaultStrokeLineCap = LineCap.butt

View File

@ -47,7 +47,6 @@ open class SVGParser {
fileprivate var defMasks = [String: Shape]()
fileprivate var defClip = [String: Locus]()
fileprivate enum PathCommandType {
case moveTo
case lineTo
@ -105,7 +104,8 @@ open class SVGParser {
return .none
}
fileprivate var styleTable: [String:[String:String]] = [:]
fileprivate var styleTable: [String: [String: String]] = [:]
fileprivate func parseStyle(_ styleNode: XMLIndexer) {
if let rawStyle = styleNode.element?.text {
var styleAttributes: [String: String] = [:]
@ -250,6 +250,7 @@ open class SVGParser {
}
var count = 0
fileprivate func parseTransformationAttribute(_ attributes: String, transform: Transform = Transform()) -> Transform {
guard let matcher = SVGParserRegexHelper.getTransformAttributeMatcher() else {
return transform
@ -312,7 +313,8 @@ open class SVGParser {
let transformMatrix = Transform(m11: m11, m12: m12, m21: m21, m22: m22, dx: dx, dy: dy)
finalTransform = GeomUtils.concat(t1: transform, t2: transformMatrix)
}
default: break
default:
break
}
let rangeToRemove = NSRange(location: 0, length: matchedAttribute.range.location + matchedAttribute.range.length)
let newAttributeString = (attributes as NSString).replacingCharacters(in: rangeToRemove, with: "")
@ -335,7 +337,7 @@ open class SVGParser {
var red = 0.0
var green = 0.0
var blue = 0.0
if (x.count == 3) {
if x.count == 3 {
if let r = Double(x[0]), let g = Double(x[1]), let b = Double(x[2]) {
blue = b
green = g
@ -490,7 +492,7 @@ open class SVGParser {
if let strokeWidth = styleParts["stroke-width"] {
let characterSet = NSCharacterSet.decimalDigits.union(NSCharacterSet.punctuationCharacters).inverted
let digitsArray = strokeWidth.components(separatedBy: characterSet)
let digits = digitsArray.joined(separator: "")
let digits = digitsArray.joined()
if let value = NumberFormatter().number(from: digits) {
return value.doubleValue
}
@ -570,8 +572,7 @@ open class SVGParser {
fileprivate func parseRect(_ rect: XMLIndexer) -> Locus? {
guard let element = rect.element,
let width = getDoubleValue(element, attribute: "width"),
let height = getDoubleValue(element, attribute: "height")
, width > 0 && height > 0 else {
let height = getDoubleValue(element, attribute: "height"), width > 0 && height > 0 else {
return .none
}
@ -584,14 +585,14 @@ open class SVGParser {
return RoundRect(rect: resultRect, rx: rx, ry: ry)
}
let rOpt = rxOpt ?? ryOpt
if let r = rOpt , r >= 0 {
if let r = rOpt, r >= 0 {
return RoundRect(rect: resultRect, rx: r, ry: r)
}
return resultRect
}
fileprivate func parseCircle(_ circle: XMLIndexer) -> Circle? {
guard let element = circle.element, let r = getDoubleValue(element, attribute: "r") , r > 0 else {
guard let element = circle.element, let r = getDoubleValue(element, attribute: "r"), r > 0 else {
return .none
}
@ -601,8 +602,7 @@ open class SVGParser {
fileprivate func parseEllipse(_ ellipse: XMLIndexer) -> Arc? {
guard let element = ellipse.element,
let rx = getDoubleValue(element, attribute: "rx"),
let ry = getDoubleValue(element, attribute: "ry")
, rx > 0 && ry > 0 else {
let ry = getDoubleValue(element, attribute: "ry"), rx > 0 && ry > 0 else {
return .none
}
return Arc(
@ -747,7 +747,7 @@ open class SVGParser {
place: Transform().move(dx: bounds.x + bounds.w, dy: bounds.y), opacity: opacity)
collection.append(text)
return collectTspans(fullString.substring(from: tagRange.location), collectedTspans: collection,
withWhitespace: nextStringWhitespace, textAnchor: textAnchor, fill: fill, stroke:stroke,
withWhitespace: nextStringWhitespace, textAnchor: textAnchor, fill: fill, stroke: stroke,
opacity: opacity, fontName: fontName, fontSize: fontSize, fontWeight: fontWeight, bounds: text.bounds())
}
@ -894,8 +894,7 @@ open class SVGParser {
}
var parentGradient: Gradient?
if let link = element.allAttributes["xlink:href"]?.text.replacingOccurrences(of: " ", with: "")
, link.hasPrefix("#") {
if let link = element.allAttributes["xlink:href"]?.text.replacingOccurrences(of: " ", with: ""), link.hasPrefix("#") {
let id = link.replacingOccurrences(of: "#", with: "")
parentGradient = defFills[id] as? Gradient
@ -928,7 +927,7 @@ open class SVGParser {
let y2 = getDoubleValueFromPercentage(element, attribute: "y2") ?? parentLinearGradient?.y2 ?? 0
var userSpace = false
if let gradientUnits = element.allAttributes["gradientUnits"]?.text , gradientUnits == "userSpaceOnUse" {
if let gradientUnits = element.allAttributes["gradientUnits"]?.text, gradientUnits == "userSpaceOnUse" {
userSpace = true
} else if let parent = parentGradient {
userSpace = parent.userSpace
@ -951,8 +950,7 @@ open class SVGParser {
}
var parentGradient: Gradient?
if let link = element.allAttributes["xlink:href"]?.text.replacingOccurrences(of: " ", with: "")
, link.hasPrefix("#") {
if let link = element.allAttributes["xlink:href"]?.text.replacingOccurrences(of: " ", with: ""), link.hasPrefix("#") {
let id = link.replacingOccurrences(of: "#", with: "")
parentGradient = defFills[id] as? Gradient
@ -986,7 +984,7 @@ open class SVGParser {
let r = getDoubleValueFromPercentage(element, attribute: "r") ?? parentRadialGradient?.r ?? 0.5
var userSpace = false
if let gradientUnits = element.allAttributes["gradientUnits"]?.text , gradientUnits == "userSpaceOnUse" {
if let gradientUnits = element.allAttributes["gradientUnits"]?.text, gradientUnits == "userSpaceOnUse" {
userSpace = true
} else if let parent = parentGradient {
userSpace = parent.userSpace

View File

@ -6,6 +6,6 @@
//
//
enum SVGParserError : Error {
enum SVGParserError: Error {
case noSuchFile(path: String)
}

View File

@ -53,13 +53,13 @@ open class SVGSerializer {
fileprivate let indentPrefixSymbol = " "
fileprivate let SVGClipPathName = "clipPath"
fileprivate let SVGEpsilon:Double = 0.00001
fileprivate let SVGDefaultOpacityValueAsAlpha = 1*255
fileprivate let SVGEpsilon: Double = 0.00001
fileprivate let SVGDefaultOpacityValueAsAlpha = 1 * 255
fileprivate func indentTextWithOffset(_ text: String, _ offset: Int) -> String {
if self.indent != 0 {
let prefix = String(repeating: indentPrefixSymbol, count:self.indent)
return "\n\(String(repeating: prefix, count:offset))\(text)"
let prefix = String(repeating: indentPrefixSymbol, count: self.indent)
return "\n\(String(repeating: prefix, count: offset))\(text)"
}
return text
}
@ -68,15 +68,15 @@ open class SVGSerializer {
return String(Int(a))
}
fileprivate func tag(_ tag: String, _ args: [String:String]=[:], close: Bool=false) -> String {
fileprivate func tag(_ tag: String, _ args: [String: String]=[:], close: Bool = false) -> String {
let attrs = args.map { "\($0)=\"\($1)\"" }.joined(separator: " ")
let closeTag = close ? " />" : ""
return "\(tag) \(attrs) \(closeTag)"
}
fileprivate func arcToSVG(_ arc: Arc) -> String {
if (arc.shift == 0.0 && abs(arc.extent - Double.pi * 2.0) < SVGEpsilon) {
return tag(SVGEllipseOpenTag, ["cx":att(arc.ellipse.cx), "cy":att(arc.ellipse.cy), "rx":att(arc.ellipse.rx), "ry":att(arc.ellipse.ry)])
if arc.shift == 0.0 && abs(arc.extent - Double.pi * 2.0) < SVGEpsilon {
return tag(SVGEllipseOpenTag, ["cx": att(arc.ellipse.cx), "cy": att(arc.ellipse.cy), "rx": att(arc.ellipse.rx), "ry": att(arc.ellipse.ry)])
} else {
let rx = arc.ellipse.rx
let ry = arc.ellipse.ry
@ -98,19 +98,18 @@ open class SVGSerializer {
var d = "M\(x1),\(y1) "
d += "A \(rx),\(ry) 0.0 \(largeArcFlag), \(sweepFlag) \(x2),\(y2)"
return tag(SVGPathOpenTag, ["d":d])
return tag(SVGPathOpenTag, ["d": d])
}
}
fileprivate func polygonToSVG(_ polygon: Polygon) -> String {
let points = polygon.points.flatMap { String($0) }.joined(separator: ",")
return tag(SVGPolygonOpenTag, ["points":points])
return tag(SVGPolygonOpenTag, ["points": points])
}
fileprivate func polylineToSVG(_ polyline: Polyline) -> String {
let points = polyline.points.flatMap { String($0) }.joined(separator: ",")
return tag(SVGPolylineOpenTag, ["points":points])
return tag(SVGPolylineOpenTag, ["points": points])
}
fileprivate func pathToSVG(_ path: Path) -> String {
@ -118,34 +117,34 @@ open class SVGSerializer {
for segment in path.segments {
if segment.type == .A || segment.type == .a {
let flags = RenderUtils.numToBools(segment.data[3])
let large:Double = flags[0] ? 1 : 0
let sweep:Double = flags[1] ? 1 : 0
let large: Double = flags[0] ? 1 : 0
let sweep: Double = flags[1] ? 1 : 0
d += "\(segment.type) \([segment.data[0], segment.data[1], segment.data[2], large, sweep, segment.data[4], segment.data[5]].flatMap { String(Int($0)) }.joined(separator: " "))"
} else {
d += "\(segment.type) \(segment.data.flatMap { String(Int($0)) }.joined(separator: " "))"
}
}
return tag(SVGPathOpenTag, ["d":d])
return tag(SVGPathOpenTag, ["d": d])
}
fileprivate func lineToSVG(_ line: Line) -> String {
return tag(SVGLineOpenTag, ["x1":String(Int(line.x1)), "y1":att(line.y1), "x2":att(line.x2), "y2":att(line.y2)])
return tag(SVGLineOpenTag, ["x1": String(Int(line.x1)), "y1": att(line.y1), "x2": att(line.x2), "y2": att(line.y2)])
}
fileprivate func ellipseToSVG(_ ellipse: Ellipse) -> String {
return tag(SVGEllipseOpenTag, ["cx":att(ellipse.cx), "cy":att(ellipse.cy), "rx":att(ellipse.rx), "ry":att(ellipse.ry)])
return tag(SVGEllipseOpenTag, ["cx": att(ellipse.cx), "cy": att(ellipse.cy), "rx": att(ellipse.rx), "ry": att(ellipse.ry)])
}
fileprivate func circleToSVG(_ circle: Circle) -> String {
return tag(SVGCircleOpenTag, ["cx":att(circle.cx), "cy":att(circle.cy), "r":att(circle.r)])
return tag(SVGCircleOpenTag, ["cx": att(circle.cx), "cy": att(circle.cy), "r": att(circle.r)])
}
fileprivate func roundRectToSVG(_ roundRect: RoundRect) -> String {
return tag(SVGRectOpenTag, ["rx":att(roundRect.rx), "ry":att(roundRect.ry), "width":att(roundRect.rect.w), "height":att(roundRect.rect.h)])
return tag(SVGRectOpenTag, ["rx": att(roundRect.rx), "ry": att(roundRect.ry), "width": att(roundRect.rect.w), "height": att(roundRect.rect.h)])
}
fileprivate func rectToSVG(_ rect: Rect) -> String {
return tag(SVGRectOpenTag, ["x":att(rect.x), "y":att(rect.y), "width":att(rect.w), "height":att(rect.h)])
return tag(SVGRectOpenTag, ["x": att(rect.x), "y": att(rect.y), "width": att(rect.w), "height": att(rect.h)])
}
fileprivate func imageToSVG(_ image: Image) -> String {
@ -167,15 +166,18 @@ open class SVGSerializer {
}
fileprivate func alignToSVG(_ align: Align) -> String {
switch (align) {
case .mid: return " text-anchor=\"middle\" "
case .max: return " text-anchor=\"end "
default: return ""
switch align {
case .mid:
return " text-anchor=\"middle\" "
case .max:
return " text-anchor=\"end "
default:
return ""
}
}
fileprivate func baselineToSVG(_ baseline: Baseline) -> String {
if (baseline == .top) {
if baseline == .top {
return " dominant-baseline=\"text-before-edge\" "
}
return ""
@ -210,7 +212,7 @@ open class SVGSerializer {
let r = color.r()
let g = color.g()
let b = color.b()
return "#\(String(format:"%02X%02X%02X", r, g, b))"
return "#\(String(format: "%02X%02X%02X", r, g, b))"
}
}
@ -229,7 +231,7 @@ open class SVGSerializer {
if alpha == SVGDefaultOpacityValueAsAlpha {
return .none
}
return String(Double(alpha)/Double(SVGDefaultOpacityValueAsAlpha))
return String(Double(alpha) / Double(SVGDefaultOpacityValueAsAlpha))
}
fileprivate func strokeToSVG(_ stroke: Stroke?) -> String {
@ -272,7 +274,7 @@ open class SVGSerializer {
}
return " transform=\"translate(\(Int(shape.place.dx)),\(Int(shape.place.dy)))\" "
}
let matrixArgs = [shape.place.m11, shape.place.m12, shape.place.m21, shape.place.m22, shape.place.dx, shape.place.dy].map{ String($0) }.joined(separator: ",")
let matrixArgs = [shape.place.m11, shape.place.m12, shape.place.m21, shape.place.m22, shape.place.dx, shape.place.dy].map { String($0) }.joined(separator: ",")
return " transform=\"matrix(\(matrixArgs))\" "
}
@ -302,6 +304,7 @@ open class SVGSerializer {
}
fileprivate var defs: String = ""
fileprivate func getDefs() -> String {
if defs.isEmpty {
return ""
@ -310,7 +313,8 @@ open class SVGSerializer {
}
fileprivate var clipPathCount: Int = 0
fileprivate func addClipToDefs(_ clip:Locus) {
fileprivate func addClipToDefs(_ clip: Locus) {
clipPathCount += 1
defs += "<clipPath id=\"\(SVGClipPathName)\(clipPathCount)\">" + locusToSVG(clip) + SVGGenericCloseTag + "</clipPath>"
}
@ -334,7 +338,6 @@ open class SVGSerializer {
return result
}
fileprivate func serialize(node: Node, offset: Int) -> String {
if let shape = node as? Shape {
return indentTextWithOffset(macawShapeToSvgShape(macawShape: shape), offset)
@ -359,7 +362,7 @@ open class SVGSerializer {
return "SVGUndefinedTag \(node)"
}
fileprivate func serialize(node:Node) -> String {
fileprivate func serialize(node: Node) -> String {
var optionalSection = ""
if let w = width {
optionalSection += "width=\"\(w)\""
@ -378,7 +381,7 @@ open class SVGSerializer {
}
open class func serialize(node: Node, width: Int? = nil, height: Int? = nil, id: String? = nil) -> String {
return SVGSerializer(width: width, height:height, id: id).serialize(node: node)
return SVGSerializer(width: width, height: height, id: id).serialize(node: node)
}
}

View File

@ -9,7 +9,7 @@
import QuartzCore
/// CAAnimation Delegation class implementation
class CAAnimationDelegateImpl:NSObject, CAAnimationDelegate {
class CAAnimationDelegateImpl: NSObject, CAAnimationDelegate {
/// start: A block (closure) object to be executed when the animation starts. This block has no return value and takes no argument.
var start: (() -> Void)?

View File

@ -13,15 +13,14 @@ import Foundation
#endif
var imagesMap = [String: MImage]()
public extension MImage {
public func image( xAlign: Align = .min, yAlign: Align = .min, aspectRatio: AspectRatio = .none, w: Int = 0, h: Int = 0, place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) -> Image {
var oldId: String?
for key in imagesMap.keys {
if self === imagesMap[key] {
for key in imagesMap.keys where self === imagesMap[key] {
oldId = key
}
}
let id = oldId ?? UUID().uuidString
imagesMap[id] = self

View File

@ -96,7 +96,7 @@ open class MacawView: MView, MGestureRecognizerDelegate {
}
public convenience init(node: Node, frame: CGRect) {
self.init(frame:frame)
self.init(frame: frame)
self.node = node
nodesMap.add(node, view: self)
@ -157,7 +157,7 @@ open class MacawView: MView, MGestureRecognizerDelegate {
renderer?.render(force: false, opacity: node.opacity)
}
private func localContext( _ callback: (CGContext) -> ()) {
private func localContext( _ callback: (CGContext) -> Void) {
MGraphicsBeginImageContextWithOptions(self.bounds.size, false, 1.0)
if let ctx = MGraphicsGetCurrentContext() {
callback(ctx)
@ -167,11 +167,11 @@ open class MacawView: MView, MGestureRecognizerDelegate {
// MARK: - Touches
override func mTouchesBegan(_ touches: [MTouchEvent]) {
override func mTouchesBegan(_ touches: [MTouchEvent]) {
if !self.node.shouldCheckForPressed() &&
!self.node.shouldCheckForMoved() &&
!self.node.shouldCheckForReleased (){
!self.node.shouldCheckForReleased () {
return
}
@ -245,7 +245,6 @@ override func mTouchesBegan(_ touches: [MTouchEvent]) {
}
}
override func mTouchesCancelled(_ touches: [MTouchEvent]) {
touchesEnded(touches: touches)
}
@ -273,9 +272,11 @@ override func mTouchesBegan(_ touches: [MTouchEvent]) {
node.handleTouchReleased(touchEvent)
if let index = touchesOfNode[node]?.index(of: touch) {
touchesOfNode[node]?.remove(at: index)
// swiftlint:disable empty_count
if let count = touchesOfNode[node]?.count, count == 0 {
touchesOfNode.removeValue(forKey: node)
}
// swiftlint:enable empty_count
}
}
@ -312,7 +313,6 @@ override func mTouchesBegan(_ touches: [MTouchEvent]) {
}
}
foundNodes.forEach { node in
let inverted = node.place.invert()!
let loc = location.applying(RenderUtils.mapTransform(inverted))
@ -389,7 +389,6 @@ override func mTouchesBegan(_ touches: [MTouchEvent]) {
if recognizer.state == .began {
let location = recognizer.location(in: self)
localContext { ctx in
guard let foundNode = renderer.findNodeAt(location: location, ctx: ctx) else {
return

View File

@ -1,4 +1,3 @@
import Foundation
#if os(iOS)
@ -83,7 +82,6 @@ class NodesMap {
add(to, view: view)
}
// Replacing node in hosting view if needed
guard let hostingNode = hostingView?.node else {
return

View File

@ -13,7 +13,7 @@ class MTouchEvent: Hashable {
return id.hashValue
}
public static func ==(lhs: MTouchEvent, rhs: MTouchEvent) -> Bool {
public static func == (lhs: MTouchEvent, rhs: MTouchEvent) -> Bool {
return lhs.id == rhs.id
}
}