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

Merge branch 'macos_support'

# Conflicts:
#	Source/animation/AnimationImpl.swift
#	Source/animation/AnimationProducer.swift
#	Source/animation/types/AnimationSequence.swift
#	Source/animation/types/CombineAnimation.swift
#	Source/animation/types/ContentsAnimation.swift
#	Source/animation/types/MorphingAnimation.swift
#	Source/animation/types/OpacityAnimation.swift
#	Source/animation/types/ShapeAnimation.swift
#	Source/animation/types/TransformAnimation.swift
#	Source/animation/types/animation_generators/MorphingGenerator.swift
#	Source/animation/types/animation_generators/OpacityGenerator.swift
#	Source/animation/types/animation_generators/ShapeAnimationGenerator.swift
#	Source/animation/types/animation_generators/TransformGenerator.swift
#	Source/model/scene/Node.swift
#	Source/render/NodeRenderer.swift
#	Source/svg/SVGConstants.swift
#	Source/svg/SVGParser.swift
#	Source/views/NodesMap.swift
This commit is contained in:
Viktor Sukochev 2017-08-25 16:32:30 +07:00
commit ffff19619e
121 changed files with 7705 additions and 4236 deletions

View File

@ -0,0 +1,480 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
970AB811D179560D74930D39 /* Pods_Example_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5184A00051CAC5E360198B48 /* Pods_Example_macOS.framework */; };
A72862CB1F4308A50033893D /* AnimationsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A72862CA1F4308A50033893D /* AnimationsViewController.swift */; };
A72862CE1F430DF00033893D /* EasingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A72862CC1F430DF00033893D /* EasingViewController.swift */; };
A753C9E81F3DB18A006615A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A753C9E71F3DB18A006615A4 /* AppDelegate.swift */; };
A753C9EA1F3DB18A006615A4 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A753C9E91F3DB18A006615A4 /* ViewController.swift */; };
A753C9EC1F3DB18A006615A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A753C9EB1F3DB18A006615A4 /* Assets.xcassets */; };
A753C9EF1F3DB18A006615A4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A753C9ED1F3DB18A006615A4 /* Main.storyboard */; };
A75939A21F41C54E000CE329 /* ShapesExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A75939A11F41C54E000CE329 /* ShapesExampleView.swift */; };
A75939A51F41C571000CE329 /* MorphingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A75939A41F41C571000CE329 /* MorphingView.swift */; };
A75939A81F41C5A8000CE329 /* TransformExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A75939A71F41C5A8000CE329 /* TransformExampleView.swift */; };
A768EAD81F42C98E00F22A17 /* EventsExampleController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A768EAD71F42C98E00F22A17 /* EventsExampleController.swift */; };
A768EADC1F42CC7C00F22A17 /* EasingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A768EADB1F42CC7C00F22A17 /* EasingView.swift */; };
A768EADE1F42CCBC00F22A17 /* AnimationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A768EADD1F42CCBC00F22A17 /* AnimationsView.swift */; };
A768EAE21F42EDAE00F22A17 /* tiger.svg in Resources */ = {isa = PBXBuildFile; fileRef = A768EAE11F42EDAE00F22A17 /* tiger.svg */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
5184A00051CAC5E360198B48 /* Pods_Example_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A72862CA1F4308A50033893D /* AnimationsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AnimationsViewController.swift; path = Examples/Animations/AnimationsViewController.swift; sourceTree = "<group>"; };
A72862CC1F430DF00033893D /* EasingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EasingViewController.swift; path = Examples/Easing/EasingViewController.swift; sourceTree = "<group>"; };
A753C9E41F3DB18A006615A4 /* Example-macOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example-macOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
A753C9E71F3DB18A006615A4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
A753C9E91F3DB18A006615A4 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
A753C9EB1F3DB18A006615A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
A753C9EE1F3DB18A006615A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
A753C9F01F3DB18A006615A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A75939A11F41C54E000CE329 /* ShapesExampleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShapesExampleView.swift; path = Examples/Shapes/ShapesExampleView.swift; sourceTree = "<group>"; };
A75939A41F41C571000CE329 /* MorphingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MorphingView.swift; path = Examples/Morphing/MorphingView.swift; sourceTree = "<group>"; };
A75939A71F41C5A8000CE329 /* TransformExampleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TransformExampleView.swift; path = Examples/Transform/TransformExampleView.swift; sourceTree = "<group>"; };
A768EAD71F42C98E00F22A17 /* EventsExampleController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EventsExampleController.swift; path = Examples/Events/EventsExampleController.swift; sourceTree = "<group>"; };
A768EADB1F42CC7C00F22A17 /* EasingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EasingView.swift; path = Examples/Easing/EasingView.swift; sourceTree = "<group>"; };
A768EADD1F42CCBC00F22A17 /* AnimationsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AnimationsView.swift; path = Examples/Animations/AnimationsView.swift; sourceTree = "<group>"; };
A768EAE11F42EDAE00F22A17 /* tiger.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = tiger.svg; path = "Example-macOS/Assets/SVG/tiger.svg"; sourceTree = "<group>"; };
B752613023F25BBB88A17503 /* Pods-Example-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example-macOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example-macOS/Pods-Example-macOS.debug.xcconfig"; sourceTree = "<group>"; };
BEA3A0212E620A41C8362253 /* Pods-Example-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example-macOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example-macOS/Pods-Example-macOS.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
A753C9E11F3DB18A006615A4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
970AB811D179560D74930D39 /* Pods_Example_macOS.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
1CB6DE34952A084DD8BB425B /* Frameworks */ = {
isa = PBXGroup;
children = (
5184A00051CAC5E360198B48 /* Pods_Example_macOS.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
4F8946156C3F28DC7B262776 /* Pods */ = {
isa = PBXGroup;
children = (
B752613023F25BBB88A17503 /* Pods-Example-macOS.debug.xcconfig */,
BEA3A0212E620A41C8362253 /* Pods-Example-macOS.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
A753C9DB1F3DB18A006615A4 = {
isa = PBXGroup;
children = (
A768EADF1F42ED9700F22A17 /* Assets */,
A753C9E61F3DB18A006615A4 /* Example-macOS */,
A753C9E51F3DB18A006615A4 /* Products */,
4F8946156C3F28DC7B262776 /* Pods */,
1CB6DE34952A084DD8BB425B /* Frameworks */,
);
sourceTree = "<group>";
};
A753C9E51F3DB18A006615A4 /* Products */ = {
isa = PBXGroup;
children = (
A753C9E41F3DB18A006615A4 /* Example-macOS.app */,
);
name = Products;
sourceTree = "<group>";
};
A753C9E61F3DB18A006615A4 /* Example-macOS */ = {
isa = PBXGroup;
children = (
A759399F1F41C51A000CE329 /* Examples */,
A753C9E71F3DB18A006615A4 /* AppDelegate.swift */,
A753C9E91F3DB18A006615A4 /* ViewController.swift */,
A753C9ED1F3DB18A006615A4 /* Main.storyboard */,
A753C9EB1F3DB18A006615A4 /* Assets.xcassets */,
A753C9F01F3DB18A006615A4 /* Info.plist */,
);
path = "Example-macOS";
sourceTree = "<group>";
};
A759399F1F41C51A000CE329 /* Examples */ = {
isa = PBXGroup;
children = (
A75939A01F41C544000CE329 /* Shapes */,
A75939A61F41C58D000CE329 /* Transform */,
A768EADA1F42CBF600F22A17 /* Animations */,
A75939A91F41CE45000CE329 /* Easing */,
A75939A31F41C566000CE329 /* Morphing */,
A768EAD61F42C97900F22A17 /* Events */,
);
name = Examples;
sourceTree = "<group>";
};
A75939A01F41C544000CE329 /* Shapes */ = {
isa = PBXGroup;
children = (
A75939A11F41C54E000CE329 /* ShapesExampleView.swift */,
);
name = Shapes;
sourceTree = "<group>";
};
A75939A31F41C566000CE329 /* Morphing */ = {
isa = PBXGroup;
children = (
A75939A41F41C571000CE329 /* MorphingView.swift */,
);
name = Morphing;
sourceTree = "<group>";
};
A75939A61F41C58D000CE329 /* Transform */ = {
isa = PBXGroup;
children = (
A75939A71F41C5A8000CE329 /* TransformExampleView.swift */,
);
name = Transform;
sourceTree = "<group>";
};
A75939A91F41CE45000CE329 /* Easing */ = {
isa = PBXGroup;
children = (
A768EADB1F42CC7C00F22A17 /* EasingView.swift */,
A72862CC1F430DF00033893D /* EasingViewController.swift */,
);
name = Easing;
sourceTree = "<group>";
};
A768EAD61F42C97900F22A17 /* Events */ = {
isa = PBXGroup;
children = (
A768EAD71F42C98E00F22A17 /* EventsExampleController.swift */,
);
name = Events;
sourceTree = "<group>";
};
A768EADA1F42CBF600F22A17 /* Animations */ = {
isa = PBXGroup;
children = (
A768EADD1F42CCBC00F22A17 /* AnimationsView.swift */,
A72862CA1F4308A50033893D /* AnimationsViewController.swift */,
);
name = Animations;
sourceTree = "<group>";
};
A768EADF1F42ED9700F22A17 /* Assets */ = {
isa = PBXGroup;
children = (
A768EAE01F42EDA300F22A17 /* SVG */,
);
name = Assets;
sourceTree = "<group>";
};
A768EAE01F42EDA300F22A17 /* SVG */ = {
isa = PBXGroup;
children = (
A768EAE11F42EDAE00F22A17 /* tiger.svg */,
);
name = SVG;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
A753C9E31F3DB18A006615A4 /* Example-macOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = A753C9F31F3DB18A006615A4 /* Build configuration list for PBXNativeTarget "Example-macOS" */;
buildPhases = (
1F28568372F4741200F4770C /* [CP] Check Pods Manifest.lock */,
A753C9E01F3DB18A006615A4 /* Sources */,
A753C9E11F3DB18A006615A4 /* Frameworks */,
A753C9E21F3DB18A006615A4 /* Resources */,
D4AD26F62FE37F7476EC4BCA /* [CP] Embed Pods Frameworks */,
3AE877354B4133CFC7CAF0DD /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = "Example-macOS";
productName = "Example-macOS";
productReference = A753C9E41F3DB18A006615A4 /* Example-macOS.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
A753C9DC1F3DB18A006615A4 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0830;
LastUpgradeCheck = 0830;
TargetAttributes = {
A753C9E31F3DB18A006615A4 = {
CreatedOnToolsVersion = 8.3.3;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = A753C9DF1F3DB18A006615A4 /* Build configuration list for PBXProject "Example-macOS" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = A753C9DB1F3DB18A006615A4;
productRefGroup = A753C9E51F3DB18A006615A4 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
A753C9E31F3DB18A006615A4 /* Example-macOS */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
A753C9E21F3DB18A006615A4 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A753C9EC1F3DB18A006615A4 /* Assets.xcassets in Resources */,
A753C9EF1F3DB18A006615A4 /* Main.storyboard in Resources */,
A768EAE21F42EDAE00F22A17 /* tiger.svg in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
1F28568372F4741200F4770C /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
3AE877354B4133CFC7CAF0DD /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example-macOS/Pods-Example-macOS-resources.sh\"\n";
showEnvVarsInLog = 0;
};
D4AD26F62FE37F7476EC4BCA /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example-macOS/Pods-Example-macOS-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
A753C9E01F3DB18A006615A4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A75939A51F41C571000CE329 /* MorphingView.swift in Sources */,
A753C9EA1F3DB18A006615A4 /* ViewController.swift in Sources */,
A75939A21F41C54E000CE329 /* ShapesExampleView.swift in Sources */,
A753C9E81F3DB18A006615A4 /* AppDelegate.swift in Sources */,
A768EAD81F42C98E00F22A17 /* EventsExampleController.swift in Sources */,
A72862CE1F430DF00033893D /* EasingViewController.swift in Sources */,
A72862CB1F4308A50033893D /* AnimationsViewController.swift in Sources */,
A768EADE1F42CCBC00F22A17 /* AnimationsView.swift in Sources */,
A75939A81F41C5A8000CE329 /* TransformExampleView.swift in Sources */,
A768EADC1F42CC7C00F22A17 /* EasingView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
A753C9ED1F3DB18A006615A4 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
A753C9EE1F3DB18A006615A4 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
A753C9F11F3DB18A006615A4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
A753C9F21F3DB18A006615A4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
};
name = Release;
};
A753C9F41F3DB18A006615A4 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = B752613023F25BBB88A17503 /* Pods-Example-macOS.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = "Example-macOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.exyte.Example-macOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
A753C9F51F3DB18A006615A4 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = BEA3A0212E620A41C8362253 /* Pods-Example-macOS.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = "Example-macOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.exyte.Example-macOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
A753C9DF1F3DB18A006615A4 /* Build configuration list for PBXProject "Example-macOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A753C9F11F3DB18A006615A4 /* Debug */,
A753C9F21F3DB18A006615A4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A753C9F31F3DB18A006615A4 /* Build configuration list for PBXNativeTarget "Example-macOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A753C9F41F3DB18A006615A4 /* Debug */,
A753C9F51F3DB18A006615A4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = A753C9DC1F3DB18A006615A4 /* Project object */;
}

View File

@ -0,0 +1,26 @@
//
// AppDelegate.swift
// Example-macOS
//
// Created by Daniil Manin on 8/11/17.
//
//
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
}

View File

@ -0,0 +1,58 @@
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 94 KiB

View File

@ -0,0 +1,343 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12121"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Application-->
<scene sceneID="JPo-4y-FX3">
<objects>
<application id="hnw-xV-0zn" sceneMemberID="viewController">
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="Example-macOS" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Example-macOS" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About Example-macOS" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
<menuItem title="Services" id="NMo-om-nkz">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
<menuItem title="Hide Example-macOS" keyEquivalent="h" id="Olw-nP-bQN">
<connections>
<action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
</connections>
</menuItem>
<menuItem title="Show All" id="Kd2-mp-pUS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
<menuItem title="Quit Example-macOS" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="dMs-cI-mzQ">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Edit" id="5QF-Oa-p0T">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Format" id="jxT-CU-nIS">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="View" id="H8h-7b-M4v">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Window" id="aUF-d1-5bR">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Help" id="wpr-3q-Mcd">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
</connections>
</application>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="Example_macOS" customModuleProvider="target"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="58" y="-294"/>
</scene>
<!--Window Controller-->
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController id="B8D-0N-5wS" sceneMemberID="viewController">
<window key="window" title="Macaw-Example" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="600" height="500"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<value key="minSize" type="size" width="600" height="500"/>
<value key="maxSize" type="size" width="600" height="500"/>
</window>
<connections>
<segue destination="hdB-7F-R9Q" kind="relationship" relationship="window.shadowedContentViewController" id="2sy-Hm-TOK"/>
</connections>
</windowController>
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="57" y="91"/>
</scene>
<!--Tab View Controller-->
<scene sceneID="HCD-4m-c8h">
<objects>
<tabViewController selectedTabViewItemIndex="0" id="hdB-7F-R9Q" sceneMemberID="viewController">
<tabViewItems>
<tabViewItem identifier="" id="3QN-7z-LrX"/>
<tabViewItem id="1e3-gs-UK8"/>
<tabViewItem id="Kue-lk-AJ2"/>
<tabViewItem id="lLO-HO-JXp"/>
<tabViewItem id="cOY-ae-H1s"/>
<tabViewItem id="h85-ch-mEO"/>
<tabViewItem id="fd7-0D-v5P"/>
</tabViewItems>
<tabView key="tabView" type="noTabsNoBorder" id="2WP-RT-S1E">
<rect key="frame" x="-57" y="5" width="615" height="95"/>
<autoresizingMask key="autoresizingMask"/>
<font key="font" metaFont="message"/>
<tabViewItems/>
</tabView>
<connections>
<segue destination="GQJ-Hp-Pf9" kind="relationship" relationship="tabItems" id="NpD-f5-aHg"/>
<segue destination="jao-64-FWC" kind="relationship" relationship="tabItems" id="2YP-Vc-nYb"/>
<segue destination="mWu-e3-ocB" kind="relationship" relationship="tabItems" id="Elo-Zo-5ec"/>
<segue destination="iWh-Ne-7Ns" kind="relationship" relationship="tabItems" id="b7l-i9-xc7"/>
<segue destination="6Ok-1N-J6E" kind="relationship" relationship="tabItems" id="Oei-AM-VA1"/>
<segue destination="Rn8-Li-WZ2" kind="relationship" relationship="tabItems" id="XnE-5e-LQB"/>
<segue destination="9aj-uf-eJX" kind="relationship" relationship="tabItems" id="dm1-xg-c0C"/>
</connections>
</tabViewController>
<customObject id="vzO-zk-Zwd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="58" y="541"/>
</scene>
<!--Shapes-->
<scene sceneID="X9O-0j-kca">
<objects>
<viewController title="Shapes" id="GQJ-Hp-Pf9" sceneMemberID="viewController">
<view key="view" id="To1-Fe-AtI">
<rect key="frame" x="0.0" y="0.0" width="600" height="500"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="D3z-wL-l2P" customClass="ShapesExampleView" customModule="Example_macOS" customModuleProvider="target">
<rect key="frame" x="125" y="0.0" width="350" height="480"/>
<constraints>
<constraint firstAttribute="width" constant="350" id="2E2-Lj-XMk"/>
</constraints>
</customView>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="D3z-wL-l2P" secondAttribute="bottom" id="8Im-Qx-btY"/>
<constraint firstItem="D3z-wL-l2P" firstAttribute="top" secondItem="To1-Fe-AtI" secondAttribute="top" constant="20" id="8w2-gW-Wjf"/>
<constraint firstItem="D3z-wL-l2P" firstAttribute="centerX" secondItem="To1-Fe-AtI" secondAttribute="centerX" id="Sg0-C8-DDx"/>
</constraints>
</view>
</viewController>
<customObject id="EYN-Mf-krY" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="57" y="1044"/>
</scene>
<!--Animations-->
<scene sceneID="mQS-s7-7Qq">
<objects>
<viewController title="Animations" id="mWu-e3-ocB" customClass="AnimationsViewController" customModule="Example_macOS" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" id="K6m-Lx-cTz">
<rect key="frame" x="0.0" y="0.0" width="600" height="500"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="1Rb-D3-XW9" customClass="AnimationsView" customModule="Example_macOS" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="600" height="500"/>
</customView>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bPP-dr-CnF">
<rect key="frame" x="260" y="39" width="80" height="19"/>
<constraints>
<constraint firstAttribute="height" constant="18" id="3MY-fR-U9d"/>
<constraint firstAttribute="width" constant="80" id="Te3-mr-Bce"/>
</constraints>
<buttonCell key="cell" type="roundRect" title="Start" bezelStyle="roundedRect" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="wkK-UK-u12">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="cellTitle"/>
</buttonCell>
<connections>
<action selector="startAnimationsAction:" target="mWu-e3-ocB" id="8K1-bW-xw9"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="bPP-dr-CnF" secondAttribute="bottom" constant="40" id="94k-Vi-ybb"/>
<constraint firstAttribute="trailing" secondItem="1Rb-D3-XW9" secondAttribute="trailing" id="9cE-er-ZBS"/>
<constraint firstItem="1Rb-D3-XW9" firstAttribute="leading" secondItem="K6m-Lx-cTz" secondAttribute="leading" id="J8j-Tu-jSk"/>
<constraint firstItem="1Rb-D3-XW9" firstAttribute="top" secondItem="K6m-Lx-cTz" secondAttribute="top" id="SdM-su-R3z"/>
<constraint firstItem="bPP-dr-CnF" firstAttribute="centerX" secondItem="K6m-Lx-cTz" secondAttribute="centerX" id="eod-st-ImC"/>
<constraint firstAttribute="bottom" secondItem="1Rb-D3-XW9" secondAttribute="bottom" id="iJZ-ip-cKT"/>
</constraints>
</view>
<connections>
<outlet property="actionButton" destination="bPP-dr-CnF" id="2Ql-Wv-czh"/>
<outlet property="animationsView" destination="1Rb-D3-XW9" id="Qgh-aE-e3M"/>
</connections>
</viewController>
<customObject id="ggI-l3-NeJ" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="828" y="1037"/>
</scene>
<!--Easing-->
<scene sceneID="UPp-EA-zFu">
<objects>
<viewController title="Easing" id="6Ok-1N-J6E" customClass="EasingViewController" customModule="Example_macOS" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" id="8S8-en-dQ9">
<rect key="frame" x="0.0" y="0.0" width="600" height="500"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="rMi-Lt-xst" customClass="EasingView" customModule="Example_macOS" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="600" height="500"/>
</customView>
</subviews>
<constraints>
<constraint firstItem="rMi-Lt-xst" firstAttribute="leading" secondItem="8S8-en-dQ9" secondAttribute="leading" id="E6d-Fs-XSu"/>
<constraint firstItem="rMi-Lt-xst" firstAttribute="top" secondItem="8S8-en-dQ9" secondAttribute="top" id="F4Q-5G-KAY"/>
<constraint firstAttribute="bottom" secondItem="rMi-Lt-xst" secondAttribute="bottom" id="STw-fO-vXO"/>
<constraint firstAttribute="trailing" secondItem="rMi-Lt-xst" secondAttribute="trailing" id="YpZ-0X-Eb4"/>
</constraints>
</view>
<connections>
<outlet property="easingView" destination="rMi-Lt-xst" id="1Lm-UJ-vZD"/>
</connections>
</viewController>
<customObject id="97s-Ny-kLm" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="57" y="1631"/>
</scene>
<!--Tranform-->
<scene sceneID="BDK-cT-fde">
<objects>
<viewController title="Tranform" id="jao-64-FWC" sceneMemberID="viewController">
<view key="view" id="LOa-Et-9Z8">
<rect key="frame" x="0.0" y="0.0" width="600" height="500"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="CHZ-ou-3pJ" customClass="TransformExampleView" customModule="Example_macOS" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="600" height="500"/>
</customView>
</subviews>
<constraints>
<constraint firstItem="CHZ-ou-3pJ" firstAttribute="top" secondItem="LOa-Et-9Z8" secondAttribute="top" id="MQ2-71-Q8T"/>
<constraint firstAttribute="bottom" secondItem="CHZ-ou-3pJ" secondAttribute="bottom" id="j0W-Jy-EsB"/>
<constraint firstAttribute="trailing" secondItem="CHZ-ou-3pJ" secondAttribute="trailing" id="xaj-cY-w1R"/>
<constraint firstItem="CHZ-ou-3pJ" firstAttribute="leading" secondItem="LOa-Et-9Z8" secondAttribute="leading" id="yJd-5F-Abz"/>
</constraints>
</view>
</viewController>
<customObject id="qef-Rz-hXA" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-701" y="1037"/>
</scene>
<!--Morhing-->
<scene sceneID="Plb-hR-bEv">
<objects>
<viewController title="Morhing" id="Rn8-Li-WZ2" sceneMemberID="viewController">
<view key="view" id="ZyY-lN-6hI">
<rect key="frame" x="0.0" y="0.0" width="600" height="500"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="tFf-Vb-fQM" customClass="MorphingView" customModule="Example_macOS" customModuleProvider="target">
<rect key="frame" x="200" y="150" width="200" height="200"/>
<constraints>
<constraint firstAttribute="height" constant="200" id="O3r-f7-WR6"/>
<constraint firstAttribute="width" constant="200" id="akU-YZ-kuF"/>
</constraints>
</customView>
</subviews>
<constraints>
<constraint firstItem="tFf-Vb-fQM" firstAttribute="centerX" secondItem="ZyY-lN-6hI" secondAttribute="centerX" id="3vl-dy-NeQ"/>
<constraint firstItem="tFf-Vb-fQM" firstAttribute="centerY" secondItem="ZyY-lN-6hI" secondAttribute="centerY" id="p6G-C4-Mkb"/>
</constraints>
</view>
</viewController>
<customObject id="hfo-iR-W9t" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-701" y="1631"/>
</scene>
<!--SVG-->
<scene sceneID="ZLO-Eh-m1d">
<objects>
<viewController title="SVG" id="iWh-Ne-7Ns" sceneMemberID="viewController">
<view key="view" id="Vz6-zz-0Xw">
<rect key="frame" x="0.0" y="0.0" width="600" height="500"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="yvE-72-Fe6" customClass="SVGView" customModule="Macaw">
<rect key="frame" x="0.0" y="0.0" width="600" height="500"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="fileName" value="tiger"/>
</userDefinedRuntimeAttributes>
</customView>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="yvE-72-Fe6" secondAttribute="trailing" id="4UL-4W-9YN"/>
<constraint firstItem="yvE-72-Fe6" firstAttribute="leading" secondItem="Vz6-zz-0Xw" secondAttribute="leading" id="Xi8-t8-OlL"/>
<constraint firstAttribute="bottom" secondItem="yvE-72-Fe6" secondAttribute="bottom" id="l48-pg-5Kp"/>
<constraint firstItem="yvE-72-Fe6" firstAttribute="top" secondItem="Vz6-zz-0Xw" secondAttribute="top" id="nQP-Ld-hzQ"/>
</constraints>
</view>
</viewController>
<customObject id="SgK-6P-fu5" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="828" y="1631"/>
</scene>
<!--Events-->
<scene sceneID="kTj-Ru-vPq">
<objects>
<viewController title="Events" id="9aj-uf-eJX" customClass="EventsExampleController" customModule="Example_macOS" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" id="Fg0-AZ-zer">
<rect key="frame" x="0.0" y="0.0" width="600" height="500"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="3dq-O5-WZ6" customClass="MacawView" customModule="Macaw">
<rect key="frame" x="0.0" y="0.0" width="600" height="500"/>
</customView>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="3dq-O5-WZ6" secondAttribute="trailing" id="FzC-3s-Kku"/>
<constraint firstItem="3dq-O5-WZ6" firstAttribute="leading" secondItem="Fg0-AZ-zer" secondAttribute="leading" id="PUF-Il-bp3"/>
<constraint firstItem="3dq-O5-WZ6" firstAttribute="top" secondItem="Fg0-AZ-zer" secondAttribute="top" id="Utd-UH-Vzg"/>
<constraint firstAttribute="bottom" secondItem="3dq-O5-WZ6" secondAttribute="bottom" id="eNi-iP-YzC"/>
</constraints>
</view>
<connections>
<outlet property="macawView" destination="3dq-O5-WZ6" id="diH-cZ-09G"/>
</connections>
</viewController>
<customObject id="RA2-nh-XE7" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="57" y="2256"/>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,118 @@
import Macaw
class AnimationsView: MacawView {
var animation: Animation?
var ballNodes = [Group]()
var onComplete: (() -> ()) = {}
let n = 100
let speed = 20.0
let r = 10.0
let ballColors = [
Color(val: 0x1abc9c),
Color(val: 0x2ecc71),
Color(val: 0x3498db),
Color(val: 0x9b59b6),
Color(val: 0xf1c40f),
Color(val: 0xe67e22),
Color(val: 0xe67e22),
Color(val: 0xe74c3c)
]
required init?(coder aDecoder: NSCoder) {
super.init(node: Group(), coder: aDecoder)
}
func startAnimation() {
if let animation = self.animation {
animation.play()
}
}
func prepareAnimation() {
ballNodes.removeAll()
var animations = [Animation]()
let screenBounds = self.bounds
let startPos = Transform.move(
dx: Double(screenBounds.width / 2) - r,
dy: Double(screenBounds.height / 2) - r
)
var velocities = [Point]()
var positions = [Point]()
func posForTime(_ t: Double, index: Int) -> Point {
let prevPos = positions[index]
var velocity = velocities[index]
var pos = prevPos.add(velocity)
// Borders
if pos.x < Double(self.bounds.width) / -2.0 || pos.x > Double(self.bounds.width) / 2.0 {
velocity = Point(x: -1.0 * velocity.x, y: velocity.y)
velocities[index] = velocity
pos = prevPos.add(velocity)
}
if pos.y < Double(self.bounds.height) / -2.0 || pos.y > Double(self.bounds.height) / 2.0 {
velocity = Point(x: velocity.x, y: -1.0 * velocity.y)
velocities[index] = velocity
pos = prevPos.add(velocity)
}
return pos
}
for i in 0 ... (n - 1) {
// Node
let circle = Circle(cx: r, cy: r, r: r)
let shape = Shape(
form: circle,
fill: ballColors[Int(arc4random() % 7)]
)
let ballGroup = Group(contents: [shape])
ballNodes.append(ballGroup)
// Animation
let velocity = Point(
x: -0.5 * speed + speed * Double(arc4random() % 1000) / 1000.0,
y: -0.5 * speed + speed * Double(arc4random() % 1000) / 1000.0)
velocities.append(velocity)
positions.append(Point(x: 0.0, y: 0.0))
let anim = ballGroup.placeVar.animation({ (t) -> Transform in
let pos = posForTime(t, index: i)
positions[i] = pos
return Transform().move(
dx: pos.x,
dy: pos.y)
}, during: 3.0)
animations.append([
anim,
ballGroup.opacityVar.animation((0.1 >> 1.0).t(3.0))
].combine())
}
animation = animations.combine().autoreversed().onComplete {
self.completeAnimation()
}
let node = Group(contents: ballNodes)
node.place = Transform().move(dx: startPos.dx, dy: startPos.dy)
self.node = node
}
func completeAnimation() {
self.node = Group()
self.prepareAnimation()
self.onComplete()
}
}

View File

@ -0,0 +1,35 @@
//
// AnimationsViewController.swift
// Example-macOS
//
// Created by Daniil Manin on 8/15/17.
//
//
import Cocoa
class AnimationsViewController: NSViewController {
@IBOutlet weak var animationsView: AnimationsView!
@IBOutlet weak var actionButton: NSButton!
override func viewDidAppear() {
super.viewDidAppear()
animationsView?.onComplete = {
self.actionButton?.isEnabled = true
}
animationsView?.prepareAnimation()
}
override func viewDidDisappear() {
super.viewDidDisappear()
self.actionButton?.isEnabled = true
}
@IBAction func startAnimationsAction(_ sender: Any) {
animationsView?.startAnimation()
actionButton?.isEnabled = false
}
}

View File

@ -0,0 +1,44 @@
import Macaw
class EasingView: MacawView {
var mAnimations = [Animation]()
var circlesNodes = [Group]()
var animation: Animation!
required init?(coder aDecoder: NSCoder) {
let screenSize = CGRect(origin: CGPoint.zero, size: CGSize(width: 600.0, height: 500.0))
let centerX = Double(screenSize.width / 2)
let fromStroke = Stroke(fill: Color.black, width: 3)
let all = [Easing.ease, Easing.linear, Easing.easeIn, Easing.easeOut, Easing.easeInOut]
for (i, easing) in all.enumerated() {
let y = Double(75 + i * 80)
let title = EasingView.title(easing: easing)
let titleText = Text(text: title, align: .mid, place: .move(dx: centerX, dy: y - 45))
let fromCircle = Circle(cx: centerX - 100, cy: y, r: 25).stroke(with: fromStroke)
let toPlace = fromCircle.place.move(dx: 200, dy: 0)
let toAnimation = fromCircle.placeVar.animation(to: toPlace).easing(easing)
mAnimations.append([toAnimation.autoreversed()].sequence())
circlesNodes.append(Group(contents: [titleText]))
circlesNodes.append(Group(contents: [fromCircle]))
}
animation = mAnimations.combine().cycle()
super.init(node: circlesNodes.group(), coder: aDecoder)
}
fileprivate static func title(easing: Easing) -> String {
switch easing {
case .ease: return "Ease"
case .linear: return "Linear"
case .easeIn: return "Ease In"
case .easeOut: return "Ease Out"
case .easeInOut: return "Ease InOut"
}
}
}

View File

@ -0,0 +1,23 @@
//
// EasingViewController.swift
// Example-macOS
//
// Created by Daniil Manin on 8/15/17.
//
//
import Cocoa
class EasingViewController: NSViewController {
@IBOutlet weak var easingView: EasingView!
override func viewDidAppear() {
super.viewDidAppear()
easingView.animation.play()
}
override func viewWillDisappear() {
super.viewDidDisappear()
easingView.animation.stop()
}
}

View File

@ -0,0 +1,139 @@
//
// EventsExampleController.swift
// Example
//
// Created by Victor Sukochev on 02/03/2017.
// Copyright © 2017 Exyte. All rights reserved.
//
import Macaw
class EventsExampleController: NSViewController {
@IBOutlet weak var macawView: MacawView?
override func viewDidLoad() {
super.viewDidLoad()
macawView?.node = loadScene()
}
enum PanelTool {
case ellipse
case rectangle
}
var selectedTool: PanelTool?
private func loadScene() -> Node {
return [createCanvas(), createPanel()].group()
}
private func createPanel() -> Node {
let panel = Shape(form: Rect(x: 10.0, y: 10.0, w: 80.0, h: 120.0), fill: Color.clear, stroke: Stroke(fill: Color.black, width: 1.0))
let panelGroup = [panel, createTools()].group()
panelGroup.onPan { event in
panelGroup.place = panelGroup.place.move(dx: event.dx, dy: event.dy)
}
return panelGroup
}
private func createCanvas() -> Node {
let canvas = Shape(form: Rect(x: 0.0, y: 0.0,
w: Double(macawView!.bounds.width),
h: Double(macawView!.bounds.height)),
fill: Color.white)
let objectsGroup = Group(contents:[])
var startPoint = Point()
var currentFigure: Shape?
canvas.onTouchPressed { event in
guard let tool = self.selectedTool else {
return
}
guard let loc = event.points.first?.location else {
return
}
startPoint = loc
switch tool {
case .ellipse:
currentFigure = Shape(form: Ellipse(cx: startPoint.x, cy: startPoint.y, rx: 0.0, ry: 0.0))
break
case .rectangle:
currentFigure = Shape(form: Rect(x: startPoint.x, y: startPoint.y, w: 0.0, h: 0.0))
break
}
var updatedContents = objectsGroup.contents
updatedContents.append(currentFigure!)
objectsGroup.contents = updatedContents
}
canvas.onTouchMoved { event in
guard let tool = self.selectedTool else {
return
}
guard let loc = event.points.first?.location else {
return
}
let width = loc.x - startPoint.x
let height = loc.y - startPoint.y
switch tool {
case .ellipse:
currentFigure?.form = Ellipse(
cx: startPoint.x + width / 2.0,
cy: startPoint.y + height / 2.0,
rx: width / 2.0,
ry: height / 2.0)
break
case .rectangle:
currentFigure?.form = Rect(x: startPoint.x, y: startPoint.y, w: width, h: height)
break
}
}
return [
canvas,
objectsGroup
].group()
}
private func createTools() -> Node {
let ellipseTool = Shape(form: Ellipse(cx: 50.0, cy: 50.0, rx: 25, ry: 15),
fill: Color.clear,
stroke: Stroke(fill: Color.black, width: 1.0))
let rectTool = Shape(form: Rect(x: 25.0, y: 75.0, w: 50.0, h: 30.0),
fill: Color.clear,
stroke: Stroke(fill: Color.black, width: 1.0))
ellipseTool.onTap { _ in
self.selectedTool = .ellipse
ellipseTool.stroke = Stroke(fill: Color.blue, width: 2.0)
rectTool.stroke = Stroke(fill: Color.black, width: 1.0)
}
rectTool.onTap { _ in
self.selectedTool = .rectangle
rectTool.stroke = Stroke(fill: Color.blue, width: 2.0)
ellipseTool.stroke = Stroke(fill: Color.black, width: 1.0)
}
return [ellipseTool, rectTool].group()
}
}

View File

@ -0,0 +1,40 @@
//
// MorphingView.swift
// Example
//
// Created by Victor Sukochev on 25/01/2017.
// Copyright © 2017 Exyte. All rights reserved.
//
import Macaw
class MorphingView: MacawView {
required init?(coder aDecoder: NSCoder) {
super.init(node: MorphingView.newScene(), coder: aDecoder)
}
class func newScene() -> Node {
let stroke = Stroke(width: 15.0, cap: .round)
let contents1 = [
Shape(form: Line(x1: 50.0, y1: 50.0, x2: 75.0, y2: 25.0), stroke: stroke),
Shape(form: Line(x1: 50.0, y1: 50.0, x2: 125.0, y2: 50.0), stroke: stroke),
Shape(form: Line(x1: 50.0, y1: 50.0, x2: 75.0, y2: 75.0), stroke: stroke),
]
let contents2 = [
Shape(form: Line(x1: 50.0, y1: 10.0, x2: 165.0, y2: 10.0), stroke: stroke),
Shape(form: Line(x1: 50.0, y1: 50.0, x2: 165.0, y2: 50.0), stroke: stroke),
Shape(form: Line(x1: 50.0, y1: 90.0, x2: 165.0, y2: 90.0), stroke: stroke),
]
var switched = false
let group = contents1.group()
group.onTap { e in
group.contentsVar.animate(to: switched ? contents1 : contents2)
switched = !switched
}
return group
}
}

View File

@ -0,0 +1,10 @@
import UIKit
import Macaw
class SVGExampleView: MacawView {
required init?(coder aDecoder: NSCoder) {
super.init(node: SVGParser.parse(path: "tiger"), coder: aDecoder)
}
}

View File

@ -0,0 +1,79 @@
//
// CustomView.swift
// Example
//
// Created by Yuri Strot on 12/19/15.
// Copyright © 2015 Exyte. All rights reserved.
//
import Macaw
class ShapesExampleView: MacawView {
required init?(coder aDecoder: NSCoder) {
let text1 = ShapesExampleView.newText("Point", .move(dx: 100, dy: 40))
let point = Point(x: 100, y: 50).stroke(fill: Color.black, width: 7, cap: .round)
let text2 = ShapesExampleView.newText("Line", .move(dx: 250, dy: 40))
let line = Line(x1: 200, y1: 50, x2: 300, y2: 50).stroke(fill: Color.black, width: 4)
let text3 = ShapesExampleView.newText("Polyline", .move(dx: 100, dy: 90))
let polyline = Polyline(points: [100, 100, 150, 150, 50, 150]).stroke(fill: Color.navy, dashes: [3, 3])
let text4 = ShapesExampleView.newText("Polygon", .move(dx: 250, dy: 90))
let polygon = Polygon(points: [250, 100, 300, 150, 200, 150]).fill(with: Color.blue)
let text5 = ShapesExampleView.newText("Rect", .move(dx: 100, dy: 200))
let rect = Rect(x: 50, y: 210, w: 100, h: 50).fill(with: LinearGradient(
x2: 1, y2: 1,
stops: [
Stop(offset: 0, color: Color(val: 0xFFAE27)),
Stop(offset: 1, color: Color(val: 0xDE496D))
]
))
let text6 = ShapesExampleView.newText("RoundRect", .move(dx: 250, dy: 200))
let round = Rect(x: 200, y: 210, w: 100, h: 50).round(rx: 10, ry: 10).fill(with: LinearGradient(
x2: 1, y2: 1,
stops: [
Stop(offset: 0, color: Color(val: 0xDE496D)),
Stop(offset: 0.5, color: Color(val: 0xAB49DE)),
Stop(offset: 1, color: Color(val: 0x4954DE))
]
))
let text7 = ShapesExampleView.newText("Circle", .move(dx: 75, dy: 300))
let circle = Circle(cx: 75, cy: 335, r: 25).fill(with: RadialGradient(
stops: [
Stop(offset: 0, color: Color(val: 0xF5027C)),
Stop(offset: 1, color: Color(val: 0x850143))
]
))
let text8 = ShapesExampleView.newText("Ellipse", .move(dx: 175, dy: 300))
let ellipse = Ellipse(cx: 175, cy: 335, rx: 50, ry: 25).fill(with: RadialGradient(
fx: 0.05, fy: 0.05, r: 0.65,
stops: [
Stop(offset: 0, color: Color(val: 0x00ee00)),
Stop(offset: 1, color: Color(val: 0x006600))
]
))
let text9 = ShapesExampleView.newText("Arc", .move(dx: 275, dy: 300))
let arc = Circle(cx: 250, cy: 310, r: 50).arc(shift: 0, extent: Double.pi / 2.0).stroke(fill: Color.green)
let group = Group(
contents: [
point, line, polyline, polygon, rect, round, circle, ellipse, arc,
text1, text2, text3, text4, text5, text6, text7, text8, text9
]
)
super.init(node: group, coder: aDecoder)
}
fileprivate static func newText(_ text: String, _ place: Transform, baseline: Baseline = .bottom) -> Text {
return Text(text: text, fill: Color.black, align: .mid, baseline: baseline, place: place)
}
}

View File

@ -0,0 +1,70 @@
//
// TransformExampleView.swift
// Example
//
// Created by Yuri Strot on 9/10/16.
// Copyright © 2016 Exyte. All rights reserved.
//
import Foundation
import Macaw
class TransformExampleView: MacawView {
fileprivate static let transforms = [Transform.scale(sx: 2, sy: 2),
Transform.move(dx: 100, dy: 30),
Transform.rotate(angle: Double.pi / 4.0, x: 150, y: 80),
Transform.rotate(angle: Double.pi / 4.0)]
fileprivate static let titles = ["Transform.scale(sx: 2, sy: 2)",
"Transform.move(dx: 100, dy: 30)",
"Transform.rotate(angle: M_PI_4, x: 150, y: 80)",
"Transform.rotate(angle: M_PI_4)"]
required init?(coder aDecoder: NSCoder) {
super.init(node: TransformExampleView.newScene(), coder: aDecoder)
}
fileprivate static func newScene() -> Node {
let shape = Shape(form: Rect(x: 0, y: 0, w: 50, h: 50), fill: Color.blue)
let textes = Group(place: .move(dx: 50, dy: 275))
for (i, item) in titles.enumerated() {
let place = Transform.move(dx: 0, dy: Double(i * 25))
textes.contents.append(Text(text: item, baseline: .bottom, place: place, opacity: 0))
}
var combines: [Transform] = [Transform.identity]
for transform in transforms {
combines.append(GeomUtils.concat(t1: transform, t2: combines.last!))
}
var state = 0
shape.onTap { _ in
if (state < textes.contents.count) {
textes.contents[state].opacityVar.animate(from: 0.0, to: 1.0, during: 0.6)
} else {
for item in textes.contents {
item.opacityVar.animate(from: 1.0, to: 0.0, during: 0.6)
}
}
state = (state + 1) % 5;
shape.placeVar.animate(to: combines[state], during: 0.6)
}
let group = Group(contents: [newAxes(), shape, textes], place: .move(dx: 10, dy: 10))
return group
}
fileprivate static func newAxes() -> Node {
var items: [Node] = []
for i in 1...20 {
let shift = Double(i) * 50.0
items.append(Line(x1: -50, y1: shift, x2: 1000, y2: shift).stroke(fill: Color.gray))
items.append(Line(x1: shift, y1: -50, x2: shift, y2: 1000).stroke(fill: Color.gray))
}
items.append(Line(x1: -10, y1: 0, x2: 1000, y2: 0).stroke())
items.append(Line(x1: 0, y1: -10, x2: 0, y2: 1000).stroke())
return Group(contents: items)
}
}

View File

@ -0,0 +1,30 @@
<?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>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSMainStoryboardFile</key>
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@ -0,0 +1,22 @@
//
// ViewController.swift
// Example-macOS
//
// Created by Daniil Manin on 8/11/17.
//
//
import Cocoa
import Macaw
class ViewController: NSViewController {
@IBOutlet weak var mainView: EasingView!
override func viewDidLoad() {
super.viewDidLoad()
//mainView.animation.play()
}
}

5
Example-macOS/Podfile Normal file
View File

@ -0,0 +1,5 @@
use_frameworks!
target 'Example-macOS' do
pod 'Macaw', :path => '../'
end

View File

@ -0,0 +1,19 @@
PODS:
- Macaw (0.8.2):
- SWXMLHash (~> 3.0.0)
- SWXMLHash (3.0.5)
DEPENDENCIES:
- Macaw (from `../`)
EXTERNAL SOURCES:
Macaw:
:path: "../"
SPEC CHECKSUMS:
Macaw: 5bd466e34d3602084f43486abbc31fc4a8060c74
SWXMLHash: 701f7d07c032089b9ff34e0352bd4fed1a24652a
PODFILE CHECKSUM: d31ba0b2048e70405adc9fbdda765e648c849781
COCOAPODS: 1.1.1

View File

@ -69,6 +69,8 @@ class EventsExampleController: UIViewController {
return
}
print("canvas pressed:\(loc.x) \(loc.y)")
startPoint = loc
switch tool {
case .ellipse:
@ -87,6 +89,7 @@ class EventsExampleController: UIViewController {
}
canvas.onTouchMoved { event in
guard let tool = self.selectedTool else {
return
}
@ -95,6 +98,8 @@ class EventsExampleController: UIViewController {
return
}
print("canvas moving \(loc.x) \(loc.y)")
let width = loc.x - startPoint.x
let height = loc.y - startPoint.y

View File

@ -11,7 +11,7 @@ EXTERNAL SOURCES:
:path: "../"
SPEC CHECKSUMS:
Macaw: d6cc4946fab3fb7dfb588fdc6701a0c92159d763
Macaw: 5bd466e34d3602084f43486abbc31fc4a8060c74
SWXMLHash: 701f7d07c032089b9ff34e0352bd4fed1a24652a
PODFILE CHECKSUM: cf6c204dbe194da8e03fcb9ffd9c99d086057155

View File

@ -26,12 +26,13 @@ Pod::Spec.new do |s|
s.source = { :git => 'https://github.com/exyte/Macaw.git', :tag => s.version.to_s }
s.social_media_url = 'http://exyte.com'
s.platform = :ios, '8.0'
s.ios.deployment_target = "8.0"
s.osx.deployment_target = "10.12"
s.requires_arc = true
s.pod_target_xcconfig = { 'SWIFT_VERSION' => '3.0' }
s.source_files = [
'Source/**/*.*'
'Source/**/*.swift'
]
# s.resource_bundles = {
# 'Macaw' => ['Pod/Assets/*.png']

View File

@ -132,6 +132,14 @@
57E5E1B41E3B393900D1CB28 /* ShapeLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1521E3B393900D1CB28 /* ShapeLayer.swift */; };
57FCD2771D76EA4600CC0FB6 /* Macaw.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57FCD26C1D76EA4600CC0FB6 /* Macaw.framework */; };
57FCD27C1D76EA4600CC0FB6 /* MacawTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57FCD27B1D76EA4600CC0FB6 /* MacawTests.swift */; };
A718CD441F45C28200966E06 /* Common_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD431F45C28200966E06 /* Common_iOS.swift */; };
A718CD471F45C28700966E06 /* Graphics_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD451F45C28700966E06 /* Graphics_iOS.swift */; };
A718CD481F45C28700966E06 /* MView_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD461F45C28700966E06 /* MView_iOS.swift */; };
A718CD4D1F45C28F00966E06 /* Common_macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD491F45C28F00966E06 /* Common_macOS.swift */; };
A718CD4E1F45C28F00966E06 /* Graphics_macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD4A1F45C28F00966E06 /* Graphics_macOS.swift */; };
A718CD4F1F45C28F00966E06 /* MDisplayLink_macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD4B1F45C28F00966E06 /* MDisplayLink_macOS.swift */; };
A718CD501F45C28F00966E06 /* MView_macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD4C1F45C28F00966E06 /* MView_macOS.swift */; };
A718CD521F45C2A400966E06 /* MBezierPath+Extension_macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD511F45C2A400966E06 /* MBezierPath+Extension_macOS.swift */; };
A7E675561EC4213500BD9ECB /* NodeBoundsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7E675551EC4213500BD9ECB /* NodeBoundsTests.swift */; };
/* End PBXBuildFile section */
@ -286,6 +294,14 @@
57FCD2761D76EA4600CC0FB6 /* MacawTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MacawTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
57FCD27B1D76EA4600CC0FB6 /* MacawTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacawTests.swift; sourceTree = "<group>"; };
57FCD27D1D76EA4600CC0FB6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A718CD431F45C28200966E06 /* Common_iOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Common_iOS.swift; path = Source/platform/iOS/Common_iOS.swift; sourceTree = SOURCE_ROOT; };
A718CD451F45C28700966E06 /* Graphics_iOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Graphics_iOS.swift; path = Source/platform/iOS/Graphics_iOS.swift; sourceTree = SOURCE_ROOT; };
A718CD461F45C28700966E06 /* MView_iOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MView_iOS.swift; path = Source/platform/iOS/MView_iOS.swift; sourceTree = SOURCE_ROOT; };
A718CD491F45C28F00966E06 /* Common_macOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Common_macOS.swift; path = Source/platform/macOS/Common_macOS.swift; sourceTree = SOURCE_ROOT; };
A718CD4A1F45C28F00966E06 /* Graphics_macOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Graphics_macOS.swift; path = Source/platform/macOS/Graphics_macOS.swift; sourceTree = SOURCE_ROOT; };
A718CD4B1F45C28F00966E06 /* MDisplayLink_macOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MDisplayLink_macOS.swift; path = Source/platform/macOS/MDisplayLink_macOS.swift; sourceTree = SOURCE_ROOT; };
A718CD4C1F45C28F00966E06 /* MView_macOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MView_macOS.swift; path = Source/platform/macOS/MView_macOS.swift; sourceTree = SOURCE_ROOT; };
A718CD511F45C2A400966E06 /* MBezierPath+Extension_macOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "MBezierPath+Extension_macOS.swift"; path = "Source/platform/macOS/MBezierPath+Extension_macOS.swift"; sourceTree = SOURCE_ROOT; };
A7E675551EC4213500BD9ECB /* NodeBoundsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NodeBoundsTests.swift; path = Bounds/NodeBoundsTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -621,6 +637,7 @@
57FCD26E1D76EA4600CC0FB6 /* Macaw */ = {
isa = PBXGroup;
children = (
A718CD2C1F45BC5300966E06 /* Platform */,
572CEFC31E2CED4B008C7C83 /* Dependencies */,
57E5E0E01E3B393900D1CB28 /* Source */,
);
@ -640,6 +657,37 @@
path = MacawTests;
sourceTree = "<group>";
};
A718CD2C1F45BC5300966E06 /* Platform */ = {
isa = PBXGroup;
children = (
A718CD361F45BD0B00966E06 /* iOS */,
A718CD351F45BCF800966E06 /* macOS */,
);
name = Platform;
sourceTree = "<group>";
};
A718CD351F45BCF800966E06 /* macOS */ = {
isa = PBXGroup;
children = (
A718CD491F45C28F00966E06 /* Common_macOS.swift */,
A718CD4A1F45C28F00966E06 /* Graphics_macOS.swift */,
A718CD4B1F45C28F00966E06 /* MDisplayLink_macOS.swift */,
A718CD4C1F45C28F00966E06 /* MView_macOS.swift */,
A718CD511F45C2A400966E06 /* MBezierPath+Extension_macOS.swift */,
);
name = macOS;
sourceTree = "<group>";
};
A718CD361F45BD0B00966E06 /* iOS */ = {
isa = PBXGroup;
children = (
A718CD431F45C28200966E06 /* Common_iOS.swift */,
A718CD451F45C28700966E06 /* Graphics_iOS.swift */,
A718CD461F45C28700966E06 /* MView_iOS.swift */,
);
name = iOS;
sourceTree = "<group>";
};
A7E675541EC4211E00BD9ECB /* Bounds */ = {
isa = PBXGroup;
children = (
@ -708,7 +756,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0730;
LastUpgradeCheck = 0820;
LastUpgradeCheck = 0830;
ORGANIZATIONNAME = Exyte;
TargetAttributes = {
57FCD26B1D76EA4600CC0FB6 = {
@ -717,7 +765,9 @@
};
57FCD2751D76EA4600CC0FB6 = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = 7T95R85V93;
LastSwiftMigration = 0800;
ProvisioningStyle = Automatic;
};
};
};
@ -784,14 +834,17 @@
57E5E1B31E3B393900D1CB28 /* NodesMap.swift in Sources */,
57E5E1A71E3B393900D1CB28 /* RenderUtils.swift in Sources */,
57E5E1601E3B393900D1CB28 /* FuncBounds.swift in Sources */,
A718CD481F45C28700966E06 /* MView_iOS.swift in Sources */,
57E5E15B1E3B393900D1CB28 /* DoubleInterpolation.swift in Sources */,
57E5E1961E3B393900D1CB28 /* PathSegmentType.swift in Sources */,
57E5E1531E3B393900D1CB28 /* AnimatableVariable.swift in Sources */,
57E5E1691E3B393900D1CB28 /* TimingFunction.swift in Sources */,
57E5E1631E3B393900D1CB28 /* AnimationCache.swift in Sources */,
57E5E19D1E3B393900D1CB28 /* Transform.swift in Sources */,
A718CD4E1F45C28F00966E06 /* Graphics_macOS.swift in Sources */,
57E5E1A81E3B393900D1CB28 /* ShapeRenderer.swift in Sources */,
57E5E1851E3B393900D1CB28 /* LinearGradient.swift in Sources */,
A718CD4F1F45C28F00966E06 /* MDisplayLink_macOS.swift in Sources */,
57E5E1721E3B393900D1CB28 /* GroupDisposable.swift in Sources */,
57E5E18A1E3B393900D1CB28 /* Stroke.swift in Sources */,
57E5E1781E3B393900D1CB28 /* TapEvent.swift in Sources */,
@ -832,6 +885,7 @@
57E5E1561E3B393900D1CB28 /* AnimationProducer.swift in Sources */,
57E5E1811E3B393900D1CB28 /* Fill.swift in Sources */,
57A27BD51E44C5840057BD3A /* ShapeInterpolation.swift in Sources */,
A718CD471F45C28700966E06 /* Graphics_iOS.swift in Sources */,
57E5E1871E3B393900D1CB28 /* LineJoin.swift in Sources */,
57E5E1881E3B393900D1CB28 /* RadialGradient.swift in Sources */,
57E5E1891E3B393900D1CB28 /* Stop.swift in Sources */,
@ -841,6 +895,8 @@
57E5E1991E3B393900D1CB28 /* Polyline.swift in Sources */,
57E5E16D1E3B393900D1CB28 /* ContentsAnimation.swift in Sources */,
5713C4E21E51EC8F00BBA4D9 /* TouchEvent.swift in Sources */,
A718CD521F45C2A400966E06 /* MBezierPath+Extension_macOS.swift in Sources */,
A718CD501F45C28F00966E06 /* MView_macOS.swift in Sources */,
57E5E1581E3B393900D1CB28 /* Easing.swift in Sources */,
57E5E1971E3B393900D1CB28 /* Point.swift in Sources */,
57E5E1681E3B393900D1CB28 /* OpacityGenerator.swift in Sources */,
@ -852,6 +908,8 @@
57E5E18E1E3B393900D1CB28 /* GeomUtils.swift in Sources */,
57E5E1AF1E3B393900D1CB28 /* CAAnimationClosure.swift in Sources */,
57E5E17F1E3B393900D1CB28 /* DropShadow.swift in Sources */,
A718CD441F45C28200966E06 /* Common_iOS.swift in Sources */,
A718CD4D1F45C28F00966E06 /* Common_macOS.swift in Sources */,
57E5E1641E3B393900D1CB28 /* AnimationRestorer.swift in Sources */,
57E5E1741E3B393900D1CB28 /* Event.swift in Sources */,
57E5E1841E3B393900D1CB28 /* Gradient.swift in Sources */,
@ -933,6 +991,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@ -948,12 +1007,16 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "";
MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SDKROOT = macosx;
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = "x86_64 i386";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
@ -985,6 +1048,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@ -994,12 +1058,16 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "";
MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SDKROOT = macosx;
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VALID_ARCHS = "x86_64 i386";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
@ -1008,42 +1076,46 @@
57FCD2811D76EA4600CC0FB6 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = NO;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
FRAMEWORK_SEARCH_PATHS = "";
GCC_PRECOMPILE_PREFIX_HEADER = NO;
INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "";
OTHER_SWIFT_FLAGS = "-D CARTHAGE";
PRODUCT_BUNDLE_IDENTIFIER = com.exyte.Macaw;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2,3,4";
};
name = Debug;
};
57FCD2821D76EA4600CC0FB6 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = NO;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
FRAMEWORK_SEARCH_PATHS = "";
GCC_PRECOMPILE_PREFIX_HEADER = NO;
INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "";
OTHER_SWIFT_FLAGS = "-D CARTHAGE";
PRODUCT_BUNDLE_IDENTIFIER = com.exyte.Macaw;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2,3,4";
};
name = Release;
};
@ -1051,11 +1123,22 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEVELOPMENT_TEAM = 7T95R85V93;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SDKROOT)",
);
INFOPLIST_FILE = MacawTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.exyte.MacawTests;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx10.12;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2,3,4";
VALID_ARCHS = "x86_64 i386";
};
name = Debug;
};
@ -1063,11 +1146,22 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEVELOPMENT_TEAM = 7T95R85V93;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SDKROOT)",
);
INFOPLIST_FILE = MacawTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.exyte.MacawTests;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx10.12;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2,3,4";
VALID_ARCHS = "x86_64 i386";
};
name = Release;
};

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0820"
LastUpgradeVersion = "0830"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -28,26 +28,7 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "57FCD2751D76EA4600CC0FB6"
BuildableName = "MacawTests.xctest"
BlueprintName = "MacawTests"
ReferencedContainer = "container:Macaw.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "57FCD26B1D76EA4600CC0FB6"
BuildableName = "Macaw.framework"
BlueprintName = "Macaw"
ReferencedContainer = "container:Macaw.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0830"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "57FCD2751D76EA4600CC0FB6"
BuildableName = "MacawTests.xctest"
BlueprintName = "MacawTests"
ReferencedContainer = "container:Macaw.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -52,12 +52,12 @@ class ImageBoundsTests: XCTestCase {
func testInMemoryImage() {
let bundle = Bundle(for: type(of: TestUtils()))
guard let uiImage = UIImage(named: "logo.png", in: bundle, compatibleWith: .none) else {
guard let mImage = MImage(named: "logo.png", in: bundle, compatibleWith: .none) else {
XCTFail()
return
}
let image = Image(image: uiImage)
let image = Image(image: mImage)
guard let bounds = image.bounds() else {
XCTFail("Bounds not available")
return

View File

@ -144,7 +144,7 @@ class NodeBoundsTests: XCTestCase {
texts.forEach { text in
let text = Text(text: text)
let stringAttributes = [NSFontAttributeName: UIFont.systemFont(ofSize: UIFont.systemFontSize)]
let stringAttributes = [NSFontAttributeName: MFont.systemFont(ofSize: MFont.systemFontSize)]
let size = text.text.size(attributes: stringAttributes)
let targetRect = Rect(x: 0.0, y: 0.0, w: size.width.doubleValue, h: size.height.doubleValue)

View File

@ -8,7 +8,6 @@
import Foundation
open class AnimatableVariable<T>: Variable<T> {
weak internal var node: Node?
weak internal var node: Node?
}

View File

@ -1,53 +1,53 @@
public enum AnimationState {
case initial
case running
case paused
case initial
case running
case paused
}
public class Animation {
internal init() {
}
public func play() {
}
public func stop() {
}
public func pause() {
}
internal init() {
}
public func play() {
}
public func stop() {
}
public func pause() {
public func state() -> AnimationState {
return .initial
}
public func easing(_ easing: Easing) -> Animation {
return self
}
public func delay(_ delay: Double) -> Animation {
return self
}
public func cycle(_ count: Double) -> Animation {
return self
}
public func cycle() -> Animation{
return self
}
public func reverse() -> Animation {
return self
}
public func autoreversed() -> Animation {
return self
}
@discardableResult public func onComplete(_: @escaping (() -> ())) -> Animation {
return self
}
}
public func state() -> AnimationState {
return .initial
}
public func easing(_ easing: Easing) -> Animation {
return self
}
public func delay(_ delay: Double) -> Animation {
return self
}
public func cycle(_ count: Double) -> Animation {
return self
}
public func cycle() -> Animation{
return self
}
public func reverse() -> Animation {
return self
}
public func autoreversed() -> Animation {
return self
}
@discardableResult public func onComplete(_: @escaping (() -> ())) -> Animation {
return self
}
}

View File

@ -1,4 +1,10 @@
import UIKit
import Foundation
#if os(iOS)
import UIKit
#elseif os(OSX)
import AppKit
#endif
let animationProducer = AnimationProducer()
@ -7,7 +13,7 @@ class AnimationProducer {
var storedAnimations = [Node: BasicAnimation]()
var delayedAnimations = [BasicAnimation: Timer]()
var displayLink: CADisplayLink?
var displayLink: MDisplayLink?
struct ContentAnimationDesc {
let animation: ContentsAnimation
@ -70,6 +76,11 @@ class AnimationProducer {
storedAnimations[node] = animation
return
}
guard let layer = macawView.mLayer else {
return
}
guard let cache = macawView.animationCache else {
return
@ -79,14 +90,14 @@ class AnimationProducer {
case .unknown:
return
case .affineTransformation:
addTransformAnimation(animation, sceneLayer: macawView.layer, animationCache: cache, completion: {
addTransformAnimation(animation, sceneLayer: layer, animationCache: cache, completion: {
if let next = animation.next {
self.addAnimation(next)
}
})
case .opacity:
addOpacityAnimation(animation, sceneLayer: macawView.layer, animationCache: cache, completion: {
addOpacityAnimation(animation, sceneLayer: layer, animationCache: cache, completion: {
if let next = animation.next {
self.addAnimation(next)
}
@ -102,13 +113,13 @@ class AnimationProducer {
}
})
case .morphing:
addMorphingAnimation(animation, sceneLayer: macawView.layer, animationCache: cache, completion: {
addMorphingAnimation(animation, sceneLayer: layer, animationCache: cache, completion: {
if let next = animation.next {
self.addAnimation(next)
}
})
case .shape:
addShapeAnimation(animation, sceneLayer: macawView.layer, animationCache: cache, completion: {
addShapeAnimation(animation, sceneLayer: layer, animationCache: cache, completion: {
if let next = animation.next {
self.addAnimation(next)
}
@ -317,9 +328,9 @@ class AnimationProducer {
contentsAnimations.append(animationDesc)
if displayLink == .none {
displayLink = CADisplayLink(target: self, selector: #selector(updateContentAnimations))
displayLink?.frameInterval = 1
if displayLink == nil {
displayLink = MDisplayLink(target: self, selector: #selector(updateContentAnimations))
//displayLink?.frameInterval = 1
displayLink?.add(to: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
}
}

View File

@ -1,104 +1,103 @@
import Foundation
class AnimationUtils {
class func absolutePosition(_ node: Node) -> Transform {
return AnimationUtils.absoluteTransform(node, pos: node.place)
}
class func absoluteTransform(_ node: Node, pos: Transform) -> Transform {
var transform = pos
var parent = nodesMap.parents(node).first
while parent != .none {
transform = GeomUtils.concat(t1: parent!.place, t2: transform)
parent = nodesMap.parents(parent!).first
}
return transform
}
class func absoluteClip(node: Node) -> Locus? {
if let _ = node.clip {
return node.clip
}
var parent = nodesMap.parents(node).first
while parent != .none {
if let _ = parent?.clip {
return parent?.clip
}
parent = nodesMap.parents(parent!).first
}
return .none
class func absolutePosition(_ node: Node) -> Transform {
return AnimationUtils.absoluteTransform(node, pos: node.place)
}
class func absoluteTransform(_ node: Node, pos: Transform) -> Transform {
var transform = pos
var parent = nodesMap.parents(node).first
while parent != .none {
transform = GeomUtils.concat(t1: parent!.place, t2: transform)
parent = nodesMap.parents(parent!).first
}
private static var indexCache = [Node: Int]()
class func absoluteIndex(_ node: Node, useCache: Bool = false) -> Int {
if useCache {
if let cachedIndex = indexCache[node] {
return cachedIndex
}
} else {
indexCache.removeAll()
}
func childrenTotalCount(_ node: Node) -> Int{
guard let group = node as? Group else {
return 1
}
var count = 1
for child in group.contents {
count += childrenTotalCount(child)
}
return count
}
var zIndex = 0
var parent = nodesMap.parents(node).first
var currentNode = node
while parent != .none {
if let group = parent as? Group {
let localIndex = group.contents.index(of: currentNode) ?? group.contents.count
for i in 0..<localIndex {
zIndex += childrenTotalCount(group.contents[i])
}
}
zIndex += 1
currentNode = parent!
parent = nodesMap.parents(parent!).first
}
if useCache {
indexCache[node] = zIndex
}
return zIndex
return transform
}
class func absoluteClip(node: Node) -> Locus? {
if let _ = node.clip {
return node.clip
}
class func animatedNodes(root: Node, animationCache: AnimationCache) -> [Node] {
if animationCache.isAnimating(root) {
return [root]
}
guard let rootGroup = root as? Group else {
return []
}
var result = [Node]()
rootGroup.contents.forEach { child in
let childAnimatedNodes = animatedNodes(root: child, animationCache: animationCache)
result.append(contentsOf: childAnimatedNodes)
}
return result
var parent = nodesMap.parents(node).first
while parent != .none {
if let _ = parent?.clip {
return parent?.clip
}
parent = nodesMap.parents(parent!).first
}
return .none
}
private static var indexCache = [Node: Int]()
class func absoluteIndex(_ node: Node, useCache: Bool = false) -> Int {
if useCache {
if let cachedIndex = indexCache[node] {
return cachedIndex
}
} else {
indexCache.removeAll()
}
func childrenTotalCount(_ node: Node) -> Int{
guard let group = node as? Group else {
return 1
}
var count = 1
for child in group.contents {
count += childrenTotalCount(child)
}
return count
}
var zIndex = 0
var parent = nodesMap.parents(node).first
var currentNode = node
while parent != .none {
if let group = parent as? Group {
let localIndex = group.contents.index(of: currentNode) ?? group.contents.count
for i in 0..<localIndex {
zIndex += childrenTotalCount(group.contents[i])
}
}
zIndex += 1
currentNode = parent!
parent = nodesMap.parents(parent!).first
}
if useCache {
indexCache[node] = zIndex
}
return zIndex
}
class func animatedNodes(root: Node, animationCache: AnimationCache) -> [Node] {
if animationCache.isAnimating(root) {
return [root]
}
guard let rootGroup = root as? Group else {
return []
}
var result = [Node]()
rootGroup.contents.forEach { child in
let childAnimatedNodes = animatedNodes(root: child, animationCache: animationCache)
result.append(contentsOf: childAnimatedNodes)
}
return result
}
}

View File

@ -7,9 +7,9 @@
//
public enum Easing {
case ease
case linear
case easeIn
case easeOut
case easeInOut
case ease
case linear
case easeIn
case easeOut
case easeInOut
}

View File

@ -1,38 +1,42 @@
import UIKit
import Foundation
#if os(iOS)
import UIKit
#endif
public extension Rect {
convenience init(cgRect: CGRect) {
self.init(
x: Double(cgRect.origin.x),
y: Double(cgRect.origin.y),
w: Double(cgRect.size.width),
h: Double(cgRect.size.height))
}
func cgRect() -> CGRect {
return CGRect(x: self.x, y: self.y, width: self.w, height: self.h)
}
func applyTransform(_ transform: Transform) -> Rect {
// TODO: Rewrite using math
let cgTransform = RenderUtils.mapTransform(transform)
return Rect(cgRect: self.cgRect().applying(cgTransform))
}
public func description() -> String {
return "x: \(self.x) y:\(self.y) w:\(self.w) h:\(self.h)"
}
convenience init(cgRect: CGRect) {
self.init(
x: Double(cgRect.origin.x),
y: Double(cgRect.origin.y),
w: Double(cgRect.size.width),
h: Double(cgRect.size.height))
}
func cgRect() -> CGRect {
return CGRect(x: self.x, y: self.y, width: self.w, height: self.h)
}
func applyTransform(_ transform: Transform) -> Rect {
// TODO: Rewrite using math
let cgTransform = RenderUtils.mapTransform(transform)
return Rect(cgRect: self.cgRect().applying(cgTransform))
}
public func description() -> String {
return "x: \(self.x) y:\(self.y) w:\(self.w) h:\(self.h)"
}
}
public extension Point {
public func cgPoint() -> CGPoint {
return CGPoint(x: self.x, y: self.y)
}
public func description() -> String {
return "x: \(self.x) y:\(self.y)"
}
public func cgPoint() -> CGPoint {
return CGPoint(x: self.x, y: self.y)
}
public func description() -> String {
return "x: \(self.x) y:\(self.y)"
}
}

View File

@ -1,25 +1,24 @@
import Foundation
public func >> (a: Double, b: Double) -> OpacityAnimationDescription {
return OpacityAnimationDescription(valueFunc: { t in
return a.interpolate(b, progress: t)
})
return OpacityAnimationDescription(valueFunc: { t in
return a.interpolate(b, progress: t)
})
}
public func >> (a: Transform, b: Transform) -> TransformAnimationDescription {
return TransformAnimationDescription(valueFunc: { t in
return a.interpolate(b, progress: t)
})
return TransformAnimationDescription(valueFunc: { t in
return a.interpolate(b, progress: t)
})
}
public func >> (a: Locus, b: Locus) -> MorphingAnimationDescription {
return MorphingAnimationDescription(valueFunc: { t in
// return a.interpolate(b, progress: t)
if t == 0.0 {
return a
}
return b
})
return MorphingAnimationDescription(valueFunc: { t in
// return a.interpolate(b, progress: t)
if t == 0.0 {
return a
}
return b
})
}

View File

@ -1,9 +1,9 @@
public protocol ContentsInterpolation: Interpolable {
}
extension Array: ContentsInterpolation {
public func interpolate(_ endValue: Array, progress: Double) -> Array {
return self
}
public func interpolate(_ endValue: Array, progress: Double) -> Array {
return self
}
}

View File

@ -1,10 +1,9 @@
public protocol DoubleInterpolation: Interpolable {
}
extension Double: DoubleInterpolation {
public func interpolate(_ endValue: Double, progress: Double) -> Double {
return self + (endValue - self) * progress
}
public func interpolate(_ endValue: Double, progress: Double) -> Double {
return self + (endValue - self) * progress
}
}

View File

@ -1,10 +1,9 @@
public protocol LocusInterpolation: Interpolable {
}
extension Locus: LocusInterpolation {
public func interpolate(_ endValue: Locus, progress: Double) -> Self {
return self
}
public func interpolate(_ endValue: Locus, progress: Double) -> Self {
return self
}
}

View File

@ -7,11 +7,11 @@
//
public protocol ShapeInterpolation: Interpolable {
}
extension Shape: ShapeInterpolation {
public func interpolate(_ endValue: Shape, progress: Double) -> Self {
return self
}
public func interpolate(_ endValue: Shape, progress: Double) -> Self {
return self
}
}

View File

@ -1,15 +1,15 @@
public protocol TransformInterpolation: Interpolable {
}
extension Transform: TransformInterpolation {
public func interpolate(_ endValue: Transform, progress: Double) -> Transform {
return Transform(m11: self.m11.interpolate(endValue.m11, progress: progress),
m12: self.m12.interpolate(endValue.m12, progress: progress),
m21: self.m21.interpolate(endValue.m21, progress: progress),
m22: self.m22.interpolate(endValue.m22, progress: progress),
dx: self.dx.interpolate(endValue.dx, progress: progress),
dy: self.dy.interpolate(endValue.dy, progress: progress))
}
public func interpolate(_ endValue: Transform, progress: Double) -> Transform {
return Transform(m11: self.m11.interpolate(endValue.m11, progress: progress),
m12: self.m12.interpolate(endValue.m12, progress: progress),
m21: self.m21.interpolate(endValue.m21, progress: progress),
m22: self.m22.interpolate(endValue.m22, progress: progress),
dx: self.dx.interpolate(endValue.dx, progress: progress),
dy: self.dy.interpolate(endValue.dy, progress: progress))
}
}

View File

@ -1,32 +1,31 @@
func boundsForFunc(_ func2d: func2D) -> Rect {
var p = func2d(0.0)
var minX = p.x
var minY = p.y
var maxX = minX
var maxY = minY
for t in stride(from: 0.0, to: 1.0, by: 0.01) {
p = func2d(t)
if minX > p.x {
minX = p.x
}
if minY > p.y {
minY = p.y
}
if maxX < p.x {
maxX = p.x
}
if maxY < p.y {
maxY = p.y
}
}
return Rect(x: minX, y: minY, w: maxX - minX, h: maxY - minY)
var p = func2d(0.0)
var minX = p.x
var minY = p.y
var maxX = minX
var maxY = minY
for t in stride(from: 0.0, to: 1.0, by: 0.01) {
p = func2d(t)
if minX > p.x {
minX = p.x
}
if minY > p.y {
minY = p.y
}
if maxX < p.x {
maxX = p.x
}
if maxY < p.y {
maxY = p.y
}
}
return Rect(x: minX, y: minY, w: maxX - minX, h: maxY - minY)
}

View File

@ -1,107 +1,107 @@
func pathBounds(_ path: Path) -> Rect? {
guard let firstSegment = path.segments.first else {
return .none
}
let firstSegmentInfo = pathSegmenInfo(firstSegment, currentPoint: .none, currentBezierPoint: .none)
var bounds = firstSegmentInfo.0
var currentPoint = firstSegmentInfo.1 ?? Point.origin
var cubicBezierPoint: Point?
for segment in path.segments {
let segmentInfo = pathSegmenInfo(segment, currentPoint: currentPoint, currentBezierPoint: cubicBezierPoint)
if let segmentBounds = segmentInfo.0 {
if segment.isAbsolute() {
bounds = bounds?.union(rect: segmentBounds)
} else {
bounds = bounds?.union(rect: segmentBounds.move(offset: currentPoint))
}
}
if let segmentLastPoint = segmentInfo.1 {
if segment.isAbsolute() {
currentPoint = segmentLastPoint
} else {
currentPoint = segmentLastPoint.add(currentPoint)
}
}
if let segmentBezierPoint = segmentInfo.2 {
if segment.isAbsolute() {
cubicBezierPoint = segmentBezierPoint
} else {
cubicBezierPoint = segmentBezierPoint.add(currentPoint)
}
}
}
return bounds
guard let firstSegment = path.segments.first else {
return .none
}
let firstSegmentInfo = pathSegmenInfo(firstSegment, currentPoint: .none, currentBezierPoint: .none)
var bounds = firstSegmentInfo.0
var currentPoint = firstSegmentInfo.1 ?? Point.origin
var cubicBezierPoint: Point?
for segment in path.segments {
let segmentInfo = pathSegmenInfo(segment, currentPoint: currentPoint, currentBezierPoint: cubicBezierPoint)
if let segmentBounds = segmentInfo.0 {
if segment.isAbsolute() {
bounds = bounds?.union(rect: segmentBounds)
} else {
bounds = bounds?.union(rect: segmentBounds.move(offset: currentPoint))
}
}
if let segmentLastPoint = segmentInfo.1 {
if segment.isAbsolute() {
currentPoint = segmentLastPoint
} else {
currentPoint = segmentLastPoint.add(currentPoint)
}
}
if let segmentBezierPoint = segmentInfo.2 {
if segment.isAbsolute() {
cubicBezierPoint = segmentBezierPoint
} else {
cubicBezierPoint = segmentBezierPoint.add(currentPoint)
}
}
}
return bounds
}
func pathSegmenInfo(_ segment: PathSegment, currentPoint: Point?, currentBezierPoint: Point?)
-> (Rect?, Point?, Point?) { // Bounds, last point, last bezier point TODO: Replace as struct
let data = segment.data
switch segment.type {
case .m, .M:
let point = Point(x: data[0], y: data[1])
return (Rect(x: point.x, y: point.y, w: 0.0, h: 0.0), point, .none)
case .c, .C:
return (cubicBounds(data), Point(x: data[4], y: data[5]), Point(x: data[2], y: data[3]))
case .s, .S:
guard let currentPoint = currentPoint else {
return (.none, .none, .none)
}
var p2 = currentPoint
if let bezierPoint = currentBezierPoint {
p2 = Point(
x: 2.0 * currentPoint.x - bezierPoint.x,
y: 2.0 * currentPoint.y - bezierPoint.y)
}
return (sCubicBounds(data, currentPoint: currentPoint, currentBezierPoint: currentBezierPoint),
Point(x: data[2], y: data[3]),
Point(x: p2.x, y: p2.y))
case .h, .H:
return (Rect(x: 0.0, y: 0.0, w: data[0], h: 0.0), Point(x: data[0], y: 0.0), .none)
case .v, .V:
return (Rect(x: 0.0, y: 0.0, w: 0.0, h: data[0]), Point(x: 0.0, y: data[0]), .none)
case .l, .L:
return (Rect(x: data[0], y: data[1], w: 0.0, h: 0.0), Point(x: data[0], y: data[1]), .none)
default:
return (.none, .none, .none)
}
-> (Rect?, Point?, Point?) { // Bounds, last point, last bezier point TODO: Replace as struct
let data = segment.data
switch segment.type {
case .m, .M:
let point = Point(x: data[0], y: data[1])
return (Rect(x: point.x, y: point.y, w: 0.0, h: 0.0), point, .none)
case .c, .C:
return (cubicBounds(data), Point(x: data[4], y: data[5]), Point(x: data[2], y: data[3]))
case .s, .S:
guard let currentPoint = currentPoint else {
return (.none, .none, .none)
}
var p2 = currentPoint
if let bezierPoint = currentBezierPoint {
p2 = Point(
x: 2.0 * currentPoint.x - bezierPoint.x,
y: 2.0 * currentPoint.y - bezierPoint.y)
}
return (sCubicBounds(data, currentPoint: currentPoint, currentBezierPoint: currentBezierPoint),
Point(x: data[2], y: data[3]),
Point(x: p2.x, y: p2.y))
case .h, .H:
return (Rect(x: 0.0, y: 0.0, w: data[0], h: 0.0), Point(x: data[0], y: 0.0), .none)
case .v, .V:
return (Rect(x: 0.0, y: 0.0, w: 0.0, h: data[0]), Point(x: 0.0, y: data[0]), .none)
case .l, .L:
return (Rect(x: data[0], y: data[1], w: 0.0, h: 0.0), Point(x: data[0], y: data[1]), .none)
default:
return (.none, .none, .none)
}
}
private func cubicBounds(_ data: [Double]) -> Rect {
let p0 = Point(x: 0, y: 0)
let p1 = Point(x: data[0], y: data[1])
let p2 = Point(x: data[2], y: data[3])
let p3 = Point(x: data[4], y: data[5])
let bezier3 = { (t: Double) -> Point in return BezierFunc2D(t, p0: p0, p1: p1, p2: p2, p3: p3) }
// TODO: Replace with accurate implementation via derivative
return boundsForFunc(bezier3)
let p0 = Point(x: 0, y: 0)
let p1 = Point(x: data[0], y: data[1])
let p2 = Point(x: data[2], y: data[3])
let p3 = Point(x: data[4], y: data[5])
let bezier3 = { (t: Double) -> Point in return BezierFunc2D(t, p0: p0, p1: p1, p2: p2, p3: p3) }
// TODO: Replace with accurate implementation via derivative
return boundsForFunc(bezier3)
}
private func sCubicBounds(_ data: [Double], currentPoint: Point, currentBezierPoint: Point?) -> Rect {
let p0 = Point(x: 0, y: 0)
let p1 = Point(x: data[0], y: data[1])
let p3 = Point(x: data[2], y: data[3])
var p2 = currentPoint
if let bezierPoint = currentBezierPoint {
p2 = Point(
x: 2.0 * currentPoint.x - bezierPoint.x,
y: 2.0 * currentPoint.y - bezierPoint.y)
}
let bezier3 = { (t: Double) -> Point in return BezierFunc2D(t, p0: p0, p1: p1, p2: p2, p3: p3) }
// TODO: Replace with accurate implementation via derivative
return boundsForFunc(bezier3)
let p0 = Point(x: 0, y: 0)
let p1 = Point(x: data[0], y: data[1])
let p3 = Point(x: data[2], y: data[3])
var p2 = currentPoint
if let bezierPoint = currentBezierPoint {
p2 = Point(
x: 2.0 * currentPoint.x - bezierPoint.x,
y: 2.0 * currentPoint.y - bezierPoint.y)
}
let bezier3 = { (t: Double) -> Point in return BezierFunc2D(t, p0: p0, p1: p1, p2: p2, p3: p3) }
// TODO: Replace with accurate implementation via derivative
return boundsForFunc(bezier3)
}

View File

@ -3,12 +3,12 @@ import Foundation
typealias func2D = ((_ t: Double) -> (Point))
func BezierFunc2D(_ t: Double, p0: Point, p1: Point, p2: Point, p3: Point) -> Point {
return Point(
x: polynom3(t, p0: p0.x, p1: p1.x, p2: p2.x, p3: p3.x),
y: polynom3(t, p0: p0.y, p1: p1.y, p2: p2.y, p3: p3.y))
return Point(
x: polynom3(t, p0: p0.x, p1: p1.x, p2: p2.x, p3: p3.x),
y: polynom3(t, p0: p0.y, p1: p1.y, p2: p2.y, p3: p3.y))
}
func polynom3(_ t: Double, p0: Double, p1: Double, p2: Double, p3: Double) -> Double {
let t1 = 1.0 - t
return pow(t1, 3.0) * p0 + 3.0 * t * pow(t1, 2.0) * p1 + 3.0 * t * t * t1 * p2 + pow(t, 3.0) * p3
let t1 = 1.0 - t
return pow(t1, 3.0) * p0 + 3.0 * t * pow(t1, 2.0) * p1 + 3.0 * t * t * t1 * p2 + pow(t, 3.0) * p3
}

View File

@ -1,189 +1,196 @@
import Foundation
import UIKit
#if os(iOS)
import UIKit
#elseif os(OSX)
import AppKit
#endif
class AnimationCache {
class CachedLayer {
let layer: ShapeLayer
let animation: Animation
var linksCounter = 1
required init(layer: ShapeLayer, animation: Animation) {
self.layer = layer
self.animation = animation
}
}
let sceneLayer: CALayer
var layerCache = [Node: CachedLayer]()
required init(sceneLayer: CALayer) {
self.sceneLayer = sceneLayer
}
func layerForNode(_ node: Node, animation: Animation, customBounds: Rect? = .none, shouldRenderContent: Bool = true) -> ShapeLayer {
guard let cachedLayer = layerCache[node] else {
let layer = ShapeLayer()
layer.shouldRenderContent = shouldRenderContent
layer.animationCache = self
// Use to debug animation layers
// layer.backgroundColor = UIColor.green.cgColor
// layer.borderWidth = 1.0
// layer.borderColor = UIColor.blue.cgColor
let calculatedBounds = customBounds ?? node.bounds()
if let shapeBounds = calculatedBounds {
let cgRect = shapeBounds.cgRect()
let origFrame = CGRect(x: 0.0, y: 0.0,
width: round(cgRect.width),
height: round(cgRect.height))
layer.bounds = origFrame
layer.anchorPoint = CGPoint(
x: -1.0 * cgRect.origin.x / cgRect.width,
y: -1.0 * cgRect.origin.y / cgRect.height
)
layer.zPosition = CGFloat(AnimationUtils.absoluteIndex(node))
layer.renderTransform = CGAffineTransform(translationX: -1.0 * cgRect.origin.x, y: -1.0 * cgRect.origin.y)
let nodeTransform = RenderUtils.mapTransform(AnimationUtils.absolutePosition(node))
layer.transform = CATransform3DMakeAffineTransform(nodeTransform)
// Clip
if let clip = AnimationUtils.absoluteClip(node: node) {
let maskLayer = CAShapeLayer()
let origPath = RenderUtils.toBezierPath(clip).cgPath
var offsetTransform = CGAffineTransform(translationX: -1.0 * cgRect.origin.x, y: -1.0 * cgRect.origin.y)
let clipPath = origPath.mutableCopy(using: &offsetTransform)
maskLayer.path = clipPath
layer.mask = maskLayer
}
}
layer.opacity = Float(node.opacity)
layer.node = node
layer.contentsScale = calculateAnimationScale(animation: animation)
layer.setNeedsDisplay()
sceneLayer.addSublayer(layer)
layerCache[node] = CachedLayer(layer: layer, animation: animation)
sceneLayer.setNeedsDisplay()
return layer
}
cachedLayer.linksCounter += 1
return cachedLayer.layer
}
class CachedLayer {
let layer: ShapeLayer
let animation: Animation
var linksCounter = 1
private func calculateAnimationScale(animation: Animation) -> CGFloat {
let defaultScale = UIScreen.main.scale
guard let transformAnimation = animation as? TransformAnimation else {
return defaultScale
}
let animFunc = transformAnimation.getVFunc()
let origBounds = Rect(x: 0.0, y: 0.0, w: 1.0, h: 1.0)
let startTransform = animFunc(0.0)
let startBounds = origBounds.applyTransform(startTransform)
var startArea = startBounds.w * startBounds.h
// zero scale protection
if startArea == 0.0 {
startArea = 0.1
}
var maxArea = startArea
var t = 0.0
let step = 0.1
while t <= 1.0 {
let currentTransform = animFunc(t)
let currentBounds = origBounds.applyTransform(currentTransform)
let currentArea = currentBounds.w * currentBounds.h
if maxArea < currentArea {
maxArea = currentArea
}
t = t + step
}
return defaultScale * CGFloat(sqrt(maxArea))
required init(layer: ShapeLayer, animation: Animation) {
self.layer = layer
self.animation = animation
}
}
let sceneLayer: CALayer
var layerCache = [Node: CachedLayer]()
required init(sceneLayer: CALayer) {
self.sceneLayer = sceneLayer
}
func layerForNode(_ node: Node, animation: Animation, customBounds: Rect? = .none, shouldRenderContent: Bool = true) -> ShapeLayer {
guard let cachedLayer = layerCache[node] else {
let layer = ShapeLayer()
layer.shouldRenderContent = shouldRenderContent
layer.animationCache = self
// Use to debug animation layers
// layer.backgroundColor = MColor.green.cgColor
// layer.borderWidth = 1.0
// layer.borderColor = MColor.blue.cgColor
let calculatedBounds = customBounds ?? node.bounds()
if let shapeBounds = calculatedBounds {
let cgRect = shapeBounds.cgRect()
let origFrame = CGRect(x: 0.0, y: 0.0,
width: round(cgRect.width),
height: round(cgRect.height))
layer.bounds = origFrame
layer.anchorPoint = CGPoint(
x: -1.0 * cgRect.origin.x / cgRect.width,
y: -1.0 * cgRect.origin.y / cgRect.height
)
layer.zPosition = CGFloat(AnimationUtils.absoluteIndex(node))
layer.renderTransform = CGAffineTransform(translationX: -1.0 * cgRect.origin.x, y: -1.0 * cgRect.origin.y)
let nodeTransform = RenderUtils.mapTransform(AnimationUtils.absolutePosition(node))
layer.transform = CATransform3DMakeAffineTransform(nodeTransform)
// Clip
if let clip = AnimationUtils.absoluteClip(node: node) {
let maskLayer = CAShapeLayer()
let origPath = RenderUtils.toBezierPath(clip).cgPath
var offsetTransform = CGAffineTransform(translationX: -1.0 * cgRect.origin.x, y: -1.0 * cgRect.origin.y)
let clipPath = origPath.mutableCopy(using: &offsetTransform)
maskLayer.path = clipPath
layer.mask = maskLayer
}
}
layer.opacity = Float(node.opacity)
layer.node = node
layer.contentsScale = calculateAnimationScale(animation: animation)
layer.setNeedsDisplay()
sceneLayer.addSublayer(layer)
layerCache[node] = CachedLayer(layer: layer, animation: animation)
sceneLayer.setNeedsDisplay()
return layer
}
func freeLayer(_ node: Node) {
guard let cachedLayer = layerCache[node] else {
return
}
cachedLayer.linksCounter -= 1
if cachedLayer.linksCounter != 0 {
return
}
let layer = cachedLayer.layer
layerCache.removeValue(forKey: node)
sceneLayer.setNeedsDisplay()
layer.removeFromSuperlayer()
}
func isAnimating(_ node: Node) -> Bool {
if let _ = layerCache[node] {
return true
}
return false
}
func isChildrenAnimating(_ group: Group) -> Bool {
for child in group.contents {
if isAnimating(child) {
return true
}
if let childGroup = child as? Group {
return isChildrenAnimating(childGroup)
}
}
return false
}
func containsAnimation(_ node: Node) -> Bool {
if isAnimating(node) {
return true
}
if let group = node as? Group {
return isChildrenAnimating(group)
}
return false
}
func animations() -> [Animation] {
return layerCache.map ({ $0.1.animation })
}
func replace(original: Node, replacement: Node) {
guard let layer = layerCache[original] else {
return
}
layerCache[replacement] = layer
layerCache.removeValue(forKey: original)
cachedLayer.linksCounter += 1
return cachedLayer.layer
}
private func calculateAnimationScale(animation: Animation) -> CGFloat {
guard let defaultScale = MMainScreen()?.mScale else {
return 1.0
}
guard let transformAnimation = animation as? TransformAnimation else {
return defaultScale
}
let animFunc = transformAnimation.getVFunc()
let origBounds = Rect(x: 0.0, y: 0.0, w: 1.0, h: 1.0)
let startTransform = animFunc(0.0)
let startBounds = origBounds.applyTransform(startTransform)
var startArea = startBounds.w * startBounds.h
// zero scale protection
if startArea == 0.0 {
startArea = 0.1
}
var maxArea = startArea
var t = 0.0
let step = 0.1
while t <= 1.0 {
let currentTransform = animFunc(t)
let currentBounds = origBounds.applyTransform(currentTransform)
let currentArea = currentBounds.w * currentBounds.h
if maxArea < currentArea {
maxArea = currentArea
}
t = t + step
}
return defaultScale * CGFloat(sqrt(maxArea))
}
func freeLayer(_ node: Node) {
guard let cachedLayer = layerCache[node] else {
return
}
cachedLayer.linksCounter -= 1
if cachedLayer.linksCounter != 0 {
return
}
let layer = cachedLayer.layer
layerCache.removeValue(forKey: node)
sceneLayer.setNeedsDisplay()
layer.removeFromSuperlayer()
}
func isAnimating(_ node: Node) -> Bool {
if let _ = layerCache[node] {
return true
}
return false
}
func isChildrenAnimating(_ group: Group) -> Bool {
for child in group.contents {
if isAnimating(child) {
return true
}
if let childGroup = child as? Group {
return isChildrenAnimating(childGroup)
}
}
return false
}
func containsAnimation(_ node: Node) -> Bool {
if isAnimating(node) {
return true
}
if let group = node as? Group {
return isChildrenAnimating(group)
}
return false
}
func animations() -> [Animation] {
return layerCache.map ({ $0.1.animation })
}
func replace(original: Node, replacement: Node) {
guard let layer = layerCache[original] else {
return
}
layerCache[replacement] = layer
layerCache.removeValue(forKey: original)
}
}

View File

@ -2,20 +2,20 @@ import Foundation
let animationRestorer = AnimationRestorer()
open class AnimationRestorer {
typealias RestoreClosure = () -> ()
var restoreClosures = [RestoreClosure]()
func addRestoreClosure(_ closure: @escaping RestoreClosure) {
restoreClosures.append(closure)
}
open class func restore() {
DispatchQueue.main.async {
animationRestorer.restoreClosures.forEach { restoreClosure in
restoreClosure()
}
animationRestorer.restoreClosures.removeAll()
}
}
typealias RestoreClosure = () -> ()
var restoreClosures = [RestoreClosure]()
func addRestoreClosure(_ closure: @escaping RestoreClosure) {
restoreClosures.append(closure)
}
open class func restore() {
DispatchQueue.main.async {
animationRestorer.restoreClosures.forEach { restoreClosure in
restoreClosure()
}
animationRestorer.restoreClosures.removeAll()
}
}
}

View File

@ -1,14 +1,12 @@
// TODO: Implement better hash
extension Node: Hashable {
public var hashValue: Int {
return Unmanaged.passUnretained(self).toOpaque().hashValue
}
public var hashValue: Int {
return Unmanaged.passUnretained(self).toOpaque().hashValue
}
}
public func == (lhs: Node, rhs: Node) -> Bool {
return lhs === rhs
return lhs === rhs
}

View File

@ -1,21 +1,20 @@
extension Transform: Hashable {
public var hashValue: Int {
return m11.hashValue ^
m12.hashValue ^
m21.hashValue ^
m22.hashValue ^
dx.hashValue ^
dy.hashValue
}
public var hashValue: Int {
return m11.hashValue ^
m12.hashValue ^
m21.hashValue ^
m22.hashValue ^
dx.hashValue ^
dy.hashValue
}
}
public func == (lhs: Transform, rhs: Transform) -> Bool {
return lhs.m11 == rhs.m11 &&
lhs.m12 == rhs.m12 &&
lhs.m21 == rhs.m21 &&
lhs.m22 == rhs.m22 &&
lhs.dx == rhs.dx &&
lhs.dy == rhs.dy
return lhs.m11 == rhs.m11 &&
lhs.m12 == rhs.m12 &&
lhs.m21 == rhs.m21 &&
lhs.m22 == rhs.m22 &&
lhs.dx == rhs.dx &&
lhs.dy == rhs.dy
}

View File

@ -6,7 +6,14 @@
//
//
import UIKit
import Foundation
#if os(iOS)
import UIKit
#elseif os(OSX)
import AppKit
#endif
func addMorphingAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animationCache: AnimationCache?, completion: @escaping (() -> ())) {
guard let morphingAnimation = animation as? MorphingAnimation else {
@ -82,7 +89,7 @@ func addMorphingAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, anim
if let color = stroke.fill as? Color {
layer.strokeColor = RenderUtils.mapColor(color)
} else {
layer.strokeColor = UIColor.black.cgColor
layer.strokeColor = MColor.black.cgColor
}
layer.lineWidth = CGFloat(stroke.width)
@ -90,7 +97,7 @@ func addMorphingAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, anim
layer.lineJoin = RenderUtils.mapLineJoinToString(stroke.join)
layer.lineDashPattern = stroke.dashes.map{ NSNumber(value: $0)}
} else {
layer.strokeColor = UIColor.black.cgColor
layer.strokeColor = MColor.black.cgColor
layer.lineWidth = 1.0
}
@ -98,7 +105,7 @@ func addMorphingAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, anim
if let color = mutatingShape.fill as? Color {
layer.fillColor = RenderUtils.mapColor(color)
} else {
layer.fillColor = UIColor.clear.cgColor
layer.fillColor = MColor.clear.cgColor
}
layer.add(generatedAnim, forKey: animation.ID)

View File

@ -1,5 +1,10 @@
import Foundation
import UIKit
#if os(iOS)
import UIKit
#elseif os(OSX)
import AppKit
#endif
func addOpacityAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animationCache: AnimationCache?, completion: @escaping (() -> ())) {
guard let opacityAnimation = animation as? OpacityAnimation else {

View File

@ -6,7 +6,13 @@
//
//
import UIKit
import Foundation
#if os(iOS)
import UIKit
#elseif os(OSX)
import AppKit
#endif
func addShapeAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animationCache: AnimationCache?, completion: @escaping (() -> ())) {
guard let shapeAnimation = animation as? ShapeAnimation else {
@ -94,7 +100,7 @@ func addShapeAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animati
if let color = stroke.fill as? Color {
layer.strokeColor = RenderUtils.mapColor(color)
} else {
layer.strokeColor = UIColor.black.cgColor
layer.strokeColor = MColor.black.cgColor
}
layer.lineWidth = CGFloat(stroke.width)
@ -102,7 +108,7 @@ func addShapeAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animati
layer.lineJoin = RenderUtils.mapLineJoinToString(stroke.join)
layer.lineDashPattern = stroke.dashes.map{ NSNumber(value: $0)}
} else if shape.fill == nil {
layer.strokeColor = UIColor.black.cgColor
layer.strokeColor = MColor.black.cgColor
layer.lineWidth = 1.0
}
@ -110,7 +116,7 @@ func addShapeAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animati
if let color = shape.fill as? Color {
layer.fillColor = RenderUtils.mapColor(color)
} else {
layer.fillColor = UIColor.clear.cgColor
layer.fillColor = MColor.clear.cgColor
}
layer.add(generatedAnim, forKey: animation.ID)

View File

@ -1,37 +1,43 @@
import UIKit
import Foundation
#if os(iOS)
import UIKit
#elseif os(OSX)
import AppKit
#endif
func caTimingFunction(_ easing: Easing) -> CAMediaTimingFunction {
switch easing {
case .ease:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault)
case .linear:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
case .easeIn:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
case .easeOut:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
case .easeInOut:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
}
switch easing {
case .ease:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault)
case .linear:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
case .easeIn:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
case .easeOut:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
case .easeInOut:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
}
}
func progressForTimingFunction(_ easing: Easing, progress: Double) -> Double {
let t = progress
switch easing {
case .ease:
return t
case .linear:
return t
case .easeIn:
return t * t
case .easeOut:
return -(t * (t - 2))
case .easeInOut:
if t < 0.5 {
return 2.0 * t * t
} else {
return -2.0 * t * t + 4.0 * t - 1.0
}
let t = progress
switch easing {
case .ease:
return t
case .linear:
return t
case .easeIn:
return t * t
case .easeOut:
return -(t * (t - 2))
case .easeInOut:
if t < 0.5 {
return 2.0 * t * t
} else {
return -2.0 * t * t + 4.0 * t - 1.0
}
}
}

View File

@ -1,4 +1,10 @@
import UIKit
import Foundation
#if os(iOS)
import UIKit
#elseif os(OSX)
import AppKit
#endif
func addTransformAnimation(_ animation: BasicAnimation, sceneLayer: CALayer, animationCache: AnimationCache?, completion: @escaping (() -> ())) {
guard let transformAnimation = animation as? TransformAnimation else {

View File

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

View File

@ -6,26 +6,25 @@
//
//
open class GroupDisposable {
fileprivate var items: [Disposable] = []
open func dispose() {
for disposable in items {
disposable.dispose()
}
items = []
}
open func add(_ item: Disposable) {
items.append(item)
}
fileprivate var items: [Disposable] = []
open func dispose() {
for disposable in items {
disposable.dispose()
}
items = []
}
open func add(_ item: Disposable) {
items.append(item)
}
}
extension Disposable {
public func addTo(_ group: GroupDisposable) {
group.add(self)
}
public func addTo(_ group: GroupDisposable) {
group.add(self)
}
}

View File

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

View File

@ -9,17 +9,16 @@
import Foundation
open class Event {
public weak var node: Node?
var consumed = false
init(node: Node) {
self.node = node
}
public func consume() {
consumed = true
}
public weak var node: Node?
var consumed = false
init(node: Node) {
self.node = node
}
public func consume() {
consumed = true
}
}

View File

@ -1,14 +1,14 @@
open class PanEvent : Event {
open let dx: Double
open let dy: Double
open let count: Int
init(node: Node, dx: Double, dy: Double, count: Int) {
self.dx = dx
self.dy = dy
self.count = count
super.init(node: node)
}
open let dx: Double
open let dy: Double
open let count: Int
init(node: Node, dx: Double, dy: Double, count: Int) {
self.dx = dx
self.dy = dy
self.count = count
super.init(node: node)
}
}

View File

@ -1,10 +1,10 @@
open class PinchEvent : Event {
open let scale: Double
init(node: Node, scale: Double) {
self.scale = scale
super.init(node: node)
}
open let scale: Double
init(node: Node, scale: Double) {
self.scale = scale
super.init(node: node)
}
}

View File

@ -1,10 +1,10 @@
open class RotateEvent : Event {
open let angle: Double
init(node: Node, angle: Double) {
self.angle = angle
super.init(node: node)
}
open let angle: Double
init(node: Node, angle: Double) {
self.angle = angle
super.init(node: node)
}
}

View File

@ -1,10 +1,10 @@
open class TapEvent : Event {
open let location: Point
init(node: Node, location: Point) {
self.location = location
super.init(node: node)
}
open let location: Point
init(node: Node, location: Point) {
self.location = location
super.init(node: node)
}
}

View File

@ -8,17 +8,17 @@
public struct TouchPoint {
public let id: Int
public let location: Point
public let id: Int
public let location: Point
}
public class TouchEvent : Event {
public let points: [TouchPoint]
public init(node: Node, points: [TouchPoint]) {
self.points = points
public let points: [TouchPoint]
public init(node: Node, points: [TouchPoint]) {
self.points = points
super.init(node: node)
}
super.init(node: node)
}
}

View File

@ -1,5 +1,5 @@
public enum Align {
case min
case mid
case max
case min
case mid
case max
}

View File

@ -1,5 +1,5 @@
public enum AspectRatio {
case none
case meet
case slice
case none
case meet
case slice
}

View File

@ -1,72 +1,72 @@
import Foundation
open class Color: Fill, Equatable {
open let val: Int
open static let white: Color = Color( val: 0xFFFFFF )
open static let silver: Color = Color( val: 0xC0C0C0 )
open static let gray: Color = Color( val: 0x808080 )
open static let black: Color = Color( val: 0 )
open static let red: Color = Color( val: 0xFF0000 )
open static let maroon: Color = Color( val: 0x800000 )
open static let yellow: Color = Color( val: 0xFFFF00 )
open static let olive: Color = Color( val: 0x808000 )
open static let lime: Color = Color( val: 0x00FF00 )
open static let green: Color = Color( val: 0x008000 )
open static let aqua: Color = Color( val: 0x00FFFF )
open static let teal: Color = Color( val: 0x008080 )
open static let blue: Color = Color( val: 0x0000FF )
open static let navy: Color = Color( val: 0x000080 )
open static let fuchsia: Color = Color( val: 0xFF00FF )
open static let purple: Color = Color( val: 0x800080 )
open static let clear: Color = Color.rgba(r: 0, g: 0, b: 0, a: 0)
public init(val: Int = 0) {
self.val = val
}
// GENERATED
open func r() -> Int {
return ( ( val >> 16 ) & 0xff )
}
// GENERATED
open func g() -> Int {
return ( ( val >> 8 ) & 0xff )
}
// GENERATED
open func b() -> Int {
return ( val & 0xff )
}
// GENERATED
open func a() -> Int {
return ( 255 - ( ( val >> 24 ) & 0xff ) )
}
// GENERATED
public func with(a: Double) -> Color {
return Color.rgba(r: r(), g: g(), b: b(), a: a)
}
// GENERATED
open class func rgbt(r: Int, g: Int, b: Int, t: Int) -> Color {
return Color( val: ( ( ( ( ( t & 0xff ) << 24 ) | ( ( r & 0xff ) << 16 ) ) | ( ( g & 0xff ) << 8 ) ) | ( b & 0xff ) ) )
}
// GENERATED
open class func rgba(r: Int, g: Int, b: Int, a: Double) -> Color {
return rgbt( r: r, g: g, b: b, t: Int( ( ( 1 - a ) * 255 ) ) )
}
// GENERATED
open class func rgb(r: Int, g: Int, b: Int) -> Color {
return rgbt( r: r, g: g, b: b, t: 0 )
}
public static func ==(lhs: Color, rhs: Color) -> Bool {
return lhs.val == rhs.val
}
open let val: Int
open static let white: Color = Color( val: 0xFFFFFF )
open static let silver: Color = Color( val: 0xC0C0C0 )
open static let gray: Color = Color( val: 0x808080 )
open static let black: Color = Color( val: 0 )
open static let red: Color = Color( val: 0xFF0000 )
open static let maroon: Color = Color( val: 0x800000 )
open static let yellow: Color = Color( val: 0xFFFF00 )
open static let olive: Color = Color( val: 0x808000 )
open static let lime: Color = Color( val: 0x00FF00 )
open static let green: Color = Color( val: 0x008000 )
open static let aqua: Color = Color( val: 0x00FFFF )
open static let teal: Color = Color( val: 0x008080 )
open static let blue: Color = Color( val: 0x0000FF )
open static let navy: Color = Color( val: 0x000080 )
open static let fuchsia: Color = Color( val: 0xFF00FF )
open static let purple: Color = Color( val: 0x800080 )
open static let clear: Color = Color.rgba(r: 0, g: 0, b: 0, a: 0)
public init(val: Int = 0) {
self.val = val
}
// GENERATED
open func r() -> Int {
return ( ( val >> 16 ) & 0xff )
}
// GENERATED
open func g() -> Int {
return ( ( val >> 8 ) & 0xff )
}
// GENERATED
open func b() -> Int {
return ( val & 0xff )
}
// GENERATED
open func a() -> Int {
return ( 255 - ( ( val >> 24 ) & 0xff ) )
}
// GENERATED
public func with(a: Double) -> Color {
return Color.rgba(r: r(), g: g(), b: b(), a: a)
}
// GENERATED
open class func rgbt(r: Int, g: Int, b: Int, t: Int) -> Color {
return Color( val: ( ( ( ( ( t & 0xff ) << 24 ) | ( ( r & 0xff ) << 16 ) ) | ( ( g & 0xff ) << 8 ) ) | ( b & 0xff ) ) )
}
// GENERATED
open class func rgba(r: Int, g: Int, b: Int, a: Double) -> Color {
return rgbt( r: r, g: g, b: b, t: Int( ( ( 1 - a ) * 255 ) ) )
}
// GENERATED
open class func rgb(r: Int, g: Int, b: Int) -> Color {
return rgbt( r: r, g: g, b: b, t: 0 )
}
public static func ==(lhs: Color, rhs: Color) -> Bool {
return lhs.val == rhs.val
}
}

View File

@ -1,13 +1,12 @@
import Foundation
open class Drawable {
open let visible: Bool
open let tag: [String]
public init(visible: Bool = true, tag: [String] = []) {
self.visible = visible
self.tag = tag
}
open let visible: Bool
open let tag: [String]
public init(visible: Bool = true, tag: [String] = []) {
self.visible = visible
self.tag = tag
}
}

View File

@ -1,17 +1,16 @@
import Foundation
open class DropShadow: Effect {
open let radius: Double
open let offset: Point
open let color: Color
open let input: Effect?
public init(radius: Double = 0, offset: Point = Point.origin, color: Color = Color.black, input: Effect? = nil) {
self.radius = radius
self.offset = offset
self.color = color
self.input = input
}
open let radius: Double
open let offset: Point
open let color: Color
open let input: Effect?
public init(radius: Double = 0, offset: Point = Point.origin, color: Color = Color.black, input: Effect? = nil) {
self.radius = radius
self.offset = offset
self.color = color
self.input = input
}
}

View File

@ -1,8 +1,8 @@
import Foundation
open class Effect {
public init() {
}
public init() {
}
}

View File

@ -1,13 +1,12 @@
import Foundation
open class Font {
open let name: String
open let size: Int
public init(name: String = "Serif", size: Int = 12) {
self.name = name
self.size = size
}
open let name: String
open let size: Int
public init(name: String = "Serif", size: Int = 12) {
self.name = name
self.size = size
}
}

View File

@ -9,5 +9,4 @@ open class GaussianBlur: Effect {
self.radius = radius
self.input = input
}
}

View File

@ -9,5 +9,4 @@ open class Gradient: Fill {
self.userSpace = userSpace
self.stops = stops
}
}

View File

@ -1,46 +1,49 @@
import Foundation
import UIKit
#if os(iOS)
import UIKit
#endif
open class LinearGradient: Gradient {
open var x1: Double
open var y1: Double
open var x2: Double
open var y2: Double
public init(x1: Double = 0, y1: Double = 0, x2: Double = 0, y2: Double = 0, userSpace: Bool = false, stops: [Stop] = []) {
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
super.init(
userSpace: userSpace,
stops: stops
)
}
public init(degree: Double = 0, from: Color, to: Color) {
self.x1 = degree >= 135 && degree < 270 ? 1 : 0
self.y1 = degree < 225 ? 0 : 1
self.x2 = degree < 90 || degree >= 315 ? 1 : 0
self.y2 = degree >= 45 && degree < 180 ? 1 : 0
super.init(
userSpace: false,
stops: [Stop(offset: 0, color: from), Stop(offset: 1, color: to)]
)
}
func applyTransform(_ transform: Transform) {
// TODO: - Check logic
let cgTransform = RenderUtils.mapTransform(transform)
let point1 = CGPoint(x: x1, y: y1).applying(cgTransform)
x1 = point1.x.doubleValue
y1 = point1.y.doubleValue
let point2 = CGPoint(x: x2, y: y2).applying(cgTransform)
x2 = point2.x.doubleValue
y2 = point2.y.doubleValue
}
open var x1: Double
open var y1: Double
open var x2: Double
open var y2: Double
public init(x1: Double = 0, y1: Double = 0, x2: Double = 0, y2: Double = 0, userSpace: Bool = false, stops: [Stop] = []) {
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
super.init(
userSpace: userSpace,
stops: stops
)
}
public init(degree: Double = 0, from: Color, to: Color) {
self.x1 = degree >= 135 && degree < 270 ? 1 : 0
self.y1 = degree < 225 ? 0 : 1
self.x2 = degree < 90 || degree >= 315 ? 1 : 0
self.y2 = degree >= 45 && degree < 180 ? 1 : 0
super.init(
userSpace: false,
stops: [Stop(offset: 0, color: from), Stop(offset: 1, color: to)]
)
}
func applyTransform(_ transform: Transform) {
// TODO: - Check logic
let cgTransform = RenderUtils.mapTransform(transform)
let point1 = CGPoint(x: x1, y: y1).applying(cgTransform)
x1 = point1.x.doubleValue
y1 = point1.y.doubleValue
let point2 = CGPoint(x: x2, y: y2).applying(cgTransform)
x2 = point2.x.doubleValue
y2 = point2.y.doubleValue
}
}

View File

@ -1,37 +1,40 @@
import Foundation
import UIKit
#if os(iOS)
import UIKit
#endif
open class RadialGradient: Gradient {
open var cx: Double
open var cy: Double
open var fx: Double
open var fy: Double
open let r: Double
public init(cx: Double = 0.5, cy: Double = 0.5, fx: Double = 0.5, fy: Double = 0.5, r: Double = 0.5, userSpace: Bool = false, stops: [Stop] = []) {
self.cx = cx
self.cy = cy
self.fx = fx
self.fy = fy
self.r = r
super.init(
userSpace: userSpace,
stops: stops
)
}
func applyTransform(_ transform: Transform) {
// TODO: - Check logic
let cgTransform = RenderUtils.mapTransform(transform)
let point1 = CGPoint(x: cx, y: cy).applying(cgTransform)
cx = point1.x.doubleValue
cy = point1.y.doubleValue
let point2 = CGPoint(x: fx, y: fy).applying(cgTransform)
fx = point2.x.doubleValue
fy = point2.y.doubleValue
}
open var cx: Double
open var cy: Double
open var fx: Double
open var fy: Double
open let r: Double
public init(cx: Double = 0.5, cy: Double = 0.5, fx: Double = 0.5, fy: Double = 0.5, r: Double = 0.5, userSpace: Bool = false, stops: [Stop] = []) {
self.cx = cx
self.cy = cy
self.fx = fx
self.fy = fy
self.r = r
super.init(
userSpace: userSpace,
stops: stops
)
}
func applyTransform(_ transform: Transform) {
// TODO: - Check logic
let cgTransform = RenderUtils.mapTransform(transform)
let point1 = CGPoint(x: cx, y: cy).applying(cgTransform)
cx = point1.x.doubleValue
cy = point1.y.doubleValue
let point2 = CGPoint(x: fx, y: fy).applying(cgTransform)
fx = point2.x.doubleValue
fy = point2.y.doubleValue
}
}

View File

@ -9,5 +9,4 @@ open class Stop {
self.offset = offset
self.color = color
}
}

View File

@ -15,5 +15,4 @@ open class Stroke {
self.join = join
self.dashes = dashes
}
}

View File

@ -1,23 +1,22 @@
import Foundation
open class Arc: Locus {
open let ellipse: Ellipse
open let shift: Double
open let extent: Double
public init(ellipse: Ellipse, shift: Double = 0, extent: Double = 0) {
self.ellipse = ellipse
self.shift = shift
self.extent = extent
}
override open func bounds() -> Rect {
return Rect(
x: ellipse.cx - ellipse.rx,
y: ellipse.cy - ellipse.ry,
w: ellipse.rx * 2.0,
h: ellipse.ry * 2.0)
}
open let ellipse: Ellipse
open let shift: Double
open let extent: Double
public init(ellipse: Ellipse, shift: Double = 0, extent: Double = 0) {
self.ellipse = ellipse
self.shift = shift
self.extent = extent
}
override open func bounds() -> Rect {
return Rect(
x: ellipse.cx - ellipse.rx,
y: ellipse.cy - ellipse.ry,
w: ellipse.rx * 2.0,
h: ellipse.ry * 2.0)
}
}

View File

@ -1,28 +1,27 @@
import Foundation
open class Circle: Locus {
open let cx: Double
open let cy: Double
open let r: Double
public init(cx: Double = 0, cy: Double = 0, r: Double = 0) {
self.cx = cx
self.cy = cy
self.r = r
}
override open func bounds() -> Rect {
return Rect(
x: cx - r,
y: cy - r,
w: r * 2.0,
h: r * 2.0)
}
// GENERATED NOT
open func arc(shift: Double, extent: Double) -> Arc {
return Arc(ellipse: Ellipse(cx: cx, cy: cy, rx: r, ry: r), shift: shift, extent: extent)
}
open let cx: Double
open let cy: Double
open let r: Double
public init(cx: Double = 0, cy: Double = 0, r: Double = 0) {
self.cx = cx
self.cy = cy
self.r = r
}
override open func bounds() -> Rect {
return Rect(
x: cx - r,
y: cy - r,
w: r * 2.0,
h: r * 2.0)
}
// GENERATED NOT
open func arc(shift: Double, extent: Double) -> Arc {
return Arc(ellipse: Ellipse(cx: cx, cy: cy, rx: r, ry: r), shift: shift, extent: extent)
}
}

View File

@ -1,30 +1,29 @@
import Foundation
open class Ellipse: Locus {
open let cx: Double
open let cy: Double
open let rx: Double
open let ry: Double
public init(cx: Double = 0, cy: Double = 0, rx: Double = 0, ry: Double = 0) {
self.cx = cx
self.cy = cy
self.rx = rx
self.ry = ry
}
override open func bounds() -> Rect {
return Rect(
x: cx - rx,
y: cy - ry,
w: rx * 2.0,
h: ry * 2.0)
}
// GENERATED NOT
open func arc(shift: Double, extent: Double) -> Arc {
return Arc(ellipse: self, shift: shift, extent: extent)
}
open let cx: Double
open let cy: Double
open let rx: Double
open let ry: Double
public init(cx: Double = 0, cy: Double = 0, rx: Double = 0, ry: Double = 0) {
self.cx = cx
self.cy = cy
self.rx = rx
self.ry = ry
}
override open func bounds() -> Rect {
return Rect(
x: cx - rx,
y: cy - ry,
w: rx * 2.0,
h: ry * 2.0)
}
// GENERATED NOT
open func arc(shift: Double, extent: Double) -> Arc {
return Arc(ellipse: self, shift: shift, extent: extent)
}
}

View File

@ -1,42 +1,42 @@
open class GeomUtils {
open class func concat(t1: Transform, t2: Transform) -> Transform {
let nm11 = t2.m11 * t1.m11 + t2.m12 * t1.m21
let nm21 = t2.m21 * t1.m11 + t2.m22 * t1.m21
let ndx = t2.dx * t1.m11 + t2.dy * t1.m21 + t1.dx
let nm12 = t2.m11 * t1.m12 + t2.m12 * t1.m22
let nm22 = t2.m21 * t1.m12 + t2.m22 * t1.m22
let ndy = t2.dx * t1.m12 + t2.dy * t1.m22 + t1.dy
return Transform(m11: nm11, m12: nm12, m21: nm21, m22: nm22, dx: ndx, dy: ndy)
}
open class func centerRotation(node: Node, place: Transform, angle: Double) -> Transform {
let center = GeomUtils.center(node: node)
let move = Transform.move(dx: center.x, dy: center.y)
guard let moveInv = move.invert() else {
return Transform()
}
let r = Transform().rotate(angle: angle)
let moveAndRotate = GeomUtils.concat(t1: moveInv, t2: r)
let returnToOrig = GeomUtils.concat(t1: moveAndRotate, t2: move)
return GeomUtils.concat(t1: returnToOrig, t2: place)
}
open class func concat(t1: Transform, t2: Transform) -> Transform {
let nm11 = t2.m11 * t1.m11 + t2.m12 * t1.m21
let nm21 = t2.m21 * t1.m11 + t2.m22 * t1.m21
let ndx = t2.dx * t1.m11 + t2.dy * t1.m21 + t1.dx
let nm12 = t2.m11 * t1.m12 + t2.m12 * t1.m22
let nm22 = t2.m21 * t1.m12 + t2.m22 * t1.m22
let ndy = t2.dx * t1.m12 + t2.dy * t1.m22 + t1.dy
return Transform(m11: nm11, m12: nm12, m21: nm21, m22: nm22, dx: ndx, dy: ndy)
}
open class func centerRotation(node: Node, place: Transform, angle: Double) -> Transform {
open class func centerScale(node: Node, sx: Double, sy: Double) -> Transform {
let center = GeomUtils.center(node: node)
return Transform.move(dx: center.x * (1.0 - sx), dy: center.y * (1.0 - sy)).scale(sx: sx, sy: sy)
let center = GeomUtils.center(node: node)
let move = Transform.move(dx: center.x, dy: center.y)
guard let moveInv = move.invert() else {
return Transform()
}
open class func center(node: Node) -> Point {
guard let bounds = node.bounds() else {
return Point()
}
return Point(x: bounds.x + bounds.w / 2.0, y: bounds.y + bounds.h / 2.0)
let r = Transform().rotate(angle: angle)
let moveAndRotate = GeomUtils.concat(t1: moveInv, t2: r)
let returnToOrig = GeomUtils.concat(t1: moveAndRotate, t2: move)
return GeomUtils.concat(t1: returnToOrig, t2: place)
}
open class func centerScale(node: Node, sx: Double, sy: Double) -> Transform {
let center = GeomUtils.center(node: node)
return Transform.move(dx: center.x * (1.0 - sx), dy: center.y * (1.0 - sy)).scale(sx: sx, sy: sy)
}
open class func center(node: Node) -> Point {
guard let bounds = node.bounds() else {
return Point()
}
return Point(x: bounds.x + bounds.w / 2.0, y: bounds.y + bounds.h / 2.0)
}
}

View File

@ -1,17 +1,16 @@
import Foundation
open class Insets {
open let top: Double
open let right: Double
open let bottom: Double
open let left: Double
public init(top: Double = 0, right: Double = 0, bottom: Double = 0, left: Double = 0) {
self.top = top
self.right = right
self.bottom = bottom
self.left = left
}
open let top: Double
open let right: Double
open let bottom: Double
open let left: Double
public init(top: Double = 0, right: Double = 0, bottom: Double = 0, left: Double = 0) {
self.top = top
self.right = right
self.bottom = bottom
self.left = left
}
}

View File

@ -1,24 +1,24 @@
import Foundation
open class Line: Locus {
open let x1: Double
open let y1: Double
open let x2: Double
open let y2: Double
public init(x1: Double = 0, y1: Double = 0, x2: Double = 0, y2: Double = 0) {
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
}
override open func bounds() -> Rect {
return Rect(
x: min(x1, x2),
y: min(y1, y2),
w: abs(x1 - x2),
h: abs(y1 - y2))
}
open let x1: Double
open let y1: Double
open let x2: Double
open let y2: Double
public init(x1: Double = 0, y1: Double = 0, x2: Double = 0, y2: Double = 0) {
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
}
override open func bounds() -> Rect {
return Rect(
x: min(x1, x2),
y: min(y1, y2),
w: abs(x1 - x2),
h: abs(y1 - y2))
}
}

View File

@ -1,28 +1,27 @@
import Foundation
open class Locus {
public init() {
}
// GENERATED NOT
open func bounds() -> Rect {
return Rect()
}
// GENERATED NOT
open func stroke(with: Stroke) -> Shape {
return Shape(form: self, stroke: with)
}
// GENERATED NOT
open func fill(with: Fill) -> Shape {
return Shape(form: self, fill: with)
}
// GENERATED NOT
open func stroke(fill: Fill = Color.black, width: Double = 1, cap: LineCap = .butt, join: LineJoin = .miter, dashes: [Double] = []) -> Shape {
return Shape(form: self, stroke: Stroke(fill: fill, width: width, cap: cap, join: join, dashes: dashes))
}
public init() {
}
// GENERATED NOT
open func bounds() -> Rect {
return Rect()
}
// GENERATED NOT
open func stroke(with: Stroke) -> Shape {
return Shape(form: self, stroke: with)
}
// GENERATED NOT
open func fill(with: Fill) -> Shape {
return Shape(form: self, fill: with)
}
// GENERATED NOT
open func stroke(fill: Fill = Color.black, width: Double = 1, cap: LineCap = .butt, join: LineJoin = .miter, dashes: [Double] = []) -> Shape {
return Shape(form: self, stroke: Stroke(fill: fill, width: width, cap: cap, join: join, dashes: dashes))
}
}

View File

@ -1,10 +1,9 @@
import Foundation
open class MoveTo: PathBuilder {
// GENERATED NOT
public init(x: Double, y: Double) {
super.init(segment: PathSegment(type: .M, data: [x, y]))
}
// GENERATED NOT
public init(x: Double, y: Double) {
super.init(segment: PathSegment(type: .M, data: [x, y]))
}
}

View File

@ -1,14 +1,14 @@
import Foundation
open class Path: Locus {
open let segments: [PathSegment]
public init(segments: [PathSegment] = []) {
self.segments = segments
}
override open func bounds() -> Rect {
return pathBounds(self)!
}
open let segments: [PathSegment]
public init(segments: [PathSegment] = []) {
self.segments = segments
}
override open func bounds() -> Rect {
return pathBounds(self)!
}
}

View File

@ -1,154 +1,153 @@
import Foundation
open class PathBuilder {
open let segment: PathSegment
open let rest: PathBuilder?
public init(segment: PathSegment, rest: PathBuilder? = nil) {
self.segment = segment
self.rest = rest
}
// GENERATED NOT
open func moveTo(x: Double, y: Double) -> PathBuilder {
return M(x, y)
open let segment: PathSegment
open let rest: PathBuilder?
public init(segment: PathSegment, rest: PathBuilder? = nil) {
self.segment = segment
self.rest = rest
}
// GENERATED NOT
open func moveTo(x: Double, y: Double) -> PathBuilder {
return M(x, y)
}
// GENERATED NOT
open func lineTo(x: Double, y: Double) -> PathBuilder {
return L(x, y)
}
// GENERATED NOT
open func cubicTo(x1: Double, y1: Double, x2: Double, y2: Double, x: Double, y: Double) -> PathBuilder {
return C(x1, y1, x2, y2, x, y)
}
// GENERATED NOT
open func quadraticTo(x1: Double, y1: Double, x: Double, y: Double) -> PathBuilder {
return Q(x1, y1, x, y)
}
// GENERATED NOT
open func arcTo(rx: Double, ry: Double, angle: Double, largeArc: Bool, sweep: Bool, x: Double, y: Double) -> PathBuilder {
return A(rx, ry, angle, largeArc, sweep, x, y)
}
// GENERATED NOT
open func close() -> PathBuilder {
return Z()
}
// GENERATED NOT
open func m(_ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .m, data: [x, y]), rest: self)
}
// GENERATED NOT
open func M(_ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .M, data: [x, y]), rest: self)
}
// GENERATED NOT
open func l(_ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .l, data: [x, y]), rest: self)
}
// GENERATED NOT
open func L(_ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .L, data: [x, y]), rest: self)
}
// GENERATED NOT
open func h(_ x: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .h, data: [x]), rest: self)
}
// GENERATED NOT
open func H(_ x: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .H, data: [x]), rest: self)
}
// GENERATED NOT
open func v(_ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .v, data: [y]), rest: self)
}
// GENERATED NOT
open func V(_ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .V, data: [y]), rest: self)
}
// GENERATED NOT
open func c(_ x1: Double, _ y1: Double, _ x2: Double, _ y2: Double, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .c, data: [x1, y1, x2, y2, x, y]), rest: self)
}
// GENERATED NOT
open func C(_ x1: Double, _ y1: Double, _ x2: Double, _ y2: Double, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .C, data: [x1, y1, x2, y2, x, y]), rest: self)
}
// GENERATED NOT
open func s(_ x2: Double, _ y2: Double, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .s, data: [x2, y2, x, y]), rest: self)
}
// GENERATED NOT
open func S(_ x2: Double, _ y2: Double, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .S, data: [x2, y2, x, y]), rest: self)
}
// GENERATED NOT
open func q(_ x1: Double, _ y1: Double, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .q, data: [x1, y1, x, y]), rest: self)
}
// GENERATED NOT
open func Q(_ x1: Double, _ y1: Double, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .Q, data: [x1, y1, x, y]), rest: self)
}
// GENERATED NOT
open func t(_ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .t, data: [x, y]), rest: self)
}
// GENERATED NOT
open func T(_ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .T, data: [x, y]), rest: self)
}
// GENERATED NOT
open func a(_ rx: Double, _ ry: Double, _ angle: Double, _ largeArc: Bool, _ sweep: Bool, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .a, data: [rx, ry, angle, boolsToNum(largeArc, sweep: sweep), x, y]), rest: self)
}
// GENERATED NOT
open func A(_ rx: Double, _ ry: Double, _ angle: Double, _ largeArc: Bool, _ sweep: Bool, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .A, data: [rx, ry, angle, boolsToNum(largeArc, sweep: sweep), x, y]), rest: self)
}
// GENERATED NOT
open func Z() -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .z), rest: self)
}
// GENERATED NOT
open func build() -> Path {
var segments : [PathSegment] = []
var builder : PathBuilder? = self
while(builder != nil) {
segments.append(builder!.segment)
builder = builder!.rest
}
// GENERATED NOT
open func lineTo(x: Double, y: Double) -> PathBuilder {
return L(x, y)
}
// GENERATED NOT
open func cubicTo(x1: Double, y1: Double, x2: Double, y2: Double, x: Double, y: Double) -> PathBuilder {
return C(x1, y1, x2, y2, x, y)
}
// GENERATED NOT
open func quadraticTo(x1: Double, y1: Double, x: Double, y: Double) -> PathBuilder {
return Q(x1, y1, x, y)
}
// GENERATED NOT
open func arcTo(rx: Double, ry: Double, angle: Double, largeArc: Bool, sweep: Bool, x: Double, y: Double) -> PathBuilder {
return A(rx, ry, angle, largeArc, sweep, x, y)
}
// GENERATED NOT
open func close() -> PathBuilder {
return Z()
}
// GENERATED NOT
open func m(_ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .m, data: [x, y]), rest: self)
}
// GENERATED NOT
open func M(_ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .M, data: [x, y]), rest: self)
}
// GENERATED NOT
open func l(_ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .l, data: [x, y]), rest: self)
}
// GENERATED NOT
open func L(_ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .L, data: [x, y]), rest: self)
}
// GENERATED NOT
open func h(_ x: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .h, data: [x]), rest: self)
}
// GENERATED NOT
open func H(_ x: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .H, data: [x]), rest: self)
}
// GENERATED NOT
open func v(_ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .v, data: [y]), rest: self)
}
// GENERATED NOT
open func V(_ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .V, data: [y]), rest: self)
}
// GENERATED NOT
open func c(_ x1: Double, _ y1: Double, _ x2: Double, _ y2: Double, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .c, data: [x1, y1, x2, y2, x, y]), rest: self)
}
// GENERATED NOT
open func C(_ x1: Double, _ y1: Double, _ x2: Double, _ y2: Double, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .C, data: [x1, y1, x2, y2, x, y]), rest: self)
}
// GENERATED NOT
open func s(_ x2: Double, _ y2: Double, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .s, data: [x2, y2, x, y]), rest: self)
}
// GENERATED NOT
open func S(_ x2: Double, _ y2: Double, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .S, data: [x2, y2, x, y]), rest: self)
}
// GENERATED NOT
open func q(_ x1: Double, _ y1: Double, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .q, data: [x1, y1, x, y]), rest: self)
}
// GENERATED NOT
open func Q(_ x1: Double, _ y1: Double, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .Q, data: [x1, y1, x, y]), rest: self)
}
// GENERATED NOT
open func t(_ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .t, data: [x, y]), rest: self)
}
// GENERATED NOT
open func T(_ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .T, data: [x, y]), rest: self)
}
// GENERATED NOT
open func a(_ rx: Double, _ ry: Double, _ angle: Double, _ largeArc: Bool, _ sweep: Bool, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .a, data: [rx, ry, angle, boolsToNum(largeArc, sweep: sweep), x, y]), rest: self)
}
// GENERATED NOT
open func A(_ rx: Double, _ ry: Double, _ angle: Double, _ largeArc: Bool, _ sweep: Bool, _ x: Double, _ y: Double) -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .A, data: [rx, ry, angle, boolsToNum(largeArc, sweep: sweep), x, y]), rest: self)
}
// GENERATED NOT
open func Z() -> PathBuilder {
return PathBuilder(segment: PathSegment(type: .z), rest: self)
}
// GENERATED NOT
open func build() -> Path {
var segments : [PathSegment] = []
var builder : PathBuilder? = self
while(builder != nil) {
segments.append(builder!.segment)
builder = builder!.rest
}
return Path(segments: segments.reversed())
}
// GENERATED NOT
fileprivate func boolsToNum(_ largeArc: Bool, sweep: Bool) -> Double {
return (largeArc ? 1 : 0) + (sweep ? 1 : 0) * 2;
}
return Path(segments: segments.reversed())
}
// GENERATED NOT
fileprivate func boolsToNum(_ largeArc: Bool, sweep: Bool) -> Double {
return (largeArc ? 1 : 0) + (sweep ? 1 : 0) * 2;
}
}

View File

@ -1,23 +1,22 @@
import Foundation
open class PathSegment {
open let type: PathSegmentType
open let data: [Double]
public init(type: PathSegmentType = .M, data: [Double] = []) {
self.type = type
self.data = data
}
// GENERATED NOT
open func isAbsolute() -> Bool {
switch type {
case .M, .L, .H, .V, .C, .S, .Q, .T, .A:
return true
default:
return false
}
open let type: PathSegmentType
open let data: [Double]
public init(type: PathSegmentType = .M, data: [Double] = []) {
self.type = type
self.data = data
}
// GENERATED NOT
open func isAbsolute() -> Bool {
switch type {
case .M, .L, .H, .V, .C, .S, .Q, .T, .A:
return true
default:
return false
}
}
}

View File

@ -1,30 +1,29 @@
import Foundation
open class Point: Locus {
open let x: Double
open let y: Double
open static let origin: Point = Point( x: 0, y: 0 )
public init(x: Double = 0, y: Double = 0) {
self.x = x
self.y = y
}
override open func bounds() -> Rect {
return Rect(
x: x,
y: y,
w: 0.0,
h: 0.0)
}
// GENERATED NOT
open func add(_ point: Point) -> Point {
return Point(
x: self.x + point.x,
y: self.y + point.y)
}
open let x: Double
open let y: Double
open static let origin: Point = Point( x: 0, y: 0 )
public init(x: Double = 0, y: Double = 0) {
self.x = x
self.y = y
}
override open func bounds() -> Rect {
return Rect(
x: x,
y: y,
w: 0.0,
h: 0.0)
}
// GENERATED NOT
open func add(_ point: Point) -> Point {
return Point(
x: self.x + point.x,
y: self.y + point.y)
}
}

View File

@ -1,46 +1,46 @@
import Foundation
open class Polygon: Locus {
open let points: [Double]
public init(points: [Double] = []) {
self.points = points
}
override open func bounds() -> Rect {
guard !points.isEmpty else { return Rect.zero() }
open let points: [Double]
var minX = Double(INT16_MAX)
var minY = Double(INT16_MAX)
var maxX = Double(INT16_MIN)
var maxY = Double(INT16_MIN)
public init(points: [Double] = []) {
self.points = points
}
override open func bounds() -> Rect {
guard !points.isEmpty else { return Rect.zero() }
var minX = Double(INT16_MAX)
var minY = Double(INT16_MAX)
var maxX = Double(INT16_MIN)
var maxY = Double(INT16_MIN)
var isX = true
for point in points {
if isX {
if minX > point {
minX = point
}
if maxX < point {
maxX = point
}
} else {
if minY > point {
minY = point
}
if maxY < point {
maxY = point
}
}
isX = !isX
var isX = true
for point in points {
if isX {
if minX > point {
minX = point
}
return Rect(x: minX, y: minY,
w: maxX - minX,
h: maxY - minY)
if maxX < point {
maxX = point
}
} else {
if minY > point {
minY = point
}
if maxY < point {
maxY = point
}
}
isX = !isX
}
return Rect(x: minX, y: minY,
w: maxX - minX,
h: maxY - minY)
}
}

View File

@ -1,46 +1,46 @@
import Foundation
open class Polyline: Locus {
open let points: [Double]
public init(points: [Double] = []) {
self.points = points
}
open let points: [Double]
public init(points: [Double] = []) {
self.points = points
}
override open func bounds() -> Rect {
guard !points.isEmpty else { return Rect.zero() }
override open func bounds() -> Rect {
guard !points.isEmpty else { return Rect.zero() }
var minX = Double(INT16_MAX)
var minY = Double(INT16_MAX)
var maxX = Double(INT16_MIN)
var maxY = Double(INT16_MIN)
var isX = true
for point in points {
if isX {
if minX > point {
minX = point
}
if maxX < point {
maxX = point
}
} else {
if minY > point {
minY = point
}
if maxY < point {
maxY = point
}
}
isX = !isX
var minX = Double(INT16_MAX)
var minY = Double(INT16_MAX)
var maxX = Double(INT16_MIN)
var maxY = Double(INT16_MIN)
var isX = true
for point in points {
if isX {
if minX > point {
minX = point
}
return Rect(x: minX, y: minY,
w: maxX - minX,
h: maxY - minY)
if maxX < point {
maxX = point
}
} else {
if minY > point {
minY = point
}
if maxY < point {
maxY = point
}
}
isX = !isX
}
return Rect(x: minX, y: minY,
w: maxX - minX,
h: maxY - minY)
}
}

View File

@ -1,68 +1,68 @@
import Foundation
open class Rect: Locus {
open let x: Double
open let y: Double
open let w: Double
open let h: Double
public init(x: Double = 0, y: Double = 0, w: Double = 0, h: Double = 0) {
self.x = x
self.y = y
self.w = w
self.h = h
}
override open func bounds() -> Rect {
return self
}
// GENERATED NOT
open func round(rx: Double, ry: Double) -> RoundRect {
return RoundRect(rect: self, rx: rx, ry: ry)
}
// GENERATED NOT
public func round(r: Double) -> RoundRect {
return RoundRect(rect: self, rx: r, ry: r)
}
// GENERATED NOT
open func contains(locus: Locus) -> Bool {
return false
}
// GENERATED NOT
class func zero() -> Rect {
return Rect(x: 0.0, y: 0.0, w: 0.0, h: 0.0)
}
// GENERATED NOT
open func move(offset: Point) -> Rect {
return Rect(
x: self.x + offset.x,
y: self.y + offset.y,
w: self.w,
h: self.h)
}
// GENERATED NOT
open func union(rect: Rect) -> Rect {
return Rect(
x: min(self.x, rect.x),
y: min(self.y, rect.y),
w: max(self.x + self.w, rect.x + rect.w) - min(self.x, rect.x),
h: max(self.y + self.h, rect.y + rect.h) - min(self.y, rect.y))
}
open let x: Double
open let y: Double
open let w: Double
open let h: Double
public init(x: Double = 0, y: Double = 0, w: Double = 0, h: Double = 0) {
self.x = x
self.y = y
self.w = w
self.h = h
}
override open func bounds() -> Rect {
return self
}
// GENERATED NOT
open func round(rx: Double, ry: Double) -> RoundRect {
return RoundRect(rect: self, rx: rx, ry: ry)
}
// GENERATED NOT
public func round(r: Double) -> RoundRect {
return RoundRect(rect: self, rx: r, ry: r)
}
// GENERATED NOT
open func contains(locus: Locus) -> Bool {
return false
}
// GENERATED NOT
class func zero() -> Rect {
return Rect(x: 0.0, y: 0.0, w: 0.0, h: 0.0)
}
// GENERATED NOT
open func move(offset: Point) -> Rect {
return Rect(
x: self.x + offset.x,
y: self.y + offset.y,
w: self.w,
h: self.h)
}
// GENERATED NOT
open func union(rect: Rect) -> Rect {
return Rect(
x: min(self.x, rect.x),
y: min(self.y, rect.y),
w: max(self.x + self.w, rect.x + rect.w) - min(self.x, rect.x),
h: max(self.y + self.h, rect.y + rect.h) - min(self.y, rect.y))
}
}
extension Rect {
public static func ==(lhs: Rect, rhs: Rect) -> Bool {
return lhs.x == rhs.x
&& lhs.y == rhs.y
&& lhs.w == rhs.w
&& lhs.h == rhs.h
}
public static func ==(lhs: Rect, rhs: Rect) -> Bool {
return lhs.x == rhs.x
&& lhs.y == rhs.y
&& lhs.w == rhs.w
&& lhs.h == rhs.h
}
}

View File

@ -1,18 +1,18 @@
import Foundation
open class RoundRect: Locus {
open let rect: Rect
open let rx: Double
open let ry: Double
public init(rect: Rect, rx: Double = 0, ry: Double = 0) {
self.rect = rect
self.rx = rx
self.ry = ry
}
override open func bounds() -> Rect {
return rect
}
open let rect: Rect
open let rx: Double
open let ry: Double
public init(rect: Rect, rx: Double = 0, ry: Double = 0) {
self.rect = rect
self.rx = rx
self.ry = ry
}
override open func bounds() -> Rect {
return rect
}
}

View File

@ -1,13 +1,12 @@
import Foundation
open class Size {
open let w: Double
open let h: Double
public init(w: Double = 0, h: Double = 0) {
self.w = w
self.h = h
}
open let w: Double
open let h: Double
public init(w: Double = 0, h: Double = 0) {
self.w = w
self.h = h
}
}

View File

@ -1,89 +1,88 @@
import Foundation
public final class Transform {
public let m11: Double
public let m12: Double
public let m21: Double
public let m22: Double
public let dx: Double
public let dy: Double
public static let identity: Transform = Transform()
public init(m11: Double = 1, m12: Double = 0, m21: Double = 0, m22: Double = 1, dx: Double = 0, dy: Double = 0) {
self.m11 = m11
self.m12 = m12
self.m21 = m21
self.m22 = m22
self.dx = dx
self.dy = dy
}
// GENERATED NOT
public func move(dx: Double, dy: Double) -> Transform {
return Transform(m11: m11, m12: m12, m21: m21, m22: m22,
dx: dx * m11 + dy * m21 + self.dx, dy: dx * m12 + dy * m22 + self.dy)
}
// GENERATED NOT
public func scale(sx: Double, sy: Double) -> Transform {
return Transform(m11: m11 * sx, m12: m12 * sx, m21: m21 * sy, m22: m22 * sy, dx: dx, dy: dy)
}
// GENERATED NOT
public func shear(shx: Double, shy: Double) -> Transform {
return Transform(m11: m11 + m21 * shy, m12: m12 + m22 * shy,
m21: m11 * shx + m21, m22: m12 * shx + m22, dx: dx, dy: dy)
}
// GENERATED NOT
public func rotate(angle: Double) -> Transform {
let asin = sin(angle); let acos = cos(angle)
return Transform(m11: acos * m11 + asin * m21, m12: acos * m12 + asin * m22,
m21: -asin * m11 + acos * m21, m22: -asin * m12 + acos * m22, dx: dx, dy: dy)
}
// GENERATED NOT
public func rotate(angle: Double, x: Double, y: Double) -> Transform {
return move(dx: x, dy: y).rotate(angle: angle).move(dx: -x, dy: -y)
}
// GENERATED
public class func move(dx: Double, dy: Double) -> Transform {
return Transform(dx: dx, dy: dy)
}
// GENERATED
public class func scale(sx: Double, sy: Double) -> Transform {
return Transform(m11: sx, m22: sy)
}
// GENERATED
public class func shear(shx: Double, shy: Double) -> Transform {
return Transform(m12: shy, m21: shx)
}
// GENERATED NOT
public class func rotate(angle: Double) -> Transform {
let asin = sin(angle); let acos = cos(angle)
return Transform(m11: acos, m12: asin, m21: -asin, m22: acos)
}
// GENERATED NOT
public class func rotate(angle: Double, x: Double, y: Double) -> Transform {
return Transform.move(dx: x, dy: y).rotate(angle: angle).move(dx: -x, dy: -y)
}
// GENERATED NOT
public func invert() -> Transform? {
let det = self.m11 * self.m22 - self.m12 * self.m21
if (det == 0) {
return nil
}
return Transform(m11: m22 / det, m12: -m12 / det, m21: -m21 / det, m22: m11 / det,
dx: (m21 * dy - m22 * dx) / det,
dy: (m12 * dx - m11 * dy) / det)
}
public let m11: Double
public let m12: Double
public let m21: Double
public let m22: Double
public let dx: Double
public let dy: Double
public static let identity: Transform = Transform()
public init(m11: Double = 1, m12: Double = 0, m21: Double = 0, m22: Double = 1, dx: Double = 0, dy: Double = 0) {
self.m11 = m11
self.m12 = m12
self.m21 = m21
self.m22 = m22
self.dx = dx
self.dy = dy
}
// GENERATED NOT
public func move(dx: Double, dy: Double) -> Transform {
return Transform(m11: m11, m12: m12, m21: m21, m22: m22,
dx: dx * m11 + dy * m21 + self.dx, dy: dx * m12 + dy * m22 + self.dy)
}
// GENERATED NOT
public func scale(sx: Double, sy: Double) -> Transform {
return Transform(m11: m11 * sx, m12: m12 * sx, m21: m21 * sy, m22: m22 * sy, dx: dx, dy: dy)
}
// GENERATED NOT
public func shear(shx: Double, shy: Double) -> Transform {
return Transform(m11: m11 + m21 * shy, m12: m12 + m22 * shy,
m21: m11 * shx + m21, m22: m12 * shx + m22, dx: dx, dy: dy)
}
// GENERATED NOT
public func rotate(angle: Double) -> Transform {
let asin = sin(angle); let acos = cos(angle)
return Transform(m11: acos * m11 + asin * m21, m12: acos * m12 + asin * m22,
m21: -asin * m11 + acos * m21, m22: -asin * m12 + acos * m22, dx: dx, dy: dy)
}
// GENERATED NOT
public func rotate(angle: Double, x: Double, y: Double) -> Transform {
return move(dx: x, dy: y).rotate(angle: angle).move(dx: -x, dy: -y)
}
// GENERATED
public class func move(dx: Double, dy: Double) -> Transform {
return Transform(dx: dx, dy: dy)
}
// GENERATED
public class func scale(sx: Double, sy: Double) -> Transform {
return Transform(m11: sx, m22: sy)
}
// GENERATED
public class func shear(shx: Double, shy: Double) -> Transform {
return Transform(m12: shy, m21: shx)
}
// GENERATED NOT
public class func rotate(angle: Double) -> Transform {
let asin = sin(angle); let acos = cos(angle)
return Transform(m11: acos, m12: asin, m21: -asin, m22: acos)
}
// GENERATED NOT
public class func rotate(angle: Double, x: Double, y: Double) -> Transform {
return Transform.move(dx: x, dy: y).rotate(angle: angle).move(dx: -x, dy: -y)
}
// GENERATED NOT
public func invert() -> Transform? {
let det = self.m11 * self.m22 - self.m12 * self.m21
if (det == 0) {
return nil
}
return Transform(m11: m22 / det, m12: -m12 / det, m21: -m21 / det, m22: m11 / det,
dx: (m21 * dy - m22 * dx) / det,
dy: (m12 * dx - m11 * dy) / det)
}
}

View File

@ -1,152 +1,151 @@
import Foundation
open class Group: Node {
open var contentsVar: AnimatableVariable<[Node]>
open var contents: [Node] {
get { return contentsVar.value }
set(val) {
contentsVar.value = val
if let view = nodesMap.getView(self) {
val.forEach { subNode in
nodesMap.add(subNode, view: view)
}
}
val.forEach { subNode in
nodesMap.add(subNode, parent: self)
}
open var contentsVar: AnimatableVariable<[Node]>
open var contents: [Node] {
get { return contentsVar.value }
set(val) {
contentsVar.value = val
if let view = nodesMap.getView(self) {
val.forEach { subNode in
nodesMap.add(subNode, view: view)
}
}
val.forEach { subNode in
nodesMap.add(subNode, parent: self)
}
}
}
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(
place: place,
opaque: opaque,
opacity: opacity,
clip: clip,
effect: effect,
visible: visible,
tag: tag
)
self.contentsVar.node = self
}
// Searching
override public func nodeBy(tag: String) -> Node? {
if let node = super.nodeBy(tag: tag) {
return 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(
place: place,
opaque: opaque,
opacity: opacity,
clip: clip,
effect: effect,
visible: visible,
tag: tag
)
self.contentsVar.node = self
for child in contents {
if let node = child.nodeBy(tag: tag) {
return node
}
}
// Searching
override public func nodeBy(tag: String) -> Node? {
if let node = super.nodeBy(tag: tag) {
return node
}
for child in contents {
if let node = child.nodeBy(tag: tag) {
return node
}
}
return .none
return .none
}
override public func nodesBy(tag: String) -> [Node] {
var result = [Node]()
contents.forEach { child in
result.append(contentsOf: child.nodesBy(tag: tag))
}
override public func nodesBy(tag: String) -> [Node] {
var result = [Node]()
contents.forEach { child in
result.append(contentsOf: child.nodesBy(tag: tag))
}
if let node = super.nodeBy(tag: tag) {
result.append(node)
}
return result
if let node = super.nodeBy(tag: tag) {
result.append(node)
}
// GENERATED NOT
override internal func bounds() -> Rect? {
var union: Rect?
contents.forEach { node in
guard let nodeBounds = node.bounds()?.applyTransform(node.place) else {
return
}
union = union?.union(rect: nodeBounds) ?? nodeBounds
}
return union
return result
}
// GENERATED NOT
override internal func bounds() -> Rect? {
var union: Rect?
contents.forEach { node in
guard let nodeBounds = node.bounds()?.applyTransform(node.place) else {
return
}
union = union?.union(rect: nodeBounds) ?? nodeBounds
}
override func shouldCheckForPressed() -> Bool {
var shouldCheck = super.shouldCheckForPressed()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForPressed()
}
return shouldCheck
return union
}
override func shouldCheckForPressed() -> Bool {
var shouldCheck = super.shouldCheckForPressed()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForPressed()
}
override func shouldCheckForMoved() -> Bool {
var shouldCheck = super.shouldCheckForMoved()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForMoved()
}
return shouldCheck
return shouldCheck
}
override func shouldCheckForMoved() -> Bool {
var shouldCheck = super.shouldCheckForMoved()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForMoved()
}
override func shouldCheckForReleased() -> Bool {
var shouldCheck = super.shouldCheckForReleased()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForReleased()
}
return shouldCheck
return shouldCheck
}
override func shouldCheckForReleased() -> Bool {
var shouldCheck = super.shouldCheckForReleased()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForReleased()
}
override func shouldCheckForTap() -> Bool {
var shouldCheck = super.shouldCheckForTap()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForTap()
}
return shouldCheck
return shouldCheck
}
override func shouldCheckForTap() -> Bool {
var shouldCheck = super.shouldCheckForTap()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForTap()
}
override func shouldCheckForPan() -> Bool {
var shouldCheck = super.shouldCheckForPan()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForPan()
}
return shouldCheck
return shouldCheck
}
override func shouldCheckForPan() -> Bool {
var shouldCheck = super.shouldCheckForPan()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForPan()
}
override func shouldCheckForPinch() -> Bool {
var shouldCheck = super.shouldCheckForPinch()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForPinch()
}
return shouldCheck
return shouldCheck
}
override func shouldCheckForPinch() -> Bool {
var shouldCheck = super.shouldCheckForPinch()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForPinch()
}
override func shouldCheckForRotate() -> Bool {
var shouldCheck = super.shouldCheckForRotate()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForRotate()
}
return shouldCheck
return shouldCheck
}
override func shouldCheckForRotate() -> Bool {
var shouldCheck = super.shouldCheckForRotate()
contents.forEach { node in
shouldCheck = shouldCheck || node.shouldCheckForRotate()
}
return shouldCheck
}
}
public extension Array where Element: Node {
public func group( place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) -> Group {
return Group(contents: self, place: place, opaque: opaque, opacity: opacity, clip: clip, effect: effect, visible: visible, tag: tag)
}
public func group( place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) -> Group {
return Group(contents: self, place: place, opaque: opaque, opacity: opacity, clip: clip, effect: effect, visible: visible, tag: tag)
}
}

View File

@ -1,133 +1,137 @@
import UIKit
import Foundation
#if os(iOS)
import UIKit
#endif
open class Image: Node {
open let srcVar: Variable<String>
open var src: String {
get { return srcVar.value }
set(val) { srcVar.value = val }
}
open let xAlignVar: Variable<Align>
open var xAlign: Align {
get { return xAlignVar.value }
set(val) { xAlignVar.value = val }
}
open let yAlignVar: Variable<Align>
open var yAlign: Align {
get { return yAlignVar.value }
set(val) { yAlignVar.value = val }
}
open let aspectRatioVar: Variable<AspectRatio>
open var aspectRatio: AspectRatio {
get { return aspectRatioVar.value }
set(val) { aspectRatioVar.value = val }
}
open let wVar: Variable<Int>
open var w: Int {
get { return wVar.value }
set(val) { wVar.value = val }
}
open let hVar: Variable<Int>
open var h: Int {
get { return hVar.value }
set(val) { hVar.value = val }
}
private var mImage: MImage?
public init(src: String, 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] = []) {
self.srcVar = Variable<String>(src)
self.xAlignVar = Variable<Align>(xAlign)
self.yAlignVar = Variable<Align>(yAlign)
self.aspectRatioVar = Variable<AspectRatio>(aspectRatio)
self.wVar = Variable<Int>(w)
self.hVar = Variable<Int>(h)
super.init(
place: place,
opaque: opaque,
opacity: opacity,
clip: clip,
effect: effect,
visible: visible,
tag: tag
)
}
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] = []) {
open let srcVar: Variable<String>
open var src: String {
get { return srcVar.value }
set(val) { srcVar.value = val }
var oldId: String?
for key in imagesMap.keys {
if image === imagesMap[key] {
oldId = key
}
}
open let xAlignVar: Variable<Align>
open var xAlign: Align {
get { return xAlignVar.value }
set(val) { xAlignVar.value = val }
let id = oldId ?? UUID().uuidString
imagesMap[id] = image
self.srcVar = Variable<String>("memory://\(id)")
self.xAlignVar = Variable<Align>(xAlign)
self.yAlignVar = Variable<Align>(yAlign)
self.aspectRatioVar = Variable<AspectRatio>(aspectRatio)
self.wVar = Variable<Int>(w)
self.hVar = Variable<Int>(h)
super.init(
place: place,
opaque: opaque,
opacity: opacity,
clip: clip,
effect: effect,
visible: visible,
tag: tag
)
}
override func bounds() -> Rect? {
if w != 0 && h != 0 {
return Rect(x: 0.0, y: 0.0, w: Double(w), h: Double(h))
}
open let yAlignVar: Variable<Align>
open var yAlign: Align {
get { return yAlignVar.value }
set(val) { yAlignVar.value = val }
mImage = image()
guard let mImage = mImage else {
return .none
}
open let aspectRatioVar: Variable<AspectRatio>
open var aspectRatio: AspectRatio {
get { return aspectRatioVar.value }
set(val) { aspectRatioVar.value = val }
return Rect(x: 0.0, y: 0.0,
w: Double(mImage.size.width),
h: Double(mImage.size.height))
}
func image() -> MImage? {
// image already loaded
if let _ = mImage {
return mImage
}
open let wVar: Variable<Int>
open var w: Int {
get { return wVar.value }
set(val) { wVar.value = val }
// In-memory image
if src.contains("memory") {
let id = src.replacingOccurrences(of: "memory://", with: "")
return imagesMap[id]
}
open let hVar: Variable<Int>
open var h: Int {
get { return hVar.value }
set(val) { hVar.value = val }
// Base64 image
if src.hasPrefix("data:image/png;base64,") {
src = src.replacingOccurrences(of: "data:image/png;base64,", with: "")
guard let decodedData = Data(base64Encoded: src, options: .ignoreUnknownCharacters) else {
return .none
}
return MImage(data: decodedData)
}
private var uiImage: UIImage?
public init(src: String, 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] = []) {
self.srcVar = Variable<String>(src)
self.xAlignVar = Variable<Align>(xAlign)
self.yAlignVar = Variable<Align>(yAlign)
self.aspectRatioVar = Variable<AspectRatio>(aspectRatio)
self.wVar = Variable<Int>(w)
self.hVar = Variable<Int>(h)
super.init(
place: place,
opaque: opaque,
opacity: opacity,
clip: clip,
effect: effect,
visible: visible,
tag: tag
)
}
public init(image: UIImage, 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] {
oldId = key
}
}
let id = oldId ?? UUID().uuidString
imagesMap[id] = image
self.srcVar = Variable<String>("memory://\(id)")
self.xAlignVar = Variable<Align>(xAlign)
self.yAlignVar = Variable<Align>(yAlign)
self.aspectRatioVar = Variable<AspectRatio>(aspectRatio)
self.wVar = Variable<Int>(w)
self.hVar = Variable<Int>(h)
super.init(
place: place,
opaque: opaque,
opacity: opacity,
clip: clip,
effect: effect,
visible: visible,
tag: tag
)
}
override func bounds() -> Rect? {
if w != 0 && h != 0 {
return Rect(x: 0.0, y: 0.0, w: Double(w), h: Double(h))
}
uiImage = image()
guard let uiImage = uiImage else {
return .none
}
return Rect(x: 0.0, y: 0.0,
w: Double(uiImage.size.width),
h: Double(uiImage.size.height))
}
func image() -> UIImage? {
// image already loaded
if let _ = uiImage {
return uiImage
}
// In-memory image
if src.contains("memory") {
let id = src.replacingOccurrences(of: "memory://", with: "")
return imagesMap[id]
}
// Base64 image
if src.hasPrefix("data:image/png;base64,") {
src = src.replacingOccurrences(of: "data:image/png;base64,", with: "")
guard let decodedData = Data(base64Encoded: src, options: .ignoreUnknownCharacters) else {
return .none
}
return UIImage(data: decodedData)
}
// General case
return UIImage(named: src)
}
// General case
return MImage(named: src)
}
}

View File

@ -7,16 +7,16 @@
//
class SceneUtils {
static func shapeCopy(from: Shape) -> Shape {
return Shape(form: from.form,
fill: from.fill,
stroke: from.stroke,
place: from.place,
opaque: from.opaque,
opacity: from.opacity,
clip: from.clip,
effect: from.effect,
visible: from.visible,
tag: from.tag)
}
static func shapeCopy(from: Shape) -> Shape {
return Shape(form: from.form,
fill: from.fill,
stroke: from.stroke,
place: from.place,
opaque: from.opaque,
opacity: from.opacity,
clip: from.clip,
effect: from.effect,
visible: from.visible,
tag: from.tag)
}
}

View File

@ -1,58 +1,57 @@
import Foundation
open class Shape: Node {
open let formVar: AnimatableVariable<Locus>
open var form: Locus {
get { return formVar.value }
set(val) { formVar.value = val }
}
open let fillVar: AnimatableVariable<Fill?>
open var fill: Fill? {
get { return fillVar.value }
set(val) { fillVar.value = val }
}
open let strokeVar: AnimatableVariable<Stroke?>
open var stroke: Stroke? {
get { return strokeVar.value }
set(val) { strokeVar.value = val }
}
public init(form: Locus, fill: Fill? = nil, stroke: Stroke? = nil, place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) {
self.formVar = AnimatableVariable<Locus>(form)
self.fillVar = AnimatableVariable<Fill?>(fill)
self.strokeVar = AnimatableVariable<Stroke?>(stroke)
super.init(
place: place,
opaque: opaque,
opacity: opacity,
clip: clip,
effect: effect,
visible: visible,
tag: tag
)
open let formVar: AnimatableVariable<Locus>
open var form: Locus {
get { return formVar.value }
set(val) { formVar.value = val }
}
open let fillVar: AnimatableVariable<Fill?>
open var fill: Fill? {
get { return fillVar.value }
set(val) { fillVar.value = val }
}
open let strokeVar: AnimatableVariable<Stroke?>
open var stroke: Stroke? {
get { return strokeVar.value }
set(val) { strokeVar.value = val }
}
public init(form: Locus, fill: Fill? = nil, stroke: Stroke? = nil, place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) {
self.formVar = AnimatableVariable<Locus>(form)
self.fillVar = AnimatableVariable<Fill?>(fill)
self.strokeVar = AnimatableVariable<Stroke?>(stroke)
super.init(
place: place,
opaque: opaque,
opacity: opacity,
clip: clip,
effect: effect,
visible: visible,
tag: tag
)
self.formVar.node = self
self.strokeVar.node = self
self.fillVar.node = self
}
// GENERATED NOT
override internal func bounds() -> Rect? {
var bounds = form.bounds()
if let shapeStroke = self.stroke {
let r = shapeStroke.width / 2.0
bounds = Rect(
x: bounds.x - r,
y: bounds.y - r,
w: bounds.w + r * 2.0,
h: bounds.h + r * 2.0)
}
return bounds
self.formVar.node = self
self.strokeVar.node = self
self.fillVar.node = self
}
// GENERATED NOT
override internal func bounds() -> Rect? {
var bounds = form.bounds()
if let shapeStroke = self.stroke {
let r = shapeStroke.width / 2.0
bounds = Rect(
x: bounds.x - r,
y: bounds.y - r,
w: bounds.w + r * 2.0,
h: bounds.h + r * 2.0)
}
return bounds
}
}

View File

@ -1,108 +1,115 @@
import UIKit
import Foundation
#if os(iOS)
import UIKit
#elseif os(OSX)
import AppKit
#endif
open class Text: Node {
open let textVar: Variable<String>
open var text: String {
get { return textVar.value }
set(val) { textVar.value = val }
open let textVar: Variable<String>
open var text: String {
get { return textVar.value }
set(val) { textVar.value = val }
}
open let fontVar: Variable<Font?>
open var font: Font? {
get { return fontVar.value }
set(val) { fontVar.value = val }
}
open let fillVar: Variable<Fill>
open var fill: Fill {
get { return fillVar.value }
set(val) { fillVar.value = val }
}
open let alignVar: Variable<Align>
open var align: Align {
get { return alignVar.value }
set(val) { alignVar.value = val }
}
open let baselineVar: Variable<Baseline>
open var baseline: Baseline {
get { return baselineVar.value }
set(val) { baselineVar.value = val }
}
public init(text: String, font: Font? = nil, fill: Fill = Color.black, align: Align = .min, baseline: Baseline = .top, place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) {
self.textVar = Variable<String>(text)
self.fontVar = Variable<Font?>(font)
self.fillVar = Variable<Fill>(fill)
self.alignVar = Variable<Align>(align)
self.baselineVar = Variable<Baseline>(baseline)
super.init(
place: place,
opaque: opaque,
opacity: opacity,
clip: clip,
effect: effect,
visible: visible,
tag: tag
)
}
// GENERATED NOT
override internal func bounds() -> Rect {
let font: MFont
if let f = self.font {
if let customFont = RenderUtils.loadFont(name: f.name, size:f.size) {
font = customFont
} else {
font = MFont.systemFont(ofSize: CGFloat(f.size))
}
} else {
font = MFont.systemFont(ofSize: MFont.mSystemFontSize)
}
open let fontVar: Variable<Font?>
open var font: Font? {
get { return fontVar.value }
set(val) { fontVar.value = val }
var stringAttributes: [String: AnyObject] = [:]
stringAttributes[NSFontAttributeName] = font
let size = (text as NSString).size(attributes: stringAttributes)
return Rect(
x: calculateAlignmentOffset(font: font),
y: calculateBaselineOffset(font: font),
w: size.width.doubleValue,
h: size.height.doubleValue
)
}
fileprivate func calculateBaselineOffset(font: MFont) -> Double {
var baselineOffset = 0.0
switch baseline {
case .alphabetic:
baselineOffset = font.ascender.doubleValue
case .bottom:
baselineOffset = (font.ascender - font.descender).doubleValue
case .mid:
baselineOffset = ((font.ascender - font.descender) / 2).doubleValue
default:
break
}
open let fillVar: Variable<Fill>
open var fill: Fill {
get { return fillVar.value }
set(val) { fillVar.value = val }
return -baselineOffset
}
fileprivate func calculateAlignmentOffset(font: MFont) -> Double {
let textAttributes = [
NSFontAttributeName: font
]
let textSize = NSString(string: text).size(attributes: textAttributes)
var alignmentOffset = 0.0
switch align {
case .mid:
alignmentOffset = (textSize.width / 2).doubleValue
case .max:
alignmentOffset = textSize.width.doubleValue
default:
break
}
open let alignVar: Variable<Align>
open var align: Align {
get { return alignVar.value }
set(val) { alignVar.value = val }
}
open let baselineVar: Variable<Baseline>
open var baseline: Baseline {
get { return baselineVar.value }
set(val) { baselineVar.value = val }
}
public init(text: String, font: Font? = nil, fill: Fill = Color.black, align: Align = .min, baseline: Baseline = .top, place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) {
self.textVar = Variable<String>(text)
self.fontVar = Variable<Font?>(font)
self.fillVar = Variable<Fill>(fill)
self.alignVar = Variable<Align>(align)
self.baselineVar = Variable<Baseline>(baseline)
super.init(
place: place,
opaque: opaque,
opacity: opacity,
clip: clip,
effect: effect,
visible: visible,
tag: tag
)
}
// GENERATED NOT
override internal func bounds() -> Rect {
let font: UIFont
if let f = self.font {
if let customFont = RenderUtils.loadFont(name: f.name, size:f.size) {
font = customFont
} else {
font = UIFont.systemFont(ofSize: CGFloat(f.size))
}
} else {
font = UIFont.systemFont(ofSize: UIFont.systemFontSize)
}
var stringAttributes: [String: AnyObject] = [:]
stringAttributes[NSFontAttributeName] = font
let size = (text as NSString).size(attributes: stringAttributes)
return Rect(
x: calculateAlignmentOffset(font: font),
y: calculateBaselineOffset(font: font),
w: size.width.doubleValue,
h: size.height.doubleValue
)
}
fileprivate func calculateBaselineOffset(font: UIFont) -> Double {
var baselineOffset = 0.0
switch baseline {
case .alphabetic:
baselineOffset = font.ascender.doubleValue
case .bottom:
baselineOffset = (font.ascender - font.descender).doubleValue
case .mid:
baselineOffset = ((font.ascender - font.descender) / 2).doubleValue
default:
break
}
return -baselineOffset
}
fileprivate func calculateAlignmentOffset(font: UIFont) -> Double {
let textAttributes = [
NSFontAttributeName: font
]
let textSize = NSString(string: text).size(attributes: textAttributes)
var alignmentOffset = 0.0
switch align {
case .mid:
alignmentOffset = (textSize.width / 2).doubleValue
case .max:
alignmentOffset = textSize.width.doubleValue
default:
break
}
return -alignmentOffset
}
return -alignmentOffset
}
}

View File

@ -0,0 +1,89 @@
//
// Common_iOS.swift
// Macaw
//
// Created by Daniil Manin on 8/10/17.
// Copyright © 2017 Exyte. All rights reserved.
//
import Foundation
#if os(iOS)
import UIKit
public typealias MRectCorner = UIRectCorner
public typealias MFont = UIFont
public typealias MColor = UIColor
public typealias MEvent = UIEvent
public typealias MTouch = UITouch
public typealias MImage = UIImage
public typealias MBezierPath = UIBezierPath
public typealias MGestureRecognizer = UIGestureRecognizer
public typealias MGestureRecognizerState = UIGestureRecognizerState
public typealias MGestureRecognizerDelegate = UIGestureRecognizerDelegate
public typealias MTapGestureRecognizer = UITapGestureRecognizer
public typealias MPanGestureRecognizer = UIPanGestureRecognizer
public typealias MPinchGestureRecognizer = UIPinchGestureRecognizer
public typealias MRotationGestureRecognizer = UIRotationGestureRecognizer
public typealias MScreen = UIScreen
public typealias MDisplayLink = CADisplayLink
public typealias MViewContentMode = UIViewContentMode
extension MTapGestureRecognizer {
func mNumberOfTouches() -> Int {
return numberOfTouches
}
}
extension MPanGestureRecognizer {
func mNumberOfTouches() -> Int {
return numberOfTouches
}
func mLocationOfTouch(_ touch: Int, inView: UIView?) -> CGPoint {
return super.location(ofTouch: touch, in: inView)
}
}
extension MRotationGestureRecognizer {
final var mRotation: CGFloat {
get {
return rotation
}
set {
rotation = newValue
}
}
}
extension MPinchGestureRecognizer {
var mScale: CGFloat {
get {
return scale
}
set {
scale = newValue
}
}
func mLocationOfTouch(_ touch: Int, inView: UIView?) -> CGPoint {
return super.location(ofTouch: touch, in: inView)
}
}
extension MFont {
class var mSystemFontSize: CGFloat {
return UIFont.systemFontSize
}
}
extension UIScreen {
var mScale: CGFloat {
return self.scale
}
}
#endif

View File

@ -0,0 +1,50 @@
//
// Graphics_iOS.swift
// Macaw
//
// Created by Daniil Manin on 8/17/17.
// Copyright © 2017 Exyte. All rights reserved.
//
import Foundation
#if os(iOS)
import UIKit
func MGraphicsGetCurrentContext() -> CGContext? {
return UIGraphicsGetCurrentContext()
}
func MGraphicsGetImageFromCurrentImageContext() -> MImage! {
return UIGraphicsGetImageFromCurrentImageContext()
}
func MGraphicsPushContext(_ context: CGContext) {
UIGraphicsPushContext(context)
}
func MGraphicsPopContext() {
UIGraphicsPopContext()
}
func MGraphicsEndImageContext() {
UIGraphicsEndImageContext()
}
func MImagePNGRepresentation(_ image: MImage) -> Data? {
return UIImagePNGRepresentation(image)
}
func MImageJPEGRepresentation(_ image: MImage, _ quality: CGFloat = 0.8) -> Data? {
return UIImageJPEGRepresentation(image, quality)
}
func MMainScreen() -> MScreen? {
return MScreen.main
}
func MGraphicsBeginImageContextWithOptions(_ size: CGSize, _ opaque: Bool, _ scale: CGFloat) {
UIGraphicsBeginImageContextWithOptions(size, opaque, scale)
}
#endif

View File

@ -0,0 +1,97 @@
//
// MView_iOS.swift
// Macaw
//
// Created by Daniil Manin on 8/17/17.
// Copyright © 2017 Exyte. All rights reserved.
//
import Foundation
#if os(iOS)
import UIKit
open class MView: UIView, Touchable {
var mLayer: CALayer? {
return self.layer
}
var mGestureRecognizers: [MGestureRecognizer]? {
return self.gestureRecognizers
}
func removeGestureRecognizers() {
self.gestureRecognizers?.removeAll()
}
open override func touchesBegan(_ touches: Set<MTouch>, with event: MEvent?) {
super.touchesBegan(touches, with: event)
let touchPoints = touches.map { touch -> MTouchEvent in
let location = touch.location(in: self)
let id = Int(bitPattern: Unmanaged.passUnretained(touch).toOpaque())
return MTouchEvent(x: Double(location.x), y: Double(location.y), id: id)
}
mTouchesBegan(touchPoints)
}
open override func touchesMoved(_ touches: Set<MTouch>, with event: MEvent?) {
super.touchesMoved(touches, with: event)
let touchPoints = touches.map { touch -> MTouchEvent in
let location = touch.location(in: self)
let id = Int(bitPattern: Unmanaged.passUnretained(touch).toOpaque())
return MTouchEvent(x: Double(location.x), y: Double(location.y), id: id)
}
self.mTouchesMoved(touchPoints)
}
open override func touchesEnded(_ touches: Set<MTouch>, with event: MEvent?) {
super.touchesEnded(touches, with: event)
let touchPoints = touches.map { touch -> MTouchEvent in
let location = touch.location(in: self)
let id = Int(bitPattern: Unmanaged.passUnretained(touch).toOpaque())
return MTouchEvent(x: Double(location.x), y: Double(location.y), id: id)
}
mTouchesEnded(touchPoints)
}
override open func touchesCancelled(_ touches: Set<MTouch>, with event: MEvent?) {
super.touchesCancelled(touches, with: event)
let touchPoints = touches.map { touch -> MTouchEvent in
let location = touch.location(in: self)
let id = Int(bitPattern: Unmanaged.passUnretained(touch).toOpaque())
return MTouchEvent(x: Double(location.x), y: Double(location.y), id: id)
}
mTouchesCancelled(touchPoints)
}
func mTouchesBegan(_ touches: [MTouchEvent]) {
}
func mTouchesMoved(_ touches: [MTouchEvent]) {
}
func mTouchesEnded(_ touches: [MTouchEvent]) {
}
func mTouchesCancelled(_ touches: [MTouchEvent]) {
}
}
#endif

View File

@ -0,0 +1,130 @@
//
// Common_macOS.swift
// Macaw
//
// Created by Daniil Manin on 8/10/17.
// Copyright © 2017 Exyte. All rights reserved.
//
import Foundation
#if os(OSX)
import Cocoa
import Quartz
public typealias MFont = NSFont
public typealias MColor = NSColor
public typealias MEvent = NSEvent
public typealias MTouch = NSTouch
public typealias MImage = NSImage
public typealias MBezierPath = NSBezierPath
public typealias MGestureRecognizer = NSGestureRecognizer
public typealias MGestureRecognizerState = NSGestureRecognizerState
public typealias MGestureRecognizerDelegate = NSGestureRecognizerDelegate
public typealias MTapGestureRecognizer = NSClickGestureRecognizer
public typealias MPanGestureRecognizer = NSPanGestureRecognizer
public typealias MPinchGestureRecognizer = NSMagnificationGestureRecognizer
public typealias MRotationGestureRecognizer = NSRotationGestureRecognizer
public typealias MScreen = NSScreen
extension MGestureRecognizer {
var cancelsTouchesInView: Bool {
get {
return false
} set { }
}
}
extension MTapGestureRecognizer {
func mNumberOfTouches() -> Int {
return 1
}
}
extension MPanGestureRecognizer {
func mNumberOfTouches() -> Int {
return 1
}
func mLocationOfTouch(_ touch: Int, inView: NSView?) -> NSPoint {
return super.location(in: inView)
}
}
extension MRotationGestureRecognizer {
var velocity: CGFloat {
return 0.1
}
var mRotation: CGFloat {
get {
return -rotation
}
set {
rotation = -newValue
}
}
}
extension MPinchGestureRecognizer {
var mScale: CGFloat {
get {
return magnification + 1.0
}
set {
magnification = newValue - 1.0
}
}
func mLocationOfTouch(_ touch: Int, inView view: NSView?) -> NSPoint {
return super.location(in: view)
}
}
extension NSFont {
var lineHeight: CGFloat {
return self.boundingRectForFont.size.height
}
class var mSystemFontSize: CGFloat {
return NSFont.systemFontSize()
}
}
extension NSScreen {
var mScale: CGFloat {
return self.backingScaleFactor
}
}
extension NSImage {
var cgImage: CGImage? {
return self.cgImage(forProposedRect: nil, context: nil, hints: nil)
}
}
extension NSTouch {
func location(in view: NSView) -> NSPoint {
let n = self.normalizedPosition
let b = view.bounds
return NSPoint(x: b.origin.x + b.size.width * n.x, y: b.origin.y + b.size.height * n.y)
}
}
extension NSString {
@nonobjc
func size(attributes attrs: [String : Any]? = nil) -> NSSize {
return size(withAttributes: attrs)
}
}
func MMainScreen() -> MScreen? {
return MScreen.main()
}
#endif

View File

@ -0,0 +1,96 @@
//
// Graphics_macOS.swift
// Macaw
//
// Created by Daniil Manin on 8/17/17.
// Copyright © 2017 Exyte. All rights reserved.
//
import Foundation
#if os(OSX)
import AppKit
private var imageContextStack: [CGFloat] = []
func MGraphicsGetCurrentContext() -> CGContext? {
return NSGraphicsContext.current()?.cgContext
}
func MGraphicsPushContext(_ context: CGContext) {
let cx = NSGraphicsContext(cgContext: context, flipped: true)
NSGraphicsContext.saveGraphicsState()
NSGraphicsContext.setCurrent(cx)
}
func MGraphicsPopContext() {
NSGraphicsContext.restoreGraphicsState()
}
func MImagePNGRepresentation(_ image: MImage) -> Data? {
image.lockFocus()
let rep = NSBitmapImageRep(focusedViewRect: NSMakeRect(0, 0, image.size.width, image.size.height))
image.unlockFocus()
return rep?.representation(using: NSPNGFileType, properties: [:])
}
func MImageJPEGRepresentation(_ image: MImage, _ quality: CGFloat = 0.9) -> Data? {
image.lockFocus()
let rep = NSBitmapImageRep(focusedViewRect: NSMakeRect(0, 0, image.size.width, image.size.height))
image.unlockFocus()
return rep?.representation(using: NSJPEGFileType, properties: [NSImageCompressionFactor: quality])
}
func MGraphicsBeginImageContextWithOptions(_ size: CGSize, _ opaque: Bool, _ scale: CGFloat) {
var scale = scale
if scale == 0.0 {
scale = NSScreen.main()?.backingScaleFactor ?? 1.0
}
let width = Int(size.width * scale)
let height = Int(size.height * scale)
if width > 0 && height > 0 {
imageContextStack.append(scale)
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 {
return
}
ctx.concatenate(CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: CGFloat(height)))
ctx.scaleBy(x: scale, y: scale)
MGraphicsPushContext(ctx)
}
}
func MGraphicsGetImageFromCurrentImageContext() -> MImage? {
if !imageContextStack.isEmpty {
guard let ctx = MGraphicsGetCurrentContext() else {
return nil
}
let scale = imageContextStack.last!
if let theCGImage = ctx.makeImage() {
let size = CGSize(width: CGFloat(ctx.width) / scale, height: CGFloat(ctx.height) / scale)
let image = NSImage(cgImage: theCGImage, size: size)
return image
}
}
return nil
}
func MGraphicsEndImageContext() {
if imageContextStack.last != nil {
imageContextStack.removeLast()
MGraphicsPopContext()
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More