├── README.md ├── MDraw ├── en.lproj │ └── InfoPlist.strings ├── MDrawArc.h ├── MDrawAngle.h ├── MDrawFatArrow.h ├── MDraw-Prefix.pch ├── MDrawComment.h ├── MDrawMeasurementInfo.h ├── MUndoManager.h ├── MDrawText.h ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── MDrawArrow.h ├── MDrawEllipse.h ├── MDrawFreeline.h ├── MDrawLine.h ├── ViewController.h ├── AppDelegate.h ├── MDraw-Info.plist ├── main.m ├── MDrawPolyline.h ├── MDrawTool_Subclass.h ├── MUndoManager.m ├── MDrawRect.h ├── MDrawText.m ├── MDrawMeasurementInfo.m ├── MDrawComment.m ├── MDrawArc.m ├── MDrawFatArrow.m ├── MDrawAngle.m ├── MDrawEllipse.m ├── AppDelegate.m ├── MDrawArrow.m ├── ViewController.m ├── MDrawView.h ├── MDrawTool.h ├── MDrawLine.m ├── MDrawFreeline.m ├── MDrawTool.m ├── MDrawRect.m ├── MDrawPolyline.m ├── Base.lproj │ └── Main.storyboard ├── MDrawMath.h └── MDrawView.m ├── MDrawTests ├── en.lproj │ └── InfoPlist.strings ├── MDrawTests-Info.plist └── MDrawTests.m ├── MDraw.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcuserdata │ └── gaoyq.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── MDraw.xcscheme └── project.pbxproj ├── .gitignore └── LICENSE /README.md: -------------------------------------------------------------------------------- 1 | MDraw 2 | ===== 3 | 4 | A simple demo for drawing tools on iOS 5 | -------------------------------------------------------------------------------- /MDraw/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /MDrawTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /MDraw/MDrawArc.h: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawArc.h 3 | // Motics 4 | // 5 | // Created by Gao Yongqing on 2/5/14. 6 | // 7 | // 8 | 9 | #import "MDrawAngle.h" 10 | 11 | @interface MDrawArc : MDrawAngle 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MDraw.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MDraw/MDrawAngle.h: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawAngle.h 3 | // Motics 4 | // 5 | // Created by Gao Yongqing on 2/6/14. 6 | // 7 | // 8 | 9 | #import "MDrawPolyline.h" 10 | 11 | @interface MDrawAngle : MDrawPolyline 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MDraw/MDrawFatArrow.h: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawFatArrow.h 3 | // Motics 4 | // 5 | // Created by Gao Yongqing on 2/5/14. 6 | // 7 | // 8 | 9 | #import "MDrawLine.h" 10 | 11 | @interface MDrawFatArrow : MDrawLine 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | -------------------------------------------------------------------------------- /MDraw/MDraw-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /MDraw/MDrawComment.h: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawComment.h 3 | // Motics 4 | // 5 | // Created by Gao Yongqing on 2/11/14. 6 | // 7 | // 8 | 9 | #import "MDrawText.h" 10 | 11 | @protocol MDrawCommentDelegate 12 | 13 | -(void)drawTool:(MDrawTool *)tool isAdded:(BOOL)added; 14 | 15 | @end 16 | 17 | @interface MDrawComment : MDrawText 18 | 19 | @property (nonatomic,weak) id delegate; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MDraw/MDrawMeasurementInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawMeasurementInfo.h 3 | // MDraw 4 | // 5 | // Created by Gao Yongqing on 9/5/14. 6 | // Copyright (c) 2014 Motic China Group Co., Ltd. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MDrawTool.h" 11 | 12 | /** 13 | * Show measurement info for tools. 14 | */ 15 | @interface MDrawMeasurementInfo : NSObject 16 | 17 | @property (nonatomic,weak,readonly) MDrawTool *tool; 18 | 19 | - (instancetype)initWithTool:(MDrawTool *)aTool; 20 | 21 | - (void)draw:(CGContextRef)ctx; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MDraw/MUndoManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // MUndoManager.h 3 | // MDraw 4 | // 5 | // Created by Gao Yongqing on 8/28/13. 6 | // Copyright (c) 2013 Motic China Group Co., Ltd. All rights reserved. 7 | // 8 | // Provide a simple undo/redo manager for drawing tools. 9 | 10 | #import 11 | 12 | @interface MUndoManager : NSObject 13 | 14 | -(id)initWithTools:(NSMutableArray *)tools; 15 | 16 | -(BOOL)undo; 17 | -(BOOL)redo; 18 | -(void)removeTool:(id)tool; 19 | -(void)addTool:(id)tool; 20 | /** 21 | * Remove all tools and histories 22 | */ 23 | -(void)reset; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /MDraw/MDrawText.h: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawText.h 3 | // Motics 4 | // 5 | // Created by Gao Yongqing on 2/10/14. 6 | // 7 | // 8 | 9 | #import "MDrawRect.h" 10 | 11 | @interface MDrawText : MDrawRect 12 | 13 | @property (nonatomic,strong) NSString *text; 14 | 15 | @property (nonatomic,strong) UIColor *backgroundColor; 16 | 17 | /** 18 | * Init a DrawText with frame and text 19 | * 20 | * @param frame The frame for text tool 21 | * @param text The text to display 22 | * 23 | * @return An instance of MDrawText 24 | */ 25 | -(id)initWithFrame:(CGRect)frame andText:(NSString *)text; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /MDraw.xcodeproj/xcuserdata/gaoyq.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MDraw.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 33E28B7317C20DA200EFC071 16 | 17 | primary 18 | 19 | 20 | 33E28B9417C20DA200EFC071 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /MDraw/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "ipad", 5 | "size" : "29x29", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "ipad", 10 | "size" : "29x29", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "ipad", 15 | "size" : "40x40", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "size" : "40x40", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "76x76", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "76x76", 31 | "scale" : "2x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /MDrawTests/MDrawTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | motic.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /MDraw/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "ipad", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "1x" 9 | }, 10 | { 11 | "orientation" : "landscape", 12 | "idiom" : "ipad", 13 | "extent" : "full-screen", 14 | "minimum-system-version" : "7.0", 15 | "scale" : "1x" 16 | }, 17 | { 18 | "orientation" : "portrait", 19 | "idiom" : "ipad", 20 | "extent" : "full-screen", 21 | "minimum-system-version" : "7.0", 22 | "scale" : "2x" 23 | }, 24 | { 25 | "orientation" : "landscape", 26 | "idiom" : "ipad", 27 | "extent" : "full-screen", 28 | "minimum-system-version" : "7.0", 29 | "scale" : "2x" 30 | } 31 | ], 32 | "info" : { 33 | "version" : 1, 34 | "author" : "xcode" 35 | } 36 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 xmkevin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /MDraw/MDrawArrow.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawLine.h" 23 | 24 | @interface MDrawArrow : MDrawLine 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /MDraw/MDrawEllipse.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawRect.h" 23 | 24 | @interface MDrawEllipse : MDrawRect 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /MDraw/MDrawFreeline.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawRect.h" 23 | 24 | @interface MDrawFreeline : MDrawRect 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /MDraw/MDrawLine.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawTool_Subclass.h" 23 | 24 | @interface MDrawLine : MDrawTool 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /MDraw/ViewController.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import 23 | 24 | @interface ViewController : UIViewController 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /MDraw/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import 23 | 24 | @interface AppDelegate : UIResponder 25 | 26 | @property (strong, nonatomic) UIWindow *window; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /MDraw/MDraw-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | motic.${PRODUCT_NAME:rfc1034identifier} 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 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations~ipad 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationPortraitUpsideDown 37 | UIInterfaceOrientationLandscapeLeft 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /MDraw/main.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import 23 | 24 | #import "AppDelegate.h" 25 | 26 | int main(int argc, char * argv[]) 27 | { 28 | @autoreleasepool { 29 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /MDraw/MDrawPolyline.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawTool_Subclass.h" 23 | 24 | @interface MDrawPolyline : MDrawTool 25 | { 26 | @protected 27 | NSMutableArray *_points; 28 | CGPoint _movePoint; 29 | int _moveHandleIndex; 30 | BOOL _closePath; 31 | } 32 | 33 | 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /MDraw/MDrawTool_Subclass.h: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawTool_Subclass.h 3 | // Motics 4 | // 5 | // Created by Gao Yongqing on 3/3/14. 6 | // 7 | // 8 | 9 | #import "MDrawTool.h" 10 | 11 | @interface MDrawTool (ForSubClassEyesOnly) 12 | 13 | /** 14 | * Draw moving handlers 15 | * 16 | * @param ctx the context to draw 17 | * @param point the handle location 18 | */ 19 | -(void)drawHandle:(CGContextRef)ctx atPoint:(CGPoint)point; 20 | 21 | /** 22 | * Determine whether or not the point is on the handle 23 | * 24 | * @param point a point to test 25 | * @param handlePoint the handle point 26 | * 27 | * @return YES if the point is on the handle, otherwise NO 28 | */ 29 | -(BOOL)isPoint:(CGPoint)point onHandle:(CGPoint)handlePoint; 30 | 31 | /** 32 | * Draw measurement information for tool 33 | * 34 | * @param ctx The context to draw 35 | * @param view The parent viewer. 36 | */ 37 | -(void)drawMeasurement:(CGContextRef)ctx inView:(UIView *)view; 38 | 39 | /** 40 | * Convert pixels to current tool's unit by calibration. 41 | * 42 | * @param pixels original pixel values 43 | * @param square Is calculate area. 44 | * 45 | * @return Value of current unit 46 | */ 47 | -(CGFloat)unitConvert:(CGFloat)pixels isSquare:(BOOL)square; 48 | 49 | /** 50 | * This method is for subclass to call, drawing without measurement information 51 | * 52 | * @param ctx Context to draw on 53 | * @param view The container view 54 | * @param noMeasurement YES: no draw measurement information 55 | */ 56 | -(void)draw:(CGContextRef)ctx inView:(UIView *)view withoutMeasurement:(BOOL)noMeasurement; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /MDraw/MUndoManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // MUndoManager.m 3 | // MDraw 4 | // 5 | // Created by Gao Yongqing on 8/28/13. 6 | // Copyright (c) 2013 Motic China Group Co., Ltd. All rights reserved. 7 | // 8 | 9 | #import "MUndoManager.h" 10 | 11 | @implementation MUndoManager 12 | { 13 | NSMutableArray *_tools; 14 | NSMutableArray *_undoTools; 15 | NSMutableArray *_redoTools; 16 | } 17 | 18 | -(id)initWithTools:(NSMutableArray *)tools 19 | { 20 | self = [super init]; 21 | if(self) 22 | { 23 | _tools = tools; 24 | _undoTools = [[NSMutableArray alloc] init]; 25 | _redoTools = [[NSMutableArray alloc] init]; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | -(BOOL)undo 32 | { 33 | if(_undoTools.count == 0 ) 34 | { 35 | return NO; 36 | } 37 | 38 | id lastTool = [_undoTools lastObject]; 39 | [_tools removeObject:lastTool]; 40 | [_undoTools removeObject:lastTool]; 41 | [_redoTools addObject:lastTool]; 42 | 43 | return YES; 44 | } 45 | 46 | -(BOOL)redo 47 | { 48 | if(_redoTools.count == 0 ) 49 | { 50 | return NO; 51 | } 52 | 53 | id tool = [_redoTools lastObject]; 54 | [_redoTools removeObject:tool]; 55 | [_undoTools addObject:tool]; 56 | [_tools addObject:tool]; 57 | 58 | return YES; 59 | } 60 | 61 | -(void)removeTool:(id)tool 62 | { 63 | [_tools removeObject:tool]; 64 | [_redoTools addObject:tool]; 65 | } 66 | 67 | -(void)addTool:(id)tool 68 | { 69 | [_redoTools removeAllObjects]; 70 | 71 | [_tools addObject:tool]; 72 | [_undoTools addObject:tool]; 73 | } 74 | 75 | -(void)reset 76 | { 77 | [_redoTools removeAllObjects]; 78 | [_undoTools removeAllObjects]; 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /MDraw/MDrawRect.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawLine.h" 23 | 24 | enum MDrawMoveDirection { 25 | MDrawMoveDirectionNone = 0, 26 | MDrawMoveDirectionWhole = 1, 27 | MDrawMoveDirectionTL = 2, 28 | MDrawMoveDirectionTM = 3, 29 | MDrawMoveDirectionTR = 4, 30 | MDrawMoveDirectionRM = 5, 31 | MDrawMoveDirectionBR = 6, 32 | MDrawMoveDirectionBM = 7, 33 | MDrawMoveDirectionBL = 8, 34 | MDrawMoveDirectionLM = 9 35 | }; 36 | 37 | @interface MDrawRect : MDrawLine 38 | { 39 | @protected 40 | enum MDrawMoveDirection _moveDirection; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /MDrawTests/MDrawTests.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import 23 | 24 | @interface MDrawTests : XCTestCase 25 | 26 | @end 27 | 28 | @implementation MDrawTests 29 | 30 | - (void)setUp 31 | { 32 | [super setUp]; 33 | // Put setup code here. This method is called before the invocation of each test method in the class. 34 | } 35 | 36 | - (void)tearDown 37 | { 38 | // Put teardown code here. This method is called after the invocation of each test method in the class. 39 | [super tearDown]; 40 | } 41 | 42 | - (void)testExample 43 | { 44 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /MDraw/MDrawText.m: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawText.m 3 | // Motics 4 | // 5 | // Created by Gao Yongqing on 2/10/14. 6 | // 7 | // 8 | 9 | #import "MDrawText.h" 10 | 11 | @implementation MDrawText 12 | { 13 | UILabel *_label; // Use a label to display text; 14 | } 15 | 16 | -(id)initWithFrame:(CGRect)frame andText:(NSString *)text 17 | { 18 | if(self = [super init]) 19 | { 20 | _startPoint = frame.origin; 21 | _endPoint = CGPointMake(_startPoint.x + frame.size.width, _startPoint.y + frame.size.height); 22 | 23 | self.text = text; 24 | } 25 | 26 | return self; 27 | } 28 | 29 | -(void)draw:(CGContextRef)ctx 30 | { 31 | if(!self.backgroundColor) 32 | { 33 | self.backgroundColor = [UIColor colorWithRed:255 green:255 blue:255 alpha:0.5]; 34 | } 35 | 36 | if(!_label) 37 | { 38 | _label = [[UILabel alloc] init]; 39 | _label.adjustsFontSizeToFitWidth = YES; 40 | _label.textAlignment = NSTextAlignmentLeft; 41 | _label.textColor = self.color; 42 | _label.font = [UIFont systemFontOfSize:60]; 43 | _label.minimumScaleFactor = 0.001f; 44 | _label.numberOfLines = 0; 45 | 46 | _label.layer.borderWidth =2; 47 | _label.layer.borderColor = self.color.CGColor; 48 | 49 | } 50 | 51 | CGRect frame = self.frame; 52 | 53 | CGContextSaveGState(ctx); 54 | 55 | 56 | if([self.text length] > 0) 57 | { 58 | _label.frame = CGRectMake(0, 0, frame.size.width, frame.size.height); 59 | _label.text = self.text; 60 | CGContextTranslateCTM(ctx, frame.origin.x, frame.origin.y); 61 | [_label.layer drawInContext:ctx]; 62 | 63 | } 64 | else 65 | { 66 | CGContextSetFillColorWithColor(ctx, self.backgroundColor.CGColor); 67 | CGContextFillRect(ctx, frame); 68 | } 69 | 70 | CGContextRestoreGState(ctx); 71 | 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /MDraw/MDrawMeasurementInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawMeasurementInfo.m 3 | // MDraw 4 | // 5 | // Created by Gao Yongqing on 9/5/14. 6 | // Copyright (c) 2014 Motic China Group Co., Ltd. All rights reserved. 7 | // 8 | 9 | #import "MDrawMeasurementInfo.h" 10 | 11 | @implementation MDrawMeasurementInfo 12 | 13 | @synthesize tool = _tool; 14 | 15 | - (id)init 16 | { 17 | [NSException raise:@"InitException" format:@"Should call initWithTool to create an instance."]; 18 | 19 | return nil; 20 | } 21 | 22 | - (instancetype)initWithTool:(MDrawTool *)aTool 23 | { 24 | if (self = [super init]) { 25 | _tool = aTool; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | - (void)draw:(CGContextRef)ctx 32 | { 33 | NSString *text = self.tool.measureText; 34 | if(text == Nil) 35 | { 36 | return; 37 | } 38 | 39 | CGSize textSize = CGSizeZero; 40 | UIFont *textFont = [UIFont systemFontOfSize:14]; 41 | 42 | if(text != Nil) 43 | { 44 | textSize= [text sizeWithFont:textFont 45 | constrainedToSize:CGSizeMake(1024, 99999.0) 46 | lineBreakMode:NSLineBreakByWordWrapping]; 47 | 48 | } 49 | 50 | CGRect textFrame = [self calculateTextFrameWithTextSize:textSize forToolFrame:self.tool.frame]; 51 | CGRect textBgFrame = CGRectMake(textFrame.origin.x - 10, textFrame.origin.y - 10, textFrame.size.width + 20, textFrame.size.height + 20); 52 | CGContextSetFillColorWithColor(ctx, [UIColor colorWithRed:255 green:255 blue:255 alpha:0.5].CGColor); 53 | CGContextFillRect(ctx, textBgFrame); 54 | 55 | [text drawWithRect:textFrame options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: textFont} context:Nil]; 56 | } 57 | 58 | -(CGRect)calculateTextFrameWithTextSize:(CGSize)textSize forToolFrame:(CGRect)toolFrame 59 | { 60 | static CGFloat MARGIN = 20; 61 | 62 | CGRect textFrame = CGRectZero; 63 | CGPoint midPoint = CGRectMid(toolFrame); 64 | textFrame = CGRectMake(midPoint.x - textSize.width / 2.0f, toolFrame.origin.y - textSize.height - MARGIN, textSize.width, textSize.height); 65 | 66 | return textFrame; 67 | 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /MDraw/MDrawComment.m: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawComment.m 3 | // Motics 4 | // 5 | // Created by Gao Yongqing on 2/11/14. 6 | // 7 | // 8 | 9 | #import "MDrawComment.h" 10 | 11 | @implementation MDrawComment 12 | 13 | -(void)drawUp:(CGPoint)point 14 | { 15 | [super drawUp:point]; 16 | 17 | [self promoteText]; 18 | } 19 | 20 | -(void)draw:(CGContextRef)ctx 21 | { 22 | [super draw:ctx]; 23 | 24 | CGRect frame = self.frame; 25 | 26 | if (self.selected) 27 | { 28 | [self drawHandle:ctx atPoint:CGRectTL(frame)]; 29 | [self drawHandle:ctx atPoint:CGRectTM(frame)]; 30 | [self drawHandle:ctx atPoint:CGRectTR(frame)]; 31 | [self drawHandle:ctx atPoint:CGRectRM(frame)]; 32 | [self drawHandle:ctx atPoint:CGRectBR(frame)]; 33 | [self drawHandle:ctx atPoint:CGRectBM(frame)]; 34 | [self drawHandle:ctx atPoint:CGRectBL(frame)]; 35 | [self drawHandle:ctx atPoint:CGRectLM(frame)]; 36 | } 37 | } 38 | 39 | #pragma Mark - Alert view delegate 40 | 41 | -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 42 | { 43 | BOOL added = buttonIndex == 1; 44 | 45 | if ( added ) 46 | { 47 | self.text = [[alertView textFieldAtIndex:0] text]; 48 | 49 | //Give a minimize size for comment. 50 | CGRect frame = self.frame; 51 | CGFloat width = frame.size.width < 200 ? 200 : frame.size.width; 52 | CGFloat height = frame.size.height < 150 ? 150 : frame.size.height; 53 | _endPoint = CGPointMake(frame.origin.x + width, frame.origin.y + height); 54 | 55 | } 56 | 57 | if(self.delegate) 58 | { 59 | [self.delegate drawTool:self isAdded:added]; 60 | } 61 | 62 | } 63 | 64 | -(void)promoteText 65 | { 66 | UIAlertView *alertView = [[UIAlertView alloc] initWithTitle: NSLocalizedString(@"enterYourText", nil) 67 | message:nil 68 | delegate:self 69 | cancelButtonTitle:NSLocalizedString(@"Cancel", nil) 70 | otherButtonTitles:NSLocalizedString(@"Confirm", nil), nil]; 71 | alertView.alertViewStyle = UIAlertViewStylePlainTextInput; 72 | [alertView show]; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /MDraw/MDrawArc.m: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawArc.m 3 | // Motics 4 | // 5 | // Created by Gao Yongqing on 2/5/14. 6 | // 7 | // 8 | 9 | #import "MDrawArc.h" 10 | 11 | @implementation MDrawArc 12 | 13 | -(void)drawUp:(CGPoint)point 14 | { 15 | _movePoint = CGPointZero; 16 | if(self.finalized) 17 | { 18 | return; 19 | } 20 | 21 | [_points addObject:[NSValue valueWithCGPoint:CGPointMidPoint(_startPoint, point)]]; 22 | [_points addObject:[NSValue valueWithCGPoint:point]]; 23 | [self finalize]; 24 | } 25 | 26 | -(void)draw:(CGContextRef)ctx 27 | { 28 | if(self.finalized) 29 | { 30 | CGPoint from = [_points[0] CGPointValue]; 31 | CGPoint arc = [_points[1] CGPointValue]; 32 | CGPoint to = [_points[2] CGPointValue]; 33 | 34 | CGContextSetStrokeColorWithColor(ctx, self.color.CGColor); 35 | CGContextSetLineWidth(ctx, 3); 36 | CGContextBeginPath(ctx); 37 | CGContextMoveToPoint(ctx, from.x, from.y); 38 | CGContextAddQuadCurveToPoint(ctx, arc.x, arc.y, to.x, to.y); 39 | CGContextStrokePath(ctx); 40 | 41 | if (self.selected) 42 | { 43 | [self drawHandle:ctx atPoint:from]; 44 | [self drawHandle:ctx atPoint:arc]; 45 | [self drawHandle:ctx atPoint:to]; 46 | } 47 | } 48 | else 49 | { 50 | [super draw:ctx]; 51 | } 52 | 53 | 54 | } 55 | 56 | -(NSString *)measureText 57 | { 58 | static NSString *lengthString, *distanceString; 59 | if (!lengthString) 60 | { 61 | lengthString = NSLocalizedString(@"Length", Nil); 62 | distanceString = NSLocalizedString(@"Distance", Nil); 63 | } 64 | 65 | CGPoint p1 = [[_points objectAtIndex:0] CGPointValue]; 66 | CGPoint arcPoint = [[_points objectAtIndex:1] CGPointValue]; 67 | CGPoint p2 = [[_points objectAtIndex:2] CGPointValue]; 68 | 69 | CGFloat length = CGArcLength(p1, arcPoint, p2); 70 | CGFloat distance = CGPointDistance(p1, p2); 71 | 72 | 73 | return [NSString stringWithFormat:@"%@: %0.2f %@\n%@: %0.2f %@", 74 | lengthString, 75 | [self unitConvert:length isSquare:NO], 76 | self.unit, 77 | distanceString, 78 | [self unitConvert:distance isSquare:NO], 79 | self.unit]; 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /MDraw/MDrawFatArrow.m: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawFatArrow.m 3 | // Motics 4 | // 5 | // Created by Gao Yongqing on 2/5/14. 6 | // 7 | // 8 | 9 | #import "MDrawFatArrow.h" 10 | 11 | @implementation MDrawFatArrow 12 | 13 | -(BOOL)hitTest:(CGPoint)point 14 | { 15 | return CGPointInRect(point, self.frame); 16 | } 17 | 18 | -(void)draw:(CGContextRef)ctx 19 | { 20 | CGFloat length = CGPointDistance(_startPoint, _endPoint); 21 | CGSize dSize = CGPointOffset(_startPoint, _endPoint); 22 | 23 | // Draw an arrow at the horizontal line and then rotate it. 24 | // Here are the horizontal points. 25 | CGPoint p1 = CGPointZero; 26 | CGPoint p2 = CGPointMake(p1.x + length * 0.6, p1.y + length * 0.4); 27 | CGPoint p3 = CGPointMake(p1.x + length * 0.6, p1.y + length * 0.15); 28 | CGPoint p4 = CGPointMake(p1.x + length, p1.y + length * 0.15); 29 | CGPoint p5 = CGPointMake(p1.x + length, p1.y - length * 0.15); 30 | CGPoint p6 = CGPointMake(p1.x + length * 0.6, p1.y - length * 0.15); 31 | CGPoint p7 = CGPointMake(p1.x + length * 0.6, p1.y - length * 0.4); 32 | 33 | CGContextSaveGState(ctx); 34 | 35 | CGContextSetStrokeColorWithColor(ctx, self.color.CGColor); 36 | CGContextSetFillColorWithColor(ctx, self.color.CGColor); 37 | CGContextSetLineWidth(ctx, self.lineWidth); 38 | 39 | 40 | CGContextBeginPath(ctx); 41 | 42 | CGContextTranslateCTM(ctx, _startPoint.x,_startPoint.y); 43 | CGContextRotateCTM(ctx, atan2f(dSize.height,dSize.width)); 44 | 45 | CGContextMoveToPoint(ctx, p1.x, p1.y); 46 | CGContextAddLineToPoint(ctx, p2.x, p2.y); 47 | CGContextAddLineToPoint(ctx, p3.x, p3.y); 48 | CGContextAddLineToPoint(ctx, p4.x, p4.y); 49 | CGContextAddLineToPoint(ctx, p5.x, p5.y); 50 | CGContextAddLineToPoint(ctx, p6.x, p6.y); 51 | CGContextAddLineToPoint(ctx, p7.x, p7.y); 52 | CGContextClosePath(ctx); 53 | 54 | CGContextFillPath(ctx); 55 | CGContextStrokePath(ctx); 56 | 57 | 58 | CGContextRestoreGState(ctx); 59 | 60 | if (self.selected) 61 | { 62 | CGContextSaveGState(ctx); 63 | CGContextSetStrokeColorWithColor(ctx, self.color.CGColor); 64 | CGContextSetFillColorWithColor(ctx, self.color.CGColor); 65 | 66 | [self drawHandle:ctx atPoint:_startPoint]; 67 | [self drawHandle:ctx atPoint:_endPoint]; 68 | 69 | CGContextRestoreGState(ctx); 70 | } 71 | 72 | 73 | } 74 | 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /MDraw/MDrawAngle.m: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawAngle.m 3 | // Motics 4 | // 5 | // Created by Gao Yongqing on 2/6/14. 6 | // 7 | // 8 | 9 | #import "MDrawAngle.h" 10 | 11 | @implementation MDrawAngle 12 | 13 | -(id)init 14 | { 15 | if(self = [super init]) 16 | { 17 | _closePath = NO; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | -(id)initWithStartPoint:(CGPoint)startPoint 24 | { 25 | if(self = [super initWithStartPoint:startPoint]) 26 | { 27 | _closePath = NO; 28 | } 29 | 30 | return self; 31 | } 32 | 33 | 34 | 35 | -(void)drawUp:(CGPoint)point 36 | { 37 | _movePoint = CGPointZero; 38 | 39 | if(self.finalized) 40 | { 41 | return; 42 | } 43 | 44 | BOOL isStartPoint = NO; 45 | if(_points.count > 0 ) 46 | { 47 | CGPoint startPoint = [[_points objectAtIndex:0] CGPointValue]; 48 | if([self isPoint:point onHandle:startPoint]) 49 | { 50 | isStartPoint = YES; 51 | } 52 | } 53 | 54 | if(!isStartPoint) 55 | { 56 | [_points addObject:[NSValue valueWithCGPoint:point]]; 57 | } 58 | 59 | if(_points.count >=3) 60 | { 61 | [self finalize]; 62 | } 63 | } 64 | 65 | -(void)draw:(CGContextRef)ctx 66 | { 67 | [super draw:ctx]; 68 | 69 | if(self.finalized) 70 | { 71 | CGPoint p1 = [_points[0] CGPointValue]; 72 | CGPoint p2 = [_points[1] CGPointValue]; 73 | CGPoint p3 = [_points[2] CGPointValue]; 74 | 75 | CGFloat line1 = CGPointDistance(p2, p1); 76 | CGFloat line2 = CGPointDistance(p2, p3); 77 | CGFloat minLength = MIN(line1, line2); 78 | CGFloat arcRadius = minLength > 20 ? 20 : minLength; 79 | 80 | CGFloat radian1 = CGVectorRadian(p2,p1); 81 | CGFloat radian2 = CGVectorRadian(p2,p3); 82 | 83 | CGContextSetStrokeColorWithColor(ctx, self.color.CGColor); 84 | CGContextBeginPath(ctx); 85 | CGContextAddArc(ctx, p2.x, p2.y, arcRadius,radian1,radian2, 0); 86 | CGContextStrokePath(ctx); 87 | } 88 | 89 | } 90 | 91 | -(NSString *)measureText 92 | { 93 | static NSString *degreeString; 94 | if(!degreeString) 95 | { 96 | degreeString = NSLocalizedString(@"Degree", Nil); 97 | } 98 | 99 | CGPoint p1 = [[_points objectAtIndex:0] CGPointValue]; 100 | CGPoint arcPoint = [[_points objectAtIndex:1] CGPointValue]; 101 | CGPoint p2 = [[_points objectAtIndex:2] CGPointValue]; 102 | 103 | return [NSString stringWithFormat:@"%@ : %0.2f", 104 | degreeString, 105 | CGAngleDegree(p1, arcPoint, p2)]; 106 | } 107 | 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /MDraw/MDrawEllipse.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawEllipse.h" 23 | 24 | @implementation MDrawEllipse 25 | 26 | -(void)draw:(CGContextRef)ctx 27 | { 28 | CGContextSetStrokeColorWithColor(ctx, self.color.CGColor); 29 | CGContextSetLineWidth(ctx, self.lineWidth); 30 | 31 | CGContextBeginPath(ctx); 32 | CGContextAddEllipseInRect(ctx, self.frame); 33 | CGContextStrokePath(ctx); 34 | 35 | if (self.selected) 36 | { 37 | CGRect frame = self.frame; 38 | [self drawHandle:ctx atPoint:CGRectTL(frame)]; 39 | [self drawHandle:ctx atPoint:CGRectTM(frame)]; 40 | [self drawHandle:ctx atPoint:CGRectTR(frame)]; 41 | [self drawHandle:ctx atPoint:CGRectRM(frame)]; 42 | [self drawHandle:ctx atPoint:CGRectBR(frame)]; 43 | [self drawHandle:ctx atPoint:CGRectBM(frame)]; 44 | [self drawHandle:ctx atPoint:CGRectBL(frame)]; 45 | [self drawHandle:ctx atPoint:CGRectLM(frame)]; 46 | } 47 | 48 | } 49 | 50 | -(NSString *)measureText 51 | { 52 | static NSString *radiusString, *areaString, *perimeterString; 53 | if(!radiusString) 54 | { 55 | radiusString = NSLocalizedString(@"Radius", nil); 56 | areaString = NSLocalizedString(@"Area", nil); 57 | perimeterString = NSLocalizedString(@"Perimeter", nil); 58 | } 59 | 60 | CGFloat radius = fabs((_startPoint.x - _endPoint.x)/2.0); 61 | CGFloat area = M_PI * pow(radius, 2); 62 | CGFloat perimeter = 2 * M_PI * radius; 63 | 64 | return [NSString stringWithFormat:@"%@: %0.2f %@\n%@: %0.2f sq%@\n%@: %0.2f %@", 65 | radiusString, 66 | [self unitConvert:radius isSquare:NO], 67 | self.unit, 68 | areaString, 69 | [self unitConvert:area isSquare:YES], 70 | self.unit, 71 | perimeterString, 72 | [self unitConvert:perimeter isSquare:NO], 73 | self.unit]; 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /MDraw/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "AppDelegate.h" 23 | 24 | @implementation AppDelegate 25 | 26 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 27 | { 28 | // Override point for customization after application launch. 29 | return YES; 30 | } 31 | 32 | - (void)applicationWillResignActive:(UIApplication *)application 33 | { 34 | // 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. 35 | // 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. 36 | } 37 | 38 | - (void)applicationDidEnterBackground:(UIApplication *)application 39 | { 40 | // 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. 41 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 42 | } 43 | 44 | - (void)applicationWillEnterForeground:(UIApplication *)application 45 | { 46 | // 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. 47 | } 48 | 49 | - (void)applicationDidBecomeActive:(UIApplication *)application 50 | { 51 | // 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. 52 | } 53 | 54 | - (void)applicationWillTerminate:(UIApplication *)application 55 | { 56 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /MDraw/MDrawArrow.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawArrow.h" 23 | 24 | @implementation MDrawArrow 25 | 26 | - (NSString *)measureText 27 | { 28 | return nil; 29 | } 30 | 31 | -(void)draw:(CGContextRef)ctx 32 | { 33 | 34 | if(CGPointEqualToPoint(_startPoint, _endPoint)) 35 | { 36 | return; 37 | } 38 | 39 | CGSize dSize = CGPointOffset(_startPoint, _endPoint); 40 | //Draw a triagnle as the arrow, the default angle is 15 degree 41 | //And the default half length is 2x line width. 42 | float radian = 15.0 /180.0 * M_PI; 43 | float length = self.lineWidth * 2; 44 | float x = length / tanf(radian); 45 | CGPoint p1 = CGPointZero; 46 | CGPoint p2 = CGPointMake(x, p1.y - length); 47 | CGPoint p3 = CGPointMake(x, p1.y + length); 48 | 49 | float lineRadian = atan2f(dSize.height, dSize.width); 50 | float xOffset = x * cosf(lineRadian); 51 | float yOffset = x * sinf(lineRadian); 52 | CGPoint newStartPoint = CGPointMake(_startPoint.x + xOffset, _startPoint.y + yOffset); 53 | 54 | 55 | CGContextSaveGState(ctx); 56 | 57 | CGContextSetStrokeColorWithColor(ctx, self.color.CGColor); 58 | CGContextSetFillColorWithColor(ctx, self.color.CGColor); 59 | CGContextSetLineWidth(ctx, self.lineWidth); 60 | 61 | //Draw line 62 | CGContextBeginPath(ctx); 63 | CGContextMoveToPoint(ctx, newStartPoint.x, newStartPoint.y); 64 | CGContextAddLineToPoint(ctx, _endPoint.x, _endPoint.y); 65 | CGContextClosePath(ctx); 66 | CGContextStrokePath(ctx); 67 | 68 | //Draw the arrow 69 | CGContextBeginPath(ctx); 70 | CGContextTranslateCTM(ctx, _startPoint.x,_startPoint.y); 71 | CGContextRotateCTM(ctx, atan2f(dSize.height,dSize.width)); 72 | CGContextMoveToPoint(ctx, p1.x, p1.y); 73 | CGContextAddLineToPoint(ctx, p2.x, p2.y); 74 | CGContextAddLineToPoint(ctx, p3.x, p3.y); 75 | CGContextClosePath(ctx); 76 | CGContextFillPath(ctx); 77 | 78 | CGContextRestoreGState(ctx); 79 | 80 | if (self.selected) 81 | { 82 | [self drawHandle:ctx atPoint:_startPoint]; 83 | [self drawHandle:ctx atPoint:_endPoint]; 84 | } 85 | } 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /MDraw/ViewController.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "ViewController.h" 23 | 24 | #import "MDrawView.h" 25 | #import "MDrawLine.h" 26 | #import "MDrawRect.h" 27 | #import "MDrawEllipse.h" 28 | #import "MDrawFreeline.h" 29 | #import "MDrawPolyline.h" 30 | 31 | @interface ViewController () 32 | 33 | @end 34 | 35 | @implementation ViewController 36 | { 37 | __weak IBOutlet MDrawView *drawView; 38 | } 39 | 40 | - (void)viewDidLoad 41 | { 42 | [super viewDidLoad]; 43 | // Do any additional setup after loading the view, typically from a nib. 44 | 45 | // drawView = [[MDrawView alloc] initWithFrame:self.view.frame]; 46 | // [self.view addSubview:drawView]; 47 | 48 | drawView.showMeasurement = YES; 49 | } 50 | 51 | - (void)didReceiveMemoryWarning 52 | { 53 | [super didReceiveMemoryWarning]; 54 | // Dispose of any resources that can be recreated. 55 | } 56 | 57 | - (UIBarPosition)positionForBar:(id)bar 58 | { 59 | return UIBarPositionTopAttached; 60 | } 61 | 62 | -(IBAction)drawLine:(id)sender 63 | { 64 | [drawView beginDrawingForType:[MDrawLine class]]; 65 | } 66 | 67 | -(IBAction)drawRect:(id)sender 68 | { 69 | [drawView beginDrawingForType:[MDrawRect class]]; 70 | } 71 | 72 | -(IBAction)drawEllipse:(id)sender 73 | { 74 | [drawView beginDrawingForType:[MDrawEllipse class]]; 75 | } 76 | 77 | -(IBAction)drawFreeline:(id)sender 78 | { 79 | [drawView beginDrawingForType:[MDrawFreeline class]]; 80 | } 81 | 82 | -(IBAction)drawPolyline:(id)sender 83 | { 84 | [drawView beginDrawingForType:[MDrawPolyline class]]; 85 | } 86 | 87 | -(IBAction)drawArrow:(id)sender 88 | { 89 | [drawView beginDrawingForType:[MDrawArrow class]]; 90 | } 91 | 92 | - (IBAction)drawArc:(id)sender 93 | { 94 | [drawView beginDrawingForType:[MDrawArc class]]; 95 | } 96 | 97 | - (IBAction)drawAngle:(id)sender 98 | { 99 | [drawView beginDrawingForType:[MDrawAngle class]]; 100 | } 101 | 102 | -(IBAction)undo:(id)sender 103 | { 104 | [drawView undo]; 105 | } 106 | 107 | -(IBAction)redo:(id)sender 108 | { 109 | [drawView redo]; 110 | } 111 | 112 | 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /MDraw/MDrawView.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import 23 | #import "MDrawTool.h" 24 | #import "MDrawLine.h" 25 | #import "MDrawRect.h" 26 | #import "MDrawEllipse.h" 27 | #import "MDrawFreeline.h" 28 | #import "MDrawPolyline.h" 29 | #import "MDrawArrow.h" 30 | #import "MDrawAngle.h" 31 | #import "MDrawArc.h" 32 | #import "MDrawText.h" 33 | #import "MDrawComment.h" 34 | 35 | @interface MDrawView : UIView 36 | 37 | 38 | @property (nonatomic,readonly) MDrawTool *activeTool; 39 | @property (nonatomic,readonly) BOOL drawing; 40 | 41 | /** 42 | * The color of new drawing tool 43 | **/ 44 | @property (nonatomic) UIColor *color; 45 | /** 46 | * The default line width of new tool 47 | **/ 48 | @property (nonatomic) CGFloat lineWidth; 49 | 50 | /** 51 | * Whether or not there are tools. 52 | */ 53 | @property (nonatomic,readonly) BOOL hasTools; 54 | 55 | /** 56 | * Tools on the view 57 | */ 58 | @property (nonatomic,readonly) NSArray *tools; 59 | 60 | /** 61 | * Whether the view recevies gestures 62 | **/ 63 | @property (nonatomic) BOOL enableGesture; 64 | 65 | /** 66 | * YES to show measurement information. 67 | */ 68 | @property (nonatomic) BOOL showMeasurement; 69 | 70 | /** 71 | * um/pixel, if calibrated. default is 0. 72 | */ 73 | @property (nonatomic) CGFloat calibration; 74 | 75 | /** 76 | * Unit of measurement information 77 | */ 78 | @property (nonatomic,strong) NSString *unit; 79 | 80 | /** 81 | * Whether or not the tools is dirty 82 | */ 83 | @property (nonatomic,readonly) BOOL isDirty; 84 | 85 | /** 86 | * Undo the drawing 87 | **/ 88 | -(BOOL)undo; 89 | 90 | /** 91 | * Redo the drawing 92 | **/ 93 | -(BOOL)redo; 94 | 95 | /** 96 | * Select the drawing tool type 97 | **/ 98 | -(void)beginDrawingForType:(Class)toolType; 99 | 100 | /** 101 | * Stop drawing. 102 | **/ 103 | -(void)finalizeDrawing; 104 | 105 | -(void)drawDown:(CGPoint)point; 106 | -(void)drawMoveFromPoint:(CGPoint)srcPoint toPoint:(CGPoint)point; 107 | -(void)drawUp:(CGPoint)point; 108 | 109 | /** 110 | * Delete the active tool 111 | **/ 112 | -(void)deleteCurrentTool; 113 | 114 | /** 115 | * Clear all tools 116 | **/ 117 | -(void)clearTools; 118 | 119 | -(void)selectNone; 120 | 121 | @end 122 | -------------------------------------------------------------------------------- /MDraw.xcodeproj/xcuserdata/gaoyq.xcuserdatad/xcschemes/MDraw.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /MDraw/MDrawTool.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import 23 | #include "MDrawMath.h" 24 | //#include "UIColor+String.h" 25 | 26 | #define HANDLE_SIZE 20 27 | #define NEAR_WIDTH 10 28 | 29 | @protocol MDrawToolProtocol 30 | 31 | 32 | /** 33 | * Name of the tool. 34 | */ 35 | @property (nonatomic,strong)NSString *name; 36 | 37 | /** 38 | * Is the tool selected 39 | */ 40 | @property (nonatomic) BOOL selected; 41 | 42 | /** 43 | * Is the tool finalized (finish drawing) 44 | **/ 45 | @property (nonatomic,readonly) BOOL finalized; 46 | 47 | /** 48 | * Frame of this tool 49 | **/ 50 | @property (nonatomic,readonly) CGRect frame; 51 | 52 | /** 53 | * Line width 54 | **/ 55 | @property (nonatomic)CGFloat lineWidth; 56 | 57 | /** 58 | * Line color 59 | **/ 60 | @property (nonatomic,strong)UIColor *color; 61 | 62 | 63 | /** 64 | * Init the tool with a start point. 65 | **/ 66 | -(id)initWithStartPoint:(CGPoint )startPoint; 67 | 68 | /** 69 | * Draw mouse down (touchesBegan) 70 | **/ 71 | -(void)drawDown:(CGPoint)point; 72 | 73 | /** 74 | * Draw mouse move (touchesMove) 75 | **/ 76 | -(void)drawMove:(CGPoint)point; 77 | 78 | /** 79 | * Draw mouse up (touchesEnd) 80 | **/ 81 | -(void)drawUp:(CGPoint)point; 82 | 83 | /** 84 | * Finalize the drawing 85 | **/ 86 | -(void)finalize; 87 | 88 | /** 89 | * Hit test to see whether or not the point is on the tool 90 | **/ 91 | -(BOOL)hitTest:(CGPoint)point; 92 | 93 | /** 94 | * Determine whether or not the point hits a handle 95 | * If it hits a handle, then it can move the tool 96 | **/ 97 | -(BOOL)hitOnHandle:(CGPoint)point; 98 | 99 | /** 100 | * Move the tool or the selected handle to the new position. 101 | **/ 102 | -(void)moveByOffset:(CGSize)offset; 103 | 104 | /** 105 | * Stop move the handle 106 | **/ 107 | -(void)stopMoveHandle; 108 | 109 | /** 110 | * Draw itself on the context 111 | * 112 | * @param ctx context to draw on 113 | * 114 | * @param view The view to draw on 115 | */ 116 | -(void)draw:(CGContextRef)ctx; 117 | 118 | @end 119 | 120 | @protocol MDrawToolMeasurementProtocol 121 | 122 | /** 123 | * YES to show measurement information while No to hide 124 | */ 125 | @property (nonatomic,assign) BOOL showMeasurement; 126 | 127 | /** 128 | * How many μm per pixel, default value is 0, means it does not have a calibration. 129 | */ 130 | @property (nonatomic,assign) CGFloat calibration; 131 | 132 | /** 133 | * Displaying unit, default is px; 134 | */ 135 | @property (nonatomic,strong) NSString *unit; 136 | 137 | /** 138 | * Get the measure text for this tool. 139 | */ 140 | @property (nonatomic, readonly) NSString *measureText; 141 | 142 | /** 143 | * Draw measurement information 144 | * 145 | * @param ctx The context to draw on. 146 | */ 147 | - (void)drawMeasurement:(CGContextRef)ctx; 148 | 149 | @end 150 | 151 | /** 152 | * Base class of draw tool 153 | **/ 154 | @interface MDrawTool : NSObject 155 | { 156 | @protected 157 | BOOL _finalized; 158 | CGPoint _startPoint, _endPoint; 159 | CGFloat _unitScale; 160 | } 161 | 162 | @end 163 | -------------------------------------------------------------------------------- /MDraw/MDrawLine.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawLine.h" 23 | 24 | @implementation MDrawLine 25 | { 26 | // 0 : no hited, 1 : startPoint, 2: endPoint, 3: Middle point 27 | int _handleHitStatus; 28 | } 29 | 30 | -(BOOL)hitTest:(CGPoint)point 31 | { 32 | float distance = CGPointToLineDistance(point, _startPoint, _endPoint); 33 | if(distance <= NEAR_WIDTH) 34 | { 35 | return YES; 36 | } 37 | 38 | return NO; 39 | } 40 | 41 | -(BOOL)hitOnHandle:(CGPoint)point 42 | { 43 | _handleHitStatus = 0; 44 | 45 | if([self isPoint:point onHandle:_startPoint]) 46 | { 47 | _handleHitStatus = 1; 48 | return YES; 49 | } 50 | 51 | if([self isPoint:point onHandle:_endPoint]) 52 | { 53 | _handleHitStatus = 2; 54 | return YES; 55 | } 56 | 57 | if([self hitTest:point]) 58 | { 59 | _handleHitStatus = 3; 60 | return YES; 61 | } 62 | 63 | return NO; 64 | } 65 | 66 | -(void)moveByOffset:(CGSize)offset 67 | { 68 | 69 | if(_handleHitStatus == 1) 70 | { 71 | _startPoint = CGPointAddOffset(_startPoint, offset); 72 | } 73 | else if(_handleHitStatus == 2) 74 | { 75 | _endPoint = CGPointAddOffset(_endPoint, offset); 76 | } 77 | else if(_handleHitStatus == 3) 78 | { 79 | _startPoint.x += offset.width; 80 | _startPoint.y += offset.height; 81 | _endPoint.x += offset.width; 82 | _endPoint.y += offset.height; 83 | } 84 | } 85 | 86 | -(void)stopMoveHandle 87 | { 88 | _handleHitStatus = 0; 89 | } 90 | 91 | -(void)drawDown:(CGPoint)point 92 | { 93 | _startPoint = point; 94 | _endPoint = point; 95 | } 96 | 97 | -(void)drawMove:(CGPoint)point 98 | { 99 | _endPoint = point; 100 | } 101 | 102 | -(void)drawUp:(CGPoint)point 103 | { 104 | if(self.finalized) 105 | { 106 | return; 107 | } 108 | 109 | _endPoint = point; 110 | 111 | if(!CGPointEqualToPoint(_startPoint, point)) 112 | { 113 | [self finalize]; 114 | } 115 | } 116 | 117 | -(void)finalize 118 | { 119 | _finalized = YES; 120 | self.selected = YES; 121 | } 122 | 123 | -(void)draw:(CGContextRef)ctx 124 | { 125 | CGContextSetStrokeColorWithColor(ctx, self.color.CGColor); 126 | CGContextSetLineWidth(ctx, self.lineWidth); 127 | 128 | CGContextBeginPath(ctx); 129 | CGContextMoveToPoint(ctx, _startPoint.x, _startPoint.y); 130 | CGContextAddLineToPoint(ctx, _endPoint.x, _endPoint.y); 131 | CGContextStrokePath(ctx); 132 | 133 | if (self.selected) 134 | { 135 | [self drawHandle:ctx atPoint:_startPoint]; 136 | [self drawHandle:ctx atPoint:_endPoint]; 137 | } 138 | 139 | } 140 | 141 | -(NSString *)measureText 142 | { 143 | static NSString *lengthText; 144 | if(!lengthText) 145 | { 146 | lengthText = NSLocalizedString(@"Length", nil); 147 | } 148 | 149 | CGFloat length = CGPointDistance(_startPoint, _endPoint); 150 | length = [self unitConvert:length isSquare:NO]; 151 | 152 | return [NSString stringWithFormat:@"%@ : %0.2f %@", 153 | lengthText, 154 | length, 155 | self.unit]; 156 | 157 | } 158 | 159 | @end 160 | -------------------------------------------------------------------------------- /MDraw/MDrawFreeline.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawFreeline.h" 23 | 24 | @implementation MDrawFreeline 25 | { 26 | NSMutableArray *_points; 27 | } 28 | 29 | -(id)init 30 | { 31 | if(self = [super init]) 32 | { 33 | _points = [[NSMutableArray alloc] init]; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | -(id)initWithStartPoint:(CGPoint)startPoint 40 | { 41 | self = [super initWithStartPoint:startPoint]; 42 | if(self) 43 | { 44 | _points = [[NSMutableArray alloc] init]; 45 | } 46 | 47 | return self; 48 | } 49 | 50 | -(CGRect)frame 51 | { 52 | CGPoint tl, rb; 53 | 54 | if(_points.count > 0 ) 55 | { 56 | CGPoint firstPoint = [[_points objectAtIndex:0] CGPointValue]; 57 | tl = firstPoint; 58 | rb = firstPoint; 59 | } 60 | 61 | for (NSValue *pValue in _points) 62 | { 63 | CGPoint p = [pValue CGPointValue]; 64 | 65 | tl.x = MIN(tl.x, p.x); 66 | tl.y = MIN(tl.y, p.y); 67 | rb.x = MAX(rb.x, p.x); 68 | rb.y = MAX(rb.y, p.y); 69 | } 70 | 71 | return CGRectMake(tl.x, 72 | tl.y, 73 | fabsf(rb.x - tl.x), 74 | fabsf(rb.y - tl.y)); 75 | 76 | 77 | } 78 | 79 | -(void)drawMove:(CGPoint)point 80 | { 81 | [_points addObject:[NSValue valueWithCGPoint:point]]; 82 | } 83 | 84 | -(void)drawUp:(CGPoint)point 85 | { 86 | [_points addObject:[NSValue valueWithCGPoint:point]]; 87 | [self finalize]; 88 | } 89 | 90 | -(void)finalize 91 | { 92 | _finalized = YES; 93 | self.selected = YES; 94 | } 95 | 96 | -(BOOL)hitOnHandle:(CGPoint)point 97 | { 98 | _moveDirection = MDrawMoveDirectionNone; 99 | 100 | CGRect frame = self.frame; 101 | 102 | if(CGPointInRect(point, frame)) 103 | { 104 | _moveDirection = MDrawMoveDirectionWhole; 105 | return YES; 106 | } 107 | 108 | return NO; 109 | } 110 | 111 | -(void)moveByOffset:(CGSize)offset 112 | { 113 | if(_moveDirection == MDrawMoveDirectionWhole) 114 | { 115 | for (int i = 0; i < _points.count; i++) { 116 | CGPoint p = [[_points objectAtIndex:i] CGPointValue]; 117 | p.x += offset.width; 118 | p.y += offset.height; 119 | 120 | [_points replaceObjectAtIndex:i withObject:[NSValue valueWithCGPoint:p]]; 121 | } 122 | } 123 | } 124 | 125 | -(void)draw:(CGContextRef)ctx 126 | { 127 | CGContextSetStrokeColorWithColor(ctx, self.color.CGColor); 128 | CGContextSetLineWidth(ctx, self.lineWidth); 129 | 130 | CGContextBeginPath(ctx); 131 | if(_points.count > 0 ) 132 | { 133 | CGPoint p = [[_points objectAtIndex:0] CGPointValue]; 134 | CGContextMoveToPoint(ctx, p.x, p.y); 135 | 136 | for (int i = 1; i < _points.count; i++) 137 | { 138 | CGPoint p = [[_points objectAtIndex:i] CGPointValue]; 139 | CGContextAddLineToPoint(ctx, p.x, p.y); 140 | } 141 | 142 | } 143 | 144 | CGContextStrokePath(ctx); 145 | 146 | if (self.selected) 147 | { 148 | [self drawHandle:ctx atPoint:CGRectMid(self.frame)]; 149 | 150 | } 151 | 152 | } 153 | 154 | -(NSString *)measureText 155 | { 156 | static NSString *lengthString; 157 | if(!lengthString) 158 | { 159 | lengthString = NSLocalizedString(@"Length", Nil); 160 | } 161 | 162 | CGFloat length = CGPolygonLength(_points); 163 | 164 | return [NSString stringWithFormat:@"%@: %0.2f %@", 165 | lengthString, 166 | [self unitConvert:length isSquare:NO], 167 | self.unit]; 168 | } 169 | 170 | @end 171 | -------------------------------------------------------------------------------- /MDraw/MDrawTool.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawTool.h" 23 | #import "MDrawMeasurementInfo.h" 24 | 25 | 26 | @implementation MDrawTool 27 | { 28 | UIColor *_handleFillColor; 29 | NSString *_unit; 30 | 31 | MDrawMeasurementInfo *_measurement; 32 | } 33 | 34 | @synthesize name; 35 | @synthesize selected; 36 | @synthesize finalized = _finalized; 37 | @synthesize lineWidth; 38 | @synthesize color; 39 | @synthesize showMeasurement; 40 | @synthesize calibration; 41 | @synthesize measureText; 42 | 43 | -(id)init 44 | { 45 | if(self = [super init]) 46 | { 47 | _handleFillColor = [UIColor colorWithRed:255 green:255 blue:255 alpha:0.6]; 48 | self.lineWidth = 3; 49 | self.calibration = 0; 50 | self.unit = @"px"; 51 | _unitScale = 1; 52 | } 53 | 54 | return self; 55 | } 56 | 57 | -(id)initWithStartPoint:(CGPoint)startPoint 58 | { 59 | if(self=[self init]) 60 | { 61 | _startPoint = startPoint; 62 | _endPoint = startPoint; 63 | } 64 | 65 | return self; 66 | } 67 | 68 | -(NSString *)unit 69 | { 70 | return [_unit copy]; 71 | } 72 | 73 | -(void)setUnit:(NSString *)unit 74 | { 75 | _unit = unit; 76 | _unitScale = 1; 77 | 78 | if([_unit isEqualToString:@"μm"] || [_unit isEqualToString:@"um"]) 79 | { 80 | _unitScale = 1; 81 | } 82 | else if([_unit isEqualToString:@"mm"]) 83 | { 84 | _unitScale = 1 / 1000.0; 85 | } 86 | else if([_unit isEqualToString:@"cm"]) 87 | { 88 | _unitScale = 1 / 1000000.0; 89 | } 90 | } 91 | 92 | -(CGRect)frame 93 | { 94 | return CGRectMake(MIN(_startPoint.x, _endPoint.x), 95 | MIN(_startPoint.y, _endPoint.y), 96 | fabsf(_endPoint.x - _startPoint.x), 97 | fabsf(_endPoint.y - _startPoint.y)); 98 | } 99 | 100 | -(void)drawDown:(CGPoint)point 101 | { 102 | } 103 | 104 | -(void)drawMove:(CGPoint)point 105 | { 106 | } 107 | 108 | -(void)drawUp:(CGPoint)point 109 | { 110 | } 111 | 112 | -(void)finalize:(CGPoint)point 113 | { 114 | _endPoint = point; 115 | } 116 | 117 | -(BOOL)hitTest:(CGPoint)point 118 | { 119 | return CGPointInRect(point, self.frame); 120 | } 121 | 122 | -(BOOL)hitOnHandle:(CGPoint)point 123 | { 124 | return NO; 125 | } 126 | 127 | -(void)moveByOffset:(CGSize)offset 128 | { 129 | } 130 | 131 | -(void)stopMoveHandle 132 | { 133 | } 134 | 135 | -(void)draw:(CGContextRef)ctx 136 | { 137 | } 138 | 139 | - (void)drawMeasurement:(CGContextRef)ctx 140 | { 141 | BOOL needDraw = self.showMeasurement && self.finalized && !self.selected && self.measureText; 142 | if (!needDraw) { 143 | return; 144 | } 145 | 146 | if (!_measurement) { 147 | _measurement = [[MDrawMeasurementInfo alloc] initWithTool:self]; 148 | } 149 | 150 | [_measurement draw:ctx]; 151 | } 152 | 153 | #pragma mark - protected methods 154 | 155 | -(void)drawHandle:(CGContextRef)ctx atPoint:(CGPoint)point 156 | { 157 | CGContextSetFillColorWithColor(ctx, _handleFillColor.CGColor); 158 | CGContextSetStrokeColorWithColor(ctx, self.color.CGColor); 159 | CGRect handleRect = CGRectMake(point.x- HANDLE_SIZE /2, point.y- HANDLE_SIZE /2, HANDLE_SIZE, HANDLE_SIZE); 160 | CGContextSetLineWidth(ctx, 2); 161 | CGContextFillEllipseInRect(ctx, handleRect); 162 | CGContextStrokeEllipseInRect(ctx, handleRect); 163 | } 164 | 165 | -(BOOL)isPoint:(CGPoint)point onHandle:(CGPoint)handlePoint 166 | { 167 | CGRect handleRect = CGRectMake(handlePoint.x- HANDLE_SIZE /2, handlePoint.y- HANDLE_SIZE /2, HANDLE_SIZE, HANDLE_SIZE); 168 | return CGPointInRect(point, handleRect); 169 | } 170 | 171 | -(CGFloat)unitConvert:(CGFloat)pixels isSquare:(BOOL)square 172 | { 173 | if (self.calibration == 0) { 174 | return pixels; 175 | } 176 | 177 | CGFloat result = pixels * self.calibration * _unitScale; 178 | if(square) 179 | { 180 | result *= ( self.calibration * _unitScale ); 181 | } 182 | 183 | return result; 184 | } 185 | 186 | @end 187 | -------------------------------------------------------------------------------- /MDraw/MDrawRect.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawRect.h" 23 | 24 | @implementation MDrawRect 25 | { 26 | 27 | } 28 | 29 | -(void)drawDown:(CGPoint)point 30 | { 31 | } 32 | 33 | -(void)drawMove:(CGPoint)point 34 | { 35 | _endPoint = point; 36 | } 37 | 38 | -(void)drawUp:(CGPoint)point 39 | { 40 | _endPoint = point; 41 | [self finalize]; 42 | } 43 | 44 | -(void)finalize 45 | { 46 | _finalized = YES; 47 | self.selected = YES; 48 | } 49 | 50 | -(BOOL)hitTest:(CGPoint)point 51 | { 52 | return CGPointInRect(point, self.frame); 53 | } 54 | 55 | -(BOOL)hitOnHandle:(CGPoint)point 56 | { 57 | 58 | _moveDirection = MDrawMoveDirectionNone; 59 | 60 | CGRect frame = self.frame; 61 | //After moving , start point and end point may not longer be the top left and bottom right 62 | // Here to correct. 63 | _startPoint = frame.origin; 64 | _endPoint = CGPointMake(_startPoint.x + frame.size.width, _startPoint.y + frame.size.height); 65 | 66 | if([self isPoint:point onHandle:CGRectTL(frame)]) 67 | { 68 | _moveDirection = MDrawMoveDirectionTL; 69 | return YES; 70 | } 71 | if([self isPoint:point onHandle:CGRectTM(frame)]) 72 | { 73 | _moveDirection = MDrawMoveDirectionTM; 74 | return YES; 75 | } 76 | if([self isPoint:point onHandle:CGRectTR(frame)]) 77 | { 78 | _moveDirection = MDrawMoveDirectionTR; 79 | return YES; 80 | } 81 | if([self isPoint:point onHandle:CGRectRM(frame)]) 82 | { 83 | _moveDirection = MDrawMoveDirectionRM; 84 | return YES; 85 | } 86 | if([self isPoint:point onHandle:CGRectBR(frame)]) 87 | { 88 | _moveDirection = MDrawMoveDirectionBR; 89 | return YES; 90 | } 91 | if([self isPoint:point onHandle:CGRectBM(frame)]) 92 | { 93 | _moveDirection = MDrawMoveDirectionBM; 94 | return YES; 95 | } 96 | if([self isPoint:point onHandle:CGRectBL(frame)]) 97 | { 98 | _moveDirection = MDrawMoveDirectionBL; 99 | return YES; 100 | } 101 | if([self isPoint:point onHandle:CGRectLM(frame)]) 102 | { 103 | _moveDirection = MDrawMoveDirectionLM; 104 | return YES; 105 | } 106 | if(CGPointInRect(point, frame)) 107 | { 108 | _moveDirection = MDrawMoveDirectionWhole; 109 | return YES; 110 | } 111 | 112 | return NO; 113 | } 114 | 115 | -(void)moveByOffset:(CGSize)offset 116 | { 117 | switch (_moveDirection) { 118 | case MDrawMoveDirectionTL: 119 | _startPoint = CGPointAddOffset(_startPoint, offset); 120 | break; 121 | case MDrawMoveDirectionTM: 122 | _startPoint.y += offset.height; 123 | break; 124 | case MDrawMoveDirectionTR: 125 | _startPoint.y += offset.height; 126 | _endPoint.x += offset.width; 127 | break; 128 | case MDrawMoveDirectionRM: 129 | _endPoint.x += offset.width; 130 | break; 131 | case MDrawMoveDirectionBR: 132 | _endPoint = CGPointAddOffset(_endPoint, offset); 133 | break; 134 | case MDrawMoveDirectionBM: 135 | _endPoint.y += offset.height; 136 | break; 137 | case MDrawMoveDirectionBL: 138 | _startPoint.x += offset.width; 139 | _endPoint.y += offset.height; 140 | break; 141 | case MDrawMoveDirectionLM: 142 | _startPoint.x += offset.width; 143 | break; 144 | case MDrawMoveDirectionWhole: 145 | { 146 | _startPoint = CGPointAddOffset(_startPoint, offset); 147 | _endPoint = CGPointAddOffset(_endPoint, offset); 148 | break; 149 | } 150 | default: 151 | break; 152 | } 153 | } 154 | 155 | -(void)stopMoveHandle 156 | { 157 | _moveDirection = MDrawMoveDirectionNone; 158 | } 159 | 160 | -(void)draw:(CGContextRef)ctx 161 | { 162 | CGContextSetStrokeColorWithColor(ctx, self.color.CGColor); 163 | CGContextSetLineWidth(ctx, self.lineWidth); 164 | 165 | CGContextBeginPath(ctx); 166 | CGContextAddRect(ctx, self.frame); 167 | CGContextStrokePath(ctx); 168 | 169 | if (self.selected) 170 | { 171 | CGRect frame = self.frame; 172 | [self drawHandle:ctx atPoint:CGRectTL(frame)]; 173 | [self drawHandle:ctx atPoint:CGRectTM(frame)]; 174 | [self drawHandle:ctx atPoint:CGRectTR(frame)]; 175 | [self drawHandle:ctx atPoint:CGRectRM(frame)]; 176 | [self drawHandle:ctx atPoint:CGRectBR(frame)]; 177 | [self drawHandle:ctx atPoint:CGRectBM(frame)]; 178 | [self drawHandle:ctx atPoint:CGRectBL(frame)]; 179 | [self drawHandle:ctx atPoint:CGRectLM(frame)]; 180 | } 181 | 182 | } 183 | 184 | -(NSString *)measureText 185 | { 186 | static NSString *widthString, *heightString, *areaString; 187 | if(!widthString) 188 | { 189 | widthString = NSLocalizedString(@"Width", nil); 190 | heightString = NSLocalizedString(@"Height", Nil); 191 | areaString = NSLocalizedString(@"Area", Nil); 192 | } 193 | 194 | CGRect frame = self.frame; 195 | 196 | return [NSString stringWithFormat:@"%@: %0.2f %@\n%@: %0.2f %@\n%@: %0.2f sq%@", 197 | widthString, 198 | [self unitConvert:frame.size.width isSquare:NO], 199 | self.unit, 200 | heightString, 201 | [self unitConvert:frame.size.height isSquare:NO], 202 | self.unit, 203 | areaString, 204 | [self unitConvert:frame.size.width * frame.size.height isSquare:YES], 205 | self.unit]; 206 | } 207 | 208 | @end 209 | -------------------------------------------------------------------------------- /MDraw/MDrawPolyline.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawPolyline.h" 23 | 24 | @implementation MDrawPolyline 25 | 26 | 27 | -(id)init 28 | { 29 | if(self = [super init]) 30 | { 31 | _points = [[NSMutableArray alloc] init]; 32 | _movePoint= CGPointZero; 33 | _moveHandleIndex = -1; 34 | _closePath = YES; 35 | } 36 | 37 | return self; 38 | } 39 | 40 | -(id)initWithStartPoint:(CGPoint)startPoint 41 | { 42 | self = [super initWithStartPoint:startPoint]; 43 | if(self) 44 | { 45 | _points = [[NSMutableArray alloc] init]; 46 | _movePoint= CGPointZero; 47 | _moveHandleIndex = -1; 48 | _closePath = YES; 49 | [_points addObject:[NSValue valueWithCGPoint:startPoint]]; 50 | } 51 | 52 | return self; 53 | } 54 | 55 | 56 | 57 | -(CGRect)frame 58 | { 59 | CGPoint tl, rb; 60 | 61 | if(_points.count > 0 ) 62 | { 63 | CGPoint firstPoint = [[_points objectAtIndex:0] CGPointValue]; 64 | tl = firstPoint; 65 | rb = firstPoint; 66 | } 67 | 68 | for (NSValue *pValue in _points) 69 | { 70 | CGPoint p = [pValue CGPointValue]; 71 | 72 | tl.x = MIN(tl.x, p.x); 73 | tl.y = MIN(tl.y, p.y); 74 | rb.x = MAX(rb.x, p.x); 75 | rb.y = MAX(rb.y, p.y); 76 | } 77 | 78 | return CGRectMake(tl.x, 79 | tl.y, 80 | fabsf(rb.x - tl.x), 81 | fabsf(rb.y - tl.y)); 82 | } 83 | 84 | -(void)drawDown:(CGPoint)point 85 | { 86 | 87 | } 88 | 89 | -(void)drawMove:(CGPoint)point 90 | { 91 | _movePoint = point; 92 | } 93 | 94 | -(void)drawUp:(CGPoint)point 95 | { 96 | _movePoint = CGPointZero; 97 | 98 | BOOL isStartPoint = NO; 99 | if(_points.count > 0 ) 100 | { 101 | CGPoint startPoint = [[_points objectAtIndex:0] CGPointValue]; 102 | if([self isPoint:point onHandle:startPoint]) 103 | { 104 | isStartPoint = YES; 105 | } 106 | } 107 | 108 | if(!isStartPoint) 109 | { 110 | [_points addObject:[NSValue valueWithCGPoint:point]]; 111 | } 112 | 113 | //User close this shape by clicking the start point. 114 | if(isStartPoint && _points.count > 1) 115 | { 116 | [self finalize]; 117 | } 118 | } 119 | 120 | -(void)finalize 121 | { 122 | _finalized = YES; 123 | self.selected = YES; 124 | } 125 | 126 | -(BOOL)hitOnHandle:(CGPoint)point 127 | { 128 | _moveHandleIndex = -1; 129 | 130 | 131 | if(_points.count > 0 ) 132 | { 133 | for (int i = 0; i < _points.count; i++) 134 | { 135 | CGPoint handlePoint = [[_points objectAtIndex:i] CGPointValue]; 136 | if([self isPoint:point onHandle:handlePoint]) 137 | { 138 | _moveHandleIndex = i; 139 | return YES; 140 | } 141 | } 142 | 143 | if(CGPointInRect(point, self.frame)) 144 | { 145 | _moveHandleIndex = -2; 146 | return YES; 147 | } 148 | } 149 | 150 | return NO; 151 | } 152 | 153 | -(void)moveByOffset:(CGSize)offset 154 | { 155 | if(_moveHandleIndex >= 0) 156 | { 157 | CGPoint movePoint = [[_points objectAtIndex:_moveHandleIndex] CGPointValue]; 158 | movePoint = CGPointAddOffset(movePoint, offset); 159 | [_points replaceObjectAtIndex:_moveHandleIndex withObject:[NSValue valueWithCGPoint:movePoint]]; 160 | } 161 | else if( _moveHandleIndex == -2) // move the shape 162 | { 163 | for (int i = 0; i < _points.count; i++) 164 | { 165 | CGPoint p = [[_points objectAtIndex:i] CGPointValue]; 166 | [_points replaceObjectAtIndex:i withObject:[NSValue valueWithCGPoint:CGPointMake(p.x + offset.width, p.y + offset.height)]]; 167 | } 168 | } 169 | } 170 | 171 | -(void)stopMoveHandle 172 | { 173 | _moveHandleIndex = -1; 174 | } 175 | 176 | -(void)draw:(CGContextRef)ctx 177 | { 178 | CGContextSetStrokeColorWithColor(ctx, self.color.CGColor); 179 | CGContextSetLineWidth(ctx, self.lineWidth); 180 | 181 | CGContextBeginPath(ctx); 182 | if(_points.count > 0 ) 183 | { 184 | CGPoint p = [[_points objectAtIndex:0] CGPointValue]; 185 | CGContextMoveToPoint(ctx, p.x, p.y); 186 | 187 | for (int i = 1; i < _points.count; i++) 188 | { 189 | CGPoint p = [[_points objectAtIndex:i] CGPointValue]; 190 | CGContextAddLineToPoint(ctx, p.x, p.y); 191 | } 192 | 193 | 194 | if(!self.finalized && !CGPointEqualToPoint(_movePoint, CGPointZero)) 195 | { 196 | CGContextAddLineToPoint(ctx, _movePoint.x,_movePoint.y); 197 | } 198 | 199 | //Close the shape 200 | if(self.finalized && _closePath) 201 | { 202 | CGContextClosePath(ctx); 203 | } 204 | 205 | } 206 | 207 | CGContextStrokePath(ctx); 208 | 209 | if (self.selected || !self.finalized) 210 | { 211 | for (int i = 0; i < _points.count; i++) 212 | { 213 | CGPoint p = [[_points objectAtIndex:i] CGPointValue]; 214 | [self drawHandle:ctx atPoint:p]; 215 | } 216 | 217 | } 218 | 219 | } 220 | 221 | -(NSString *)measureText 222 | { 223 | static NSString *lengthString, *areaString; 224 | if(!lengthString) 225 | { 226 | lengthString = NSLocalizedString(@"Length", Nil); 227 | areaString = NSLocalizedString(@"Area", Nil); 228 | } 229 | 230 | CGFloat length = CGPolygonLength(_points); 231 | CGFloat area = CGPolygonArea(_points); 232 | return [NSString stringWithFormat:@"%@: %0.2f %@\n%@: %0.2f sq%@", 233 | lengthString, 234 | [self unitConvert:length isSquare:NO], 235 | self.unit, 236 | areaString, 237 | [self unitConvert:area isSquare:YES], 238 | self.unit]; 239 | } 240 | 241 | @end 242 | -------------------------------------------------------------------------------- /MDraw/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /MDraw/MDrawMath.h: -------------------------------------------------------------------------------- 1 | // 2 | // MDrawMath.h 3 | // Motics 4 | // 5 | // Created by Gao Yongqing on 2/6/14. 6 | // 7 | // 8 | 9 | 10 | 11 | #ifndef Motics_MDrawMath_h 12 | #define Motics_MDrawMath_h 13 | 14 | #import 15 | 16 | 17 | CG_INLINE float CGPointDistance(CGPoint p1, CGPoint p2) 18 | { 19 | CGFloat dx = p2.x - p1.x; 20 | CGFloat dy = p2.y - p1.y; 21 | return sqrt(dx*dx + dy*dy); 22 | } 23 | 24 | CG_INLINE CGSize CGPointOffset(CGPoint p1, CGPoint p2) 25 | { 26 | CGFloat dx = p2.x - p1.x; 27 | CGFloat dy = p2.y - p1.y; 28 | return CGSizeMake(dx, dy); 29 | } 30 | 31 | CG_INLINE CGPoint CGPointAddOffset(CGPoint p, CGSize offset) 32 | { 33 | return CGPointMake(p.x + offset.width, p.y + offset.height); 34 | } 35 | 36 | CG_INLINE CGPoint CGPointMidPoint(CGPoint p1, CGPoint p2) 37 | { 38 | return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5); 39 | } 40 | 41 | CG_INLINE float CGPointToLineDistance(CGPoint p, CGPoint p1,CGPoint p2) 42 | { 43 | float a = p1.y - p2.y; 44 | float b = p2.x - p1.x; 45 | float c = (p1.x - b) * p1.y - p1.x * (p1.y + a); 46 | 47 | return fabsf(a * p.x + b * p.y + c) / sqrtf(a*a + b*b); 48 | } 49 | 50 | CG_INLINE BOOL CGPointInRect(CGPoint p, CGRect rect) 51 | { 52 | return (p.x >= rect.origin.x && 53 | p.x <= (rect.origin.x + rect.size.width) && 54 | p.y >= rect.origin.y && 55 | p.y <= (rect.origin.y + rect.size.height)); 56 | } 57 | 58 | CG_INLINE CGPoint CGRectTL(CGRect rect) 59 | { 60 | return rect.origin; 61 | } 62 | 63 | CG_INLINE CGPoint CGRectTM(CGRect rect) 64 | { 65 | return CGPointMake(rect.origin.x + rect.size.width * 0.5, rect.origin.y); 66 | } 67 | 68 | CG_INLINE CGPoint CGRectTR(CGRect rect) 69 | { 70 | return CGPointMake(rect.origin.x + rect.size.width, rect.origin.y); 71 | } 72 | 73 | CG_INLINE CGPoint CGRectRM(CGRect rect) 74 | { 75 | return CGPointMake(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height * 0.5); 76 | } 77 | 78 | CG_INLINE CGPoint CGRectBR(CGRect rect) 79 | { 80 | return CGPointMake(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height); 81 | } 82 | 83 | CG_INLINE CGPoint CGRectBM(CGRect rect) 84 | { 85 | return CGPointMake(rect.origin.x + rect.size.width * 0.5, rect.origin.y + rect.size.height); 86 | } 87 | 88 | CG_INLINE CGPoint CGRectBL(CGRect rect) 89 | { 90 | return CGPointMake(rect.origin.x , rect.origin.y + rect.size.height); 91 | } 92 | 93 | CG_INLINE CGPoint CGRectLM(CGRect rect) 94 | { 95 | return CGPointMake(rect.origin.x , rect.origin.y + rect.size.height * 0.5); 96 | } 97 | 98 | CG_INLINE CGPoint CGRectMid(CGRect rect) 99 | { 100 | return CGPointMake(rect.origin.x + rect.size.width * 0.5, rect.origin.y + rect.size.height * 0.5); 101 | } 102 | 103 | /** 104 | * 三点画圆,计算圆心X坐标 105 | * 三点确定的圆的圆心到三点的距离相等,就有以下两个不等式: 106 | * (x - x1 )^2 + (y-y1) ^2 = (x-x2)^2 + (y-y2)^2 = (x-x3)^2 + (y-y3)^2 107 | * 根据两个不等式,可以推出 x 和 y 108 | * 109 | * @param x1 x of point 1 110 | * @param y1 y of point 1 111 | * @param x2 x of point 2 112 | * @param y2 y of point 2 113 | * @param x3 x of point 3 114 | * @param y3 y of point 3 115 | * 116 | * @return x of center point 117 | */ 118 | CG_INLINE CGFloat CGCenterX(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2,CGFloat x3, CGFloat y3) 119 | { 120 | CGFloat x = ((x1 * x1 + y1 * y1) * (y2 - y3) - (x2 * x2 + y2 * y2) * (y2 - y3) 121 | - (x2 * x2 + y2 * y2) * (y1 - y2) + (x3 * x3 + y3 * y3) * (y1 - y2)) 122 | / (2 * ((x1 - x2) * (y2 - y3) - (x2 - x3) * (y1 - y2))); 123 | 124 | return x; 125 | } 126 | 127 | CG_INLINE CGFloat CGCenterY(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2,CGFloat x3, CGFloat y3) 128 | { 129 | CGFloat x = CGCenterX(x1, y1, x2, y2, x3, y3); 130 | CGFloat y = ((x2 * x2 + y2 * y2) - (x3 * x3 + y3 * y3) - 2 * x * (x2 - x3)) 131 | / (2 * (y2 - y3)); 132 | 133 | return y; 134 | } 135 | 136 | CG_INLINE CGPoint CGCenterPoint(CGPoint p1, CGPoint p2, CGPoint p3) 137 | { 138 | CGFloat x = CGCenterX(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); 139 | CGFloat y = CGCenterY(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); 140 | 141 | return CGPointMake(x, y); 142 | } 143 | 144 | /** 145 | * 计算圆的半径 146 | **/ 147 | CG_INLINE CGFloat CGRadius(CGPoint centerPoint,CGPoint edgePoint) 148 | { 149 | return sqrtf((edgePoint.x - centerPoint.x) * (edgePoint.x - centerPoint.x) + 150 | (edgePoint.y - centerPoint.y) * (edgePoint.y - centerPoint.y)); 151 | } 152 | 153 | /** 154 | * 求三点构成的角的弧度,其中中间那点(x2,y2)是角度的顶点 155 | **/ 156 | CG_INLINE CGFloat CGAngleRadianS(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat x3, CGFloat y3) 157 | { 158 | CGFloat a1 = atan2f(y1 - y2, x1 - x2); 159 | CGFloat a2 = atan2f(y3 - y2, x3 - x2); 160 | 161 | return a2 - a1; 162 | } 163 | 164 | CG_INLINE CGFloat CGAngleRadian(CGPoint p1, CGPoint p2, CGPoint p3) 165 | { 166 | return CGAngleRadianS(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); 167 | } 168 | 169 | /** 170 | * 求三点构成的角度,其中中间那点(x2,y2)是角度的顶点 171 | **/ 172 | CG_INLINE CGFloat CGAngleDegreeS(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat x3, CGFloat y3) 173 | { 174 | CGFloat radian = CGAngleRadianS(x1, y1, x2, y2, x3, y3); 175 | CGFloat degree = radian / M_PI * 180; 176 | if (degree < 0) { 177 | return 360 + degree; 178 | } 179 | else { 180 | return degree; 181 | } 182 | } 183 | 184 | /** 185 | * 求三点构成的角的角度,其中中间那点p2是角的顶点 186 | **/ 187 | CG_INLINE CGFloat CGAngleDegree(CGPoint p1, CGPoint p2, CGPoint p3) 188 | { 189 | CGFloat radian = CGAngleRadian(p1, p2, p3); 190 | CGFloat degree = radian / M_PI * 180; 191 | if (degree < 0) { 192 | return 360 + degree; 193 | } 194 | else { 195 | return degree; 196 | } 197 | } 198 | 199 | /** 200 | * 求向量的弧度 201 | * p1 为原点 202 | **/ 203 | CG_INLINE CGFloat CGVectorRadian(CGPoint p1, CGPoint p2) 204 | { 205 | return atan2f(p2.y - p1.y, p2.x - p1.x); 206 | } 207 | 208 | /// 209 | /// 求角度所对应的弧上的一点 210 | /// 211 | /// 中间点的X坐标 212 | /// 中间点的Y坐标 213 | /// 214 | /// 215 | /// 这个弧的长度,一般是固定的 216 | /// 217 | CG_INLINE CGPoint CGAngleArcPointS(CGFloat xCenter, CGFloat yCenter, CGFloat x,CGFloat y, CGFloat arcLength) 218 | { 219 | CGFloat angle = atan2(y - yCenter, x - xCenter); 220 | CGFloat height = sin(angle) * arcLength; 221 | CGFloat width = cos(angle) * arcLength; 222 | 223 | return CGPointMake(xCenter + width, yCenter +height); 224 | } 225 | 226 | CG_INLINE BOOL IsLargeArc(CGFloat radian) 227 | { 228 | //如果弧度小余0,用2π - 弧度来计算 229 | CGFloat absR = radian < 0 ? 2 * M_PI + radian : radian; 230 | 231 | return absR < 0.5 * M_PI || absR > 1.5 * M_PI; 232 | } 233 | 234 | /** 235 | * 是否是逆时针 236 | **/ 237 | CG_INLINE BOOL IsCounterClockwise(CGFloat radian) 238 | { 239 | //如果弧度小余0,用2π - 弧度来计算 240 | CGFloat absR = radian < 0 ? 2 * M_PI + radian : radian; 241 | return absR > 0 && absR < M_PI; 242 | } 243 | 244 | 245 | /** 246 | * 多边形的面积 247 | **/ 248 | CG_INLINE CGFloat CGPolygonArea(NSArray *points) 249 | { 250 | int count = points.count; 251 | int i, j; 252 | CGFloat area = 0; 253 | 254 | for (i = 0; i < count; i++) { 255 | j = (i + 1) % count; 256 | 257 | CGPoint pi = [points[i] CGPointValue]; 258 | CGPoint pj = [points[j] CGPointValue]; 259 | 260 | area += pi.x * pj.y; 261 | area -= pi.y * pj.x; 262 | } 263 | 264 | area /= 2.0; 265 | 266 | return abs(area); 267 | 268 | } 269 | 270 | /** 271 | * 多边形的周长 272 | **/ 273 | CG_INLINE CGFloat CGPolygonLength(NSArray *points) 274 | { 275 | if(points.count < 2) 276 | { 277 | return 0; 278 | } 279 | 280 | NSInteger count = points.count; 281 | CGFloat length = 0.0; 282 | for (int i = 1; i < count; i++) 283 | { 284 | length += CGPointDistance([points[i - 1] CGPointValue], [points[i] CGPointValue]); 285 | } 286 | 287 | return length; 288 | } 289 | 290 | /** 291 | * 闭合多边形的周长 292 | **/ 293 | CG_INLINE CGFloat CGPolygonLengthClosed(NSArray *points) 294 | { 295 | if(points.count < 2) 296 | { 297 | return 0; 298 | } 299 | 300 | CGFloat length = CGPolygonLength(points); 301 | // Add last line length 302 | length += CGPointDistance([points[0] CGPointValue], [points[points.count -1] CGPointValue]); 303 | 304 | return length; 305 | } 306 | 307 | CG_INLINE CGPoint CGArcPointParameter(CGPoint p1, CGPoint p2, CGPoint p3, float u) 308 | { 309 | CGFloat x = (powf(1 - u, 2) * p1.x) + 310 | (2 * u * (1 - u) * p2.x ) + 311 | (powf(u, 2) * p3.x); 312 | 313 | CGFloat y = (powf(1 - u, 2) * p1.y) + 314 | (2 * u * (1 - u) * p2.y ) + 315 | (powf(u, 2) * p3.y); 316 | 317 | return CGPointMake(x, y); 318 | } 319 | 320 | CG_INLINE float CGArcLength(CGPoint p1, CGPoint p2, CGPoint p3) 321 | { 322 | float u = 0; 323 | float length = 0; 324 | CGPoint pt1 = CGArcPointParameter(p1, p2, p3, u); 325 | for (int i = 0; i < 10; i++) { 326 | u += 0.1; 327 | if ( u > 1 ) { 328 | u = 1; 329 | } 330 | CGPoint pt2 = CGArcPointParameter(p1, p2, p3, u); 331 | length += CGPointDistance(pt1, pt2); 332 | pt1 = pt2; 333 | } 334 | return length; 335 | } 336 | 337 | 338 | 339 | 340 | 341 | #endif 342 | -------------------------------------------------------------------------------- /MDraw/MDrawView.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013 xmkevin 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "MDrawView.h" 23 | #import "MUndoManager.h" 24 | 25 | @implementation MDrawView 26 | { 27 | NSMutableArray *_tools; 28 | Class _drawToolClass; 29 | MUndoManager *_undoManager; 30 | BOOL _isMoved; // Is mouse or figure moved 31 | CGFloat _lineWidth; 32 | BOOL _enableGesture; 33 | BOOL _showMeasurement; 34 | NSString *_unit; 35 | } 36 | 37 | @synthesize color; 38 | @synthesize calibration = _calibration; 39 | @synthesize isDirty = _isDirty; 40 | 41 | 42 | -(id)initWithCoder:(NSCoder *)aDecoder 43 | { 44 | if(self = [super initWithCoder:aDecoder]) 45 | { 46 | // Initialization code 47 | _tools = [[NSMutableArray alloc] init]; 48 | _undoManager = [[MUndoManager alloc] initWithTools:_tools]; 49 | 50 | self.color = [UIColor colorWithRed:0 green:255 blue:0 alpha:0.6]; 51 | _lineWidth = 3; 52 | _calibration = 0; 53 | 54 | _enableGesture = YES; 55 | [self initGestures]; 56 | } 57 | 58 | return self; 59 | } 60 | 61 | - (id)initWithFrame:(CGRect)frame 62 | { 63 | self = [super initWithFrame:frame]; 64 | if (self) { 65 | // Initialization code 66 | _tools = [[NSMutableArray alloc] init]; 67 | [self initGestures]; 68 | } 69 | return self; 70 | } 71 | 72 | - (void)refreshCalibrations 73 | { 74 | for (MDrawTool *tool in _tools) 75 | { 76 | tool.calibration = self.calibration; 77 | tool.unit = self.unit; 78 | tool.showMeasurement = self.showMeasurement; 79 | } 80 | 81 | [self setNeedsDisplay]; 82 | } 83 | 84 | -(BOOL)hasTools 85 | { 86 | return _tools.count > 0; 87 | } 88 | 89 | -(NSArray *)tools 90 | { 91 | return _tools; 92 | } 93 | 94 | -(CGFloat)lineWidth 95 | { 96 | return _lineWidth; 97 | } 98 | 99 | -(void)setLineWidth:(CGFloat)lineWidth 100 | { 101 | if(_activeTool) 102 | { 103 | _activeTool.lineWidth = lineWidth; 104 | 105 | [self setNeedsDisplay]; 106 | } 107 | 108 | _lineWidth = lineWidth; 109 | } 110 | 111 | -(BOOL)enableGesture 112 | { 113 | return _enableGesture; 114 | } 115 | 116 | -(void)setEnableGesture:(BOOL)enableGesture 117 | { 118 | _enableGesture = enableGesture; 119 | 120 | for (UIGestureRecognizer *g in self.gestureRecognizers) { 121 | g.enabled = _enableGesture; 122 | } 123 | 124 | self.multipleTouchEnabled = _enableGesture; 125 | } 126 | 127 | -(BOOL)showMeasurement 128 | { 129 | return _showMeasurement; 130 | } 131 | 132 | -(void)setShowMeasurement:(BOOL)showMeasurement 133 | { 134 | _showMeasurement = showMeasurement; 135 | 136 | for (MDrawTool *tool in _tools) { 137 | tool.showMeasurement = showMeasurement; 138 | } 139 | 140 | [self setNeedsDisplay]; 141 | 142 | } 143 | 144 | - (CGFloat)calibration 145 | { 146 | return _calibration; 147 | } 148 | 149 | - (void)setCalibration:(CGFloat)calibration 150 | { 151 | _calibration = calibration; 152 | 153 | [self refreshCalibrations]; 154 | } 155 | 156 | -(NSString *)unit 157 | { 158 | if(_unit == Nil) 159 | { 160 | _unit = @"px"; 161 | } 162 | 163 | return _unit; 164 | } 165 | 166 | -(void)setUnit:(NSString *)unit 167 | { 168 | _unit = unit; 169 | 170 | [self refreshCalibrations]; 171 | } 172 | 173 | 174 | -(BOOL)undo 175 | { 176 | if([_undoManager undo]) 177 | { 178 | [self setNeedsDisplay]; 179 | return YES; 180 | } 181 | 182 | return NO; 183 | } 184 | 185 | -(BOOL)redo 186 | { 187 | if([_undoManager redo]) 188 | { 189 | [self setNeedsDisplay]; 190 | return YES; 191 | } 192 | 193 | return NO; 194 | } 195 | 196 | - (void)drawRect:(CGRect)rect 197 | { 198 | if (_tools && _tools.count > 0) { 199 | // Drawing code 200 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 201 | //CGContextClearRect(ctx,self.frame); 202 | for (MDrawTool *tool in _tools) 203 | { 204 | [tool draw:ctx]; 205 | [tool drawMeasurement:ctx]; 206 | } 207 | } 208 | } 209 | 210 | -(void)beginDrawingForType:(Class)toolType 211 | { 212 | if(toolType == Nil) 213 | { 214 | _drawToolClass = Nil; 215 | _drawing = NO; 216 | 217 | return; 218 | } 219 | 220 | if(_activeTool) 221 | { 222 | _activeTool.selected = NO; 223 | _activeTool = Nil; 224 | [self setNeedsDisplay]; 225 | } 226 | 227 | _drawToolClass = toolType; 228 | _drawing = YES; 229 | } 230 | 231 | -(void)finalizeDrawing 232 | { 233 | [_activeTool finalize]; 234 | _drawing = NO; 235 | [self setNeedsDisplay]; 236 | } 237 | 238 | -(void)deleteCurrentTool 239 | { 240 | if(_activeTool) 241 | { 242 | [_undoManager removeTool:_activeTool]; 243 | _activeTool = Nil; 244 | 245 | _isDirty = YES; 246 | 247 | [self setNeedsDisplay]; 248 | } 249 | } 250 | 251 | -(void)clearTools 252 | { 253 | [_tools removeAllObjects]; 254 | [_undoManager reset]; 255 | [self setNeedsDisplay]; 256 | } 257 | 258 | -(void)selectNone 259 | { 260 | if(_activeTool) 261 | { 262 | _activeTool.selected = NO; 263 | [self setNeedsDisplay]; 264 | } 265 | } 266 | 267 | #pragma mark - private methods 268 | 269 | -(void)initGestures 270 | { 271 | UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)]; 272 | tapGesture.numberOfTouchesRequired = 1; 273 | tapGesture.delegate = self; 274 | [self addGestureRecognizer:tapGesture]; 275 | } 276 | 277 | -(void)handleTapGesture:(UITapGestureRecognizer *)gesture 278 | { 279 | CGPoint point = [gesture locationInView:self]; 280 | if(_drawing) 281 | { 282 | [self drawUp:point]; 283 | [self setNeedsDisplay]; 284 | } 285 | else 286 | { 287 | [self selectTool:point]; 288 | } 289 | } 290 | 291 | -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 292 | { 293 | UITouch *touch = [[event allTouches] anyObject]; 294 | CGPoint point = [touch locationInView:self]; 295 | 296 | [self drawDown:point]; 297 | 298 | 299 | [self.nextResponder touchesBegan:touches withEvent:event]; 300 | } 301 | 302 | -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 303 | { 304 | UITouch *touch = [[event allTouches] anyObject]; 305 | CGPoint prePoint = [touch previousLocationInView:self]; 306 | CGPoint point = [touch locationInView:self]; 307 | 308 | [self drawMoveFromPoint:prePoint toPoint:point]; 309 | 310 | [self.nextResponder touchesMoved:touches withEvent:event]; 311 | } 312 | 313 | -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 314 | { 315 | UITouch *touch = [[event allTouches] anyObject]; 316 | CGPoint point = [touch locationInView:self]; 317 | 318 | [self drawUp:point]; 319 | 320 | [self.nextResponder touchesEnded:touches withEvent:event]; 321 | } 322 | 323 | #pragma mark - draw 324 | 325 | -(void)drawDown:(CGPoint)point 326 | { 327 | _isMoved = NO; 328 | 329 | if(self.drawing) 330 | { 331 | if(_activeTool && !_activeTool.finalized && _drawing) 332 | { 333 | [_activeTool drawDown:point]; 334 | } 335 | else 336 | { 337 | _activeTool = [[_drawToolClass alloc] initWithStartPoint:point]; 338 | _activeTool.color = self.color; 339 | _activeTool.lineWidth = self.lineWidth; 340 | _activeTool.showMeasurement = self.showMeasurement; 341 | _activeTool.unit = self.unit; 342 | _activeTool.calibration = self.calibration; 343 | //Comment tool is special, it should interate with alert views. 344 | if([_activeTool isKindOfClass:[MDrawComment class]]) 345 | { 346 | MDrawComment *comment = (MDrawComment *)_activeTool; 347 | comment.delegate = self; 348 | } 349 | 350 | [_undoManager addTool:_activeTool]; 351 | 352 | _isDirty = YES; 353 | } 354 | 355 | [self setNeedsDisplay]; 356 | } 357 | else 358 | { 359 | [self.activeTool hitOnHandle:point]; 360 | } 361 | } 362 | 363 | -(void)drawMoveFromPoint:(CGPoint)srcPoint toPoint:(CGPoint)point 364 | { 365 | _isMoved = YES; 366 | _isDirty = YES; 367 | 368 | if(self.drawing) 369 | { 370 | [self.activeTool drawMove:point]; 371 | } 372 | else 373 | { 374 | CGSize offset = CGPointOffset(srcPoint, point); 375 | [self.activeTool moveByOffset:offset]; 376 | } 377 | 378 | [self setNeedsDisplay]; 379 | } 380 | 381 | -(void)drawUp:(CGPoint)point 382 | { 383 | if(self.drawing) 384 | { 385 | [self.activeTool drawUp:point]; 386 | 387 | if(self.activeTool.finalized) 388 | { 389 | _drawing = NO; 390 | } 391 | } 392 | else 393 | { 394 | if(_isMoved) 395 | { 396 | [self.activeTool stopMoveHandle]; 397 | } 398 | else 399 | { 400 | //Click or tap 401 | [self selectTool:point]; 402 | } 403 | 404 | } 405 | 406 | [self setNeedsDisplay]; 407 | 408 | _isMoved = NO; 409 | } 410 | 411 | #pragma mark - hit tests 412 | 413 | -(void)selectTool:(CGPoint)point 414 | { 415 | BOOL hasSelected = NO; 416 | _activeTool = Nil; 417 | 418 | for (int i = _tools.count -1; i >= 0; i--) 419 | { 420 | MDrawTool *tool = [_tools objectAtIndex:i]; 421 | 422 | if([tool hitTest:point] && !hasSelected) 423 | { 424 | hasSelected = YES; 425 | 426 | tool.selected = YES; 427 | _activeTool = tool; 428 | } 429 | else 430 | { 431 | tool.selected = NO; 432 | } 433 | } 434 | 435 | [self setNeedsDisplay]; 436 | } 437 | 438 | #pragma mark - draw comment protocol 439 | 440 | -(void)drawTool:(MDrawTool *)tool isAdded:(BOOL)added 441 | { 442 | if(added) 443 | { 444 | [self setNeedsDisplay]; 445 | } 446 | else 447 | { 448 | [self deleteCurrentTool]; 449 | } 450 | } 451 | 452 | 453 | @end 454 | -------------------------------------------------------------------------------- /MDraw.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 330B58CA19B98CFD0078C2FF /* MDrawAngle.m in Sources */ = {isa = PBXBuildFile; fileRef = 330B58BF19B98CFD0078C2FF /* MDrawAngle.m */; }; 11 | 330B58CB19B98CFD0078C2FF /* MDrawArc.m in Sources */ = {isa = PBXBuildFile; fileRef = 330B58C119B98CFD0078C2FF /* MDrawArc.m */; }; 12 | 330B58CC19B98CFD0078C2FF /* MDrawComment.m in Sources */ = {isa = PBXBuildFile; fileRef = 330B58C319B98CFD0078C2FF /* MDrawComment.m */; }; 13 | 330B58CD19B98CFD0078C2FF /* MDrawFatArrow.m in Sources */ = {isa = PBXBuildFile; fileRef = 330B58C519B98CFD0078C2FF /* MDrawFatArrow.m */; }; 14 | 330B58CE19B98CFD0078C2FF /* MDrawText.m in Sources */ = {isa = PBXBuildFile; fileRef = 330B58C819B98CFD0078C2FF /* MDrawText.m */; }; 15 | 330B58D119B9B00E0078C2FF /* MDrawMeasurementInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 330B58D019B9B00E0078C2FF /* MDrawMeasurementInfo.m */; }; 16 | 3317D07B17C6F40D008443C6 /* MDrawRect.m in Sources */ = {isa = PBXBuildFile; fileRef = 3317D07A17C6F40D008443C6 /* MDrawRect.m */; }; 17 | 3317D07E17C74AF3008443C6 /* MDrawEllipse.m in Sources */ = {isa = PBXBuildFile; fileRef = 3317D07D17C74AF3008443C6 /* MDrawEllipse.m */; }; 18 | 33AEF08417D07B21003C376A /* MDrawArrow.m in Sources */ = {isa = PBXBuildFile; fileRef = 33AEF08317D07B21003C376A /* MDrawArrow.m */; }; 19 | 33C0988317CD8DB400C3EC1B /* MUndoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 33C0988217CD8DB400C3EC1B /* MUndoManager.m */; }; 20 | 33D7940A17CADB97007E2E94 /* MDrawFreeline.m in Sources */ = {isa = PBXBuildFile; fileRef = 33D7940917CADB97007E2E94 /* MDrawFreeline.m */; }; 21 | 33D7940D17CAFA76007E2E94 /* MDrawPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 33D7940C17CAFA76007E2E94 /* MDrawPolyline.m */; }; 22 | 33DE966017C466B600A6F222 /* MDrawLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 33DE965F17C466B600A6F222 /* MDrawLine.m */; }; 23 | 33E28B7817C20DA200EFC071 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33E28B7717C20DA200EFC071 /* Foundation.framework */; }; 24 | 33E28B7A17C20DA200EFC071 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33E28B7917C20DA200EFC071 /* CoreGraphics.framework */; }; 25 | 33E28B7C17C20DA200EFC071 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33E28B7B17C20DA200EFC071 /* UIKit.framework */; }; 26 | 33E28B8217C20DA200EFC071 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 33E28B8017C20DA200EFC071 /* InfoPlist.strings */; }; 27 | 33E28B8417C20DA200EFC071 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 33E28B8317C20DA200EFC071 /* main.m */; }; 28 | 33E28B8817C20DA200EFC071 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 33E28B8717C20DA200EFC071 /* AppDelegate.m */; }; 29 | 33E28B8B17C20DA200EFC071 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 33E28B8917C20DA200EFC071 /* Main.storyboard */; }; 30 | 33E28B8E17C20DA200EFC071 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 33E28B8D17C20DA200EFC071 /* ViewController.m */; }; 31 | 33E28B9017C20DA200EFC071 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33E28B8F17C20DA200EFC071 /* Images.xcassets */; }; 32 | 33E28B9717C20DA200EFC071 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33E28B9617C20DA200EFC071 /* XCTest.framework */; }; 33 | 33E28B9817C20DA200EFC071 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33E28B7717C20DA200EFC071 /* Foundation.framework */; }; 34 | 33E28B9917C20DA200EFC071 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33E28B7B17C20DA200EFC071 /* UIKit.framework */; }; 35 | 33E28BA117C20DA200EFC071 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 33E28B9F17C20DA200EFC071 /* InfoPlist.strings */; }; 36 | 33E28BA317C20DA200EFC071 /* MDrawTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33E28BA217C20DA200EFC071 /* MDrawTests.m */; }; 37 | 33E28BAF17C20E6D00EFC071 /* MDrawTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 33E28BAE17C20E6D00EFC071 /* MDrawTool.m */; }; 38 | 33E28BB217C2140B00EFC071 /* MDrawView.m in Sources */ = {isa = PBXBuildFile; fileRef = 33E28BB117C2140B00EFC071 /* MDrawView.m */; }; 39 | /* End PBXBuildFile section */ 40 | 41 | /* Begin PBXContainerItemProxy section */ 42 | 33E28B9A17C20DA200EFC071 /* PBXContainerItemProxy */ = { 43 | isa = PBXContainerItemProxy; 44 | containerPortal = 33E28B6C17C20DA200EFC071 /* Project object */; 45 | proxyType = 1; 46 | remoteGlobalIDString = 33E28B7317C20DA200EFC071; 47 | remoteInfo = MDraw; 48 | }; 49 | /* End PBXContainerItemProxy section */ 50 | 51 | /* Begin PBXFileReference section */ 52 | 330B58BE19B98CFD0078C2FF /* MDrawAngle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawAngle.h; sourceTree = ""; }; 53 | 330B58BF19B98CFD0078C2FF /* MDrawAngle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawAngle.m; sourceTree = ""; }; 54 | 330B58C019B98CFD0078C2FF /* MDrawArc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawArc.h; sourceTree = ""; }; 55 | 330B58C119B98CFD0078C2FF /* MDrawArc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawArc.m; sourceTree = ""; }; 56 | 330B58C219B98CFD0078C2FF /* MDrawComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawComment.h; sourceTree = ""; }; 57 | 330B58C319B98CFD0078C2FF /* MDrawComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawComment.m; sourceTree = ""; }; 58 | 330B58C419B98CFD0078C2FF /* MDrawFatArrow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawFatArrow.h; sourceTree = ""; }; 59 | 330B58C519B98CFD0078C2FF /* MDrawFatArrow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawFatArrow.m; sourceTree = ""; }; 60 | 330B58C619B98CFD0078C2FF /* MDrawMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawMath.h; sourceTree = ""; }; 61 | 330B58C719B98CFD0078C2FF /* MDrawText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawText.h; sourceTree = ""; }; 62 | 330B58C819B98CFD0078C2FF /* MDrawText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawText.m; sourceTree = ""; }; 63 | 330B58C919B98CFD0078C2FF /* MDrawTool_Subclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawTool_Subclass.h; sourceTree = ""; }; 64 | 330B58CF19B9B00E0078C2FF /* MDrawMeasurementInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawMeasurementInfo.h; sourceTree = ""; }; 65 | 330B58D019B9B00E0078C2FF /* MDrawMeasurementInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawMeasurementInfo.m; sourceTree = ""; }; 66 | 3317D07917C6F40D008443C6 /* MDrawRect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawRect.h; sourceTree = ""; }; 67 | 3317D07A17C6F40D008443C6 /* MDrawRect.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawRect.m; sourceTree = ""; }; 68 | 3317D07C17C74AF3008443C6 /* MDrawEllipse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawEllipse.h; sourceTree = ""; }; 69 | 3317D07D17C74AF3008443C6 /* MDrawEllipse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawEllipse.m; sourceTree = ""; }; 70 | 33AEF08217D07B21003C376A /* MDrawArrow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawArrow.h; sourceTree = ""; }; 71 | 33AEF08317D07B21003C376A /* MDrawArrow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawArrow.m; sourceTree = ""; }; 72 | 33C0988117CD8DB400C3EC1B /* MUndoManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MUndoManager.h; sourceTree = ""; }; 73 | 33C0988217CD8DB400C3EC1B /* MUndoManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MUndoManager.m; sourceTree = ""; }; 74 | 33D7940817CADB97007E2E94 /* MDrawFreeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawFreeline.h; sourceTree = ""; }; 75 | 33D7940917CADB97007E2E94 /* MDrawFreeline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawFreeline.m; sourceTree = ""; }; 76 | 33D7940B17CAFA76007E2E94 /* MDrawPolyline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawPolyline.h; sourceTree = ""; }; 77 | 33D7940C17CAFA76007E2E94 /* MDrawPolyline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawPolyline.m; sourceTree = ""; }; 78 | 33DE965E17C466B600A6F222 /* MDrawLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawLine.h; sourceTree = ""; }; 79 | 33DE965F17C466B600A6F222 /* MDrawLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawLine.m; sourceTree = ""; }; 80 | 33E28B7417C20DA200EFC071 /* MDraw.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MDraw.app; sourceTree = BUILT_PRODUCTS_DIR; }; 81 | 33E28B7717C20DA200EFC071 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 82 | 33E28B7917C20DA200EFC071 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 83 | 33E28B7B17C20DA200EFC071 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 84 | 33E28B7F17C20DA200EFC071 /* MDraw-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MDraw-Info.plist"; sourceTree = ""; }; 85 | 33E28B8117C20DA200EFC071 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 86 | 33E28B8317C20DA200EFC071 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 87 | 33E28B8517C20DA200EFC071 /* MDraw-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MDraw-Prefix.pch"; sourceTree = ""; }; 88 | 33E28B8617C20DA200EFC071 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 89 | 33E28B8717C20DA200EFC071 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 90 | 33E28B8A17C20DA200EFC071 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 91 | 33E28B8C17C20DA200EFC071 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 92 | 33E28B8D17C20DA200EFC071 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 93 | 33E28B8F17C20DA200EFC071 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 94 | 33E28B9517C20DA200EFC071 /* MDrawTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MDrawTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 95 | 33E28B9617C20DA200EFC071 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 96 | 33E28B9E17C20DA200EFC071 /* MDrawTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MDrawTests-Info.plist"; sourceTree = ""; }; 97 | 33E28BA017C20DA200EFC071 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 98 | 33E28BA217C20DA200EFC071 /* MDrawTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MDrawTests.m; sourceTree = ""; }; 99 | 33E28BAD17C20E6D00EFC071 /* MDrawTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawTool.h; sourceTree = ""; }; 100 | 33E28BAE17C20E6D00EFC071 /* MDrawTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawTool.m; sourceTree = ""; }; 101 | 33E28BB017C2140B00EFC071 /* MDrawView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDrawView.h; sourceTree = ""; }; 102 | 33E28BB117C2140B00EFC071 /* MDrawView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDrawView.m; sourceTree = ""; }; 103 | /* End PBXFileReference section */ 104 | 105 | /* Begin PBXFrameworksBuildPhase section */ 106 | 33E28B7117C20DA200EFC071 /* Frameworks */ = { 107 | isa = PBXFrameworksBuildPhase; 108 | buildActionMask = 2147483647; 109 | files = ( 110 | 33E28B7A17C20DA200EFC071 /* CoreGraphics.framework in Frameworks */, 111 | 33E28B7C17C20DA200EFC071 /* UIKit.framework in Frameworks */, 112 | 33E28B7817C20DA200EFC071 /* Foundation.framework in Frameworks */, 113 | ); 114 | runOnlyForDeploymentPostprocessing = 0; 115 | }; 116 | 33E28B9217C20DA200EFC071 /* Frameworks */ = { 117 | isa = PBXFrameworksBuildPhase; 118 | buildActionMask = 2147483647; 119 | files = ( 120 | 33E28B9717C20DA200EFC071 /* XCTest.framework in Frameworks */, 121 | 33E28B9917C20DA200EFC071 /* UIKit.framework in Frameworks */, 122 | 33E28B9817C20DA200EFC071 /* Foundation.framework in Frameworks */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXFrameworksBuildPhase section */ 127 | 128 | /* Begin PBXGroup section */ 129 | 33E28B6B17C20DA200EFC071 = { 130 | isa = PBXGroup; 131 | children = ( 132 | 33E28B7D17C20DA200EFC071 /* MDraw */, 133 | 33E28B9C17C20DA200EFC071 /* MDrawTests */, 134 | 33E28B7617C20DA200EFC071 /* Frameworks */, 135 | 33E28B7517C20DA200EFC071 /* Products */, 136 | ); 137 | sourceTree = ""; 138 | }; 139 | 33E28B7517C20DA200EFC071 /* Products */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 33E28B7417C20DA200EFC071 /* MDraw.app */, 143 | 33E28B9517C20DA200EFC071 /* MDrawTests.xctest */, 144 | ); 145 | name = Products; 146 | sourceTree = ""; 147 | }; 148 | 33E28B7617C20DA200EFC071 /* Frameworks */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | 33E28B7717C20DA200EFC071 /* Foundation.framework */, 152 | 33E28B7917C20DA200EFC071 /* CoreGraphics.framework */, 153 | 33E28B7B17C20DA200EFC071 /* UIKit.framework */, 154 | 33E28B9617C20DA200EFC071 /* XCTest.framework */, 155 | ); 156 | name = Frameworks; 157 | sourceTree = ""; 158 | }; 159 | 33E28B7D17C20DA200EFC071 /* MDraw */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | 33E28BAC17C20DB500EFC071 /* DrawTool */, 163 | 33E28B8617C20DA200EFC071 /* AppDelegate.h */, 164 | 33E28B8717C20DA200EFC071 /* AppDelegate.m */, 165 | 33E28B8917C20DA200EFC071 /* Main.storyboard */, 166 | 33E28B8C17C20DA200EFC071 /* ViewController.h */, 167 | 33E28B8D17C20DA200EFC071 /* ViewController.m */, 168 | 33E28B8F17C20DA200EFC071 /* Images.xcassets */, 169 | 33E28B7E17C20DA200EFC071 /* Supporting Files */, 170 | ); 171 | path = MDraw; 172 | sourceTree = ""; 173 | }; 174 | 33E28B7E17C20DA200EFC071 /* Supporting Files */ = { 175 | isa = PBXGroup; 176 | children = ( 177 | 33E28B7F17C20DA200EFC071 /* MDraw-Info.plist */, 178 | 33E28B8017C20DA200EFC071 /* InfoPlist.strings */, 179 | 33E28B8317C20DA200EFC071 /* main.m */, 180 | 33E28B8517C20DA200EFC071 /* MDraw-Prefix.pch */, 181 | ); 182 | name = "Supporting Files"; 183 | sourceTree = ""; 184 | }; 185 | 33E28B9C17C20DA200EFC071 /* MDrawTests */ = { 186 | isa = PBXGroup; 187 | children = ( 188 | 33E28BA217C20DA200EFC071 /* MDrawTests.m */, 189 | 33E28B9D17C20DA200EFC071 /* Supporting Files */, 190 | ); 191 | path = MDrawTests; 192 | sourceTree = ""; 193 | }; 194 | 33E28B9D17C20DA200EFC071 /* Supporting Files */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | 33E28B9E17C20DA200EFC071 /* MDrawTests-Info.plist */, 198 | 33E28B9F17C20DA200EFC071 /* InfoPlist.strings */, 199 | ); 200 | name = "Supporting Files"; 201 | sourceTree = ""; 202 | }; 203 | 33E28BAC17C20DB500EFC071 /* DrawTool */ = { 204 | isa = PBXGroup; 205 | children = ( 206 | 330B58BE19B98CFD0078C2FF /* MDrawAngle.h */, 207 | 330B58BF19B98CFD0078C2FF /* MDrawAngle.m */, 208 | 330B58C019B98CFD0078C2FF /* MDrawArc.h */, 209 | 330B58C119B98CFD0078C2FF /* MDrawArc.m */, 210 | 330B58C219B98CFD0078C2FF /* MDrawComment.h */, 211 | 330B58C319B98CFD0078C2FF /* MDrawComment.m */, 212 | 330B58C419B98CFD0078C2FF /* MDrawFatArrow.h */, 213 | 330B58C519B98CFD0078C2FF /* MDrawFatArrow.m */, 214 | 330B58C619B98CFD0078C2FF /* MDrawMath.h */, 215 | 330B58C719B98CFD0078C2FF /* MDrawText.h */, 216 | 330B58C819B98CFD0078C2FF /* MDrawText.m */, 217 | 330B58C919B98CFD0078C2FF /* MDrawTool_Subclass.h */, 218 | 33E28BAD17C20E6D00EFC071 /* MDrawTool.h */, 219 | 33E28BAE17C20E6D00EFC071 /* MDrawTool.m */, 220 | 33E28BB017C2140B00EFC071 /* MDrawView.h */, 221 | 33E28BB117C2140B00EFC071 /* MDrawView.m */, 222 | 33DE965E17C466B600A6F222 /* MDrawLine.h */, 223 | 33DE965F17C466B600A6F222 /* MDrawLine.m */, 224 | 3317D07917C6F40D008443C6 /* MDrawRect.h */, 225 | 3317D07A17C6F40D008443C6 /* MDrawRect.m */, 226 | 3317D07C17C74AF3008443C6 /* MDrawEllipse.h */, 227 | 3317D07D17C74AF3008443C6 /* MDrawEllipse.m */, 228 | 33D7940817CADB97007E2E94 /* MDrawFreeline.h */, 229 | 33D7940917CADB97007E2E94 /* MDrawFreeline.m */, 230 | 33D7940B17CAFA76007E2E94 /* MDrawPolyline.h */, 231 | 33D7940C17CAFA76007E2E94 /* MDrawPolyline.m */, 232 | 33C0988117CD8DB400C3EC1B /* MUndoManager.h */, 233 | 33C0988217CD8DB400C3EC1B /* MUndoManager.m */, 234 | 33AEF08217D07B21003C376A /* MDrawArrow.h */, 235 | 33AEF08317D07B21003C376A /* MDrawArrow.m */, 236 | 330B58CF19B9B00E0078C2FF /* MDrawMeasurementInfo.h */, 237 | 330B58D019B9B00E0078C2FF /* MDrawMeasurementInfo.m */, 238 | ); 239 | name = DrawTool; 240 | sourceTree = ""; 241 | }; 242 | /* End PBXGroup section */ 243 | 244 | /* Begin PBXNativeTarget section */ 245 | 33E28B7317C20DA200EFC071 /* MDraw */ = { 246 | isa = PBXNativeTarget; 247 | buildConfigurationList = 33E28BA617C20DA200EFC071 /* Build configuration list for PBXNativeTarget "MDraw" */; 248 | buildPhases = ( 249 | 33E28B7017C20DA200EFC071 /* Sources */, 250 | 33E28B7117C20DA200EFC071 /* Frameworks */, 251 | 33E28B7217C20DA200EFC071 /* Resources */, 252 | ); 253 | buildRules = ( 254 | ); 255 | dependencies = ( 256 | ); 257 | name = MDraw; 258 | productName = MDraw; 259 | productReference = 33E28B7417C20DA200EFC071 /* MDraw.app */; 260 | productType = "com.apple.product-type.application"; 261 | }; 262 | 33E28B9417C20DA200EFC071 /* MDrawTests */ = { 263 | isa = PBXNativeTarget; 264 | buildConfigurationList = 33E28BA917C20DA200EFC071 /* Build configuration list for PBXNativeTarget "MDrawTests" */; 265 | buildPhases = ( 266 | 33E28B9117C20DA200EFC071 /* Sources */, 267 | 33E28B9217C20DA200EFC071 /* Frameworks */, 268 | 33E28B9317C20DA200EFC071 /* Resources */, 269 | ); 270 | buildRules = ( 271 | ); 272 | dependencies = ( 273 | 33E28B9B17C20DA200EFC071 /* PBXTargetDependency */, 274 | ); 275 | name = MDrawTests; 276 | productName = MDrawTests; 277 | productReference = 33E28B9517C20DA200EFC071 /* MDrawTests.xctest */; 278 | productType = "com.apple.product-type.bundle.unit-test"; 279 | }; 280 | /* End PBXNativeTarget section */ 281 | 282 | /* Begin PBXProject section */ 283 | 33E28B6C17C20DA200EFC071 /* Project object */ = { 284 | isa = PBXProject; 285 | attributes = { 286 | LastUpgradeCheck = 0500; 287 | ORGANIZATIONNAME = "Motic China Group Co., Ltd"; 288 | TargetAttributes = { 289 | 33E28B9417C20DA200EFC071 = { 290 | TestTargetID = 33E28B7317C20DA200EFC071; 291 | }; 292 | }; 293 | }; 294 | buildConfigurationList = 33E28B6F17C20DA200EFC071 /* Build configuration list for PBXProject "MDraw" */; 295 | compatibilityVersion = "Xcode 3.2"; 296 | developmentRegion = English; 297 | hasScannedForEncodings = 0; 298 | knownRegions = ( 299 | en, 300 | Base, 301 | ); 302 | mainGroup = 33E28B6B17C20DA200EFC071; 303 | productRefGroup = 33E28B7517C20DA200EFC071 /* Products */; 304 | projectDirPath = ""; 305 | projectRoot = ""; 306 | targets = ( 307 | 33E28B7317C20DA200EFC071 /* MDraw */, 308 | 33E28B9417C20DA200EFC071 /* MDrawTests */, 309 | ); 310 | }; 311 | /* End PBXProject section */ 312 | 313 | /* Begin PBXResourcesBuildPhase section */ 314 | 33E28B7217C20DA200EFC071 /* Resources */ = { 315 | isa = PBXResourcesBuildPhase; 316 | buildActionMask = 2147483647; 317 | files = ( 318 | 33E28B9017C20DA200EFC071 /* Images.xcassets in Resources */, 319 | 33E28B8217C20DA200EFC071 /* InfoPlist.strings in Resources */, 320 | 33E28B8B17C20DA200EFC071 /* Main.storyboard in Resources */, 321 | ); 322 | runOnlyForDeploymentPostprocessing = 0; 323 | }; 324 | 33E28B9317C20DA200EFC071 /* Resources */ = { 325 | isa = PBXResourcesBuildPhase; 326 | buildActionMask = 2147483647; 327 | files = ( 328 | 33E28BA117C20DA200EFC071 /* InfoPlist.strings in Resources */, 329 | ); 330 | runOnlyForDeploymentPostprocessing = 0; 331 | }; 332 | /* End PBXResourcesBuildPhase section */ 333 | 334 | /* Begin PBXSourcesBuildPhase section */ 335 | 33E28B7017C20DA200EFC071 /* Sources */ = { 336 | isa = PBXSourcesBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | 330B58CB19B98CFD0078C2FF /* MDrawArc.m in Sources */, 340 | 330B58CE19B98CFD0078C2FF /* MDrawText.m in Sources */, 341 | 33E28B8E17C20DA200EFC071 /* ViewController.m in Sources */, 342 | 33E28B8817C20DA200EFC071 /* AppDelegate.m in Sources */, 343 | 330B58CA19B98CFD0078C2FF /* MDrawAngle.m in Sources */, 344 | 3317D07E17C74AF3008443C6 /* MDrawEllipse.m in Sources */, 345 | 33D7940D17CAFA76007E2E94 /* MDrawPolyline.m in Sources */, 346 | 33E28BB217C2140B00EFC071 /* MDrawView.m in Sources */, 347 | 330B58D119B9B00E0078C2FF /* MDrawMeasurementInfo.m in Sources */, 348 | 33E28B8417C20DA200EFC071 /* main.m in Sources */, 349 | 3317D07B17C6F40D008443C6 /* MDrawRect.m in Sources */, 350 | 33D7940A17CADB97007E2E94 /* MDrawFreeline.m in Sources */, 351 | 33C0988317CD8DB400C3EC1B /* MUndoManager.m in Sources */, 352 | 330B58CD19B98CFD0078C2FF /* MDrawFatArrow.m in Sources */, 353 | 33AEF08417D07B21003C376A /* MDrawArrow.m in Sources */, 354 | 33E28BAF17C20E6D00EFC071 /* MDrawTool.m in Sources */, 355 | 33DE966017C466B600A6F222 /* MDrawLine.m in Sources */, 356 | 330B58CC19B98CFD0078C2FF /* MDrawComment.m in Sources */, 357 | ); 358 | runOnlyForDeploymentPostprocessing = 0; 359 | }; 360 | 33E28B9117C20DA200EFC071 /* Sources */ = { 361 | isa = PBXSourcesBuildPhase; 362 | buildActionMask = 2147483647; 363 | files = ( 364 | 33E28BA317C20DA200EFC071 /* MDrawTests.m in Sources */, 365 | ); 366 | runOnlyForDeploymentPostprocessing = 0; 367 | }; 368 | /* End PBXSourcesBuildPhase section */ 369 | 370 | /* Begin PBXTargetDependency section */ 371 | 33E28B9B17C20DA200EFC071 /* PBXTargetDependency */ = { 372 | isa = PBXTargetDependency; 373 | target = 33E28B7317C20DA200EFC071 /* MDraw */; 374 | targetProxy = 33E28B9A17C20DA200EFC071 /* PBXContainerItemProxy */; 375 | }; 376 | /* End PBXTargetDependency section */ 377 | 378 | /* Begin PBXVariantGroup section */ 379 | 33E28B8017C20DA200EFC071 /* InfoPlist.strings */ = { 380 | isa = PBXVariantGroup; 381 | children = ( 382 | 33E28B8117C20DA200EFC071 /* en */, 383 | ); 384 | name = InfoPlist.strings; 385 | sourceTree = ""; 386 | }; 387 | 33E28B8917C20DA200EFC071 /* Main.storyboard */ = { 388 | isa = PBXVariantGroup; 389 | children = ( 390 | 33E28B8A17C20DA200EFC071 /* Base */, 391 | ); 392 | name = Main.storyboard; 393 | sourceTree = ""; 394 | }; 395 | 33E28B9F17C20DA200EFC071 /* InfoPlist.strings */ = { 396 | isa = PBXVariantGroup; 397 | children = ( 398 | 33E28BA017C20DA200EFC071 /* en */, 399 | ); 400 | name = InfoPlist.strings; 401 | sourceTree = ""; 402 | }; 403 | /* End PBXVariantGroup section */ 404 | 405 | /* Begin XCBuildConfiguration section */ 406 | 33E28BA417C20DA200EFC071 /* Debug */ = { 407 | isa = XCBuildConfiguration; 408 | buildSettings = { 409 | ALWAYS_SEARCH_USER_PATHS = NO; 410 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 411 | CLANG_CXX_LIBRARY = "libc++"; 412 | CLANG_ENABLE_MODULES = YES; 413 | CLANG_ENABLE_OBJC_ARC = YES; 414 | CLANG_WARN_BOOL_CONVERSION = YES; 415 | CLANG_WARN_CONSTANT_CONVERSION = YES; 416 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 417 | CLANG_WARN_EMPTY_BODY = YES; 418 | CLANG_WARN_ENUM_CONVERSION = YES; 419 | CLANG_WARN_INT_CONVERSION = YES; 420 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 421 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 422 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 423 | COPY_PHASE_STRIP = NO; 424 | GCC_C_LANGUAGE_STANDARD = gnu99; 425 | GCC_DYNAMIC_NO_PIC = NO; 426 | GCC_OPTIMIZATION_LEVEL = 0; 427 | GCC_PREPROCESSOR_DEFINITIONS = ( 428 | "DEBUG=1", 429 | "$(inherited)", 430 | ); 431 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 432 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 433 | GCC_WARN_UNDECLARED_SELECTOR = YES; 434 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 435 | GCC_WARN_UNUSED_FUNCTION = YES; 436 | GCC_WARN_UNUSED_VARIABLE = YES; 437 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 438 | ONLY_ACTIVE_ARCH = YES; 439 | SDKROOT = iphoneos; 440 | TARGETED_DEVICE_FAMILY = 2; 441 | }; 442 | name = Debug; 443 | }; 444 | 33E28BA517C20DA200EFC071 /* Release */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | ALWAYS_SEARCH_USER_PATHS = NO; 448 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 449 | CLANG_CXX_LIBRARY = "libc++"; 450 | CLANG_ENABLE_MODULES = YES; 451 | CLANG_ENABLE_OBJC_ARC = YES; 452 | CLANG_WARN_BOOL_CONVERSION = YES; 453 | CLANG_WARN_CONSTANT_CONVERSION = YES; 454 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 455 | CLANG_WARN_EMPTY_BODY = YES; 456 | CLANG_WARN_ENUM_CONVERSION = YES; 457 | CLANG_WARN_INT_CONVERSION = YES; 458 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 459 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 460 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 461 | COPY_PHASE_STRIP = YES; 462 | ENABLE_NS_ASSERTIONS = NO; 463 | GCC_C_LANGUAGE_STANDARD = gnu99; 464 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 465 | GCC_WARN_UNDECLARED_SELECTOR = YES; 466 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 467 | GCC_WARN_UNUSED_FUNCTION = YES; 468 | GCC_WARN_UNUSED_VARIABLE = YES; 469 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 470 | SDKROOT = iphoneos; 471 | TARGETED_DEVICE_FAMILY = 2; 472 | VALIDATE_PRODUCT = YES; 473 | }; 474 | name = Release; 475 | }; 476 | 33E28BA717C20DA200EFC071 /* Debug */ = { 477 | isa = XCBuildConfiguration; 478 | buildSettings = { 479 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 480 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 481 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 482 | GCC_PREFIX_HEADER = "MDraw/MDraw-Prefix.pch"; 483 | INFOPLIST_FILE = "MDraw/MDraw-Info.plist"; 484 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 485 | PRODUCT_NAME = "$(TARGET_NAME)"; 486 | WRAPPER_EXTENSION = app; 487 | }; 488 | name = Debug; 489 | }; 490 | 33E28BA817C20DA200EFC071 /* Release */ = { 491 | isa = XCBuildConfiguration; 492 | buildSettings = { 493 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 494 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 495 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 496 | GCC_PREFIX_HEADER = "MDraw/MDraw-Prefix.pch"; 497 | INFOPLIST_FILE = "MDraw/MDraw-Info.plist"; 498 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 499 | PRODUCT_NAME = "$(TARGET_NAME)"; 500 | WRAPPER_EXTENSION = app; 501 | }; 502 | name = Release; 503 | }; 504 | 33E28BAA17C20DA200EFC071 /* Debug */ = { 505 | isa = XCBuildConfiguration; 506 | buildSettings = { 507 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/MDraw.app/MDraw"; 508 | FRAMEWORK_SEARCH_PATHS = ( 509 | "$(SDKROOT)/Developer/Library/Frameworks", 510 | "$(inherited)", 511 | "$(DEVELOPER_FRAMEWORKS_DIR)", 512 | ); 513 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 514 | GCC_PREFIX_HEADER = "MDraw/MDraw-Prefix.pch"; 515 | GCC_PREPROCESSOR_DEFINITIONS = ( 516 | "DEBUG=1", 517 | "$(inherited)", 518 | ); 519 | INFOPLIST_FILE = "MDrawTests/MDrawTests-Info.plist"; 520 | PRODUCT_NAME = "$(TARGET_NAME)"; 521 | TEST_HOST = "$(BUNDLE_LOADER)"; 522 | WRAPPER_EXTENSION = xctest; 523 | }; 524 | name = Debug; 525 | }; 526 | 33E28BAB17C20DA200EFC071 /* Release */ = { 527 | isa = XCBuildConfiguration; 528 | buildSettings = { 529 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/MDraw.app/MDraw"; 530 | FRAMEWORK_SEARCH_PATHS = ( 531 | "$(SDKROOT)/Developer/Library/Frameworks", 532 | "$(inherited)", 533 | "$(DEVELOPER_FRAMEWORKS_DIR)", 534 | ); 535 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 536 | GCC_PREFIX_HEADER = "MDraw/MDraw-Prefix.pch"; 537 | INFOPLIST_FILE = "MDrawTests/MDrawTests-Info.plist"; 538 | PRODUCT_NAME = "$(TARGET_NAME)"; 539 | TEST_HOST = "$(BUNDLE_LOADER)"; 540 | WRAPPER_EXTENSION = xctest; 541 | }; 542 | name = Release; 543 | }; 544 | /* End XCBuildConfiguration section */ 545 | 546 | /* Begin XCConfigurationList section */ 547 | 33E28B6F17C20DA200EFC071 /* Build configuration list for PBXProject "MDraw" */ = { 548 | isa = XCConfigurationList; 549 | buildConfigurations = ( 550 | 33E28BA417C20DA200EFC071 /* Debug */, 551 | 33E28BA517C20DA200EFC071 /* Release */, 552 | ); 553 | defaultConfigurationIsVisible = 0; 554 | defaultConfigurationName = Release; 555 | }; 556 | 33E28BA617C20DA200EFC071 /* Build configuration list for PBXNativeTarget "MDraw" */ = { 557 | isa = XCConfigurationList; 558 | buildConfigurations = ( 559 | 33E28BA717C20DA200EFC071 /* Debug */, 560 | 33E28BA817C20DA200EFC071 /* Release */, 561 | ); 562 | defaultConfigurationIsVisible = 0; 563 | defaultConfigurationName = Release; 564 | }; 565 | 33E28BA917C20DA200EFC071 /* Build configuration list for PBXNativeTarget "MDrawTests" */ = { 566 | isa = XCConfigurationList; 567 | buildConfigurations = ( 568 | 33E28BAA17C20DA200EFC071 /* Debug */, 569 | 33E28BAB17C20DA200EFC071 /* Release */, 570 | ); 571 | defaultConfigurationIsVisible = 0; 572 | defaultConfigurationName = Release; 573 | }; 574 | /* End XCConfigurationList section */ 575 | }; 576 | rootObject = 33E28B6C17C20DA200EFC071 /* Project object */; 577 | } 578 | --------------------------------------------------------------------------------