├── ACEDrawingView ├── include │ ├── ACEDrawingView.h │ ├── ACEDrawingTools.h │ ├── ACEDrawingLabelView.h │ └── ACEDrawingToolState.h ├── ACEDraggableText │ ├── sticker_close.png │ ├── sticker_resize.png │ ├── sticker_close@2x.png │ ├── sticker_close@3x.png │ ├── sticker_resize@2x.png │ └── sticker_resize@3x.png ├── ACEDrawingToolState.h ├── ACEDrawingToolState.m ├── ACEDrawingTools.h ├── ACEDrawingView.h ├── ACEDrawingLabelView.h ├── ACEDrawingLabelView.m └── ACEDrawingTools.m ├── Example.png ├── .gitignore ├── Example2.png ├── ACEDrawingViewDemo ├── en.lproj │ ├── InfoPlist.strings │ └── ACEViewController.xib ├── Default.png ├── Default@2x.png ├── Default-568h@2x.png ├── ACEDrawingViewDemo-Prefix.pch ├── main.m ├── ACEAppDelegate.h ├── ACEViewController.h ├── ACEDrawingViewDemo-Info.plist ├── ACEAppDelegate.m └── ACEViewController.m ├── Pods ├── Headers │ ├── Private │ │ └── ACEDrawingView │ │ │ ├── ACEDrawingTools.h │ │ │ ├── ACEDrawingView.h │ │ │ ├── ACEDrawingLabelView.h │ │ │ └── ACEDrawingToolState.h │ └── Public │ │ └── ACEDrawingView │ │ ├── ACEDrawingTools.h │ │ ├── ACEDrawingView.h │ │ ├── ACEDrawingLabelView.h │ │ └── ACEDrawingToolState.h ├── Target Support Files │ ├── ACEDrawingView │ │ ├── ACEDrawingView-prefix.pch │ │ ├── ACEDrawingView-dummy.m │ │ ├── ACEDrawingView.xcconfig │ │ └── ResourceBundle-ACEDraggableText-Info.plist │ ├── Pods-ACEDrawingViewDemo │ │ ├── Pods-ACEDrawingViewDemo-dummy.m │ │ ├── Pods-ACEDrawingViewDemo.debug.xcconfig │ │ ├── Pods-ACEDrawingViewDemo.release.xcconfig │ │ ├── Pods-ACEDrawingViewDemo-frameworks.sh │ │ ├── Pods-ACEDrawingViewDemo-resources.sh │ │ ├── Pods-ACEDrawingViewDemo-acknowledgements.markdown │ │ └── Pods-ACEDrawingViewDemo-acknowledgements.plist │ └── Pods-ACEDrawingViewDemoTests │ │ ├── Pods-ACEDrawingViewDemoTests-acknowledgements.markdown │ │ ├── Pods-ACEDrawingViewDemoTests-dummy.m │ │ ├── Pods-ACEDrawingViewDemoTests.debug.xcconfig │ │ ├── Pods-ACEDrawingViewDemoTests.release.xcconfig │ │ ├── Pods-ACEDrawingViewDemoTests-acknowledgements.plist │ │ ├── Pods-ACEDrawingViewDemoTests-frameworks.sh │ │ └── Pods-ACEDrawingViewDemoTests-resources.sh ├── Manifest.lock ├── Local Podspecs │ └── ACEDrawingView.podspec.json └── Pods.xcodeproj │ └── xcuserdata │ └── amin.xcuserdatad │ └── xcschemes │ ├── xcschememanagement.plist │ ├── ACEDrawingView.xcscheme │ ├── Pods-ACEDrawingViewDemo.xcscheme │ ├── ACEDrawingView-ACEDraggableText.xcscheme │ └── Pods-ACEDrawingViewDemoTests.xcscheme ├── ACEDrawingViewDemo.xcworkspace ├── xcuserdata │ └── amin.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── contents.xcworkspacedata ├── Podfile ├── Podfile.lock ├── ChangeLog.txt ├── Package.swift ├── ACEDrawingView.podspec ├── ACEDrawingViewDemoTests ├── Info.plist └── ACEDrawingViewTest.m ├── ACEDrawingViewDemo.xcodeproj ├── xcuserdata │ └── amin.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── xcshareddata │ └── xcschemes │ ├── ACEDrawingViewDemoTests.xcscheme │ └── ACEDrawingViewDemo.xcscheme ├── .github └── workflows │ └── CI.yml ├── README.md └── LICENSE.txt /ACEDrawingView/include/ACEDrawingView.h: -------------------------------------------------------------------------------- 1 | ../ACEDrawingView.h -------------------------------------------------------------------------------- /ACEDrawingView/include/ACEDrawingTools.h: -------------------------------------------------------------------------------- 1 | ../ACEDrawingTools.h -------------------------------------------------------------------------------- /ACEDrawingView/include/ACEDrawingLabelView.h: -------------------------------------------------------------------------------- 1 | ../ACEDrawingLabelView.h -------------------------------------------------------------------------------- /ACEDrawingView/include/ACEDrawingToolState.h: -------------------------------------------------------------------------------- 1 | ../ACEDrawingToolState.h -------------------------------------------------------------------------------- /Example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acerbetti/ACEDrawingView/HEAD/Example.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Swift Package Manager 2 | .build/ 3 | .swiftpm/ 4 | Package.resolved 5 | -------------------------------------------------------------------------------- /Example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acerbetti/ACEDrawingView/HEAD/Example2.png -------------------------------------------------------------------------------- /ACEDrawingViewDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Pods/Headers/Private/ACEDrawingView/ACEDrawingTools.h: -------------------------------------------------------------------------------- 1 | ../../../../ACEDrawingView/ACEDrawingTools.h -------------------------------------------------------------------------------- /Pods/Headers/Private/ACEDrawingView/ACEDrawingView.h: -------------------------------------------------------------------------------- 1 | ../../../../ACEDrawingView/ACEDrawingView.h -------------------------------------------------------------------------------- /Pods/Headers/Public/ACEDrawingView/ACEDrawingTools.h: -------------------------------------------------------------------------------- 1 | ../../../../ACEDrawingView/ACEDrawingTools.h -------------------------------------------------------------------------------- /Pods/Headers/Public/ACEDrawingView/ACEDrawingView.h: -------------------------------------------------------------------------------- 1 | ../../../../ACEDrawingView/ACEDrawingView.h -------------------------------------------------------------------------------- /Pods/Headers/Private/ACEDrawingView/ACEDrawingLabelView.h: -------------------------------------------------------------------------------- 1 | ../../../../ACEDrawingView/ACEDrawingLabelView.h -------------------------------------------------------------------------------- /Pods/Headers/Private/ACEDrawingView/ACEDrawingToolState.h: -------------------------------------------------------------------------------- 1 | ../../../../ACEDrawingView/ACEDrawingToolState.h -------------------------------------------------------------------------------- /Pods/Headers/Public/ACEDrawingView/ACEDrawingLabelView.h: -------------------------------------------------------------------------------- 1 | ../../../../ACEDrawingView/ACEDrawingLabelView.h -------------------------------------------------------------------------------- /Pods/Headers/Public/ACEDrawingView/ACEDrawingToolState.h: -------------------------------------------------------------------------------- 1 | ../../../../ACEDrawingView/ACEDrawingToolState.h -------------------------------------------------------------------------------- /ACEDrawingViewDemo/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acerbetti/ACEDrawingView/HEAD/ACEDrawingViewDemo/Default.png -------------------------------------------------------------------------------- /ACEDrawingViewDemo/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acerbetti/ACEDrawingView/HEAD/ACEDrawingViewDemo/Default@2x.png -------------------------------------------------------------------------------- /Pods/Target Support Files/ACEDrawingView/ACEDrawingView-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acerbetti/ACEDrawingView/HEAD/ACEDrawingViewDemo/Default-568h@2x.png -------------------------------------------------------------------------------- /ACEDrawingView/ACEDraggableText/sticker_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acerbetti/ACEDrawingView/HEAD/ACEDrawingView/ACEDraggableText/sticker_close.png -------------------------------------------------------------------------------- /ACEDrawingView/ACEDraggableText/sticker_resize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acerbetti/ACEDrawingView/HEAD/ACEDrawingView/ACEDraggableText/sticker_resize.png -------------------------------------------------------------------------------- /ACEDrawingView/ACEDraggableText/sticker_close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acerbetti/ACEDrawingView/HEAD/ACEDrawingView/ACEDraggableText/sticker_close@2x.png -------------------------------------------------------------------------------- /ACEDrawingView/ACEDraggableText/sticker_close@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acerbetti/ACEDrawingView/HEAD/ACEDrawingView/ACEDraggableText/sticker_close@3x.png -------------------------------------------------------------------------------- /ACEDrawingView/ACEDraggableText/sticker_resize@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acerbetti/ACEDrawingView/HEAD/ACEDrawingView/ACEDraggableText/sticker_resize@2x.png -------------------------------------------------------------------------------- /ACEDrawingView/ACEDraggableText/sticker_resize@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acerbetti/ACEDrawingView/HEAD/ACEDrawingView/ACEDraggableText/sticker_resize@3x.png -------------------------------------------------------------------------------- /ACEDrawingViewDemo.xcworkspace/xcuserdata/amin.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/ACEDrawingView/ACEDrawingView-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_ACEDrawingView : NSObject 3 | @end 4 | @implementation PodsDummy_ACEDrawingView 5 | @end 6 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo.xcworkspace/xcuserdata/amin.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acerbetti/ACEDrawingView/HEAD/ACEDrawingViewDemo.xcworkspace/xcuserdata/amin.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemo/Pods-ACEDrawingViewDemo-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_ACEDrawingViewDemo : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_ACEDrawingViewDemo 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemoTests/Pods-ACEDrawingViewDemoTests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemoTests/Pods-ACEDrawingViewDemoTests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_ACEDrawingViewDemoTests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_ACEDrawingViewDemoTests 5 | @end 6 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | platform :ios, '8.0' 3 | 4 | target 'ACEDrawingViewDemo' do 5 | pod 'ACEDrawingView', :path => './' 6 | 7 | target 'ACEDrawingViewDemoTests' do 8 | inherit! :search_paths 9 | # Pods for testing 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - ACEDrawingView (2.0.0) 3 | 4 | DEPENDENCIES: 5 | - ACEDrawingView (from `./`) 6 | 7 | EXTERNAL SOURCES: 8 | ACEDrawingView: 9 | :path: "./" 10 | 11 | SPEC CHECKSUMS: 12 | ACEDrawingView: bb4d609aca2bb87095159ef6b2b315fe8f906134 13 | 14 | PODFILE CHECKSUM: ae4a0cce198c076347e75dadfc2e014676d9c60e 15 | 16 | COCOAPODS: 1.1.0.rc.2 17 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - ACEDrawingView (2.0.0) 3 | 4 | DEPENDENCIES: 5 | - ACEDrawingView (from `./`) 6 | 7 | EXTERNAL SOURCES: 8 | ACEDrawingView: 9 | :path: "./" 10 | 11 | SPEC CHECKSUMS: 12 | ACEDrawingView: bb4d609aca2bb87095159ef6b2b315fe8f906134 13 | 14 | PODFILE CHECKSUM: ae4a0cce198c076347e75dadfc2e014676d9c60e 15 | 16 | COCOAPODS: 1.1.0.rc.2 17 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo/ACEDrawingViewDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ACEDrawingViewDemo' target in the 'ACEDrawingViewDemo' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /ChangeLog.txt: -------------------------------------------------------------------------------- 1 | 01/15/2012 - v1.0 2 | ----------------- 3 | + Draw with multiple tools (pen, line, rectangle, ellipse) 4 | 5 | 6 | 01/13/2012 - v0.2 7 | ----------------- 8 | - Performance improvements (use an image to cache the drawing) 9 | 10 | 11 | 01/06/2013 - v0.1 12 | ----------------- 13 | + Initial release 14 | + Undo / Redo stack 15 | + Multiple color lines 16 | + Multiple width lines 17 | + Multiple alpha values 18 | + Export screenshot -------------------------------------------------------------------------------- /ACEDrawingViewDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ACEDrawingViewDemo 4 | // 5 | // Created by Stefano Acerbetti on 1/6/13. 6 | // Copyright (c) 2013 Stefano Acerbetti. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "ACEAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([ACEAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo/ACEAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ACEAppDelegate.h 3 | // ACEDrawingViewDemo 4 | // 5 | // Created by Stefano Acerbetti on 1/6/13. 6 | // Copyright (c) 2013 Stefano Acerbetti. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ACEViewController; 12 | 13 | @interface ACEAppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) ACEViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "ACEDrawingView", 7 | platforms: [ 8 | .iOS(.v9), 9 | ], 10 | products: [ 11 | .library( 12 | name: "ACEDrawingView", 13 | targets: ["ACEDrawingView"]), 14 | ], 15 | dependencies: [], 16 | targets: [ 17 | .target( 18 | name: "ACEDrawingView", 19 | path: "ACEDrawingView", 20 | resources: [.process("ACEDraggableText")]), 21 | ] 22 | ) 23 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo.xcworkspace/xcuserdata/amin.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | IssueFilterStyle 12 | ShowActiveSchemeOnly 13 | LiveSourceIssuesEnabled 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/ACEDrawingView/ACEDrawingView.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/ACEDrawingView 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/ACEDrawingView" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/ACEDrawingView" 4 | OTHER_LDFLAGS = -framework "QuartzCore" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemoTests/Pods-ACEDrawingViewDemoTests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/ACEDrawingView" 4 | LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/ACEDrawingView" 5 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/ACEDrawingView" 6 | OTHER_LDFLAGS = $(inherited) -ObjC 7 | PODS_BUILD_DIR = $BUILD_DIR 8 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemoTests/Pods-ACEDrawingViewDemoTests.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/ACEDrawingView" 4 | LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/ACEDrawingView" 5 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/ACEDrawingView" 6 | OTHER_LDFLAGS = $(inherited) -ObjC 7 | PODS_BUILD_DIR = $BUILD_DIR 8 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemo/Pods-ACEDrawingViewDemo.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/ACEDrawingView" 4 | LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/ACEDrawingView" 5 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/ACEDrawingView" 6 | OTHER_LDFLAGS = $(inherited) -ObjC -l"ACEDrawingView" -framework "QuartzCore" 7 | PODS_BUILD_DIR = $BUILD_DIR 8 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemo/Pods-ACEDrawingViewDemo.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/ACEDrawingView" 4 | LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/ACEDrawingView" 5 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/ACEDrawingView" 6 | OTHER_LDFLAGS = $(inherited) -ObjC -l"ACEDrawingView" -framework "QuartzCore" 7 | PODS_BUILD_DIR = $BUILD_DIR 8 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /ACEDrawingView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'ACEDrawingView' 3 | s.version = '2.4.1' 4 | s.license = { :type => 'Apache 2.0 License', :file => 'LICENSE.txt' } 5 | s.summary = 'An open source iOS component to create a drawing app.' 6 | s.homepage = 'https://github.com/acerbetti/ACEDrawingView' 7 | s.author = { 'Stefano Acerbetti' => 'acerbetti@gmail.com' } 8 | s.source = { :git => 'https://github.com/acerbetti/ACEDrawingView.git', :tag => s.version.to_s } 9 | s.frameworks = 'QuartzCore' 10 | s.platform = :ios, '8.0' 11 | s.source_files = 'ACEDrawingView/*.{h,m}' 12 | s.resource_bundles = { 13 | 'ACEDraggableText' => ['ACEDrawingView/ACEDraggableText/*.png'], 14 | } 15 | s.requires_arc = true 16 | end 17 | -------------------------------------------------------------------------------- /Pods/Local Podspecs/ACEDrawingView.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ACEDrawingView", 3 | "version": "2.0.0", 4 | "license": { 5 | "type": "Apache 2.0 License", 6 | "file": "LICENSE.txt" 7 | }, 8 | "summary": "An open source iOS component to create a drawing app.", 9 | "homepage": "https://github.com/acerbetti/ACEDrawingView", 10 | "authors": { 11 | "Stefano Acerbetti": "acerbetti@gmail.com" 12 | }, 13 | "source": { 14 | "git": "https://github.com/acerbetti/ACEDrawingView.git", 15 | "tag": "v2.0.0" 16 | }, 17 | "frameworks": "QuartzCore", 18 | "platforms": { 19 | "ios": "7.0" 20 | }, 21 | "source_files": "ACEDrawingView/*.{h,m}", 22 | "resource_bundles": { 23 | "ACEDraggableText": [ 24 | "ACEDrawingView/ACEDraggableText/*.png" 25 | ] 26 | }, 27 | "requires_arc": true 28 | } 29 | -------------------------------------------------------------------------------- /ACEDrawingViewDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Pods/Target Support Files/ACEDrawingView/ResourceBundle-ACEDraggableText-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleIdentifier 8 | ${PRODUCT_BUNDLE_IDENTIFIER} 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | ${PRODUCT_NAME} 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 2.0.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo.xcodeproj/xcuserdata/amin.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ACEDrawingViewDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | ACEDrawingViewDemoTests.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 50F58C4B1D7F0F4B0050A4A0 21 | 22 | primary 23 | 24 | 25 | 7B5AD3F5169A072800904C6B 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemoTests/Pods-ACEDrawingViewDemoTests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /ACEDrawingViewDemoTests/ACEDrawingViewTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACEDrawingViewTest.m 3 | // ACEDrawingViewDemo 4 | // 5 | // Created by Stefano Acerbetti on 3/17/16. 6 | // Copyright © 2016 Stefano Acerbetti. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "ACEDrawingTools.h" 12 | #import "ACEDrawingView.h" 13 | 14 | @interface ACEDrawingViewTest : XCTestCase 15 | @property(nonatomic, strong) ACEDrawingView *drawingView; 16 | @end 17 | 18 | @implementation ACEDrawingViewTest 19 | 20 | - (void)setUp 21 | { 22 | [super setUp]; 23 | 24 | self.drawingView = [[ACEDrawingView alloc] initWithFrame:CGRectZero]; 25 | } 26 | 27 | - (void)tearDown 28 | { 29 | self.drawingView = nil; 30 | [super tearDown]; 31 | } 32 | 33 | - (void)testSetLineColor 34 | { 35 | self.drawingView.lineColor = [UIColor orangeColor]; 36 | 37 | ACEDrawingPenTool *tool = [[ACEDrawingPenTool alloc] init]; 38 | self.drawingView.customDrawTool = tool; 39 | XCTAssertNil(tool.lineColor); 40 | 41 | // this will initialize the tool 42 | [self.drawingView touchesBegan:[NSSet set] withEvent:nil]; 43 | XCTAssertEqualObjects(self.drawingView.lineColor, tool.lineColor); 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/amin.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ACEDrawingView-ACEDraggableText.xcscheme 8 | 9 | orderHint 10 | 3 11 | 12 | ACEDrawingView.xcscheme 13 | 14 | orderHint 15 | 2 16 | 17 | Pods-ACEDrawingViewDemo.xcscheme 18 | 19 | orderHint 20 | 4 21 | 22 | Pods-ACEDrawingViewDemoTests.xcscheme 23 | 24 | orderHint 25 | 5 26 | 27 | 28 | SuppressBuildableAutocreation 29 | 30 | 1EAC2211C6831F8284721A533FBC7F71 31 | 32 | primary 33 | 34 | 35 | 71203E851C1BBD4E7827AB6C6517F675 36 | 37 | primary 38 | 39 | 40 | B67CCED6D7A04DBA5CEECAA6287B1AD1 41 | 42 | primary 43 | 44 | 45 | F17D872C3F43222A59FFEBCC653E70BB 46 | 47 | primary 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo/ACEViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ACEViewController.h 3 | // ACEDrawingViewDemo 4 | // 5 | // Created by Stefano Acerbetti on 1/6/13. 6 | // Copyright (c) 2013 Stefano Acerbetti. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ACEDrawingView; 12 | 13 | @interface ACEViewController : UIViewController 14 | 15 | @property (nonatomic, unsafe_unretained) IBOutlet ACEDrawingView *drawingView; 16 | @property (nonatomic, unsafe_unretained) IBOutlet UISlider *lineWidthSlider; 17 | @property (nonatomic, unsafe_unretained) IBOutlet UISlider *lineAlphaSlider; 18 | @property (nonatomic, unsafe_unretained) IBOutlet UIImageView *previewImageView; 19 | @property (nonatomic, unsafe_unretained) IBOutlet UIImageView *baseImageView; 20 | 21 | @property (nonatomic, unsafe_unretained) IBOutlet UIBarButtonItem *undoButton; 22 | @property (nonatomic, unsafe_unretained) IBOutlet UIBarButtonItem *redoButton; 23 | @property (nonatomic, unsafe_unretained) IBOutlet UIBarButtonItem *colorButton; 24 | @property (nonatomic, unsafe_unretained) IBOutlet UIBarButtonItem *toolButton; 25 | @property (nonatomic, unsafe_unretained) IBOutlet UIBarButtonItem *alphaButton; 26 | 27 | // actions 28 | - (IBAction)undo:(id)sender; 29 | - (IBAction)redo:(id)sender; 30 | - (IBAction)clear:(id)sender; 31 | - (IBAction)takeScreenshot:(id)sender; 32 | 33 | // settings 34 | - (IBAction)colorChange:(id)sender; 35 | - (IBAction)toolChange:(id)sender; 36 | - (IBAction)toggleWidthSlider:(id)sender; 37 | - (IBAction)widthChange:(UISlider *)sender; 38 | - (IBAction)toggleAlphaSlider:(id)sender; 39 | - (IBAction)alphaChange:(UISlider *)sender; 40 | - (IBAction)imageChange:(id)sender; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /ACEDrawingView/ACEDrawingToolState.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ACEDrawingView: https://github.com/acerbetti/ACEDrawingView 3 | * 4 | * Copyright (c) 2016 Matthew Jackson 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #import "ACEDrawingTools.h" 27 | 28 | @protocol ACEDrawingTool; 29 | 30 | @interface ACEDrawingToolState : NSObject 31 | 32 | + (instancetype)stateForTool:(id)tool; 33 | + (instancetype)stateForTool:(id)tool capturePosition:(BOOL)capture; 34 | 35 | @property (nonatomic, readonly) id tool; 36 | 37 | @property (nonatomic, readonly) BOOL hasPositionObject; 38 | @property (nonatomic, readonly) id positionObject; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo/ACEDrawingViewDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSApplicationCategoryType 26 | 27 | LSRequiresIPhoneOS 28 | 29 | NSPhotoLibraryUsageDescription 30 | This app requires access to the photo library. 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UIStatusBarHidden 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | UISupportedInterfaceOrientations~ipad 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationPortraitUpsideDown 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /ACEDrawingView/ACEDrawingToolState.m: -------------------------------------------------------------------------------- 1 | /* 2 | * ACEDrawingView: https://github.com/acerbetti/ACEDrawingView 3 | * 4 | * Copyright (c) 2016 Matthew Jackson 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #import "ACEDrawingToolState.h" 27 | 28 | @interface ACEDrawingToolState () 29 | @property (nonatomic, strong) id tool; 30 | @property (nonatomic, strong) id positionObject; 31 | @end 32 | 33 | @implementation ACEDrawingToolState 34 | 35 | + (instancetype)stateForTool:(id)tool 36 | { 37 | return [ACEDrawingToolState stateForTool:tool capturePosition:NO]; 38 | } 39 | 40 | + (instancetype)stateForTool:(id)tool capturePosition:(BOOL)capture 41 | { 42 | ACEDrawingToolState *state = [ACEDrawingToolState new]; 43 | state.tool = tool; 44 | 45 | if (capture && [tool respondsToSelector:@selector(capturePositionObject)]) { 46 | state.positionObject = [tool capturePositionObject]; 47 | } 48 | 49 | return state; 50 | } 51 | 52 | - (BOOL)hasPositionObject 53 | { 54 | return self.positionObject != nil; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: "ACEDrawingView CI" 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - '*' 10 | 11 | jobs: 12 | Example: 13 | name: Example Project (Latest Stable Xcode) 14 | runs-on: macOS-11 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v2 18 | 19 | - name: Setup Xcode version 20 | uses: maxim-lobanov/setup-xcode@v1.4.0 21 | with: 22 | xcode-version: latest-stable 23 | 24 | - name: Run pod install 25 | run: pod install 26 | 27 | - name: Build Project 28 | uses: sersoft-gmbh/xcodebuild-action@v1.8.0 29 | with: 30 | workspace: ACEDrawingViewDemo.xcworkspace 31 | scheme: ACEDrawingViewDemo 32 | destination: name=iPhone 13 Pro 33 | action: test 34 | 35 | Pods: 36 | name: Cocoapods Lint (Latest Stable Xcode) 37 | runs-on: macOS-11 38 | steps: 39 | - name: Checkout 40 | uses: actions/checkout@v2 41 | 42 | - name: Setup Xcode version 43 | uses: maxim-lobanov/setup-xcode@v1.4.0 44 | with: 45 | xcode-version: latest-stable 46 | 47 | - name: Run pod lib lint dynamic-framework 48 | run: pod lib lint --allow-warnings --fail-fast 49 | 50 | - name: Run pod lib lint static-framework 51 | run: pod lib lint --allow-warnings --fail-fast --use-libraries --use-modular-headers 52 | 53 | SwiftPM: 54 | name: SwiftPM (Latest Stable Xcode) 55 | runs-on: macOS-11 56 | steps: 57 | - name: Checkout 58 | uses: actions/checkout@v2 59 | 60 | - name: Setup Xcode version 61 | uses: maxim-lobanov/setup-xcode@v1.4.0 62 | with: 63 | xcode-version: latest-stable 64 | 65 | - name: Build 66 | run: | # Move projects files temporarily to avoid interfering with SwiftPM build. 67 | mv "ACEDrawingViewDemo.xcodeproj" "ACEDrawingViewDemo.xcodeproj_temp" 68 | mv "ACEDrawingViewDemo.xcworkspace" "ACEDrawingViewDemo.xcworkspace_temp" 69 | xcodebuild -scheme ACEDrawingView -destination generic/platform=iOS 70 | mv "ACEDrawingViewDemo.xcodeproj_temp" "ACEDrawingViewDemo.xcodeproj" 71 | mv "ACEDrawingViewDemo.xcworkspace_temp" "ACEDrawingViewDemo.xcworkspace" 72 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo/ACEAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACEAppDelegate.m 3 | // ACEDrawingViewDemo 4 | // 5 | // Created by Stefano Acerbetti on 1/6/13. 6 | // Copyright (c) 2013 Stefano Acerbetti. All rights reserved. 7 | // 8 | 9 | #import "ACEAppDelegate.h" 10 | 11 | #import "ACEViewController.h" 12 | 13 | @implementation ACEAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 18 | self.viewController = [ACEViewController new]; 19 | self.window.rootViewController = self.viewController; 20 | [self.window makeKeyAndVisible]; 21 | return YES; 22 | } 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application 25 | { 26 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 27 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 28 | } 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application 31 | { 32 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 33 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 34 | } 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application 37 | { 38 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 39 | } 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application 42 | { 43 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 44 | } 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application 47 | { 48 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/amin.xcuserdatad/xcschemes/ACEDrawingView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/amin.xcuserdatad/xcschemes/Pods-ACEDrawingViewDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/amin.xcuserdatad/xcschemes/ACEDrawingView-ACEDraggableText.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/amin.xcuserdatad/xcschemes/Pods-ACEDrawingViewDemoTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo.xcodeproj/xcshareddata/xcschemes/ACEDrawingViewDemoTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 66 | 67 | 73 | 74 | 76 | 77 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemo/Pods-ACEDrawingViewDemo-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemoTests/Pods-ACEDrawingViewDemoTests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ACEDrawingView 2 | ============== 3 | [![Build Status](https://github.com/acerbetti/ACEDrawingView/workflows/ACEDrawingView%20CI/badge.svg?branch=master)](https://github.com/acerbetti/ACEDrawingView/actions) [![Swift Package Manager compatible](https://img.shields.io/badge/Swift%20Package%20Manager-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager) [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/ACEDrawingView.svg)](http://cocoadocs.org/docsets/ACEDrawingView) [![Platform](https://img.shields.io/cocoapods/p/ACEDrawingView.svg?style=flat)](http://cocoadocs.org/docsets/ACEDrawingView) 4 | 5 | See it in action 6 | -------------- 7 | Check out the [Doodle+](https://doodle.caplaz.com/) app to see this powerful library in action 8 | 9 | [![Download_on_the_App_Store_Badge_US-UK_RGB_blk_092917](https://user-images.githubusercontent.com/1741946/166181359-78139cc6-4c85-4cee-b783-0c9401ccdaeb.svg)](https://apps.apple.com/app/apple-store/id1615495712?pt=118008813&ct=GitHub&mt=8) 10 | 11 | 12 | Screenshots 13 | -------------- 14 | ![](https://github.com/acerbetti/ACEDrawingView/blob/master/Example.png?raw=true) ![](https://github.com/deviserRahul/ACEDrawingView/blob/master/Example2.png?raw=true) 15 | 16 | Purpose 17 | -------------- 18 | ACEDrawingView is a sample project showing exactly how to create a nice and smooth drawing application. In a few lines of code it supports drawing with different colors and line width. 19 | It also includes a full undo/redo stack and it can export the view as an UIImage. 20 | 21 | 22 | How-To 23 | ------------------ 24 | - Import the files from the folder "ACEDrawingView" to your project 25 | - From IB create a view and set the class to "ACEDrawingView" 26 | - Programmatically use the initWithFrame: and add it as subview 27 | 28 | ### CocoaPods(Recommended) 29 | 30 | 1. Add `pod 'ACEDrawingView'` to your Podfile. 31 | 2. Run `pod install` 32 | 33 | ### SwiftPM 34 | 35 | Add `.package(url: "https://github.com/acerbetti/ACEDrawingView.git", from: "2.3.0")` to your `package.swift` 36 | 37 | 38 | Features 39 | ------------------ 40 | - Undo / Redo stack 41 | - Multiple color lines 42 | - Multiple width lines 43 | - Multiple alpha values 44 | - Draw on image 45 | - Create screenshot of your masterpiece 46 | - Support for multiple tools (pen, line, rectangle, ellipse) 47 | - Eraser tool 48 | 49 | 50 | ARC Compatibility 51 | ------------------ 52 | This component can be used in projects using ARC or not 53 | 54 | 55 | Change Log 56 | ------------------ 57 | 09/21/2016 - v2.0 58 | - Added advanced draggable text tool 59 | - Removed legacy text tools 60 | 61 | 05/20/2014 - v1.3 62 | - Enhancements to text tool workflow 63 | - Fixed undo/redo with text tool 64 | 65 | 05/06/2014 - v1.2 66 | - Added text tool #16 67 | 68 | 06/09/2013 - v1.1 69 | - Added eraser tool #3 70 | 71 | 72 | 06/05/2013 - v1.0.1 73 | - Performance improvements (thanks to [ozzie](https://github.com/oziee)) 74 | 75 | 76 | 01/15/2012 - v1.0 77 | - Draw with multiple tools (pen, line, rectangle, ellipse) 78 | 79 | 80 | 01/13/2012 - v0.2 81 | - Performance improvements (use an image to cache the drawing) 82 | 83 | 84 | 01/06/2013 - v0.1 85 | - Initial release 86 | 87 | 88 | License 89 | ------------------ 90 | Copyright (c) 2016 Stefano Acerbetti 91 | 92 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 93 | 94 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 95 | 96 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 97 | -------------------------------------------------------------------------------- /ACEDrawingView/ACEDrawingTools.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ACEDrawingView: https://github.com/acerbetti/ACEDrawingView 3 | * 4 | * Copyright (c) 2013 Stefano Acerbetti 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #import 27 | #import "ACEDrawingToolState.h" 28 | 29 | @class ACEDrawingView; 30 | @class ACEDrawingLabelView; 31 | @class ACEDrawingToolState; 32 | 33 | #if __has_feature(objc_arc) 34 | #define ACE_HAS_ARC 1 35 | #define ACE_RETAIN(exp) (exp) 36 | #define ACE_RELEASE(exp) 37 | #define ACE_AUTORELEASE(exp) (exp) 38 | #else 39 | #define ACE_HAS_ARC 0 40 | #define ACE_RETAIN(exp) [(exp) retain] 41 | #define ACE_RELEASE(exp) [(exp) release] 42 | #define ACE_AUTORELEASE(exp) [(exp) autorelease] 43 | #endif 44 | 45 | 46 | @protocol ACEDrawingTool 47 | 48 | @property (nonatomic, strong) UIColor *lineColor; 49 | @property (nonatomic, assign) CGFloat lineAlpha; 50 | @property (nonatomic, assign) CGFloat lineWidth; 51 | 52 | - (void)setInitialPoint:(CGPoint)firstPoint; 53 | - (void)moveFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint; 54 | 55 | - (void)draw; 56 | 57 | - (ACEDrawingToolState *)captureToolState; 58 | 59 | @optional 60 | 61 | - (void)applyToolState:(ACEDrawingToolState *)state; 62 | 63 | - (id)capturePositionObject; 64 | 65 | @end 66 | 67 | #pragma mark - 68 | 69 | @interface ACEDrawingPenTool : UIBezierPath { 70 | CGMutablePathRef path; 71 | } 72 | 73 | - (CGRect)addPathPreviousPreviousPoint:(CGPoint)p2Point withPreviousPoint:(CGPoint)p1Point withCurrentPoint:(CGPoint)cpoint; 74 | 75 | @end 76 | 77 | #pragma mark - 78 | 79 | @interface ACEDrawingEraserTool : ACEDrawingPenTool 80 | 81 | @end 82 | 83 | #pragma mark - 84 | 85 | @interface ACEDrawingLineTool : NSObject 86 | 87 | @end 88 | 89 | #pragma mark - 90 | 91 | @interface ACEDrawingDraggableTextTool : NSObject 92 | 93 | @property (nonatomic, weak) ACEDrawingView *drawingView; 94 | @property (nonatomic, readonly) ACEDrawingLabelView *labelView; 95 | 96 | - (void)capturePosition; 97 | - (void)hideHandle; 98 | - (void)undraw; 99 | 100 | - (BOOL)canRedo; 101 | - (BOOL)redo; 102 | 103 | - (BOOL)canUndo; 104 | - (void)undo; 105 | 106 | @end 107 | 108 | #pragma mark - 109 | 110 | @interface ACEDrawingRectangleTool : NSObject 111 | 112 | @property (nonatomic, assign) BOOL fill; 113 | 114 | @end 115 | 116 | #pragma mark - 117 | 118 | @interface ACEDrawingEllipseTool : NSObject 119 | 120 | @property (nonatomic, assign) BOOL fill; 121 | 122 | @end 123 | 124 | #pragma mark - 125 | 126 | @interface ACEDrawingArrowTool : NSObject 127 | @end 128 | 129 | 130 | #pragma mark - 131 | 132 | @interface ACEDrawingTriangleTool : NSObject 133 | @property (nonatomic, assign) BOOL fill; 134 | @end 135 | 136 | #pragma mark - 137 | 138 | @interface ACEDrawingPentagonTool : NSObject 139 | @property (nonatomic, assign) BOOL fill; 140 | @end 141 | 142 | 143 | #pragma mark - 144 | 145 | @interface ACEDrawingHexagonTool : NSObject 146 | @property (nonatomic, assign) BOOL fill; 147 | @end 148 | 149 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo.xcodeproj/xcshareddata/xcschemes/ACEDrawingViewDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /ACEDrawingView/ACEDrawingView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ACEDrawingView: https://github.com/acerbetti/ACEDrawingView 3 | * 4 | * Copyright (c) 2013 Stefano Acerbetti 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #import 27 | 28 | /** 29 | Swift Package Manager uses this header as the umbrella header. Therefore import all public headers here. 30 | */ 31 | #import "ACEDrawingLabelView.h" 32 | #import "ACEDrawingTools.h" 33 | #import "ACEDrawingToolState.h" 34 | 35 | #define ACEDrawingViewVersion 2.0.1 36 | 37 | typedef enum { 38 | ACEDrawingToolTypePen, 39 | ACEDrawingToolTypeLine, 40 | ACEDrawingToolTypeArrow, 41 | ACEDrawingToolTypeRectagleStroke, 42 | ACEDrawingToolTypeRectagleFill, 43 | ACEDrawingToolTypeEllipseStroke, 44 | ACEDrawingToolTypeEllipseFill, 45 | ACEDrawingToolTypeEraser, 46 | ACEDrawingToolTypeDraggableText, 47 | ACEDrawingToolTypeCustom, 48 | ACEDrawingToolTypeTriangleStrokeFill, 49 | ACEDrawingToolTypeTriangleStroke, 50 | ACEDrawingToolTypePentagonStrokeFill, 51 | ACEDrawingToolTypePentagonStroke, 52 | ACEDrawingToolTypeHexagoneStrokeFill, 53 | ACEDrawingToolTypeHexagoneStroke, 54 | } ACEDrawingToolType; 55 | 56 | typedef NS_ENUM(NSUInteger, ACEDrawingMode) { 57 | ACEDrawingModeScale, 58 | ACEDrawingModeOriginalSize 59 | }; 60 | 61 | @protocol ACEDrawingViewDelegate, ACEDrawingTool; 62 | 63 | @interface ACEDrawingView : UIView 64 | 65 | @property (nonatomic, assign) ACEDrawingToolType drawTool; 66 | @property (nonatomic, strong) id customDrawTool; 67 | @property (nonatomic, assign) id delegate; 68 | 69 | // public properties 70 | @property (nonatomic, strong) UIColor *lineColor; 71 | @property (nonatomic, assign) CGFloat lineWidth; 72 | @property (nonatomic, assign) CGFloat lineAlpha; 73 | @property (nonatomic, assign) CGFloat edgeSnapThreshold; 74 | @property (nonatomic, assign) ACEDrawingMode drawMode; 75 | 76 | @property (nonatomic, strong) NSString *draggableTextFontName; 77 | @property (nonatomic, strong) UIImage *draggableTextCloseImage; 78 | @property (nonatomic, strong) UIImage *draggableTextRotateImage; 79 | 80 | // get the current drawing 81 | @property (nonatomic, strong, readonly) UIImage *image; 82 | @property (nonatomic, strong) UIImage *backgroundImage; 83 | @property (nonatomic, readonly) NSUInteger undoSteps; 84 | 85 | // load external image 86 | - (void)loadImage:(UIImage *)image; 87 | - (void)loadImageData:(NSData *)imageData; 88 | 89 | // erase all 90 | - (void)clear; 91 | 92 | // cleanup in preparation for taking a snapshot 93 | - (void)prepareForSnapshot; 94 | 95 | // undo / redo 96 | - (BOOL)canUndo; 97 | - (void)undoLatestStep; 98 | 99 | - (BOOL)canRedo; 100 | - (void)redoLatestStep; 101 | 102 | - (UIImage *)applyDrawToImage:(UIImage *)baseImage; 103 | 104 | /** 105 | @discussion Discards the tool stack and renders them to prev_image, making the current state the 'start' state. 106 | (Can be called before resize to make content more predictable) 107 | */ 108 | - (void)commitAndDiscardToolStack; 109 | 110 | @end 111 | 112 | #pragma mark - 113 | 114 | @interface ACEDrawingView (Deprecated) 115 | @property (nonatomic, strong) UIImage *prev_image DEPRECATED_MSG_ATTRIBUTE("Use 'backgroundImage' instead."); 116 | @end 117 | 118 | #pragma mark - 119 | 120 | @protocol ACEDrawingViewDelegate 121 | 122 | @optional 123 | - (void)drawingView:(ACEDrawingView *)view willBeginDrawUsingTool:(id)tool; 124 | - (void)drawingView:(ACEDrawingView *)view didEndDrawUsingTool:(id)tool; 125 | - (void)drawingView:(ACEDrawingView *)view didRedoDrawUsingTool:(id)tool; 126 | - (void)drawingView:(ACEDrawingView *)view didUndoDrawUsingTool:(id)tool; 127 | - (void)drawingView:(ACEDrawingView *)view configureTextToolLabelView:(ACEDrawingLabelView *)label; 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemoTests/Pods-ACEDrawingViewDemoTests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | realpath() { 27 | DIRECTORY="$(cd "${1%/*}" && pwd)" 28 | FILENAME="${1##*/}" 29 | echo "$DIRECTORY/$FILENAME" 30 | } 31 | 32 | install_resource() 33 | { 34 | if [[ "$1" = /* ]] ; then 35 | RESOURCE_PATH="$1" 36 | else 37 | RESOURCE_PATH="${PODS_ROOT}/$1" 38 | fi 39 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 40 | cat << EOM 41 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 42 | EOM 43 | exit 1 44 | fi 45 | case $RESOURCE_PATH in 46 | *.storyboard) 47 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 48 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 49 | ;; 50 | *.xib) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.framework) 55 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 57 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 58 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 59 | ;; 60 | *.xcdatamodel) 61 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 62 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 63 | ;; 64 | *.xcdatamodeld) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 67 | ;; 68 | *.xcmappingmodel) 69 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 70 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 71 | ;; 72 | *.xcassets) 73 | ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") 74 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 75 | ;; 76 | *) 77 | echo "$RESOURCE_PATH" 78 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 79 | ;; 80 | esac 81 | } 82 | 83 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 85 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 86 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 87 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | fi 89 | rm -f "$RESOURCES_TO_COPY" 90 | 91 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 92 | then 93 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 94 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 95 | while read line; do 96 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 97 | XCASSET_FILES+=("$line") 98 | fi 99 | done <<<"$OTHER_XCASSETS" 100 | 101 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 102 | fi 103 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemo/Pods-ACEDrawingViewDemo-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | realpath() { 27 | DIRECTORY="$(cd "${1%/*}" && pwd)" 28 | FILENAME="${1##*/}" 29 | echo "$DIRECTORY/$FILENAME" 30 | } 31 | 32 | install_resource() 33 | { 34 | if [[ "$1" = /* ]] ; then 35 | RESOURCE_PATH="$1" 36 | else 37 | RESOURCE_PATH="${PODS_ROOT}/$1" 38 | fi 39 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 40 | cat << EOM 41 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 42 | EOM 43 | exit 1 44 | fi 45 | case $RESOURCE_PATH in 46 | *.storyboard) 47 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 48 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 49 | ;; 50 | *.xib) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.framework) 55 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 57 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 58 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 59 | ;; 60 | *.xcdatamodel) 61 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 62 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 63 | ;; 64 | *.xcdatamodeld) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 67 | ;; 68 | *.xcmappingmodel) 69 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 70 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 71 | ;; 72 | *.xcassets) 73 | ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") 74 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 75 | ;; 76 | *) 77 | echo "$RESOURCE_PATH" 78 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 79 | ;; 80 | esac 81 | } 82 | if [[ "$CONFIGURATION" == "Debug" ]]; then 83 | install_resource "$PODS_CONFIGURATION_BUILD_DIR/ACEDrawingView/ACEDraggableText.bundle" 84 | fi 85 | if [[ "$CONFIGURATION" == "Release" ]]; then 86 | install_resource "$PODS_CONFIGURATION_BUILD_DIR/ACEDrawingView/ACEDraggableText.bundle" 87 | fi 88 | 89 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 90 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 91 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 92 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 93 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 94 | fi 95 | rm -f "$RESOURCES_TO_COPY" 96 | 97 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 98 | then 99 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 100 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 101 | while read line; do 102 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 103 | XCASSET_FILES+=("$line") 104 | fi 105 | done <<<"$OTHER_XCASSETS" 106 | 107 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 108 | fi 109 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo/en.lproj/ACEViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 71 | 78 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /ACEDrawingView/ACEDrawingLabelView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ACEDrawingView: https://github.com/acerbetti/ACEDrawingView 3 | * 4 | * Copyright (c) 2016 Matthew Jackson 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #import 27 | #import 28 | 29 | @protocol ACEDrawingLabelViewDelegate; 30 | 31 | @interface ACEDrawingLabelView : UIView 32 | 33 | /** 34 | * Text Value 35 | */ 36 | @property (nonatomic, readonly) NSString *textValue; 37 | 38 | /** 39 | * Text color. 40 | * 41 | * Default: white color. 42 | */ 43 | @property (nonatomic, strong) UIColor *textColor; 44 | 45 | /** 46 | * Border stroke color. 47 | * 48 | * Default: red color. 49 | */ 50 | @property (nonatomic, strong) UIColor *borderColor; 51 | 52 | /** 53 | * Name of text field font. 54 | * 55 | * Default: current system font 56 | */ 57 | @property (nonatomic, copy) NSString *fontName; 58 | 59 | /** 60 | * Size of text field font. 61 | */ 62 | @property (nonatomic, assign) CGFloat fontSize; 63 | 64 | /** 65 | * Image for close button. 66 | * 67 | * Default: 68 | */ 69 | @property (nonatomic, strong) UIImage *closeImage; 70 | 71 | /** 72 | * Image for rotation button. 73 | * 74 | * Default: 75 | */ 76 | @property (nonatomic, strong) UIImage *rotateImage; 77 | 78 | /** 79 | * Placeholder. 80 | * 81 | * Default: nil 82 | */ 83 | @property (nonatomic, copy) NSAttributedString *attributedPlaceholder; 84 | 85 | /* 86 | * Base delegate protocols. 87 | */ 88 | @property (nonatomic, weak) id delegate; 89 | 90 | /** 91 | * Shows content shadow. 92 | * 93 | * Default: YES. 94 | */ 95 | @property (nonatomic) BOOL showsContentShadow; 96 | 97 | /** 98 | * Shows close button. 99 | * 100 | * Default: YES. 101 | */ 102 | @property (nonatomic, getter=isEnableClose) BOOL enableClose; 103 | 104 | /** 105 | * Shows rotate/resize butoon. 106 | * 107 | * Default: YES. 108 | */ 109 | @property (nonatomic, getter=isEnableRotate) BOOL enableRotate; 110 | 111 | /** 112 | * Resticts movements in superview bounds. 113 | * 114 | * Default: NO. 115 | */ 116 | @property (nonatomic, getter=isEnableMoveRestriction) BOOL enableMoveRestriction; 117 | 118 | /** 119 | * Check if underlying textField is first responder 120 | */ 121 | @property (nonatomic, readonly) BOOL isEditing; 122 | 123 | /** 124 | * Offset of the close button from the upper left corner 125 | * 126 | * Default: CGPointZero 127 | */ 128 | @property (nonatomic, assign) CGPoint closeButtonOffset; 129 | 130 | /** 131 | * Offset of the rotate button from the bottom right corner 132 | * 133 | * Default: CGPointZero 134 | */ 135 | @property (nonatomic, assign) CGPoint rotateButtonOffset; 136 | 137 | /** 138 | * Size of the close button 139 | * 140 | * Default: CGSize(24, 24) 141 | */ 142 | @property (nonatomic, assign) CGSize closeButtonSize; 143 | 144 | /** 145 | * Size of the rotate button 146 | * 147 | * Default: CGSize(24, 24) 148 | */ 149 | @property (nonatomic, assign) CGSize rotateButtonSize; 150 | 151 | /** 152 | * UIButton instance for the close button so you can configure e.g. the corner 153 | * radius 154 | */ 155 | @property (nonatomic, readonly) UIButton *closeButton; 156 | 157 | /** 158 | * UIButton instance for the rotate button so you can configure e.g. the corner 159 | * radius 160 | */ 161 | @property (nonatomic, readonly) UIButton *rotateButton; 162 | 163 | /** 164 | * Layer shadow color 165 | * 166 | * Default: UIColor.black 167 | */ 168 | @property (nonatomic, retain) UIColor *shadowColor; 169 | 170 | /** 171 | * Layer shadow offset 172 | * 173 | * Default: CGSize(0, 5) 174 | */ 175 | @property (nonatomic, assign) CGSize shadowOffset; 176 | 177 | /** 178 | * Layer shadow opacity 179 | * 180 | * Default: 1 181 | */ 182 | @property (nonatomic, assign) CGFloat shadowOpacity; 183 | 184 | /** 185 | * Layer shadow radius 186 | * 187 | * Default: 4 188 | */ 189 | @property (nonatomic, assign) CGFloat shadowRadius; 190 | 191 | /** 192 | * Hides border and control buttons. 193 | */ 194 | - (void)hideEditingHandles; 195 | 196 | /** 197 | * Shows border and control buttons. 198 | */ 199 | - (void)showEditingHandles; 200 | 201 | /** Sets the text alpha. 202 | * 203 | * @param alpha A value of text transparency. 204 | */ 205 | - (void)setTextAlpha:(CGFloat)alpha; 206 | 207 | /** Returns text alpha. 208 | * 209 | * @return A value of text transparency. 210 | */ 211 | - (CGFloat)textAlpha; 212 | 213 | /** 214 | * Resizes content to fit rect 215 | */ 216 | - (void)resizeInRect:(CGRect)rect; 217 | 218 | /** 219 | * Internal 220 | */ 221 | - (void)beginEditing; 222 | 223 | /** 224 | * Internal 225 | */ 226 | - (void)applyLayout; 227 | 228 | @end 229 | 230 | @protocol ACEDrawingLabelViewDelegate 231 | 232 | @optional 233 | 234 | /** 235 | * Occurs when a touch gesture event occurs on close button. 236 | * 237 | * @param label A label object informing the delegate about action. 238 | */ 239 | - (void)labelViewDidClose:(ACEDrawingLabelView *)label; 240 | 241 | /** 242 | * Occurs before border and control buttons will show. 243 | * 244 | * @param label A label object informing the delegate about showing. 245 | */ 246 | - (void)labelViewWillShowEditingHandles:(ACEDrawingLabelView *)label; 247 | 248 | /** 249 | * Occurs when border and control buttons was shown. 250 | * 251 | * @param label A label object informing the delegate about showing. 252 | */ 253 | - (void)labelViewDidShowEditingHandles:(ACEDrawingLabelView *)label; 254 | 255 | /** 256 | * Occurs when border and control buttons was hidden. 257 | * 258 | * @param label A label object informing the delegate about hiding. 259 | */ 260 | - (void)labelViewDidHideEditingHandles:(ACEDrawingLabelView *)label; 261 | 262 | /** 263 | * Occurs when label become first responder. 264 | * 265 | * @param label A label object informing the delegate about action. 266 | */ 267 | - (void)labelViewDidStartEditing:(ACEDrawingLabelView *)label; 268 | 269 | /** 270 | * Occurs when label starts move or rotate. 271 | * 272 | * @param label A label object informing the delegate about action. 273 | */ 274 | - (void)labelViewDidBeginEditing:(ACEDrawingLabelView *)label; 275 | 276 | /** 277 | * Occurs when label continues move or rotate. 278 | * 279 | * @param label A label object informing the delegate about action. 280 | */ 281 | - (void)labelViewDidChangeEditing:(ACEDrawingLabelView *)label; 282 | 283 | /** 284 | * Occurs when label ends move or rotate. 285 | * 286 | * @param label A label object informing the delegate about action. 287 | */ 288 | - (void)labelViewDidEndEditing:(ACEDrawingLabelView *)label; 289 | 290 | /** 291 | * Called just before a label is displayed. Configure values to make it look 292 | * the way you want. 293 | * 294 | * @param label A label object informing the delegate about action. 295 | */ 296 | - (void)labelViewNeedsConfiguration:(ACEDrawingLabelView *)label; 297 | 298 | @end 299 | 300 | #pragma mark - UITextField Category for DynamicFontSize 301 | 302 | @interface UITextField (DynamicFontSize) 303 | 304 | /** 305 | * Adjust font size to new bounds. 306 | * 307 | * @param newBounds A new bounds. 308 | */ 309 | - (void)adjustsFontSizeToFillRect:(CGRect)newBounds; 310 | 311 | /** 312 | * Adjust width to new text. 313 | */ 314 | - (void)adjustsWidthToFillItsContents; 315 | 316 | @end 317 | 318 | #pragma mark - ACEDrawingLabelViewTransform 319 | 320 | @interface ACEDrawingLabelViewTransform : NSObject 321 | 322 | + (instancetype)transform:(CGAffineTransform)transform atCenter:(CGPoint)center withBounds:(CGRect)bounds; 323 | 324 | @property (nonatomic, readonly) CGAffineTransform transform; 325 | @property (nonatomic, readonly) CGPoint center; 326 | @property (nonatomic, readonly) CGRect bounds; 327 | 328 | @end 329 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [2012] [JBoss, Home of Professional Open Source] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /ACEDrawingViewDemo/ACEViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACEViewController.m 3 | // ACEDrawingViewDemo 4 | // 5 | // Created by Stefano Acerbetti on 1/6/13. 6 | // Copyright (c) 2013 Stefano Acerbetti. All rights reserved. 7 | // 8 | 9 | #import "ACEViewController.h" 10 | #import "ACEDrawingView.h" 11 | #import 12 | #import 13 | 14 | #define kActionSheetColor 100 15 | #define kActionSheetTool 101 16 | 17 | @interface ACEViewController () 18 | 19 | @end 20 | 21 | @implementation ACEViewController 22 | 23 | - (void)viewDidLoad 24 | { 25 | [super viewDidLoad]; 26 | 27 | // set the delegate 28 | self.drawingView.delegate = self; 29 | 30 | // start with a black pen 31 | self.lineWidthSlider.value = self.drawingView.lineWidth; 32 | 33 | // init the preview image 34 | self.previewImageView.layer.borderColor = [[UIColor blackColor] CGColor]; 35 | self.previewImageView.layer.borderWidth = 2.0f; 36 | 37 | // set draggable text properties 38 | self.drawingView.draggableTextFontName = @"MarkerFelt-Thin"; 39 | } 40 | 41 | - (void)didReceiveMemoryWarning 42 | { 43 | [super didReceiveMemoryWarning]; 44 | // Dispose of any resources that can be recreated. 45 | } 46 | 47 | 48 | #pragma mark - Actions 49 | 50 | - (void)updateButtonStatus 51 | { 52 | self.undoButton.enabled = [self.drawingView canUndo]; 53 | self.redoButton.enabled = [self.drawingView canRedo]; 54 | } 55 | 56 | - (IBAction)takeScreenshot:(id)sender 57 | { 58 | // show the preview image 59 | UIImage *baseImage = [self.baseImageView image]; 60 | self.previewImageView.image = baseImage ? [self.drawingView applyDrawToImage:baseImage] : self.drawingView.image; 61 | self.previewImageView.hidden = NO; 62 | 63 | // close it after 3 seconds 64 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 65 | self.previewImageView.hidden = YES; 66 | }); 67 | 68 | // Save Snapshot in DocumentDirectory 69 | [self saveDrawingSnapshot]; 70 | } 71 | 72 | - (void)saveDrawingSnapshot 73 | { 74 | UIImage *snapShotImage = [self takeSnapshotOfDrawing:self.previewImageView]; 75 | NSData *data=UIImagePNGRepresentation(snapShotImage); 76 | 77 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 78 | NSString *documentsDirectory = [paths objectAtIndex:0]; 79 | 80 | NSString * timestamp = [NSString stringWithFormat:@"%@.png",[NSDate date]]; 81 | NSString *filePath = [documentsDirectory stringByAppendingPathComponent:timestamp]; 82 | [data writeToFile:filePath atomically:YES]; 83 | } 84 | 85 | - (UIImage *)takeSnapshotOfDrawing:(UIImageView *)imageView 86 | { 87 | UIGraphicsBeginImageContext(CGSizeMake(self.drawingView.frame.size.width, self.drawingView.frame.size.height)); 88 | [imageView drawViewHierarchyInRect:CGRectMake(0, 0, self.drawingView.frame.size.width, self.drawingView.frame.size.height) afterScreenUpdates:YES]; 89 | 90 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 91 | UIGraphicsEndImageContext(); 92 | 93 | return image; 94 | } 95 | 96 | 97 | - (IBAction)undo:(id)sender 98 | { 99 | [self.drawingView undoLatestStep]; 100 | [self updateButtonStatus]; 101 | } 102 | 103 | - (IBAction)redo:(id)sender 104 | { 105 | [self.drawingView redoLatestStep]; 106 | [self updateButtonStatus]; 107 | } 108 | 109 | - (IBAction)clear:(id)sender 110 | { 111 | if ([self.baseImageView image]) 112 | { 113 | [self.baseImageView setImage:nil]; 114 | [self.drawingView setFrame:self.baseImageView.frame]; 115 | } 116 | 117 | [self.drawingView clear]; 118 | [self updateButtonStatus]; 119 | } 120 | 121 | 122 | #pragma mark - ACEDrawing View Delegate 123 | 124 | - (void)drawingView:(ACEDrawingView *)view didEndDrawUsingTool:(id)tool; 125 | { 126 | [self updateButtonStatus]; 127 | } 128 | 129 | - (void)drawingView:(ACEDrawingView *)view configureTextToolLabelView:(ACEDrawingLabelView *)label; 130 | { 131 | // If you don't like the default text control styles, you can tweak them 132 | // in this delegate method. 133 | label.shadowOffset = CGSizeMake(0, 1); 134 | label.shadowOpacity = 0.5; 135 | label.shadowRadius = 1; 136 | label.closeButtonOffset = CGPointMake(-6, -6); 137 | label.rotateButtonOffset = CGPointMake(6, 6); 138 | } 139 | 140 | 141 | #pragma mark - Action Sheet Delegate 142 | 143 | - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 144 | { 145 | if (actionSheet.cancelButtonIndex != buttonIndex) { 146 | if (actionSheet.tag == kActionSheetColor) { 147 | 148 | self.colorButton.title = [actionSheet buttonTitleAtIndex:buttonIndex]; 149 | switch (buttonIndex) { 150 | case 0: 151 | self.drawingView.lineColor = [UIColor blackColor]; 152 | break; 153 | 154 | case 1: 155 | self.drawingView.lineColor = [UIColor redColor]; 156 | break; 157 | 158 | case 2: 159 | self.drawingView.lineColor = [UIColor greenColor]; 160 | break; 161 | 162 | case 3: 163 | self.drawingView.lineColor = [UIColor blueColor]; 164 | break; 165 | } 166 | 167 | } else { 168 | 169 | self.toolButton.title = [actionSheet buttonTitleAtIndex:buttonIndex]; 170 | switch (buttonIndex) { 171 | case 0: 172 | self.drawingView.drawTool = ACEDrawingToolTypePen; 173 | break; 174 | 175 | case 1: 176 | self.drawingView.drawTool = ACEDrawingToolTypeLine; 177 | break; 178 | 179 | case 2: 180 | self.drawingView.drawTool = ACEDrawingToolTypeArrow; 181 | break; 182 | 183 | case 3: 184 | self.drawingView.drawTool = ACEDrawingToolTypeRectagleStroke; 185 | break; 186 | 187 | case 4: 188 | self.drawingView.drawTool = ACEDrawingToolTypeRectagleFill; 189 | break; 190 | 191 | case 5: 192 | self.drawingView.drawTool = ACEDrawingToolTypeEllipseStroke; 193 | break; 194 | 195 | case 6: 196 | self.drawingView.drawTool = ACEDrawingToolTypeEllipseFill; 197 | break; 198 | 199 | case 7: 200 | self.drawingView.drawTool = ACEDrawingToolTypeEraser; 201 | break; 202 | 203 | case 8: 204 | self.drawingView.drawTool = ACEDrawingToolTypeDraggableText; 205 | break; 206 | 207 | case 9: 208 | self.drawingView.drawTool = ACEDrawingToolTypeTriangleStroke; 209 | break; 210 | 211 | 212 | case 10: 213 | self.drawingView.drawTool = ACEDrawingToolTypeTriangleStrokeFill; 214 | break; 215 | 216 | case 11: 217 | self.drawingView.drawTool = ACEDrawingToolTypePentagonStroke; 218 | break; 219 | 220 | case 12: 221 | self.drawingView.drawTool = ACEDrawingToolTypePentagonStrokeFill; 222 | break; 223 | 224 | case 13: 225 | 226 | self.drawingView.drawTool = ACEDrawingToolTypeHexagoneStroke; 227 | break; 228 | 229 | case 14: 230 | 231 | self.drawingView.drawTool = ACEDrawingToolTypeHexagoneStrokeFill; 232 | break; 233 | } 234 | 235 | // if eraser, disable color and alpha selection 236 | self.colorButton.enabled = self.alphaButton.enabled = buttonIndex != 6; 237 | } 238 | } 239 | } 240 | 241 | #pragma mark - Settings 242 | 243 | - (IBAction)colorChange:(id)sender 244 | { 245 | UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Selet a color" 246 | delegate:self 247 | cancelButtonTitle:@"Cancel" 248 | destructiveButtonTitle:nil 249 | otherButtonTitles:@"Black", @"Red", @"Green", @"Blue", nil]; 250 | 251 | [actionSheet setTag:kActionSheetColor]; 252 | [actionSheet showInView:self.view]; 253 | } 254 | 255 | - (IBAction)toolChange:(id)sender 256 | { 257 | UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Selet a tool" 258 | delegate:self 259 | cancelButtonTitle:@"Cancel" 260 | destructiveButtonTitle:nil 261 | otherButtonTitles:@"Pen", @"Line", @"Arrow", 262 | @"Rect (Stroke)", @"Rect (Fill)", 263 | @"Ellipse (Stroke)", @"Ellipse (Fill)", 264 | @"Eraser", @"Draggable Text", 265 | @"Tringle (Stroke)", 266 | @"Tringle (Fill)", 267 | @"Pentagon (Stroke)", 268 | @"Pentagon (Fill)", 269 | @"Hexagone (Stroke)", 270 | @"Hexagone (Fill)", 271 | nil]; 272 | 273 | [actionSheet setTag:kActionSheetTool]; 274 | [actionSheet showInView:self.view]; 275 | } 276 | 277 | - (IBAction)toggleWidthSlider:(id)sender 278 | { 279 | // toggle the slider 280 | self.lineWidthSlider.hidden = !self.lineWidthSlider.hidden; 281 | self.lineAlphaSlider.hidden = YES; 282 | } 283 | 284 | - (IBAction)widthChange:(UISlider *)sender 285 | { 286 | self.drawingView.lineWidth = sender.value; 287 | } 288 | 289 | - (IBAction)toggleAlphaSlider:(id)sender 290 | { 291 | // toggle the slider 292 | self.lineAlphaSlider.hidden = !self.lineAlphaSlider.hidden; 293 | self.lineWidthSlider.hidden = YES; 294 | } 295 | 296 | - (IBAction)alphaChange:(UISlider *)sender 297 | { 298 | self.drawingView.lineAlpha = sender.value; 299 | } 300 | 301 | - (IBAction)imageChange:(id)sender 302 | { 303 | UIImagePickerController* imagePicker = [[UIImagePickerController alloc] init]; 304 | imagePicker.sourceType = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] ? UIImagePickerControllerSourceTypeCamera : UIImagePickerControllerSourceTypePhotoLibrary; 305 | imagePicker.delegate = self; 306 | [self presentViewController:imagePicker animated:YES completion:nil]; 307 | } 308 | 309 | - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info 310 | { 311 | [self.drawingView clear]; 312 | [self updateButtonStatus]; 313 | 314 | UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage]; 315 | [self.baseImageView setImage:image]; 316 | [self.drawingView setFrame:AVMakeRectWithAspectRatioInsideRect(image.size, self.baseImageView.frame)]; 317 | 318 | [self dismissViewControllerAnimated:YES completion:nil]; 319 | } 320 | 321 | @end 322 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemo/Pods-ACEDrawingViewDemo-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## ACEDrawingView 5 | 6 | 7 | Apache License 8 | Version 2.0, January 2004 9 | http://www.apache.org/licenses/ 10 | 11 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 12 | 13 | 1. Definitions. 14 | 15 | "License" shall mean the terms and conditions for use, reproduction, 16 | and distribution as defined by Sections 1 through 9 of this document. 17 | 18 | "Licensor" shall mean the copyright owner or entity authorized by 19 | the copyright owner that is granting the License. 20 | 21 | "Legal Entity" shall mean the union of the acting entity and all 22 | other entities that control, are controlled by, or are under common 23 | control with that entity. For the purposes of this definition, 24 | "control" means (i) the power, direct or indirect, to cause the 25 | direction or management of such entity, whether by contract or 26 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 27 | outstanding shares, or (iii) beneficial ownership of such entity. 28 | 29 | "You" (or "Your") shall mean an individual or Legal Entity 30 | exercising permissions granted by this License. 31 | 32 | "Source" form shall mean the preferred form for making modifications, 33 | including but not limited to software source code, documentation 34 | source, and configuration files. 35 | 36 | "Object" form shall mean any form resulting from mechanical 37 | transformation or translation of a Source form, including but 38 | not limited to compiled object code, generated documentation, 39 | and conversions to other media types. 40 | 41 | "Work" shall mean the work of authorship, whether in Source or 42 | Object form, made available under the License, as indicated by a 43 | copyright notice that is included in or attached to the work 44 | (an example is provided in the Appendix below). 45 | 46 | "Derivative Works" shall mean any work, whether in Source or Object 47 | form, that is based on (or derived from) the Work and for which the 48 | editorial revisions, annotations, elaborations, or other modifications 49 | represent, as a whole, an original work of authorship. For the purposes 50 | of this License, Derivative Works shall not include works that remain 51 | separable from, or merely link (or bind by name) to the interfaces of, 52 | the Work and Derivative Works thereof. 53 | 54 | "Contribution" shall mean any work of authorship, including 55 | the original version of the Work and any modifications or additions 56 | to that Work or Derivative Works thereof, that is intentionally 57 | submitted to Licensor for inclusion in the Work by the copyright owner 58 | or by an individual or Legal Entity authorized to submit on behalf of 59 | the copyright owner. For the purposes of this definition, "submitted" 60 | means any form of electronic, verbal, or written communication sent 61 | to the Licensor or its representatives, including but not limited to 62 | communication on electronic mailing lists, source code control systems, 63 | and issue tracking systems that are managed by, or on behalf of, the 64 | Licensor for the purpose of discussing and improving the Work, but 65 | excluding communication that is conspicuously marked or otherwise 66 | designated in writing by the copyright owner as "Not a Contribution." 67 | 68 | "Contributor" shall mean Licensor and any individual or Legal Entity 69 | on behalf of whom a Contribution has been received by Licensor and 70 | subsequently incorporated within the Work. 71 | 72 | 2. Grant of Copyright License. Subject to the terms and conditions of 73 | this License, each Contributor hereby grants to You a perpetual, 74 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 75 | copyright license to reproduce, prepare Derivative Works of, 76 | publicly display, publicly perform, sublicense, and distribute the 77 | Work and such Derivative Works in Source or Object form. 78 | 79 | 3. Grant of Patent License. Subject to the terms and conditions of 80 | this License, each Contributor hereby grants to You a perpetual, 81 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 82 | (except as stated in this section) patent license to make, have made, 83 | use, offer to sell, sell, import, and otherwise transfer the Work, 84 | where such license applies only to those patent claims licensable 85 | by such Contributor that are necessarily infringed by their 86 | Contribution(s) alone or by combination of their Contribution(s) 87 | with the Work to which such Contribution(s) was submitted. If You 88 | institute patent litigation against any entity (including a 89 | cross-claim or counterclaim in a lawsuit) alleging that the Work 90 | or a Contribution incorporated within the Work constitutes direct 91 | or contributory patent infringement, then any patent licenses 92 | granted to You under this License for that Work shall terminate 93 | as of the date such litigation is filed. 94 | 95 | 4. Redistribution. You may reproduce and distribute copies of the 96 | Work or Derivative Works thereof in any medium, with or without 97 | modifications, and in Source or Object form, provided that You 98 | meet the following conditions: 99 | 100 | (a) You must give any other recipients of the Work or 101 | Derivative Works a copy of this License; and 102 | 103 | (b) You must cause any modified files to carry prominent notices 104 | stating that You changed the files; and 105 | 106 | (c) You must retain, in the Source form of any Derivative Works 107 | that You distribute, all copyright, patent, trademark, and 108 | attribution notices from the Source form of the Work, 109 | excluding those notices that do not pertain to any part of 110 | the Derivative Works; and 111 | 112 | (d) If the Work includes a "NOTICE" text file as part of its 113 | distribution, then any Derivative Works that You distribute must 114 | include a readable copy of the attribution notices contained 115 | within such NOTICE file, excluding those notices that do not 116 | pertain to any part of the Derivative Works, in at least one 117 | of the following places: within a NOTICE text file distributed 118 | as part of the Derivative Works; within the Source form or 119 | documentation, if provided along with the Derivative Works; or, 120 | within a display generated by the Derivative Works, if and 121 | wherever such third-party notices normally appear. The contents 122 | of the NOTICE file are for informational purposes only and 123 | do not modify the License. You may add Your own attribution 124 | notices within Derivative Works that You distribute, alongside 125 | or as an addendum to the NOTICE text from the Work, provided 126 | that such additional attribution notices cannot be construed 127 | as modifying the License. 128 | 129 | You may add Your own copyright statement to Your modifications and 130 | may provide additional or different license terms and conditions 131 | for use, reproduction, or distribution of Your modifications, or 132 | for any such Derivative Works as a whole, provided Your use, 133 | reproduction, and distribution of the Work otherwise complies with 134 | the conditions stated in this License. 135 | 136 | 5. Submission of Contributions. Unless You explicitly state otherwise, 137 | any Contribution intentionally submitted for inclusion in the Work 138 | by You to the Licensor shall be under the terms and conditions of 139 | this License, without any additional terms or conditions. 140 | Notwithstanding the above, nothing herein shall supersede or modify 141 | the terms of any separate license agreement you may have executed 142 | with Licensor regarding such Contributions. 143 | 144 | 6. Trademarks. This License does not grant permission to use the trade 145 | names, trademarks, service marks, or product names of the Licensor, 146 | except as required for reasonable and customary use in describing the 147 | origin of the Work and reproducing the content of the NOTICE file. 148 | 149 | 7. Disclaimer of Warranty. Unless required by applicable law or 150 | agreed to in writing, Licensor provides the Work (and each 151 | Contributor provides its Contributions) on an "AS IS" BASIS, 152 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 153 | implied, including, without limitation, any warranties or conditions 154 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 155 | PARTICULAR PURPOSE. You are solely responsible for determining the 156 | appropriateness of using or redistributing the Work and assume any 157 | risks associated with Your exercise of permissions under this License. 158 | 159 | 8. Limitation of Liability. In no event and under no legal theory, 160 | whether in tort (including negligence), contract, or otherwise, 161 | unless required by applicable law (such as deliberate and grossly 162 | negligent acts) or agreed to in writing, shall any Contributor be 163 | liable to You for damages, including any direct, indirect, special, 164 | incidental, or consequential damages of any character arising as a 165 | result of this License or out of the use or inability to use the 166 | Work (including but not limited to damages for loss of goodwill, 167 | work stoppage, computer failure or malfunction, or any and all 168 | other commercial damages or losses), even if such Contributor 169 | has been advised of the possibility of such damages. 170 | 171 | 9. Accepting Warranty or Additional Liability. While redistributing 172 | the Work or Derivative Works thereof, You may choose to offer, 173 | and charge a fee for, acceptance of support, warranty, indemnity, 174 | or other liability obligations and/or rights consistent with this 175 | License. However, in accepting such obligations, You may act only 176 | on Your own behalf and on Your sole responsibility, not on behalf 177 | of any other Contributor, and only if You agree to indemnify, 178 | defend, and hold each Contributor harmless for any liability 179 | incurred by, or claims asserted against, such Contributor by reason 180 | of your accepting any such warranty or additional liability. 181 | 182 | END OF TERMS AND CONDITIONS 183 | 184 | APPENDIX: How to apply the Apache License to your work. 185 | 186 | To apply the Apache License to your work, attach the following 187 | boilerplate notice, with the fields enclosed by brackets "[]" 188 | replaced with your own identifying information. (Don't include 189 | the brackets!) The text should be enclosed in the appropriate 190 | comment syntax for the file format. We also recommend that a 191 | file or class name and description of purpose be included on the 192 | same "printed page" as the copyright notice for easier 193 | identification within third-party archives. 194 | 195 | Copyright [2012] [JBoss, Home of Professional Open Source] 196 | 197 | Licensed under the Apache License, Version 2.0 (the "License"); 198 | you may not use this file except in compliance with the License. 199 | You may obtain a copy of the License at 200 | 201 | http://www.apache.org/licenses/LICENSE-2.0 202 | 203 | Unless required by applicable law or agreed to in writing, software 204 | distributed under the License is distributed on an "AS IS" BASIS, 205 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 206 | See the License for the specific language governing permissions and 207 | limitations under the License. 208 | 209 | Generated by CocoaPods - https://cocoapods.org 210 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-ACEDrawingViewDemo/Pods-ACEDrawingViewDemo-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | 18 | Apache License 19 | Version 2.0, January 2004 20 | http://www.apache.org/licenses/ 21 | 22 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 23 | 24 | 1. Definitions. 25 | 26 | "License" shall mean the terms and conditions for use, reproduction, 27 | and distribution as defined by Sections 1 through 9 of this document. 28 | 29 | "Licensor" shall mean the copyright owner or entity authorized by 30 | the copyright owner that is granting the License. 31 | 32 | "Legal Entity" shall mean the union of the acting entity and all 33 | other entities that control, are controlled by, or are under common 34 | control with that entity. For the purposes of this definition, 35 | "control" means (i) the power, direct or indirect, to cause the 36 | direction or management of such entity, whether by contract or 37 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 38 | outstanding shares, or (iii) beneficial ownership of such entity. 39 | 40 | "You" (or "Your") shall mean an individual or Legal Entity 41 | exercising permissions granted by this License. 42 | 43 | "Source" form shall mean the preferred form for making modifications, 44 | including but not limited to software source code, documentation 45 | source, and configuration files. 46 | 47 | "Object" form shall mean any form resulting from mechanical 48 | transformation or translation of a Source form, including but 49 | not limited to compiled object code, generated documentation, 50 | and conversions to other media types. 51 | 52 | "Work" shall mean the work of authorship, whether in Source or 53 | Object form, made available under the License, as indicated by a 54 | copyright notice that is included in or attached to the work 55 | (an example is provided in the Appendix below). 56 | 57 | "Derivative Works" shall mean any work, whether in Source or Object 58 | form, that is based on (or derived from) the Work and for which the 59 | editorial revisions, annotations, elaborations, or other modifications 60 | represent, as a whole, an original work of authorship. For the purposes 61 | of this License, Derivative Works shall not include works that remain 62 | separable from, or merely link (or bind by name) to the interfaces of, 63 | the Work and Derivative Works thereof. 64 | 65 | "Contribution" shall mean any work of authorship, including 66 | the original version of the Work and any modifications or additions 67 | to that Work or Derivative Works thereof, that is intentionally 68 | submitted to Licensor for inclusion in the Work by the copyright owner 69 | or by an individual or Legal Entity authorized to submit on behalf of 70 | the copyright owner. For the purposes of this definition, "submitted" 71 | means any form of electronic, verbal, or written communication sent 72 | to the Licensor or its representatives, including but not limited to 73 | communication on electronic mailing lists, source code control systems, 74 | and issue tracking systems that are managed by, or on behalf of, the 75 | Licensor for the purpose of discussing and improving the Work, but 76 | excluding communication that is conspicuously marked or otherwise 77 | designated in writing by the copyright owner as "Not a Contribution." 78 | 79 | "Contributor" shall mean Licensor and any individual or Legal Entity 80 | on behalf of whom a Contribution has been received by Licensor and 81 | subsequently incorporated within the Work. 82 | 83 | 2. Grant of Copyright License. Subject to the terms and conditions of 84 | this License, each Contributor hereby grants to You a perpetual, 85 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 86 | copyright license to reproduce, prepare Derivative Works of, 87 | publicly display, publicly perform, sublicense, and distribute the 88 | Work and such Derivative Works in Source or Object form. 89 | 90 | 3. Grant of Patent License. Subject to the terms and conditions of 91 | this License, each Contributor hereby grants to You a perpetual, 92 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 93 | (except as stated in this section) patent license to make, have made, 94 | use, offer to sell, sell, import, and otherwise transfer the Work, 95 | where such license applies only to those patent claims licensable 96 | by such Contributor that are necessarily infringed by their 97 | Contribution(s) alone or by combination of their Contribution(s) 98 | with the Work to which such Contribution(s) was submitted. If You 99 | institute patent litigation against any entity (including a 100 | cross-claim or counterclaim in a lawsuit) alleging that the Work 101 | or a Contribution incorporated within the Work constitutes direct 102 | or contributory patent infringement, then any patent licenses 103 | granted to You under this License for that Work shall terminate 104 | as of the date such litigation is filed. 105 | 106 | 4. Redistribution. You may reproduce and distribute copies of the 107 | Work or Derivative Works thereof in any medium, with or without 108 | modifications, and in Source or Object form, provided that You 109 | meet the following conditions: 110 | 111 | (a) You must give any other recipients of the Work or 112 | Derivative Works a copy of this License; and 113 | 114 | (b) You must cause any modified files to carry prominent notices 115 | stating that You changed the files; and 116 | 117 | (c) You must retain, in the Source form of any Derivative Works 118 | that You distribute, all copyright, patent, trademark, and 119 | attribution notices from the Source form of the Work, 120 | excluding those notices that do not pertain to any part of 121 | the Derivative Works; and 122 | 123 | (d) If the Work includes a "NOTICE" text file as part of its 124 | distribution, then any Derivative Works that You distribute must 125 | include a readable copy of the attribution notices contained 126 | within such NOTICE file, excluding those notices that do not 127 | pertain to any part of the Derivative Works, in at least one 128 | of the following places: within a NOTICE text file distributed 129 | as part of the Derivative Works; within the Source form or 130 | documentation, if provided along with the Derivative Works; or, 131 | within a display generated by the Derivative Works, if and 132 | wherever such third-party notices normally appear. The contents 133 | of the NOTICE file are for informational purposes only and 134 | do not modify the License. You may add Your own attribution 135 | notices within Derivative Works that You distribute, alongside 136 | or as an addendum to the NOTICE text from the Work, provided 137 | that such additional attribution notices cannot be construed 138 | as modifying the License. 139 | 140 | You may add Your own copyright statement to Your modifications and 141 | may provide additional or different license terms and conditions 142 | for use, reproduction, or distribution of Your modifications, or 143 | for any such Derivative Works as a whole, provided Your use, 144 | reproduction, and distribution of the Work otherwise complies with 145 | the conditions stated in this License. 146 | 147 | 5. Submission of Contributions. Unless You explicitly state otherwise, 148 | any Contribution intentionally submitted for inclusion in the Work 149 | by You to the Licensor shall be under the terms and conditions of 150 | this License, without any additional terms or conditions. 151 | Notwithstanding the above, nothing herein shall supersede or modify 152 | the terms of any separate license agreement you may have executed 153 | with Licensor regarding such Contributions. 154 | 155 | 6. Trademarks. This License does not grant permission to use the trade 156 | names, trademarks, service marks, or product names of the Licensor, 157 | except as required for reasonable and customary use in describing the 158 | origin of the Work and reproducing the content of the NOTICE file. 159 | 160 | 7. Disclaimer of Warranty. Unless required by applicable law or 161 | agreed to in writing, Licensor provides the Work (and each 162 | Contributor provides its Contributions) on an "AS IS" BASIS, 163 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 164 | implied, including, without limitation, any warranties or conditions 165 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 166 | PARTICULAR PURPOSE. You are solely responsible for determining the 167 | appropriateness of using or redistributing the Work and assume any 168 | risks associated with Your exercise of permissions under this License. 169 | 170 | 8. Limitation of Liability. In no event and under no legal theory, 171 | whether in tort (including negligence), contract, or otherwise, 172 | unless required by applicable law (such as deliberate and grossly 173 | negligent acts) or agreed to in writing, shall any Contributor be 174 | liable to You for damages, including any direct, indirect, special, 175 | incidental, or consequential damages of any character arising as a 176 | result of this License or out of the use or inability to use the 177 | Work (including but not limited to damages for loss of goodwill, 178 | work stoppage, computer failure or malfunction, or any and all 179 | other commercial damages or losses), even if such Contributor 180 | has been advised of the possibility of such damages. 181 | 182 | 9. Accepting Warranty or Additional Liability. While redistributing 183 | the Work or Derivative Works thereof, You may choose to offer, 184 | and charge a fee for, acceptance of support, warranty, indemnity, 185 | or other liability obligations and/or rights consistent with this 186 | License. However, in accepting such obligations, You may act only 187 | on Your own behalf and on Your sole responsibility, not on behalf 188 | of any other Contributor, and only if You agree to indemnify, 189 | defend, and hold each Contributor harmless for any liability 190 | incurred by, or claims asserted against, such Contributor by reason 191 | of your accepting any such warranty or additional liability. 192 | 193 | END OF TERMS AND CONDITIONS 194 | 195 | APPENDIX: How to apply the Apache License to your work. 196 | 197 | To apply the Apache License to your work, attach the following 198 | boilerplate notice, with the fields enclosed by brackets "[]" 199 | replaced with your own identifying information. (Don't include 200 | the brackets!) The text should be enclosed in the appropriate 201 | comment syntax for the file format. We also recommend that a 202 | file or class name and description of purpose be included on the 203 | same "printed page" as the copyright notice for easier 204 | identification within third-party archives. 205 | 206 | Copyright [2012] [JBoss, Home of Professional Open Source] 207 | 208 | Licensed under the Apache License, Version 2.0 (the "License"); 209 | you may not use this file except in compliance with the License. 210 | You may obtain a copy of the License at 211 | 212 | http://www.apache.org/licenses/LICENSE-2.0 213 | 214 | Unless required by applicable law or agreed to in writing, software 215 | distributed under the License is distributed on an "AS IS" BASIS, 216 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 217 | See the License for the specific language governing permissions and 218 | limitations under the License. 219 | 220 | License 221 | Apache 2.0 License 222 | Title 223 | ACEDrawingView 224 | Type 225 | PSGroupSpecifier 226 | 227 | 228 | FooterText 229 | Generated by CocoaPods - https://cocoapods.org 230 | Title 231 | 232 | Type 233 | PSGroupSpecifier 234 | 235 | 236 | StringsTable 237 | Acknowledgements 238 | Title 239 | Acknowledgements 240 | 241 | 242 | -------------------------------------------------------------------------------- /ACEDrawingView/ACEDrawingLabelView.m: -------------------------------------------------------------------------------- 1 | /* 2 | * ACEDrawingView: https://github.com/acerbetti/ACEDrawingView 3 | * 4 | * Copyright (c) 2016 Matthew Jackson 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #import "ACEDrawingLabelView.h" 27 | 28 | CG_INLINE CGPoint CGRectGetCenter(CGRect rect) 29 | { 30 | return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); 31 | } 32 | 33 | CG_INLINE CGRect CGRectScale(CGRect rect, CGFloat wScale, CGFloat hScale) 34 | { 35 | return CGRectMake(rect.origin.x * wScale, rect.origin.y * hScale, rect.size.width * wScale, rect.size.height * hScale); 36 | } 37 | 38 | CG_INLINE CGFloat CGPointGetDistance(CGPoint point1, CGPoint point2) 39 | { 40 | CGFloat fx = (point2.x - point1.x); 41 | CGFloat fy = (point2.y - point1.y); 42 | 43 | return sqrt((fx*fx + fy*fy)); 44 | } 45 | 46 | CG_INLINE CGFloat CGAffineTransformGetAngle(CGAffineTransform t) 47 | { 48 | return atan2(t.b, t.a); 49 | } 50 | 51 | 52 | CG_INLINE CGSize CGAffineTransformGetScale(CGAffineTransform t) 53 | { 54 | return CGSizeMake(sqrt(t.a * t.a + t.c * t.c), sqrt(t.b * t.b + t.d * t.d)) ; 55 | } 56 | 57 | @interface ACEDrawingLabelView () 58 | 59 | @property (nonatomic, assign) CGRect initialBounds; 60 | @property (nonatomic, assign) CGFloat initialDistance; 61 | 62 | @property (nonatomic, assign) CGPoint beginningPoint; 63 | @property (nonatomic, assign) CGPoint beginningCenter; 64 | 65 | @property (nonatomic, assign) CGPoint touchLocation; 66 | 67 | @property (nonatomic, assign) CGFloat deltaAngle; 68 | @property (nonatomic, assign) CGRect beginBounds; 69 | 70 | @property (nonatomic, assign) CGSize globalInsets; 71 | @property (nonatomic, strong) CAShapeLayer *border; 72 | @property (nonatomic, strong) UITextField *labelTextField; 73 | @property (nonatomic, strong) UIButton *rotateButton; 74 | @property (nonatomic, strong) UIButton *closeButton; 75 | 76 | @property (nonatomic, assign, getter=isShowingEditingHandles) BOOL showEditingHandles; 77 | 78 | @end 79 | 80 | @implementation ACEDrawingLabelView 81 | 82 | - (void)refresh 83 | { 84 | if (self.superview) { 85 | CGSize scale = CGAffineTransformGetScale(self.superview.transform); 86 | CGAffineTransform t = CGAffineTransformMakeScale(scale.width, scale.height); 87 | [self.closeButton setTransform:CGAffineTransformInvert(t)]; 88 | [self.rotateButton setTransform:CGAffineTransformInvert(t)]; 89 | 90 | if (self.isShowingEditingHandles) { 91 | [self.labelTextField.layer addSublayer:self.border]; 92 | } else { 93 | [self.border removeFromSuperlayer]; 94 | } 95 | } 96 | } 97 | 98 | -(void)didMoveToSuperview 99 | { 100 | [super didMoveToSuperview]; 101 | [self refresh]; 102 | } 103 | 104 | - (void)setFrame:(CGRect)newFrame 105 | { 106 | [super setFrame:newFrame]; 107 | [self refresh]; 108 | } 109 | 110 | - (id)initWithFrame:(CGRect)frame 111 | { 112 | if (frame.size.width < 25) frame.size.width = 25; 113 | if (frame.size.height < 25) frame.size.height = 25; 114 | 115 | self = [super initWithFrame:frame]; 116 | if (self) { 117 | self.labelTextField = [[UITextField alloc] initWithFrame:CGRectZero]; 118 | self.border = [CAShapeLayer layer]; 119 | 120 | _globalInsets = CGSizeMake(12, 12); 121 | _closeButtonOffset = CGPointZero; 122 | _rotateButtonOffset = CGPointZero; 123 | _closeButtonSize = CGSizeMake(24, 24); 124 | _rotateButtonSize = CGSizeMake(24, 24); 125 | _shadowColor = [UIColor blackColor]; 126 | _shadowOffset = CGSizeMake(0, 5); 127 | _shadowOpacity = 1; 128 | _shadowRadius = 4; 129 | 130 | self.backgroundColor = [UIColor clearColor]; 131 | [self setAutoresizingMask:(UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth)]; 132 | self.borderColor = [UIColor redColor]; 133 | 134 | [self.labelTextField setAutoresizingMask:(UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight)]; 135 | [self.labelTextField setClipsToBounds:YES]; 136 | self.labelTextField.delegate = self; 137 | self.labelTextField.backgroundColor = [UIColor clearColor]; 138 | self.labelTextField.tintColor = [UIColor redColor]; 139 | self.labelTextField.textColor = [UIColor whiteColor]; 140 | self.labelTextField.text = @""; 141 | [self.labelTextField addTarget:self action:@selector(textFieldEditingChanged:) forControlEvents:UIControlEventEditingChanged]; 142 | 143 | self.border.strokeColor = self.borderColor.CGColor; 144 | self.border.fillColor = nil; 145 | self.border.lineDashPattern = @[@4, @3]; 146 | 147 | [self insertSubview:self.labelTextField atIndex:0]; 148 | 149 | self.closeButton = [[UIButton alloc] initWithFrame:CGRectZero]; 150 | [self.closeButton setAutoresizingMask:(UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin)]; 151 | self.closeButton.backgroundColor = [UIColor whiteColor]; 152 | self.closeButton.layer.cornerRadius = self.globalInsets.width - 5; 153 | self.closeButton.userInteractionEnabled = YES; 154 | [self addSubview:self.closeButton]; 155 | 156 | self.rotateButton = [[UIButton alloc] initWithFrame:CGRectZero]; 157 | [self.rotateButton setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleTopMargin)]; 158 | self.rotateButton.backgroundColor = [UIColor whiteColor]; 159 | self.rotateButton.layer.cornerRadius = self.globalInsets.width - 5; 160 | self.rotateButton.contentMode = UIViewContentModeCenter; 161 | self.rotateButton.userInteractionEnabled = YES; 162 | [self addSubview:self.rotateButton]; 163 | 164 | [self applyLayout]; 165 | 166 | UIPanGestureRecognizer *moveGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveGesture:)]; 167 | [self addGestureRecognizer:moveGesture]; 168 | 169 | UITapGestureRecognizer *singleTapShowHide = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(contentTapped:)]; 170 | [self addGestureRecognizer:singleTapShowHide]; 171 | 172 | UITapGestureRecognizer *closeTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeTap:)]; 173 | [self.closeButton addGestureRecognizer:closeTap]; 174 | 175 | UIPanGestureRecognizer *panRotateGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(rotateViewPanGesture:)]; 176 | [self.rotateButton addGestureRecognizer:panRotateGesture]; 177 | 178 | [moveGesture requireGestureRecognizerToFail:closeTap]; 179 | 180 | [self setEnableMoveRestriction:NO]; 181 | [self setEnableClose:YES]; 182 | [self setEnableRotate:YES]; 183 | [self setShowsContentShadow:YES]; 184 | 185 | [self showEditingHandles]; 186 | } 187 | return self; 188 | } 189 | 190 | - (void)layoutSubviews 191 | { 192 | if (self.labelTextField) { 193 | self.border.path = [UIBezierPath bezierPathWithRect:self.labelTextField.bounds].CGPath; 194 | self.border.frame = self.labelTextField.bounds; 195 | } 196 | } 197 | 198 | - (void)beginEditing 199 | { 200 | [self.labelTextField becomeFirstResponder]; 201 | } 202 | 203 | - (void)applyLayout 204 | { 205 | _labelTextField.frame = CGRectInset(self.bounds, self.globalInsets.width, self.globalInsets.height); 206 | _closeButton.frame = CGRectMake(self.closeButtonOffset.x, self.closeButtonOffset.y, self.closeButtonSize.width, self.closeButtonSize.height); 207 | _rotateButton.frame = CGRectMake( 208 | self.bounds.size.width - self.rotateButtonSize.width + self.rotateButtonOffset.x, 209 | self.bounds.size.height - self.rotateButtonSize.height + self.rotateButtonOffset.y, 210 | self.rotateButtonSize.width, 211 | self.rotateButtonSize.height); 212 | } 213 | 214 | - (void)updateShadow 215 | { 216 | if (_showsContentShadow) { 217 | [self.layer setShadowColor:self.shadowColor.CGColor]; 218 | [self.layer setShadowOffset:self.shadowOffset]; 219 | [self.layer setShadowOpacity:self.shadowOpacity]; 220 | [self.layer setShadowRadius:self.shadowRadius]; 221 | } else { 222 | [self.layer setShadowColor:[UIColor clearColor].CGColor]; 223 | [self.layer setShadowOffset:CGSizeZero]; 224 | [self.layer setShadowOpacity:0.0]; 225 | [self.layer setShadowRadius:0.0]; 226 | } 227 | } 228 | 229 | #pragma mark - Set Control Buttons 230 | 231 | - (void)setEnableClose:(BOOL)value 232 | { 233 | _enableClose = value; 234 | [self.closeButton setHidden:!_enableClose]; 235 | [self.closeButton setUserInteractionEnabled:_enableClose]; 236 | } 237 | 238 | - (void)setEnableRotate:(BOOL)value 239 | { 240 | _enableRotate = value; 241 | [self.rotateButton setHidden:!_enableRotate]; 242 | [self.rotateButton setUserInteractionEnabled:_enableRotate]; 243 | } 244 | 245 | - (void)setShadowColor:(UIColor *)shadowColor 246 | { 247 | _shadowColor = shadowColor; 248 | [self updateShadow]; 249 | } 250 | 251 | - (void)setShadowOffset:(CGSize)shadowOffset 252 | { 253 | _shadowOffset = shadowOffset; 254 | [self updateShadow]; 255 | } 256 | 257 | - (void)setShadowOpacity:(CGFloat)shadowOpacity 258 | { 259 | _shadowOpacity = shadowOpacity; 260 | [self updateShadow]; 261 | } 262 | 263 | - (void)setShadowRadius:(CGFloat)shadowRadius 264 | { 265 | _shadowRadius = shadowRadius; 266 | [self updateShadow]; 267 | } 268 | 269 | - (void)setShowsContentShadow:(BOOL)showShadow 270 | { 271 | _showsContentShadow = showShadow; 272 | [self updateShadow]; 273 | } 274 | 275 | - (void)setCloseImage:(UIImage *)image 276 | { 277 | _closeImage = image; 278 | [self.closeButton setImage:_closeImage forState:UIControlStateNormal]; 279 | } 280 | 281 | - (void)setRotateImage:(UIImage *)image 282 | { 283 | _rotateImage = image; 284 | [self.rotateButton setImage:_rotateImage forState:UIControlStateNormal]; 285 | 286 | } 287 | 288 | #pragma mark - Set Text Field 289 | 290 | - (void)setFontName:(NSString *)name 291 | { 292 | if (name.length > 0) { 293 | _fontName = name; 294 | self.labelTextField.font = [UIFont fontWithName:_fontName size:self.fontSize]; 295 | [self.labelTextField adjustsWidthToFillItsContents]; 296 | } 297 | } 298 | 299 | - (void)setFontSize:(CGFloat)size 300 | { 301 | _fontSize = size; 302 | self.labelTextField.font = [UIFont fontWithName:self.fontName size:_fontSize]; 303 | } 304 | 305 | - (void)setTextColor:(UIColor *)color 306 | { 307 | _textColor = color; 308 | self.labelTextField.textColor = _textColor; 309 | } 310 | 311 | - (void)setBorderColor:(UIColor *)color 312 | { 313 | _borderColor = color; 314 | self.border.strokeColor = _borderColor.CGColor; 315 | } 316 | 317 | - (void)setTextAlpha:(CGFloat)alpha 318 | { 319 | self.labelTextField.alpha = alpha; 320 | } 321 | 322 | - (CGFloat)textAlpha 323 | { 324 | return self.labelTextField.alpha; 325 | } 326 | 327 | - (void)setAttributedPlaceholder:(NSAttributedString *)attributedPlaceholder 328 | { 329 | _attributedPlaceholder = attributedPlaceholder; 330 | [self.labelTextField setAttributedPlaceholder:attributedPlaceholder]; 331 | [self.labelTextField adjustsWidthToFillItsContents]; 332 | } 333 | 334 | #pragma mark - Bounds 335 | 336 | - (void)hideEditingHandles 337 | { 338 | self.showEditingHandles = NO; 339 | 340 | if (self.isEnableClose) self.closeButton.hidden = YES; 341 | if (self.isEnableRotate) self.rotateButton.hidden = YES; 342 | 343 | [self.labelTextField resignFirstResponder]; 344 | 345 | [self refresh]; 346 | 347 | if([self.delegate respondsToSelector:@selector(labelViewDidHideEditingHandles:)]) { 348 | [self.delegate labelViewDidHideEditingHandles:self]; 349 | } 350 | } 351 | 352 | - (void)showEditingHandles 353 | { 354 | if ([self.delegate respondsToSelector:@selector(labelViewWillShowEditingHandles:)]) { 355 | [self.delegate labelViewWillShowEditingHandles:self]; 356 | } 357 | 358 | self.showEditingHandles = YES; 359 | 360 | if (self.isEnableClose) self.closeButton.hidden = NO; 361 | if (self.isEnableRotate) self.rotateButton.hidden = NO; 362 | 363 | [self refresh]; 364 | 365 | if ([self.delegate respondsToSelector:@selector(labelViewDidShowEditingHandles:)]) { 366 | [self.delegate labelViewDidShowEditingHandles:self]; 367 | } 368 | } 369 | 370 | - (void)resizeInRect:(CGRect)rect 371 | { 372 | [self.labelTextField adjustsFontSizeToFillRect:rect]; 373 | } 374 | 375 | #pragma mark - Gestures 376 | 377 | - (void)contentTapped:(UITapGestureRecognizer*)tapGesture 378 | { 379 | if (self.isShowingEditingHandles) { 380 | [self hideEditingHandles]; 381 | [self.superview bringSubviewToFront:self]; 382 | } else { 383 | [self showEditingHandles]; 384 | } 385 | } 386 | 387 | - (void)closeTap:(UITapGestureRecognizer *)recognizer 388 | { 389 | [self removeFromSuperview]; 390 | 391 | if ([self.delegate respondsToSelector:@selector(labelViewDidClose:)]) { 392 | [self.delegate labelViewDidClose:self]; 393 | } 394 | } 395 | 396 | - (void)moveGesture:(UIPanGestureRecognizer *)recognizer 397 | { 398 | if (!self.isShowingEditingHandles) { 399 | [self showEditingHandles]; 400 | } 401 | self.touchLocation = [recognizer locationInView:self.superview]; 402 | 403 | if (recognizer.state == UIGestureRecognizerStateBegan) { 404 | self.beginningPoint = self.touchLocation; 405 | self.beginningCenter = self.center; 406 | 407 | [self setCenter:[self estimatedCenter]]; 408 | self.beginBounds = self.bounds; 409 | 410 | if ([self.delegate respondsToSelector:@selector(labelViewDidBeginEditing:)]) { 411 | [self.delegate labelViewDidBeginEditing:self]; 412 | } 413 | } else if (recognizer.state == UIGestureRecognizerStateChanged) { 414 | [self setCenter:[self estimatedCenter]]; 415 | 416 | if ([self.delegate respondsToSelector:@selector(labelViewDidChangeEditing:)]) { 417 | [self.delegate labelViewDidChangeEditing:self]; 418 | } 419 | } else if (recognizer.state == UIGestureRecognizerStateEnded) { 420 | [self setCenter:[self estimatedCenter]]; 421 | 422 | if ([self.delegate respondsToSelector:@selector(labelViewDidEndEditing:)]) { 423 | [self.delegate labelViewDidEndEditing:self]; 424 | } 425 | } 426 | } 427 | 428 | - (CGPoint)estimatedCenter 429 | { 430 | CGPoint newCenter; 431 | CGFloat newCenterX = self.beginningCenter.x + (self.touchLocation.x - self.beginningPoint.x); 432 | CGFloat newCenterY = self.beginningCenter.y + (self.touchLocation.y - self.beginningPoint.y); 433 | if (self.isEnableMoveRestriction) { 434 | if (!(newCenterX - 0.5 * CGRectGetWidth(self.frame) > 0 && 435 | newCenterX + 0.5 * CGRectGetWidth(self.frame) < CGRectGetWidth(self.superview.bounds))) { 436 | newCenterX = self.center.x; 437 | } 438 | if (!(newCenterY - 0.5 * CGRectGetHeight(self.frame) > 0 && 439 | newCenterY + 0.5 * CGRectGetHeight(self.frame) < CGRectGetHeight(self.superview.bounds))) { 440 | newCenterY = self.center.y; 441 | } 442 | newCenter = CGPointMake(newCenterX, newCenterY); 443 | } else { 444 | newCenter = CGPointMake(newCenterX, newCenterY); 445 | } 446 | return newCenter; 447 | } 448 | 449 | - (void)rotateViewPanGesture:(UIPanGestureRecognizer *)recognizer 450 | { 451 | self.touchLocation = [recognizer locationInView:self.superview]; 452 | 453 | CGPoint center = CGRectGetCenter(self.frame); 454 | 455 | if ([recognizer state] == UIGestureRecognizerStateBegan) { 456 | self.deltaAngle = atan2(self.touchLocation.y-center.y, self.touchLocation.x-center.x)-CGAffineTransformGetAngle(self.transform); 457 | 458 | self.initialBounds = self.bounds; 459 | self.initialDistance = CGPointGetDistance(center, self.touchLocation); 460 | 461 | if([self.delegate respondsToSelector:@selector(labelViewDidBeginEditing:)]) { 462 | [self.delegate labelViewDidBeginEditing:self]; 463 | } 464 | } else if ([recognizer state] == UIGestureRecognizerStateChanged) { 465 | float ang = atan2(self.touchLocation.y-center.y, self.touchLocation.x-center.x); 466 | 467 | float angleDiff = self.deltaAngle - ang; 468 | [self setTransform:CGAffineTransformMakeRotation(-angleDiff)]; 469 | [self setNeedsDisplay]; 470 | 471 | //Finding scale between current touchPoint and previous touchPoint 472 | double scale = sqrtf(CGPointGetDistance(center, self.touchLocation)/self.initialDistance); 473 | 474 | CGRect scaleRect = CGRectScale(self.initialBounds, scale, scale); 475 | 476 | if (scaleRect.size.width >= (1+self.globalInsets.width*2 + 20) && scaleRect.size.height >= (1+self.globalInsets.height*2 + 20)) { 477 | if (self.fontSize < 100 || CGRectGetWidth(scaleRect) < CGRectGetWidth(self.bounds)) { 478 | CGRect boundsCheckRect = scaleRect; 479 | boundsCheckRect.size.width -= self.globalInsets.width * 2; 480 | [self.labelTextField adjustsFontSizeToFillRect:boundsCheckRect]; 481 | [self setBounds:scaleRect]; 482 | } 483 | } 484 | 485 | if ([self.delegate respondsToSelector:@selector(labelViewDidChangeEditing:)]) { 486 | [self.delegate labelViewDidChangeEditing:self]; 487 | } 488 | } else if ([recognizer state] == UIGestureRecognizerStateEnded) { 489 | if ([self.delegate respondsToSelector:@selector(labelViewDidEndEditing:)]) { 490 | [self.delegate labelViewDidEndEditing:self]; 491 | } 492 | } 493 | } 494 | 495 | #pragma mark - UITextField Delegate 496 | 497 | - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField 498 | { 499 | if (self.isShowingEditingHandles) { 500 | return YES; 501 | } 502 | [self contentTapped:nil]; 503 | return NO; 504 | } 505 | 506 | - (void)textFieldDidBeginEditing:(UITextField *)textField 507 | { 508 | if ([self.delegate respondsToSelector:@selector(labelViewDidStartEditing:)]) { 509 | [self.delegate labelViewDidStartEditing:self]; 510 | } 511 | 512 | [textField adjustsWidthToFillItsContents]; 513 | } 514 | 515 | 516 | #pragma mark - UITextField UIControlEvent 517 | - (void)textFieldEditingChanged:(UITextField *)textField { 518 | if (!self.isShowingEditingHandles) { 519 | [self showEditingHandles]; 520 | } 521 | [textField adjustsWidthToFillItsContents]; 522 | } 523 | 524 | 525 | #pragma mark - Additional Properties 526 | 527 | - (BOOL)isEditing 528 | { 529 | return self.isShowingEditingHandles; 530 | } 531 | 532 | - (NSString *)textValue 533 | { 534 | return self.labelTextField.text; 535 | } 536 | 537 | @end 538 | 539 | 540 | #pragma mark - UITextField Category for DynamicFontSize 541 | 542 | @implementation UITextField (DynamicFontSize) 543 | 544 | static const NSUInteger ACELVMaximumFontSize = 101; 545 | static const NSUInteger ACELVMinimumFontSize = 9; 546 | 547 | - (void)adjustsFontSizeToFillRect:(CGRect)newBounds 548 | { 549 | NSString *text = (![self.text isEqualToString:@""] || !self.placeholder) ? self.text : self.placeholder; 550 | 551 | for (NSUInteger i = ACELVMaximumFontSize; i > ACELVMinimumFontSize; i--) { 552 | UIFont *font = [UIFont fontWithName:self.font.fontName size:(CGFloat)i]; 553 | NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text 554 | attributes:@{ NSFontAttributeName : font }]; 555 | 556 | CGRect rectSize = [attributedText boundingRectWithSize:CGSizeMake(CGRectGetWidth(newBounds), CGFLOAT_MAX) 557 | options:NSStringDrawingUsesLineFragmentOrigin 558 | context:nil]; 559 | 560 | if (CGRectGetHeight(rectSize) <= CGRectGetHeight(newBounds)) { 561 | ((ACEDrawingLabelView *)self.superview).fontSize = (CGFloat)i-1; 562 | break; 563 | } 564 | } 565 | } 566 | 567 | - (void)adjustsWidthToFillItsContents 568 | { 569 | NSString *text = (![self.text isEqualToString:@""] || !self.placeholder) ? self.text : self.placeholder; 570 | UIFont *font = [UIFont fontWithName:self.font.fontName size:self.font.pointSize]; 571 | // Hotfix: despite exact text measurement, label text ends up clipped either on the beginning or the end. 572 | // Inserting a couple extra characters here makes the end stick out awkwardly sometimes, but avoids the 573 | // issue if you rotate the text. 574 | NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:[text stringByAppendingString:@"xx"] 575 | attributes:@{ NSFontAttributeName : font }]; 576 | 577 | CGRect rectSize = [attributedText boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGRectGetHeight(self.frame)-24) 578 | options:NSStringDrawingUsesLineFragmentOrigin 579 | context:nil]; 580 | 581 | float w1 = (ceilf(rectSize.size.width) + 24 < 50) ? self.frame.size.width : ceilf(rectSize.size.width) + 24; 582 | float h1 =(ceilf(rectSize.size.height) + 24 < 50) ? 50 : ceilf(rectSize.size.height) + 24; 583 | 584 | CGRect viewFrame = self.superview.bounds; 585 | viewFrame.size.width = w1 + 24; 586 | viewFrame.size.height = h1; 587 | self.superview.bounds = viewFrame; 588 | } 589 | 590 | @end 591 | 592 | #pragma mark - ACEDrawingLabelViewTransform 593 | 594 | @interface ACEDrawingLabelViewTransform () 595 | @property (nonatomic, assign) CGAffineTransform transform; 596 | @property (nonatomic, assign) CGPoint center; 597 | @property (nonatomic, assign) CGRect bounds; 598 | @end 599 | 600 | @implementation ACEDrawingLabelViewTransform 601 | 602 | + (instancetype)transform:(CGAffineTransform)transform atCenter:(CGPoint)center withBounds:(CGRect)bounds 603 | { 604 | ACEDrawingLabelViewTransform *t = [ACEDrawingLabelViewTransform new]; 605 | t.transform = transform; 606 | t.center = center; 607 | t.bounds = bounds; 608 | 609 | return t; 610 | } 611 | 612 | @end 613 | -------------------------------------------------------------------------------- /ACEDrawingView/ACEDrawingTools.m: -------------------------------------------------------------------------------- 1 | /* 2 | * ACEDrawingView: https://github.com/acerbetti/ACEDrawingView 3 | * 4 | * Copyright (c) 2013 Stefano Acerbetti 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #import "ACEDrawingTools.h" 27 | #import "ACEDrawingView.h" 28 | #import "ACEDrawingToolState.h" 29 | #if (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) 30 | #import 31 | #else 32 | #import 33 | #endif 34 | 35 | CGPoint midPoint(CGPoint p1, CGPoint p2) 36 | { 37 | return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5); 38 | } 39 | 40 | #pragma mark - ACEDrawingPenTool 41 | 42 | @implementation ACEDrawingPenTool 43 | 44 | @synthesize lineColor = _lineColor; 45 | @synthesize lineAlpha = _lineAlpha; 46 | 47 | - (id)init 48 | { 49 | self = [super init]; 50 | if (self != nil) { 51 | self.lineCapStyle = kCGLineCapRound; 52 | path = CGPathCreateMutable(); 53 | } 54 | return self; 55 | } 56 | 57 | - (void)setInitialPoint:(CGPoint)firstPoint 58 | { 59 | //[self moveToPoint:firstPoint]; 60 | } 61 | 62 | - (void)moveFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint 63 | { 64 | //[self addQuadCurveToPoint:midPoint(endPoint, startPoint) controlPoint:startPoint]; 65 | } 66 | 67 | - (CGRect)addPathPreviousPreviousPoint:(CGPoint)p2Point withPreviousPoint:(CGPoint)p1Point withCurrentPoint:(CGPoint)cpoint { 68 | 69 | CGPoint mid1 = midPoint(p1Point, p2Point); 70 | CGPoint mid2 = midPoint(cpoint, p1Point); 71 | CGMutablePathRef subpath = CGPathCreateMutable(); 72 | CGPathMoveToPoint(subpath, NULL, mid1.x, mid1.y); 73 | CGPathAddQuadCurveToPoint(subpath, NULL, p1Point.x, p1Point.y, mid2.x, mid2.y); 74 | CGRect bounds = CGPathGetBoundingBox(subpath); 75 | 76 | CGPathAddPath(path, NULL, subpath); 77 | CGPathRelease(subpath); 78 | 79 | return bounds; 80 | } 81 | 82 | - (void)draw 83 | { 84 | CGContextRef context = UIGraphicsGetCurrentContext(); 85 | 86 | CGContextAddPath(context, path); 87 | CGContextSetLineCap(context, kCGLineCapRound); 88 | CGContextSetLineWidth(context, self.lineWidth); 89 | CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor); 90 | CGContextSetBlendMode(context, kCGBlendModeNormal); 91 | CGContextSetAlpha(context, self.lineAlpha); 92 | CGContextStrokePath(context); 93 | } 94 | 95 | - (ACEDrawingToolState *)captureToolState 96 | { 97 | return [ACEDrawingToolState stateForTool:self]; 98 | } 99 | 100 | - (void)dealloc 101 | { 102 | CGPathRelease(path); 103 | self.lineColor = nil; 104 | #if !ACE_HAS_ARC 105 | [super dealloc]; 106 | #endif 107 | } 108 | 109 | @end 110 | 111 | 112 | #pragma mark - ACEDrawingEraserTool 113 | 114 | @implementation ACEDrawingEraserTool 115 | 116 | - (void)draw 117 | { 118 | CGContextRef context = UIGraphicsGetCurrentContext(); 119 | CGContextSaveGState(context); 120 | 121 | CGContextAddPath(context, path); 122 | CGContextSetLineCap(context, kCGLineCapRound); 123 | CGContextSetLineWidth(context, self.lineWidth); 124 | CGContextSetBlendMode(context, kCGBlendModeClear); 125 | CGContextStrokePath(context); 126 | CGContextRestoreGState(context); 127 | } 128 | 129 | - (ACEDrawingToolState *)captureToolState 130 | { 131 | return [ACEDrawingToolState stateForTool:self]; 132 | } 133 | 134 | @end 135 | 136 | 137 | #pragma mark - ACEDrawingLineTool 138 | 139 | @interface ACEDrawingLineTool () 140 | @property (nonatomic, assign) CGPoint firstPoint; 141 | @property (nonatomic, assign) CGPoint lastPoint; 142 | @end 143 | 144 | #pragma mark - 145 | 146 | @implementation ACEDrawingLineTool 147 | 148 | @synthesize lineColor = _lineColor; 149 | @synthesize lineAlpha = _lineAlpha; 150 | @synthesize lineWidth = _lineWidth; 151 | 152 | - (void)setInitialPoint:(CGPoint)firstPoint 153 | { 154 | self.firstPoint = firstPoint; 155 | } 156 | 157 | - (void)moveFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint 158 | { 159 | self.lastPoint = endPoint; 160 | } 161 | 162 | - (void)draw 163 | { 164 | CGContextRef context = UIGraphicsGetCurrentContext(); 165 | 166 | // set the line properties 167 | CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor); 168 | CGContextSetLineCap(context, kCGLineCapRound); 169 | CGContextSetLineWidth(context, self.lineWidth); 170 | CGContextSetAlpha(context, self.lineAlpha); 171 | 172 | // draw the line 173 | CGContextMoveToPoint(context, self.firstPoint.x, self.firstPoint.y); 174 | CGContextAddLineToPoint(context, self.lastPoint.x, self.lastPoint.y); 175 | CGContextStrokePath(context); 176 | } 177 | 178 | - (ACEDrawingToolState *)captureToolState 179 | { 180 | return [ACEDrawingToolState stateForTool:self]; 181 | } 182 | 183 | - (void)dealloc 184 | { 185 | self.lineColor = nil; 186 | #if !ACE_HAS_ARC 187 | [super dealloc]; 188 | #endif 189 | } 190 | 191 | @end 192 | 193 | #pragma mark - ACEDrawingDraggableTextTool 194 | 195 | @interface ACEDrawingDraggableTextTool () 196 | @property (nonatomic, strong) NSMutableArray *redoPositions; 197 | @property (nonatomic, strong) NSMutableArray *undoPositions; 198 | @end 199 | 200 | #pragma mark - 201 | 202 | @implementation ACEDrawingDraggableTextTool 203 | 204 | @synthesize lineColor = _lineColor; 205 | @synthesize lineAlpha = _lineAlpha; // Not used for this tool 206 | @synthesize lineWidth = _lineWidth; // Not used for this tool 207 | @synthesize drawingView = _drawingView; 208 | @synthesize labelView = _labelView; 209 | 210 | - (void)setInitialPoint:(CGPoint)firstPoint 211 | { 212 | CGRect frame = CGRectMake(firstPoint.x, firstPoint.y, 50, 100); 213 | 214 | _labelView = [[ACEDrawingLabelView alloc] initWithFrame:frame]; 215 | 216 | [self configureLabelView]; 217 | 218 | [_labelView beginEditing]; 219 | } 220 | 221 | - (void)moveFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint 222 | { 223 | // Not used for this tool 224 | } 225 | 226 | - (void)configureLabelView 227 | { 228 | _labelView.delegate = self.drawingView; 229 | _labelView.fontSize = 18.0; 230 | _labelView.textColor = self.lineColor; 231 | _labelView.fontName = self.drawingView.draggableTextFontName ?: [UIFont systemFontOfSize:_labelView.fontSize].fontName; 232 | _labelView.closeImage = self.drawingView.draggableTextCloseImage; 233 | _labelView.rotateImage = self.drawingView.draggableTextRotateImage; 234 | 235 | [_labelView.delegate labelViewNeedsConfiguration:_labelView]; 236 | [_labelView applyLayout]; 237 | } 238 | 239 | - (void)draw 240 | { 241 | if (self.labelView != nil && self.labelView.superview == nil) { 242 | [self.drawingView addSubview:self.labelView]; 243 | } 244 | } 245 | 246 | - (void)applyToolState:(ACEDrawingToolState *)state 247 | { 248 | if (state.hasPositionObject) { 249 | [self applyTransform:state.positionObject]; 250 | } 251 | 252 | [self draw]; 253 | } 254 | 255 | - (ACEDrawingToolState *)captureToolState 256 | { 257 | return [ACEDrawingToolState stateForTool:self capturePosition:YES]; 258 | } 259 | 260 | - (id)capturePositionObject 261 | { 262 | return [ACEDrawingLabelViewTransform transform:self.labelView.transform 263 | atCenter:self.labelView.center 264 | withBounds:self.labelView.bounds]; 265 | } 266 | 267 | - (void)hideHandle 268 | { 269 | [self.labelView hideEditingHandles]; 270 | } 271 | 272 | - (NSMutableArray *)redoPositions 273 | { 274 | if (!_redoPositions) { 275 | _redoPositions = [NSMutableArray new]; 276 | } 277 | return _redoPositions; 278 | } 279 | 280 | - (NSMutableArray *)undoPositions 281 | { 282 | if (!_undoPositions) { 283 | _undoPositions = [NSMutableArray new]; 284 | } 285 | return _undoPositions; 286 | } 287 | 288 | - (void)applyTransform:(ACEDrawingLabelViewTransform *)t 289 | { 290 | [UIView animateWithDuration:0.3 animations:^{ 291 | self.labelView.center = t.center; 292 | self.labelView.transform = t.transform; 293 | self.labelView.bounds = t.bounds; 294 | [self.labelView resizeInRect:t.bounds]; 295 | }]; 296 | } 297 | 298 | - (void)capturePosition 299 | { 300 | [self.undoPositions addObject:[ACEDrawingLabelViewTransform transform:self.labelView.transform 301 | atCenter:self.labelView.center 302 | withBounds:self.labelView.bounds]]; 303 | // clear redoPositions 304 | self.redoPositions = nil; 305 | } 306 | 307 | - (void)undraw 308 | { 309 | [self.labelView removeFromSuperview]; 310 | } 311 | 312 | - (BOOL)canRedo 313 | { 314 | return self.redoPositions.count > 0 && self.labelView.superview; 315 | } 316 | 317 | - (BOOL)redo 318 | { 319 | // add transform to undoPositions 320 | [self.undoPositions addObject:[ACEDrawingLabelViewTransform transform:self.labelView.transform 321 | atCenter:self.labelView.center 322 | withBounds:self.labelView.bounds]]; 323 | // apply transform 324 | ACEDrawingLabelViewTransform *t = [self.redoPositions lastObject]; 325 | [self applyTransform:t]; 326 | 327 | // remove transform from redoPositions 328 | [self.redoPositions removeLastObject]; 329 | 330 | return ![self canRedo]; 331 | } 332 | 333 | - (BOOL)canUndo 334 | { 335 | return self.undoPositions.count > 0; 336 | } 337 | 338 | - (void)undo 339 | { 340 | // add transform to redoPositions 341 | [self.redoPositions addObject:[ACEDrawingLabelViewTransform transform:self.labelView.transform 342 | atCenter:self.labelView.center 343 | withBounds:self.labelView.bounds]]; 344 | // apply transform 345 | ACEDrawingLabelViewTransform *t = [self.undoPositions lastObject]; 346 | [self applyTransform:t]; 347 | 348 | // remove transform from undoPositions 349 | [self.undoPositions removeLastObject]; 350 | } 351 | 352 | @end 353 | 354 | #pragma mark - ACEDrawingRectangleTool 355 | 356 | @interface ACEDrawingRectangleTool () 357 | @property (nonatomic, assign) CGPoint firstPoint; 358 | @property (nonatomic, assign) CGPoint lastPoint; 359 | @end 360 | 361 | #pragma mark - 362 | 363 | @implementation ACEDrawingRectangleTool 364 | 365 | @synthesize lineColor = _lineColor; 366 | @synthesize lineAlpha = _lineAlpha; 367 | @synthesize lineWidth = _lineWidth; 368 | 369 | - (void)setInitialPoint:(CGPoint)firstPoint 370 | { 371 | self.firstPoint = firstPoint; 372 | } 373 | 374 | - (void)moveFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint 375 | { 376 | self.lastPoint = endPoint; 377 | } 378 | 379 | - (void)draw 380 | { 381 | CGContextRef context = UIGraphicsGetCurrentContext(); 382 | 383 | // set the properties 384 | CGContextSetAlpha(context, self.lineAlpha); 385 | 386 | // draw the rectangle 387 | CGRect rectToFill = CGRectMake(self.firstPoint.x, self.firstPoint.y, self.lastPoint.x - self.firstPoint.x, self.lastPoint.y - self.firstPoint.y); 388 | if (self.fill) { 389 | CGContextSetFillColorWithColor(context, self.lineColor.CGColor); 390 | CGContextFillRect(UIGraphicsGetCurrentContext(), rectToFill); 391 | 392 | } else { 393 | CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor); 394 | CGContextSetLineWidth(context, self.lineWidth); 395 | CGContextStrokeRect(UIGraphicsGetCurrentContext(), rectToFill); 396 | } 397 | } 398 | 399 | - (ACEDrawingToolState *)captureToolState 400 | { 401 | return [ACEDrawingToolState stateForTool:self]; 402 | } 403 | 404 | - (void)dealloc 405 | { 406 | self.lineColor = nil; 407 | #if !ACE_HAS_ARC 408 | [super dealloc]; 409 | #endif 410 | } 411 | 412 | @end 413 | 414 | 415 | #pragma mark - ACEDrawingEllipseTool 416 | 417 | @interface ACEDrawingEllipseTool () 418 | @property (nonatomic, assign) CGPoint firstPoint; 419 | @property (nonatomic, assign) CGPoint lastPoint; 420 | @end 421 | 422 | #pragma mark - 423 | 424 | @implementation ACEDrawingEllipseTool 425 | 426 | @synthesize lineColor = _lineColor; 427 | @synthesize lineAlpha = _lineAlpha; 428 | @synthesize lineWidth = _lineWidth; 429 | 430 | - (void)setInitialPoint:(CGPoint)firstPoint 431 | { 432 | self.firstPoint = firstPoint; 433 | } 434 | 435 | - (void)moveFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint 436 | { 437 | self.lastPoint = endPoint; 438 | } 439 | 440 | - (void)draw 441 | { 442 | CGContextRef context = UIGraphicsGetCurrentContext(); 443 | 444 | // set the properties 445 | CGContextSetAlpha(context, self.lineAlpha); 446 | 447 | // draw the ellipse 448 | CGRect rectToFill = CGRectMake(self.firstPoint.x, self.firstPoint.y, self.lastPoint.x - self.firstPoint.x, self.lastPoint.y - self.firstPoint.y); 449 | if (self.fill) { 450 | CGContextSetFillColorWithColor(context, self.lineColor.CGColor); 451 | CGContextFillEllipseInRect(UIGraphicsGetCurrentContext(), rectToFill); 452 | 453 | } else { 454 | CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor); 455 | CGContextSetLineWidth(context, self.lineWidth); 456 | CGContextStrokeEllipseInRect(UIGraphicsGetCurrentContext(), rectToFill); 457 | } 458 | } 459 | 460 | - (ACEDrawingToolState *)captureToolState 461 | { 462 | return [ACEDrawingToolState stateForTool:self]; 463 | } 464 | 465 | - (void)dealloc 466 | { 467 | self.lineColor = nil; 468 | #if !ACE_HAS_ARC 469 | [super dealloc]; 470 | #endif 471 | } 472 | 473 | @end 474 | 475 | #pragma mark - ACEDrawingArrowTool 476 | 477 | @interface ACEDrawingArrowTool () 478 | @property (nonatomic, assign) CGPoint firstPoint; 479 | @property (nonatomic, assign) CGPoint lastPoint; 480 | @end 481 | 482 | @implementation ACEDrawingArrowTool 483 | 484 | @synthesize lineColor = _lineColor; 485 | @synthesize lineAlpha = _lineAlpha; 486 | @synthesize lineWidth = _lineWidth; 487 | 488 | - (void)setInitialPoint:(CGPoint)firstPoint 489 | { 490 | self.firstPoint = firstPoint; 491 | } 492 | 493 | - (void)moveFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint 494 | { 495 | self.lastPoint = endPoint; 496 | } 497 | 498 | - (void)draw 499 | { 500 | CGContextRef context = UIGraphicsGetCurrentContext(); 501 | 502 | CGFloat capHeight = self.lineWidth * 4.0f; 503 | // set the line properties 504 | CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor); 505 | CGContextSetLineCap(context, kCGLineCapSquare); 506 | CGContextSetLineWidth(context, self.lineWidth); 507 | CGContextSetAlpha(context, self.lineAlpha); 508 | 509 | // draw the line 510 | CGContextMoveToPoint(context, self.firstPoint.x, self.firstPoint.y); 511 | CGContextAddLineToPoint(context, self.lastPoint.x, self.lastPoint.y); 512 | 513 | // draw arrow cap 514 | CGFloat angle = [self angleWithFirstPoint:self.firstPoint secondPoint:self.lastPoint]; 515 | CGPoint p1 = [self pointWithAngle:angle + 7.0f * M_PI / 8.0f distance:capHeight]; 516 | CGPoint p2 = [self pointWithAngle:angle - 7.0f * M_PI / 8.0f distance:capHeight]; 517 | CGPoint endPointOffset = [self pointWithAngle:angle distance:self.lineWidth]; 518 | 519 | p1 = CGPointMake(self.lastPoint.x + p1.x, self.lastPoint.y + p1.y); 520 | p2 = CGPointMake(self.lastPoint.x + p2.x, self.lastPoint.y + p2.y); 521 | 522 | CGContextMoveToPoint(context, p1.x, p1.y); 523 | CGContextAddLineToPoint(context, self.lastPoint.x + endPointOffset.x, self.lastPoint.y + endPointOffset.y); 524 | CGContextAddLineToPoint(context, p2.x, p2.y); 525 | 526 | CGContextStrokePath(context); 527 | } 528 | 529 | - (ACEDrawingToolState *)captureToolState 530 | { 531 | return [ACEDrawingToolState stateForTool:self]; 532 | } 533 | 534 | - (CGFloat)angleWithFirstPoint:(CGPoint)first secondPoint:(CGPoint)second 535 | { 536 | CGFloat dx = second.x - first.x; 537 | CGFloat dy = second.y - first.y; 538 | CGFloat angle = atan2f(dy, dx); 539 | 540 | return angle; 541 | } 542 | 543 | - (CGPoint)pointWithAngle:(CGFloat)angle distance:(CGFloat)distance 544 | { 545 | CGFloat x = distance * cosf(angle); 546 | CGFloat y = distance * sinf(angle); 547 | 548 | return CGPointMake(x, y); 549 | } 550 | 551 | - (void)dealloc 552 | { 553 | self.lineColor = nil; 554 | #if !ACE_HAS_ARC 555 | [super dealloc]; 556 | #endif 557 | } 558 | 559 | @end 560 | 561 | 562 | #pragma mark - ACEDrawingTriangleTool 563 | 564 | @interface ACEDrawingTriangleTool () 565 | @property (nonatomic, assign) CGPoint firstPoint; 566 | @property (nonatomic, assign) CGPoint lastPoint; 567 | @end 568 | 569 | #pragma mark - 570 | 571 | @implementation ACEDrawingTriangleTool 572 | 573 | @synthesize lineColor = _lineColor; 574 | @synthesize lineAlpha = _lineAlpha; 575 | @synthesize lineWidth = _lineWidth; 576 | 577 | - (void)setInitialPoint:(CGPoint)firstPoint 578 | { 579 | self.firstPoint = firstPoint; 580 | } 581 | 582 | - (void)moveFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint 583 | { 584 | self.lastPoint = endPoint; 585 | } 586 | 587 | - (void)draw 588 | { 589 | CGContextRef context = UIGraphicsGetCurrentContext(); 590 | 591 | // set the properties 592 | CGContextSetAlpha(context, self.lineAlpha); 593 | CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor); 594 | CGContextSetLineWidth(context, self.lineWidth); 595 | CGContextSetLineCap(context, kCGLineCapRound); 596 | CGContextSetLineJoin(context, kCGLineJoinRound); 597 | 598 | double dx = (self.lastPoint.x - self.firstPoint.x); 599 | double dy = (self.lastPoint.y - self.firstPoint.y); 600 | double dist = sqrt(dx*dx + dy*dy); 601 | 602 | 603 | CGPoint center = midPoint(self.firstPoint, self.lastPoint); 604 | CGFloat diameter = dist / 2; 605 | CGFloat sidesNumber = 3; 606 | 607 | // Now add the hexagon to the current path 608 | CGContextMoveToPoint(context, center.x, center.y + diameter); 609 | for(int i = 1; i < sidesNumber+1; ++i) 610 | { 611 | CGFloat x = diameter * sinf(i * 2.0 * M_PI / sidesNumber); 612 | CGFloat y = diameter * cosf(i * 2.0 * M_PI / sidesNumber); 613 | CGContextAddLineToPoint(context, center.x + x, center.y + y); 614 | } 615 | 616 | 617 | if (self.fill) { 618 | CGContextDrawPath(context, kCGPathFillStroke); 619 | CGContextSetFillColorWithColor(context, self.lineColor.CGColor); 620 | } else { 621 | CGContextStrokePath(context); 622 | } 623 | 624 | // And close the subpath. 625 | CGContextClosePath(context); 626 | } 627 | 628 | - (ACEDrawingToolState *)captureToolState 629 | { 630 | return [ACEDrawingToolState stateForTool:self]; 631 | } 632 | 633 | - (void)dealloc 634 | { 635 | self.lineColor = nil; 636 | #if !ACE_HAS_ARC 637 | [super dealloc]; 638 | #endif 639 | } 640 | 641 | @end 642 | 643 | 644 | 645 | #pragma mark - ACEDrawingPentagonTool 646 | 647 | @interface ACEDrawingPentagonTool () 648 | @property (nonatomic, assign) CGPoint firstPoint; 649 | @property (nonatomic, assign) CGPoint lastPoint; 650 | @end 651 | 652 | #pragma mark - 653 | 654 | @implementation ACEDrawingPentagonTool 655 | 656 | @synthesize lineColor = _lineColor; 657 | @synthesize lineAlpha = _lineAlpha; 658 | @synthesize lineWidth = _lineWidth; 659 | 660 | - (void)setInitialPoint:(CGPoint)firstPoint 661 | { 662 | self.firstPoint = firstPoint; 663 | } 664 | 665 | - (void)moveFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint 666 | { 667 | self.lastPoint = endPoint; 668 | } 669 | 670 | - (void)draw 671 | { 672 | CGContextRef context = UIGraphicsGetCurrentContext(); 673 | 674 | // set the properties 675 | CGContextSetAlpha(context, self.lineAlpha); 676 | CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor); 677 | CGContextSetLineWidth(context, self.lineWidth); 678 | CGContextSetLineCap(context, kCGLineCapRound); 679 | CGContextSetLineJoin(context, kCGLineJoinRound); 680 | 681 | double dx = (self.lastPoint.x - self.firstPoint.x); 682 | double dy = (self.lastPoint.y - self.firstPoint.y); 683 | double dist = sqrt(dx*dx + dy*dy); 684 | 685 | 686 | CGPoint center = midPoint(self.firstPoint, self.lastPoint); 687 | CGFloat diameter = dist / 2; 688 | CGFloat sidesNumber = 5; 689 | 690 | // Now add the hexagon to the current path 691 | CGContextMoveToPoint(context, center.x, center.y + diameter); 692 | for(int i = 1; i < sidesNumber+1; ++i) 693 | { 694 | CGFloat x = diameter * sinf(i * 2.0 * M_PI / sidesNumber); 695 | CGFloat y = diameter * cosf(i * 2.0 * M_PI / sidesNumber); 696 | CGContextAddLineToPoint(context, center.x + x, center.y + y); 697 | } 698 | 699 | 700 | if (self.fill) { 701 | CGContextDrawPath(context, kCGPathFillStroke); 702 | CGContextSetFillColorWithColor(context, self.lineColor.CGColor); 703 | } else { 704 | CGContextStrokePath(context); 705 | } 706 | 707 | // And close the subpath. 708 | CGContextClosePath(context); 709 | } 710 | 711 | - (ACEDrawingToolState *)captureToolState 712 | { 713 | return [ACEDrawingToolState stateForTool:self]; 714 | } 715 | 716 | - (void)dealloc 717 | { 718 | self.lineColor = nil; 719 | #if !ACE_HAS_ARC 720 | [super dealloc]; 721 | #endif 722 | } 723 | 724 | @end 725 | 726 | 727 | #pragma mark - ACEDrawingHexagonTool 728 | 729 | @interface ACEDrawingHexagonTool () 730 | @property (nonatomic, assign) CGPoint firstPoint; 731 | @property (nonatomic, assign) CGPoint lastPoint; 732 | @end 733 | 734 | #pragma mark - 735 | 736 | @implementation ACEDrawingHexagonTool 737 | 738 | @synthesize lineColor = _lineColor; 739 | @synthesize lineAlpha = _lineAlpha; 740 | @synthesize lineWidth = _lineWidth; 741 | 742 | - (void)setInitialPoint:(CGPoint)firstPoint 743 | { 744 | self.firstPoint = firstPoint; 745 | } 746 | 747 | - (void)moveFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint 748 | { 749 | self.lastPoint = endPoint; 750 | } 751 | 752 | - (void)draw 753 | { 754 | CGContextRef context = UIGraphicsGetCurrentContext(); 755 | 756 | // set the properties 757 | CGContextSetAlpha(context, self.lineAlpha); 758 | CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor); 759 | CGContextSetLineWidth(context, self.lineWidth); 760 | CGContextSetLineCap(context, kCGLineCapRound); 761 | CGContextSetLineJoin(context, kCGLineJoinRound); 762 | 763 | double dx = (self.lastPoint.x - self.firstPoint.x); 764 | double dy = (self.lastPoint.y - self.firstPoint.y); 765 | double dist = sqrt(dx*dx + dy*dy); 766 | 767 | 768 | CGPoint center = midPoint(self.firstPoint, self.lastPoint); 769 | CGFloat diameter = dist / 2; 770 | CGFloat sidesNumber = 6; 771 | 772 | // Now add the hexagon to the current path 773 | CGContextMoveToPoint(context, center.x, center.y + diameter); 774 | for(int i = 1; i < sidesNumber+1; ++i) 775 | { 776 | CGFloat x = diameter * sinf(i * 2.0 * M_PI / sidesNumber); 777 | CGFloat y = diameter * cosf(i * 2.0 * M_PI / sidesNumber); 778 | CGContextAddLineToPoint(context, center.x + x, center.y + y); 779 | } 780 | 781 | 782 | if (self.fill) { 783 | CGContextDrawPath(context, kCGPathFillStroke); 784 | CGContextSetFillColorWithColor(context, self.lineColor.CGColor); 785 | } else { 786 | CGContextStrokePath(context); 787 | } 788 | 789 | // And close the subpath. 790 | CGContextClosePath(context); 791 | } 792 | 793 | - (ACEDrawingToolState *)captureToolState 794 | { 795 | return [ACEDrawingToolState stateForTool:self]; 796 | } 797 | 798 | - (void)dealloc 799 | { 800 | self.lineColor = nil; 801 | #if !ACE_HAS_ARC 802 | [super dealloc]; 803 | #endif 804 | } 805 | 806 | @end 807 | --------------------------------------------------------------------------------