├── .gitignore ├── CIMicroPaint.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── CIMicroPaint.xccheckout └── xcuserdata │ └── gus.xcuserdatad │ └── xcschemes │ ├── CIMicroPaint.xcscheme │ └── xcschememanagement.plist ├── CIMicroPaint ├── CIMicroPaint-Info.plist ├── CIMicroPaint-Prefix.pch ├── FMCIView.h ├── FMCIView.m ├── FMIOSurfaceAccumulator.h ├── FMIOSurfaceAccumulator.m ├── aoraki-90388.jpg ├── en.lproj │ ├── InfoPlist.strings │ └── MainMenu.xib └── main.m └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | CIMicroPaint.xcodeproj/project.xcworkspace/xcuserdata/gus.xcuserdatad/UserInterfaceState.xcuserstate 2 | CIMicroPaint.xcodeproj/xcuserdata/gus.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist 3 | -------------------------------------------------------------------------------- /CIMicroPaint.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 287DD8BA156838D1005216D8 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 287DD8B9156838D1005216D8 /* Cocoa.framework */; }; 11 | 287DD8C4156838D2005216D8 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 287DD8C2156838D2005216D8 /* InfoPlist.strings */; }; 12 | 287DD8C6156838D2005216D8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 287DD8C5156838D2005216D8 /* main.m */; }; 13 | 287DD8D0156838D2005216D8 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 287DD8CE156838D2005216D8 /* MainMenu.xib */; }; 14 | 287DD8E415683AC9005216D8 /* FMCIView.m in Sources */ = {isa = PBXBuildFile; fileRef = 287DD8E215683AC9005216D8 /* FMCIView.m */; }; 15 | 287DD8E615683CBB005216D8 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 287DD8E515683CBB005216D8 /* OpenGL.framework */; }; 16 | 287DD8E815683CC0005216D8 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 287DD8E715683CC0005216D8 /* QuartzCore.framework */; }; 17 | CCC7E32617BBFDBA004A04EE /* aoraki-90388.jpg in Resources */ = {isa = PBXBuildFile; fileRef = CCC7E32517BBFDBA004A04EE /* aoraki-90388.jpg */; }; 18 | CCD758AB17BB47B0001D930B /* IOSurface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CCD758AA17BB47B0001D930B /* IOSurface.framework */; }; 19 | CCD9721617EF8C21000813D5 /* FMIOSurfaceAccumulator.m in Sources */ = {isa = PBXBuildFile; fileRef = CCD9721517EF8C21000813D5 /* FMIOSurfaceAccumulator.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 287DD8B5156838D1005216D8 /* FMMicroPaintPlus.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FMMicroPaintPlus.app; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 287DD8B9156838D1005216D8 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 25 | 287DD8BC156838D1005216D8 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 26 | 287DD8BD156838D1005216D8 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 27 | 287DD8BE156838D1005216D8 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 28 | 287DD8C1156838D2005216D8 /* CIMicroPaint-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CIMicroPaint-Info.plist"; sourceTree = ""; }; 29 | 287DD8C3156838D2005216D8 /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 30 | 287DD8C5156838D2005216D8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 31 | 287DD8C7156838D2005216D8 /* CIMicroPaint-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CIMicroPaint-Prefix.pch"; sourceTree = ""; }; 32 | 287DD8CF156838D2005216D8 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 33 | 287DD8E115683AC9005216D8 /* FMCIView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMCIView.h; sourceTree = ""; }; 34 | 287DD8E215683AC9005216D8 /* FMCIView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMCIView.m; sourceTree = ""; }; 35 | 287DD8E515683CBB005216D8 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; 36 | 287DD8E715683CC0005216D8 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 37 | CCC7E32517BBFDBA004A04EE /* aoraki-90388.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "aoraki-90388.jpg"; sourceTree = ""; }; 38 | CCD758AA17BB47B0001D930B /* IOSurface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOSurface.framework; path = System/Library/Frameworks/IOSurface.framework; sourceTree = SDKROOT; }; 39 | CCD9721417EF8C21000813D5 /* FMIOSurfaceAccumulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMIOSurfaceAccumulator.h; sourceTree = ""; }; 40 | CCD9721517EF8C21000813D5 /* FMIOSurfaceAccumulator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMIOSurfaceAccumulator.m; sourceTree = ""; }; 41 | /* End PBXFileReference section */ 42 | 43 | /* Begin PBXFrameworksBuildPhase section */ 44 | 287DD8B2156838D1005216D8 /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | CCD758AB17BB47B0001D930B /* IOSurface.framework in Frameworks */, 49 | 287DD8E815683CC0005216D8 /* QuartzCore.framework in Frameworks */, 50 | 287DD8E615683CBB005216D8 /* OpenGL.framework in Frameworks */, 51 | 287DD8BA156838D1005216D8 /* Cocoa.framework in Frameworks */, 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 287DD8AA156838D1005216D8 = { 59 | isa = PBXGroup; 60 | children = ( 61 | 287DD8BF156838D1005216D8 /* CIMicroPaint */, 62 | 287DD8B8156838D1005216D8 /* Frameworks */, 63 | 287DD8B6156838D1005216D8 /* Products */, 64 | ); 65 | sourceTree = ""; 66 | }; 67 | 287DD8B6156838D1005216D8 /* Products */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 287DD8B5156838D1005216D8 /* FMMicroPaintPlus.app */, 71 | ); 72 | name = Products; 73 | sourceTree = ""; 74 | }; 75 | 287DD8B8156838D1005216D8 /* Frameworks */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | CCD758AA17BB47B0001D930B /* IOSurface.framework */, 79 | 287DD8E715683CC0005216D8 /* QuartzCore.framework */, 80 | 287DD8E515683CBB005216D8 /* OpenGL.framework */, 81 | 287DD8B9156838D1005216D8 /* Cocoa.framework */, 82 | 287DD8BB156838D1005216D8 /* Other Frameworks */, 83 | ); 84 | name = Frameworks; 85 | sourceTree = ""; 86 | }; 87 | 287DD8BB156838D1005216D8 /* Other Frameworks */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 287DD8BC156838D1005216D8 /* AppKit.framework */, 91 | 287DD8BD156838D1005216D8 /* CoreData.framework */, 92 | 287DD8BE156838D1005216D8 /* Foundation.framework */, 93 | ); 94 | name = "Other Frameworks"; 95 | sourceTree = ""; 96 | }; 97 | 287DD8BF156838D1005216D8 /* CIMicroPaint */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | CCD9721417EF8C21000813D5 /* FMIOSurfaceAccumulator.h */, 101 | CCD9721517EF8C21000813D5 /* FMIOSurfaceAccumulator.m */, 102 | 287DD8E115683AC9005216D8 /* FMCIView.h */, 103 | 287DD8E215683AC9005216D8 /* FMCIView.m */, 104 | 287DD8CE156838D2005216D8 /* MainMenu.xib */, 105 | 287DD8C0156838D2005216D8 /* Supporting Files */, 106 | ); 107 | path = CIMicroPaint; 108 | sourceTree = ""; 109 | }; 110 | 287DD8C0156838D2005216D8 /* Supporting Files */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | CCC7E32517BBFDBA004A04EE /* aoraki-90388.jpg */, 114 | 287DD8C1156838D2005216D8 /* CIMicroPaint-Info.plist */, 115 | 287DD8C2156838D2005216D8 /* InfoPlist.strings */, 116 | 287DD8C5156838D2005216D8 /* main.m */, 117 | 287DD8C7156838D2005216D8 /* CIMicroPaint-Prefix.pch */, 118 | ); 119 | name = "Supporting Files"; 120 | sourceTree = ""; 121 | }; 122 | /* End PBXGroup section */ 123 | 124 | /* Begin PBXNativeTarget section */ 125 | 287DD8B4156838D1005216D8 /* FMMicroPaintPlus */ = { 126 | isa = PBXNativeTarget; 127 | buildConfigurationList = 287DD8D3156838D2005216D8 /* Build configuration list for PBXNativeTarget "FMMicroPaintPlus" */; 128 | buildPhases = ( 129 | 287DD8B1156838D1005216D8 /* Sources */, 130 | 287DD8B2156838D1005216D8 /* Frameworks */, 131 | 287DD8B3156838D1005216D8 /* Resources */, 132 | ); 133 | buildRules = ( 134 | ); 135 | dependencies = ( 136 | ); 137 | name = FMMicroPaintPlus; 138 | productName = CIMicroPaint; 139 | productReference = 287DD8B5156838D1005216D8 /* FMMicroPaintPlus.app */; 140 | productType = "com.apple.product-type.application"; 141 | }; 142 | /* End PBXNativeTarget section */ 143 | 144 | /* Begin PBXProject section */ 145 | 287DD8AC156838D1005216D8 /* Project object */ = { 146 | isa = PBXProject; 147 | attributes = { 148 | LastUpgradeCheck = 0450; 149 | }; 150 | buildConfigurationList = 287DD8AF156838D1005216D8 /* Build configuration list for PBXProject "CIMicroPaint" */; 151 | compatibilityVersion = "Xcode 3.2"; 152 | developmentRegion = English; 153 | hasScannedForEncodings = 0; 154 | knownRegions = ( 155 | en, 156 | ); 157 | mainGroup = 287DD8AA156838D1005216D8; 158 | productRefGroup = 287DD8B6156838D1005216D8 /* Products */; 159 | projectDirPath = ""; 160 | projectRoot = ""; 161 | targets = ( 162 | 287DD8B4156838D1005216D8 /* FMMicroPaintPlus */, 163 | ); 164 | }; 165 | /* End PBXProject section */ 166 | 167 | /* Begin PBXResourcesBuildPhase section */ 168 | 287DD8B3156838D1005216D8 /* Resources */ = { 169 | isa = PBXResourcesBuildPhase; 170 | buildActionMask = 2147483647; 171 | files = ( 172 | 287DD8C4156838D2005216D8 /* InfoPlist.strings in Resources */, 173 | CCC7E32617BBFDBA004A04EE /* aoraki-90388.jpg in Resources */, 174 | 287DD8D0156838D2005216D8 /* MainMenu.xib in Resources */, 175 | ); 176 | runOnlyForDeploymentPostprocessing = 0; 177 | }; 178 | /* End PBXResourcesBuildPhase section */ 179 | 180 | /* Begin PBXSourcesBuildPhase section */ 181 | 287DD8B1156838D1005216D8 /* Sources */ = { 182 | isa = PBXSourcesBuildPhase; 183 | buildActionMask = 2147483647; 184 | files = ( 185 | 287DD8C6156838D2005216D8 /* main.m in Sources */, 186 | 287DD8E415683AC9005216D8 /* FMCIView.m in Sources */, 187 | CCD9721617EF8C21000813D5 /* FMIOSurfaceAccumulator.m in Sources */, 188 | ); 189 | runOnlyForDeploymentPostprocessing = 0; 190 | }; 191 | /* End PBXSourcesBuildPhase section */ 192 | 193 | /* Begin PBXVariantGroup section */ 194 | 287DD8C2156838D2005216D8 /* InfoPlist.strings */ = { 195 | isa = PBXVariantGroup; 196 | children = ( 197 | 287DD8C3156838D2005216D8 /* en */, 198 | ); 199 | name = InfoPlist.strings; 200 | sourceTree = ""; 201 | }; 202 | 287DD8CE156838D2005216D8 /* MainMenu.xib */ = { 203 | isa = PBXVariantGroup; 204 | children = ( 205 | 287DD8CF156838D2005216D8 /* en */, 206 | ); 207 | name = MainMenu.xib; 208 | sourceTree = ""; 209 | }; 210 | /* End PBXVariantGroup section */ 211 | 212 | /* Begin XCBuildConfiguration section */ 213 | 287DD8D1156838D2005216D8 /* Debug */ = { 214 | isa = XCBuildConfiguration; 215 | buildSettings = { 216 | ALWAYS_SEARCH_USER_PATHS = NO; 217 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 218 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 219 | CLANG_ENABLE_OBJC_ARC = YES; 220 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 221 | COPY_PHASE_STRIP = NO; 222 | GCC_C_LANGUAGE_STANDARD = gnu99; 223 | GCC_DYNAMIC_NO_PIC = NO; 224 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 225 | GCC_OPTIMIZATION_LEVEL = 0; 226 | GCC_PREPROCESSOR_DEFINITIONS = ( 227 | "DEBUG=1", 228 | "$(inherited)", 229 | ); 230 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 231 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 232 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 233 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 234 | GCC_WARN_UNUSED_VARIABLE = YES; 235 | ONLY_ACTIVE_ARCH = YES; 236 | SDKROOT = macosx; 237 | }; 238 | name = Debug; 239 | }; 240 | 287DD8D2156838D2005216D8 /* Release */ = { 241 | isa = XCBuildConfiguration; 242 | buildSettings = { 243 | ALWAYS_SEARCH_USER_PATHS = NO; 244 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 245 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 246 | CLANG_ENABLE_OBJC_ARC = YES; 247 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 248 | COPY_PHASE_STRIP = YES; 249 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 250 | GCC_C_LANGUAGE_STANDARD = gnu99; 251 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 252 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 253 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 254 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 255 | GCC_WARN_UNUSED_VARIABLE = YES; 256 | SDKROOT = macosx; 257 | }; 258 | name = Release; 259 | }; 260 | 287DD8D4156838D2005216D8 /* Debug */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | COMBINE_HIDPI_IMAGES = YES; 264 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 265 | GCC_PREFIX_HEADER = "CIMicroPaint/CIMicroPaint-Prefix.pch"; 266 | INFOPLIST_FILE = "CIMicroPaint/CIMicroPaint-Info.plist"; 267 | PRODUCT_NAME = "$(TARGET_NAME)"; 268 | WRAPPER_EXTENSION = app; 269 | }; 270 | name = Debug; 271 | }; 272 | 287DD8D5156838D2005216D8 /* Release */ = { 273 | isa = XCBuildConfiguration; 274 | buildSettings = { 275 | COMBINE_HIDPI_IMAGES = YES; 276 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 277 | GCC_PREFIX_HEADER = "CIMicroPaint/CIMicroPaint-Prefix.pch"; 278 | INFOPLIST_FILE = "CIMicroPaint/CIMicroPaint-Info.plist"; 279 | PRODUCT_NAME = "$(TARGET_NAME)"; 280 | WRAPPER_EXTENSION = app; 281 | }; 282 | name = Release; 283 | }; 284 | /* End XCBuildConfiguration section */ 285 | 286 | /* Begin XCConfigurationList section */ 287 | 287DD8AF156838D1005216D8 /* Build configuration list for PBXProject "CIMicroPaint" */ = { 288 | isa = XCConfigurationList; 289 | buildConfigurations = ( 290 | 287DD8D1156838D2005216D8 /* Debug */, 291 | 287DD8D2156838D2005216D8 /* Release */, 292 | ); 293 | defaultConfigurationIsVisible = 0; 294 | defaultConfigurationName = Release; 295 | }; 296 | 287DD8D3156838D2005216D8 /* Build configuration list for PBXNativeTarget "FMMicroPaintPlus" */ = { 297 | isa = XCConfigurationList; 298 | buildConfigurations = ( 299 | 287DD8D4156838D2005216D8 /* Debug */, 300 | 287DD8D5156838D2005216D8 /* Release */, 301 | ); 302 | defaultConfigurationIsVisible = 0; 303 | defaultConfigurationName = Release; 304 | }; 305 | /* End XCConfigurationList section */ 306 | }; 307 | rootObject = 287DD8AC156838D1005216D8 /* Project object */; 308 | } 309 | -------------------------------------------------------------------------------- /CIMicroPaint.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CIMicroPaint.xcodeproj/project.xcworkspace/xcshareddata/CIMicroPaint.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | ACC286FB-F9AD-48E0-85E0-372A8E6470CE 9 | IDESourceControlProjectName 10 | CIMicroPaint 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | FF9D2B01-B0BA-48BC-A4F0-179CC21BE929 14 | https://github.com/ccgus/FMMicroPaintPlus 15 | 16 | IDESourceControlProjectPath 17 | CIMicroPaint.xcodeproj/project.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | FF9D2B01-B0BA-48BC-A4F0-179CC21BE929 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/ccgus/FMMicroPaintPlus 25 | IDESourceControlProjectVersion 26 | 110 27 | IDESourceControlProjectWCCIdentifier 28 | FF9D2B01-B0BA-48BC-A4F0-179CC21BE929 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | FF9D2B01-B0BA-48BC-A4F0-179CC21BE929 36 | IDESourceControlWCCName 37 | FMMicroPaintPlus 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /CIMicroPaint.xcodeproj/xcuserdata/gus.xcuserdatad/xcschemes/CIMicroPaint.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /CIMicroPaint.xcodeproj/xcuserdata/gus.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CIMicroPaint.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 287DD8B4156838D1005216D8 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CIMicroPaint/CIMicroPaint-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.flyingmeat.${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 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /CIMicroPaint/CIMicroPaint-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'CIMicroPaint' target in the 'CIMicroPaint' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | 9 | #define debug NSLog 10 | -------------------------------------------------------------------------------- /CIMicroPaint/FMCIView.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface FMCIView : NSOpenGLView { 5 | 6 | NSRect _lastBounds; 7 | CGLContextObj _cglContext; 8 | NSOpenGLPixelFormat *pixelFormat; 9 | CGDirectDisplayID _directDisplayID; 10 | } 11 | 12 | @property (assign) IBOutlet NSTextField *scaleField; 13 | 14 | - (void)setContextOptions:(NSDictionary *)dict; 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /CIMicroPaint/FMCIView.m: -------------------------------------------------------------------------------- 1 | #import "FMCIView.h" 2 | 3 | #import 4 | #import 5 | #import "FMIOSurfaceAccumulator.h" 6 | 7 | @interface FMCIView () 8 | 9 | @property (nonatomic, strong) CIContext *context; 10 | @property (nonatomic, strong) NSDictionary *contextOptions; 11 | @property (nonatomic, strong) FMIOSurfaceAccumulator *imageAccumulator; 12 | @property (nonatomic, strong) FMIOSurfaceAccumulator *hudSurface; 13 | @property (nonatomic, strong) NSColor *color; 14 | @property (nonatomic, strong) CIFilter *brushFilter; 15 | @property (nonatomic, strong) CIFilter *gradientFilter; 16 | @property (nonatomic, strong) CIImage *scaledImage; 17 | @property (assign) CGFloat scale; 18 | @property (assign) CGFloat filterRadius; 19 | @property (assign) NSPoint filterCenter; 20 | @property (assign) NSPoint canvasTranslate; 21 | @property (assign) BOOL movingFilter; 22 | @property (assign) CGColorSpaceRef imageColorSpace; 23 | 24 | - (BOOL)displaysWhenScreenProfileChanges; 25 | - (void)viewWillMoveToWindow:(NSWindow*)newWindow; 26 | - (void)displayProfileChanged:(NSNotification*)notification; 27 | 28 | @end 29 | 30 | @implementation FMCIView 31 | 32 | + (NSOpenGLPixelFormat *)defaultPixelFormat { 33 | static NSOpenGLPixelFormat *pf; 34 | 35 | if (pf == nil) { 36 | /* 37 | Making sure the context's pixel format doesn't have a recovery renderer is important - otherwise CoreImage may not be able to create deeper context's that share textures with this one. 38 | */ 39 | static const NSOpenGLPixelFormatAttribute attr[] = { 40 | NSOpenGLPFAAccelerated, 41 | NSOpenGLPFANoRecovery, 42 | NSOpenGLPFAColorSize, 24, 43 | NSOpenGLPFAAlphaSize, 8, 44 | NSOpenGLPFAMultisample, 45 | NSOpenGLPFASampleBuffers, 1, 46 | NSOpenGLPFASamples, 4, 47 | 0 48 | }; 49 | 50 | pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr]; 51 | } 52 | 53 | return pf; 54 | } 55 | 56 | 57 | - (id)initWithFrame:(NSRect)frame { 58 | self = [super initWithFrame:frame]; 59 | if (self != nil) { 60 | _scale = 1.0; 61 | 62 | _color = [NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 63 | 64 | _brushFilter = [CIFilter filterWithName: @"CIRadialGradient" keysAndValues: 65 | @"inputColor1", [CIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0], 66 | @"inputRadius0", @0.0, nil]; 67 | 68 | _gradientFilter = [CIFilter filterWithName:@"CIRadialGradient"]; 69 | 70 | if ([[NSUserDefaults standardUserDefaults] floatForKey:@"brushSize"] < 1) { 71 | [[NSUserDefaults standardUserDefaults] setFloat:25 forKey:@"brushSize"]; 72 | } 73 | 74 | } 75 | 76 | return self; 77 | } 78 | 79 | 80 | - (void)dealloc { 81 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 82 | 83 | if (_imageColorSpace) { 84 | CGColorSpaceRelease(_imageColorSpace); 85 | } 86 | 87 | } 88 | 89 | - (void)awakeFromNib { 90 | 91 | [[[self enclosingScrollView] contentView] setCopiesOnScroll:NO]; 92 | 93 | [[self window] setPreferredBackingLocation:NSWindowBackingLocationVideoMemory]; 94 | 95 | [[self window] makeFirstResponder:self]; 96 | 97 | CIImage *baseImage = [CIImage imageWithContentsOfURL:[[NSBundle mainBundle] URLForImageResource:@"aoraki-90388.jpg"]]; 98 | 99 | CGColorSpaceRef colorSpace = [baseImage colorSpace]; 100 | if (colorSpace) { 101 | _imageColorSpace = CGColorSpaceRetain(colorSpace); 102 | } 103 | else { 104 | _imageColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 105 | } 106 | 107 | [self setFrame:[baseImage extent]]; 108 | 109 | FMIOSurfaceAccumulator *acc = [FMIOSurfaceAccumulator accumulatorWithSize:[baseImage extent].size 110 | colorSpace:_imageColorSpace]; 111 | 112 | [acc setImage:baseImage dirtyRect:[baseImage extent]]; 113 | 114 | [self setImageAccumulator:acc]; 115 | 116 | [self setNeedsDisplay:YES]; 117 | 118 | [self scrollPoint:NSZeroPoint]; 119 | 120 | [self setFilterRadius:[baseImage extent].size.height/2]; 121 | 122 | [_gradientFilter setValue:@(0) forKey:@"inputRadius0"]; 123 | [_gradientFilter setValue:@([self filterRadius]) forKey:@"inputRadius1"]; 124 | [_gradientFilter setValue:[CIColor colorWithRed:0 green:0 blue:0 alpha:0] forKey:@"inputColor0"]; 125 | [_gradientFilter setValue:[CIColor colorWithRed:0 green:0 blue:0 alpha:1] forKey:@"inputColor1"]; 126 | 127 | _filterCenter = NSMakePoint(NSMidX([baseImage extent]), NSMidY([baseImage extent])); 128 | 129 | [self takeScaleValueFrom:@(.25)]; 130 | 131 | } 132 | 133 | - (void)setContextOptions:(NSDictionary *)dict { 134 | _contextOptions = dict; 135 | [self setContext:nil]; 136 | } 137 | 138 | - (void)prepareOpenGL { 139 | GLint parm = 1; 140 | 141 | /* Enable beam-synced updates. */ 142 | 143 | [[self openGLContext] setValues:&parm forParameter:NSOpenGLCPSwapInterval]; 144 | 145 | /* Make sure that everything we don't need is disabled. Some of these 146 | * are enabled by default and can slow down rendering. */ 147 | 148 | glDisable(GL_ALPHA_TEST); 149 | glDisable(GL_DEPTH_TEST); 150 | glDisable(GL_SCISSOR_TEST); 151 | glDisable(GL_BLEND); 152 | glDisable(GL_DITHER); 153 | glDisable(GL_CULL_FACE); 154 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 155 | glDepthMask(GL_FALSE); 156 | glStencilMask(0); 157 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 158 | glHint(GL_TRANSFORM_HINT_APPLE, GL_FASTEST); 159 | 160 | glEnable(GL_TEXTURE_RECTANGLE_ARB); 161 | 162 | } 163 | 164 | 165 | - (void)updateMatrices { 166 | 167 | NSRect visibleRect = [[[self enclosingScrollView] contentView] documentVisibleRect]; 168 | 169 | if (!NSEqualRects(visibleRect, _lastBounds)) { 170 | 171 | GLsizei w = visibleRect.size.width; 172 | GLsizei h = visibleRect.size.height; 173 | 174 | 175 | [[self openGLContext] update]; 176 | 177 | /* Install an orthographic projection matrix (no perspective) 178 | * with the origin in the bottom left and one unit equal to one 179 | * device pixel. */ 180 | 181 | glViewport(0, 0, w, h); 182 | 183 | glMatrixMode(GL_PROJECTION); 184 | glLoadIdentity(); 185 | glOrtho(0, w, 0, h, -1, 1); 186 | 187 | glMatrixMode(GL_MODELVIEW); 188 | glLoadIdentity(); 189 | 190 | _lastBounds = visibleRect; 191 | } 192 | } 193 | 194 | 195 | - (BOOL)displaysWhenScreenProfileChanges { 196 | return YES; 197 | } 198 | 199 | 200 | - (void)viewWillMoveToWindow:(NSWindow*)newWindow { 201 | 202 | NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 203 | [center removeObserver:self name:NSWindowDidChangeScreenProfileNotification object:nil]; 204 | [center addObserver:self selector:@selector(displayProfileChanged:) name:NSWindowDidChangeScreenProfileNotification object:newWindow]; 205 | [center addObserver:self selector:@selector(displayProfileChanged:) name:NSWindowDidMoveNotification object:newWindow]; 206 | 207 | // When using OpenGL, we should disable the window's "one-shot" feature 208 | [newWindow setOneShot:NO]; 209 | } 210 | 211 | 212 | - (void)displayProfileChanged:(NSNotification*)notification { 213 | CGDirectDisplayID oldDid = _directDisplayID; 214 | _directDisplayID = (CGDirectDisplayID)[[[[[self window] screen] deviceDescription] objectForKey:@"NSScreenNumber"] pointerValue]; 215 | 216 | if (_directDisplayID == oldDid) { 217 | return; 218 | } 219 | 220 | _cglContext = [[self openGLContext] CGLContextObj]; 221 | 222 | if (pixelFormat == nil) { 223 | pixelFormat = [self pixelFormat]; 224 | if (pixelFormat == nil) { 225 | pixelFormat = [[self class] defaultPixelFormat]; 226 | } 227 | } 228 | 229 | CGLLockContext(_cglContext); { 230 | // Create a new CIContext using the new output color space 231 | // Since the cgl context will be rendered to the display, it is valid to rely on CI to get the colorspace from the context. 232 | [self setContext:[CIContext contextWithCGLContext:_cglContext pixelFormat:[pixelFormat CGLPixelFormatObj] colorSpace:_imageColorSpace options:_contextOptions]]; 233 | } 234 | 235 | CGLUnlockContext(_cglContext); 236 | } 237 | 238 | 239 | - (void)drawRect:(NSRect)updateRect { 240 | 241 | [[self openGLContext] makeCurrentContext]; 242 | 243 | if (!_context) { 244 | [self displayProfileChanged:nil]; 245 | } 246 | 247 | NSRect visibleRect = [[[self enclosingScrollView] contentView] documentVisibleRect]; 248 | 249 | [self updateMatrices]; 250 | 251 | // let's do a clip in GL land, which is in window coordinates, not in our image coordinates. 252 | CGRect glClipRect = CGRectInset(CGRectIntegral(updateRect), -1.0f, -1.0f); 253 | glClipRect.origin.x -= visibleRect.origin.x; 254 | glClipRect.origin.y -= visibleRect.origin.y; 255 | glScissor(glClipRect.origin.x, glClipRect.origin.y, glClipRect.size.width, glClipRect.size.height); 256 | glEnable(GL_SCISSOR_TEST); 257 | 258 | { 259 | CIImage *img = [[self imageAccumulator] image]; 260 | 261 | [_gradientFilter setValue:[CIVector vectorWithX:_filterCenter.x Y:_filterCenter.y] forKey:kCIInputCenterKey]; 262 | 263 | static CIFilter *backgroundFilter = nil; 264 | if (!backgroundFilter) { 265 | backgroundFilter = [CIFilter filterWithName:@"CIConstantColorGenerator" keysAndValues:@"inputColor", [CIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0], nil]; 266 | } 267 | 268 | static CIFilter *compFilter = nil; 269 | if (!compFilter) { 270 | compFilter = [CIFilter filterWithName: @"CISourceOverCompositing"]; 271 | } 272 | 273 | 274 | if (!_scaledImage) { 275 | 276 | static CIFilter *gradientCompFilter = nil; 277 | if (!gradientCompFilter) { 278 | gradientCompFilter = [CIFilter filterWithName: @"CISourceOverCompositing"]; 279 | } 280 | 281 | [gradientCompFilter setValue:[_gradientFilter valueForKey:kCIOutputImageKey] forKey:kCIInputImageKey]; 282 | [gradientCompFilter setValue:img forKey:kCIInputBackgroundImageKey]; 283 | 284 | img = [gradientCompFilter valueForKey:kCIOutputImageKey]; 285 | 286 | [self setScaledImage:[img imageByApplyingTransform:CGAffineTransformMakeScale(_scale, _scale)]]; 287 | } 288 | 289 | [compFilter setValue:_scaledImage forKey:kCIInputImageKey]; 290 | [compFilter setValue:[backgroundFilter valueForKey:kCIOutputImageKey] forKey:kCIInputBackgroundImageKey]; 291 | 292 | img = [compFilter valueForKey:kCIOutputImageKey]; 293 | 294 | if ([[NSUserDefaults standardUserDefaults] boolForKey:@"showHUD"]) { 295 | 296 | [self drawHUDRect:glClipRect]; 297 | 298 | CIImage *hud = [_hudSurface image]; 299 | 300 | [compFilter setValue:hud forKey:kCIInputImageKey]; 301 | [compFilter setValue:img forKey:kCIInputBackgroundImageKey]; 302 | img = [compFilter valueForKey:kCIOutputImageKey]; 303 | } 304 | 305 | img = [img imageByApplyingTransform:CGAffineTransformMakeTranslation(-visibleRect.origin.x, -visibleRect.origin.y)]; 306 | 307 | img = [img imageByApplyingTransform:CGAffineTransformMakeTranslation(_canvasTranslate.x, _canvasTranslate.y)]; 308 | 309 | [[self context] drawImage:img inRect:glClipRect fromRect:glClipRect]; 310 | 311 | } 312 | 313 | glDisable(GL_SCISSOR_TEST); 314 | 315 | // [self glStrokeRect:glClipRect]; 316 | 317 | // Flush the OpenGL command stream. If the view is double buffered this should be replaced by [[self openGLContext] flushBuffer]. 318 | glFlush(); 319 | //[[self openGLContext] flushBuffer]; 320 | } 321 | 322 | - (void)glStrokeRect:(NSRect)r { 323 | glColor3f(0.0, 1.0, 0.0); 324 | glBegin(GL_LINE_LOOP); 325 | 326 | glVertex3f(NSMinX(r), NSMinY(r), 0.0f); // The bottom left corner 327 | glVertex3f(NSMinX(r), NSMaxY(r), 0.0f); // The top left corner 328 | glVertex3f(NSMaxX(r), NSMaxY(r), 0.0f); // The top right corner 329 | glVertex3f(NSMaxX(r), NSMinY(r), 0.0f); // The bottom right corner 330 | 331 | glEnd(); 332 | } 333 | 334 | 335 | - (NSPoint)transformCanvasPointToView:(NSPoint)p { 336 | 337 | p.x = p.x * _scale; 338 | p.y = p.y * _scale; 339 | 340 | p.x += _canvasTranslate.x; 341 | p.y += _canvasTranslate.y; 342 | 343 | return p; 344 | } 345 | 346 | - (NSPoint)transformViewPointToCanvas:(NSPoint)p { 347 | 348 | p.x -= _canvasTranslate.x; 349 | p.y -= _canvasTranslate.y; 350 | 351 | p.x = p.x / _scale; 352 | p.y = p.y / _scale; 353 | 354 | return p; 355 | 356 | } 357 | 358 | - (NSRect)transformCanvasRectToView:(NSRect)r { 359 | 360 | r.origin.x = floor(r.origin.x * _scale); 361 | r.origin.y = floor(r.origin.y * _scale); 362 | r.size.width = ceil(r.size.width * _scale); 363 | r.size.height = ceil(r.size.height * _scale); 364 | 365 | r.origin.x += _canvasTranslate.x; 366 | r.origin.y += _canvasTranslate.y; 367 | 368 | return r; 369 | } 370 | 371 | 372 | - (NSRect)transformViewRectToCanvas:(NSRect)r { 373 | 374 | r.origin.x -= _canvasTranslate.x; 375 | r.origin.y -= _canvasTranslate.y; 376 | 377 | r.origin.x = floor(r.origin.x / _scale); 378 | r.origin.y = floor(r.origin.y / _scale); 379 | r.size.width = ceil(r.size.width / _scale); 380 | r.size.height = ceil(r.size.height / _scale); 381 | 382 | return r; 383 | } 384 | 385 | - (void)mouseUp:(NSEvent *)event { 386 | _movingFilter = NO; 387 | [[self window] invalidateCursorRectsForView:self]; 388 | } 389 | 390 | - (void)mouseDown:(NSEvent *)event { 391 | 392 | NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; 393 | NSRect filterCenterBox = [self viewRectForFilterCenter]; 394 | 395 | if (NSPointInRect(loc, filterCenterBox)) { 396 | _movingFilter = YES; 397 | } 398 | 399 | } 400 | 401 | - (void)mouseDragged:(NSEvent *)event { 402 | 403 | NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil]; 404 | 405 | loc = [self transformViewPointToCanvas:loc]; 406 | 407 | 408 | if (_movingFilter) { 409 | _filterCenter = loc; 410 | [self setScaledImage:nil]; 411 | [self setNeedsDisplay:YES]; 412 | return; 413 | } 414 | 415 | if ([NSEvent modifierFlags] & NSEventModifierFlagCommand) { 416 | 417 | NSPoint offset = NSMakePoint([event deltaX], [event deltaY]); 418 | 419 | 420 | NSPoint currentScrollPosition = [[[self enclosingScrollView] contentView] bounds].origin; 421 | 422 | currentScrollPosition.x -= offset.x; 423 | currentScrollPosition.y += offset.y; 424 | 425 | [[[self enclosingScrollView] documentView] scrollPoint:currentScrollPosition]; 426 | 427 | return; 428 | 429 | } 430 | 431 | CGFloat brushSize = [[NSUserDefaults standardUserDefaults] floatForKey:@"brushSize"]; 432 | 433 | CIFilter *brushFilter = [self brushFilter]; 434 | 435 | [brushFilter setValue:@(brushSize) forKey:@"inputRadius1"]; 436 | [brushFilter setValue:@(brushSize - 2) forKey:@"inputRadius0"]; 437 | 438 | CIColor *cicolor = [[CIColor alloc] initWithColor:_color]; 439 | [brushFilter setValue:cicolor forKey:@"inputColor0"]; 440 | 441 | CIVector *inputCenter = [CIVector vectorWithX:loc.x Y:loc.y]; 442 | [brushFilter setValue:inputCenter forKey:@"inputCenter"]; 443 | 444 | CGRect rect = CGRectMake(loc.x-brushSize, loc.y-brushSize, 2.0*brushSize, 2.0*brushSize); 445 | 446 | [[self imageAccumulator] sourceAtopImage:[brushFilter outputImage] dirtyRect:rect]; 447 | 448 | [self setScaledImage:nil]; 449 | 450 | [self setNeedsDisplayInRect:[self transformCanvasRectToView:rect]]; 451 | 452 | [self autoscroll:event]; 453 | 454 | } 455 | 456 | - (IBAction)takeScaleValueFrom:(id)sender { 457 | 458 | CGFloat newScale = [sender floatValue]; 459 | 460 | if (newScale > 20) { 461 | newScale *= 4; 462 | } 463 | else if (newScale > 10) { 464 | newScale *= 3; 465 | } 466 | else if (newScale > 5) { 467 | newScale *= 2; 468 | } 469 | 470 | [self setScale:newScale]; 471 | 472 | [self setScaledImage:nil]; 473 | 474 | [self setNeedsDisplay:YES]; 475 | 476 | NSRect originalFrame = [[self imageAccumulator] extent]; 477 | 478 | NSRect newFrame = NSMakeRect(0, 0, originalFrame.size.width * _scale, originalFrame.size.height * _scale); 479 | 480 | newFrame = NSIntegralRectWithOptions(newFrame, NSAlignAllEdgesOutward); 481 | 482 | [self setFrame:newFrame]; 483 | 484 | [_scaleField setStringValue:[NSString stringWithFormat:@"%ld%%", (NSInteger)(_scale * 100)]]; 485 | 486 | [[self window] invalidateCursorRectsForView:self]; 487 | 488 | } 489 | 490 | - (void)drawHUDRect:(NSRect)dirtyRect { 491 | 492 | NSRect visibleRect = [[[self enclosingScrollView] contentView] documentVisibleRect]; 493 | visibleRect = [self convertRectToBacking:visibleRect]; 494 | 495 | 496 | if (_hudSurface && (!NSEqualSizes(visibleRect.size, [_hudSurface extent].size))) { 497 | debug(@"killing hud"); 498 | _hudSurface = nil; 499 | } 500 | 501 | if (!_hudSurface) { 502 | [self setHudSurface:[FMIOSurfaceAccumulator accumulatorWithSize:visibleRect.size colorSpace:_imageColorSpace]]; 503 | } 504 | else { 505 | [_hudSurface clearRect:dirtyRect]; 506 | } 507 | 508 | [_hudSurface drawOnCGContextWithBlock:^(CGContextRef context) { 509 | 510 | [[NSColor colorWithCalibratedWhite:0.0 alpha:.5] set]; 511 | [[NSBezierPath bezierPathWithOvalInRect:NSInsetRect([self viewRectForFilterCenter], 1, 1)] fill]; 512 | 513 | [[NSColor whiteColor] set]; 514 | 515 | [[NSBezierPath bezierPathWithOvalInRect:[self viewRectForFilterCenter]] stroke]; 516 | [[NSBezierPath bezierPathWithOvalInRect:[self viewRectForFilterOutsideOval]] stroke]; 517 | 518 | }]; 519 | 520 | } 521 | 522 | - (NSRect)viewRectForFilterCenter { 523 | 524 | NSPoint p = [self transformCanvasPointToView:_filterCenter]; 525 | 526 | return NSMakeRect(p.x - 5, p.y - 5, 20, 20); 527 | } 528 | 529 | - (NSRect)viewRectForFilterOutsideOval { 530 | CGFloat h = [self filterRadius]; 531 | return [self transformCanvasRectToView:NSMakeRect(_filterCenter.x - h, _filterCenter.y - h, h * 2, h * 2)]; 532 | } 533 | 534 | - (void)resetCursorRects { 535 | [self addCursorRect:[self viewRectForFilterCenter] cursor:[NSCursor openHandCursor]]; 536 | } 537 | 538 | 539 | @end 540 | -------------------------------------------------------------------------------- /CIMicroPaint/FMIOSurfaceAccumulator.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface FMIOSurfaceAccumulator : NSObject 4 | 5 | + (id)accumulatorWithSize:(NSSize)s colorSpace:(CGColorSpaceRef)colorSpace; 6 | 7 | - (CIImage*)image; 8 | 9 | - (void)setImage:(CIImage *)im dirtyRect:(CGRect)r; 10 | - (void)sourceAtopImage:(CIImage*)im dirtyRect:(CGRect)r; 11 | 12 | - (CGRect)extent; 13 | 14 | - (void)clear; 15 | - (void)clearRect:(CGRect)r; 16 | 17 | 18 | - (void)drawOnCGContextWithBlock:(void (^)(CGContextRef context))b; 19 | 20 | @end 21 | 22 | -------------------------------------------------------------------------------- /CIMicroPaint/FMIOSurfaceAccumulator.m: -------------------------------------------------------------------------------- 1 | 2 | #import "FMIOSurfaceAccumulator.h" 3 | #import 4 | #import 5 | 6 | @interface FMIOSurfaceAccumulator () 7 | 8 | @property (assign) IOSurfaceRef ioSurface; 9 | 10 | @property (strong) CIContext *context; 11 | @property (strong) CIRenderDestination *renderDest; 12 | @property (assign) CGContextRef bitmapContext; 13 | @property (strong) CIImage *lastImage; 14 | @property (assign) CGColorSpaceRef colorSpace; 15 | @property (assign) NSSize size; 16 | 17 | @end 18 | 19 | @implementation FMIOSurfaceAccumulator 20 | 21 | 22 | + (id)accumulatorWithSize:(NSSize)s colorSpace:(CGColorSpaceRef)colorSpace; { 23 | 24 | FMIOSurfaceAccumulator *surf = [FMIOSurfaceAccumulator new]; 25 | 26 | [surf setColorSpace:CGColorSpaceRetain(colorSpace)]; 27 | 28 | [surf createContextOfSize:s]; 29 | 30 | return surf; 31 | } 32 | 33 | - (void)dealloc { 34 | 35 | if (_ioSurface) { 36 | CFRelease(_ioSurface); 37 | } 38 | 39 | if (_colorSpace) { 40 | CGColorSpaceRelease(_colorSpace); 41 | } 42 | } 43 | 44 | - (void)createContextOfSize:(NSSize)s { 45 | 46 | _size = s; 47 | 48 | size_t alignment = 16; 49 | size_t bpr = (((size_t)s.width * 4) + (alignment -1)) & ~(alignment-1); 50 | 51 | NSDictionary * opts = @{(id)kIOSurfaceWidth: @(s.width), 52 | (id)kIOSurfaceHeight: @(s.height), 53 | (id)kIOSurfaceBytesPerElement: @(4), 54 | (id)kIOSurfaceBytesPerRow: @(bpr), 55 | (id)kIOSurfacePixelFormat: @(kCVPixelFormatType_32RGBA) 56 | }; 57 | 58 | assert(!_ioSurface); 59 | _ioSurface = IOSurfaceCreate((__bridge CFDictionaryRef)opts); 60 | 61 | _context = [CIContext contextWithOptions:@{}]; 62 | 63 | _renderDest = [[CIRenderDestination alloc] initWithIOSurface:(__bridge IOSurface * _Nonnull)(_ioSurface)]; 64 | [_renderDest setColorSpace:_colorSpace]; 65 | 66 | 67 | } 68 | 69 | 70 | - (CIImage*)image { 71 | 72 | if (_lastImage) { 73 | return _lastImage; 74 | } 75 | 76 | _lastImage = [CIImage imageWithIOSurface:_ioSurface options:@{(id)kCIImageColorSpace: (__bridge id)_colorSpace}]; 77 | 78 | return _lastImage; 79 | } 80 | 81 | - (void)setImage:(CIImage *)im dirtyRect:(CGRect)r { 82 | 83 | _lastImage = nil; 84 | 85 | r = NSIntegralRect(r); 86 | 87 | NSError *outErr; 88 | CIRenderTask *renderTask = [_context startTaskToRender:[im imageByCroppingToRect:r] toDestination:_renderDest error:&outErr]; 89 | [renderTask waitUntilCompletedAndReturnError:&outErr]; 90 | 91 | 92 | } 93 | 94 | - (void)sourceAtopImage:(CIImage*)im dirtyRect:(CGRect)r { 95 | 96 | _lastImage = nil; 97 | 98 | [_renderDest setBlendKernel:[CIBlendKernel sourceOver]]; 99 | 100 | r = NSIntegralRect(r); 101 | 102 | NSError *outErr; 103 | CIRenderTask *renderTask = [_context startTaskToRender:[im imageByCroppingToRect:r] toDestination:_renderDest error:&outErr]; 104 | [renderTask waitUntilCompletedAndReturnError:&outErr]; 105 | 106 | [_renderDest setBlendKernel:nil]; 107 | 108 | } 109 | 110 | - (CGRect)extent { 111 | return CGRectMake(0, 0, _size.width, _size.height); 112 | } 113 | 114 | - (void)setupBitmapContext { 115 | 116 | if (_bitmapContext) { 117 | return; 118 | } 119 | 120 | uint32_t bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big; 121 | uint32_t bpc = 8; 122 | uint32_t seed; 123 | IOSurfaceLock(_ioSurface, 0, &seed); 124 | 125 | _bitmapContext = CGBitmapContextCreate(IOSurfaceGetBaseAddress(_ioSurface), 126 | IOSurfaceGetWidth(_ioSurface), 127 | IOSurfaceGetHeight(_ioSurface), 128 | bpc, 129 | IOSurfaceGetBytesPerRow(_ioSurface), 130 | _colorSpace, 131 | bitmapInfo); 132 | 133 | IOSurfaceUnlock(_ioSurface, 0, &seed); 134 | } 135 | 136 | - (void)drawOnCGContextWithBlock:(void (^)(CGContextRef context))b { 137 | 138 | [self setupBitmapContext]; 139 | 140 | IOSurfaceLock(_ioSurface, 0, nil); 141 | 142 | CGContextSaveGState(_bitmapContext); 143 | 144 | NSGraphicsContext *currentNSContext = [NSGraphicsContext graphicsContextWithGraphicsPort:_bitmapContext flipped:NO]; 145 | [NSGraphicsContext saveGraphicsState]; 146 | [NSGraphicsContext setCurrentContext:currentNSContext]; 147 | b(_bitmapContext); 148 | [NSGraphicsContext restoreGraphicsState]; 149 | 150 | CGContextRestoreGState(_bitmapContext); 151 | 152 | IOSurfaceUnlock(_ioSurface, 0, nil); 153 | 154 | _lastImage = nil; 155 | } 156 | 157 | 158 | 159 | - (void)clear { 160 | [self clearRect:[self extent]]; 161 | } 162 | 163 | - (void)clearRect:(CGRect)r { 164 | 165 | // There's two ways to do this. 166 | // The first is via CG like so: 167 | // 168 | // IOSurfaceLock(_ioSurface, 0, nil); 169 | // CGContextClearRect(context, r); 170 | // IOSurfaceUnlock(_ioSurface, 0, nil); 171 | // 172 | // Or you can stay in CI Land: 173 | 174 | static CIImage *clearImage = nil; 175 | static dispatch_once_t onceToken; 176 | dispatch_once(&onceToken, ^{ 177 | 178 | CIFilter *transparent = [CIFilter filterWithName:@"CIConstantColorGenerator"]; 179 | 180 | [transparent setValue:[CIColor colorWithRed:0 green:0 blue:0 alpha:0] forKey:kCIInputColorKey]; 181 | 182 | clearImage = [transparent outputImage]; 183 | }); 184 | 185 | [self setImage:clearImage dirtyRect:r]; 186 | } 187 | 188 | @end 189 | 190 | -------------------------------------------------------------------------------- /CIMicroPaint/aoraki-90388.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccgus/FMMicroPaintPlus/5e0f4fef25dbf21e067afac594a6ccad7da4f47b/CIMicroPaint/aoraki-90388.jpg -------------------------------------------------------------------------------- /CIMicroPaint/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccgus/FMMicroPaintPlus/5e0f4fef25dbf21e067afac594a6ccad7da4f47b/CIMicroPaint/en.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /CIMicroPaint/en.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1080 5 | 12F37 6 | 4504 7 | 1187.39 8 | 626.00 9 | 10 | com.apple.InterfaceBuilder.CocoaPlugin 11 | 4504 12 | 13 | 14 | NSButton 15 | NSButtonCell 16 | NSColorWell 17 | NSCustomObject 18 | NSCustomView 19 | NSMenu 20 | NSMenuItem 21 | NSObjectController 22 | NSScrollView 23 | NSScroller 24 | NSSlider 25 | NSSliderCell 26 | NSTextField 27 | NSTextFieldCell 28 | NSUserDefaultsController 29 | NSView 30 | NSWindowTemplate 31 | 32 | 33 | com.apple.InterfaceBuilder.CocoaPlugin 34 | 35 | 36 | PluginDependencyRecalculationVersion 37 | 38 | 39 | 40 | 41 | NSApplication 42 | 43 | 44 | FirstResponder 45 | 46 | 47 | NSApplication 48 | 49 | 50 | AMainMenu 51 | 52 | 53 | 54 | CIMicroPaint 55 | 56 | 1048576 57 | 2147483647 58 | 59 | NSImage 60 | NSMenuCheckmark 61 | 62 | 63 | NSImage 64 | NSMenuMixedState 65 | 66 | submenuAction: 67 | 68 | CIMicroPaint 69 | 70 | 71 | 72 | About CIMicroPaint 73 | 74 | 2147483647 75 | 76 | 77 | 78 | 79 | 80 | YES 81 | YES 82 | 83 | 84 | 1048576 85 | 2147483647 86 | 87 | 88 | 89 | 90 | 91 | Preferences… 92 | , 93 | 1048576 94 | 2147483647 95 | 96 | 97 | 98 | 99 | 100 | YES 101 | YES 102 | 103 | 104 | 1048576 105 | 2147483647 106 | 107 | 108 | 109 | 110 | 111 | Services 112 | 113 | 1048576 114 | 2147483647 115 | 116 | 117 | submenuAction: 118 | 119 | Services 120 | 121 | _NSServicesMenu 122 | 123 | 124 | 125 | 126 | YES 127 | YES 128 | 129 | 130 | 1048576 131 | 2147483647 132 | 133 | 134 | 135 | 136 | 137 | Hide CIMicroPaint 138 | h 139 | 1048576 140 | 2147483647 141 | 142 | 143 | 144 | 145 | 146 | Hide Others 147 | h 148 | 1572864 149 | 2147483647 150 | 151 | 152 | 153 | 154 | 155 | Show All 156 | 157 | 1048576 158 | 2147483647 159 | 160 | 161 | 162 | 163 | 164 | YES 165 | YES 166 | 167 | 168 | 1048576 169 | 2147483647 170 | 171 | 172 | 173 | 174 | 175 | Quit CIMicroPaint 176 | q 177 | 1048576 178 | 2147483647 179 | 180 | 181 | 182 | 183 | _NSAppleMenu 184 | 185 | 186 | 187 | 188 | Window 189 | 190 | 1048576 191 | 2147483647 192 | 193 | 194 | submenuAction: 195 | 196 | Window 197 | 198 | 199 | 200 | Minimize 201 | m 202 | 1048576 203 | 2147483647 204 | 205 | 206 | 207 | 208 | 209 | Zoom 210 | 211 | 1048576 212 | 2147483647 213 | 214 | 215 | 216 | 217 | 218 | YES 219 | YES 220 | 221 | 222 | 1048576 223 | 2147483647 224 | 225 | 226 | 227 | 228 | 229 | Bring All to Front 230 | 231 | 1048576 232 | 2147483647 233 | 234 | 235 | 236 | 237 | _NSWindowsMenu 238 | 239 | 240 | 241 | 242 | Help 243 | 244 | 2147483647 245 | 246 | 247 | submenuAction: 248 | 249 | Help 250 | 251 | 252 | 253 | CIMicroPaint Help 254 | ? 255 | 1048576 256 | 2147483647 257 | 258 | 259 | 260 | 261 | _NSHelpMenu 262 | 263 | 264 | 265 | _NSMainMenu 266 | 267 | 268 | 15 269 | 2 270 | {{97, 379}, {531, 461}} 271 | 1886915584 272 | CIMicroPaint 273 | NSWindow 274 | 275 | View 276 | 277 | 278 | {213, 107} 279 | 280 | 281 | 256 282 | 283 | 284 | 285 | 290 286 | {{134, 52}, {379, 21}} 287 | 288 | 289 | 290 | _NS:9 291 | YES 292 | 293 | -2080112384 294 | 0 295 | 296 | _NS:9 297 | 298 | 30 299 | 0.10000000000000001 300 | 0.5 301 | 0.0 302 | 0 303 | 1 304 | NO 305 | NO 306 | 307 | NO 308 | 309 | 310 | 311 | 292 312 | {{78, 56}, {53, 17}} 313 | 314 | 315 | 316 | _NS:397 317 | {251, 750} 318 | YES 319 | 320 | 68157504 321 | 71304192 322 | Scale 323 | 324 | LucidaGrande 325 | 13 326 | 1044 327 | 328 | _NS:397 329 | 330 | 331 | 6 332 | System 333 | controlColor 334 | 335 | 3 336 | MC42NjY2NjY2NjY3AA 337 | 338 | 339 | 340 | 6 341 | System 342 | controlTextColor 343 | 344 | 3 345 | MAA 346 | 347 | 348 | 349 | NO 350 | 351 | 352 | 353 | 274 354 | 355 | 356 | 357 | 2322 358 | 359 | 360 | 361 | 301 362 | {531, 379} 363 | 364 | 365 | 366 | {120, 120} 367 | FMCIView 368 | NSView 369 | 370 | 371 | {{1, 1}, {531, 379}} 372 | 373 | 374 | 375 | _NS:11 376 | 377 | 378 | 6 379 | 380 | 381 | 382 | 256 383 | {{516, 1}, {16, 379}} 384 | 385 | 386 | 387 | _NS:26 388 | NO 389 | 390 | _doScroller: 391 | 1 392 | 0.96363627910614014 393 | 394 | 395 | 396 | 256 397 | {{1, 364}, {531, 16}} 398 | 399 | 400 | 401 | _NS:30 402 | NO 403 | 1 404 | 405 | _doScroller: 406 | 0.50602412223815918 407 | 408 | 409 | {{-1, 81}, {533, 381}} 410 | 411 | 412 | 413 | _NS:9 414 | 133170 415 | 416 | 417 | 418 | QSAAAEEgAAA/gAAAP4AAAA 419 | 0.25 420 | 4 421 | 1 422 | 423 | 424 | 425 | 289 426 | {{134, 18}, {80, 21}} 427 | 428 | 429 | 430 | {1000, 1000} 431 | YES 432 | 433 | 67108864 434 | 0 435 | 436 | 437 | 438 | 439 | Helvetica-Oblique 440 | 12 441 | 16 442 | 443 | 444 | 50 445 | 1 446 | 25 447 | 0.0 448 | 0 449 | 1 450 | NO 451 | NO 452 | 453 | NO 454 | 455 | 456 | 457 | 289 458 | 459 | 460 | NSColor pasteboard type 461 | 462 | 463 | {{220, 16}, {76, 24}} 464 | 465 | 466 | 467 | {1000, 1000} 468 | YES 469 | NO 470 | YES 471 | 472 | 1 473 | MCAwIDAgMC41AA 474 | 475 | 476 | 477 | 478 | 292 479 | {{95, 20}, {40, 17}} 480 | 481 | 482 | 483 | _NS:397 484 | {251, 750} 485 | YES 486 | 487 | 68157504 488 | 272630784 489 | Brush 490 | 491 | _NS:397 492 | 493 | 494 | 495 | 496 | NO 497 | 498 | 499 | 500 | 292 501 | {{12, 54}, {51, 18}} 502 | 503 | 504 | 505 | _NS:9 506 | YES 507 | 508 | -2080374784 509 | 268435456 510 | HUD 511 | 512 | _NS:9 513 | 514 | 1211912448 515 | 2 516 | 517 | NSImage 518 | NSSwitch 519 | 520 | 521 | NSSwitch 522 | 523 | 524 | 525 | 200 526 | 25 527 | 528 | NO 529 | 530 | 531 | {531, 461} 532 | 533 | 534 | 535 | 536 | {{0, 0}, {2560, 1418}} 537 | {213, 129} 538 | {10000000000000, 10000000000000} 539 | YES 540 | 541 | 542 | 543 | color 544 | brushSize 545 | 546 | YES 547 | 548 | 549 | 550 | YES 551 | 552 | 553 | 554 | 555 | 556 | 557 | terminate: 558 | 559 | 560 | 561 | 449 562 | 563 | 564 | 565 | orderFrontStandardAboutPanel: 566 | 567 | 568 | 569 | 142 570 | 571 | 572 | 573 | performMiniaturize: 574 | 575 | 576 | 577 | 37 578 | 579 | 580 | 581 | arrangeInFront: 582 | 583 | 584 | 585 | 39 586 | 587 | 588 | 589 | performZoom: 590 | 591 | 592 | 593 | 240 594 | 595 | 596 | 597 | hide: 598 | 599 | 600 | 601 | 367 602 | 603 | 604 | 605 | hideOtherApplications: 606 | 607 | 608 | 609 | 368 610 | 611 | 612 | 613 | unhideAllApplications: 614 | 615 | 616 | 617 | 370 618 | 619 | 620 | 621 | showHelp: 622 | 623 | 624 | 625 | 493 626 | 627 | 628 | 629 | content 630 | 631 | 632 | 633 | 547 634 | 635 | 636 | 637 | value: values.brushSize 638 | 639 | 640 | 641 | 642 | 643 | value: values.brushSize 644 | value 645 | values.brushSize 646 | 2 647 | 648 | 649 | 767 650 | 651 | 652 | 653 | value: selection.color 654 | 655 | 656 | 657 | 658 | 659 | value: selection.color 660 | value 661 | selection.color 662 | 2 663 | 664 | 665 | 545 666 | 667 | 668 | 669 | takeScaleValueFrom: 670 | 671 | 672 | 673 | 734 674 | 675 | 676 | 677 | scaleField 678 | 679 | 680 | 681 | 765 682 | 683 | 684 | 685 | value: values.showHUD 686 | 687 | 688 | 689 | 690 | 691 | value: values.showHUD 692 | value 693 | values.showHUD 694 | 2 695 | 696 | 697 | 764 698 | 699 | 700 | 701 | 702 | 703 | 0 704 | 705 | 706 | 707 | 708 | 709 | -2 710 | 711 | 712 | File's Owner 713 | 714 | 715 | -1 716 | 717 | 718 | First Responder 719 | 720 | 721 | -3 722 | 723 | 724 | Application 725 | 726 | 727 | 29 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 19 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 56 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 57 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 58 772 | 773 | 774 | 775 | 776 | 134 777 | 778 | 779 | 780 | 781 | 150 782 | 783 | 784 | 785 | 786 | 136 787 | 788 | 789 | 790 | 791 | 144 792 | 793 | 794 | 795 | 796 | 129 797 | 798 | 799 | 800 | 801 | 143 802 | 803 | 804 | 805 | 806 | 236 807 | 808 | 809 | 810 | 811 | 131 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 149 820 | 821 | 822 | 823 | 824 | 145 825 | 826 | 827 | 828 | 829 | 130 830 | 831 | 832 | 833 | 834 | 24 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 92 846 | 847 | 848 | 849 | 850 | 5 851 | 852 | 853 | 854 | 855 | 239 856 | 857 | 858 | 859 | 860 | 23 861 | 862 | 863 | 864 | 865 | 490 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 491 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 492 882 | 883 | 884 | 885 | 886 | 536 887 | 888 | 889 | 890 | 891 | 892 | Window 893 | 894 | 895 | 537 896 | 897 | 898 | 899 | 900 | 538 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 730 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 731 923 | 924 | 925 | 926 | 927 | 732 928 | 929 | 930 | 931 | 932 | 933 | 934 | 935 | 733 936 | 937 | 938 | 939 | 940 | 754 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 756 951 | 952 | 953 | 954 | 955 | 757 956 | 957 | 958 | 959 | 960 | 542 961 | 962 | 963 | 964 | 965 | 540 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 543 974 | 975 | 976 | 977 | 978 | 541 979 | 980 | 981 | 982 | 983 | 758 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 759 992 | 993 | 994 | 995 | 996 | 760 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 761 1005 | 1006 | 1007 | 1008 | 1009 | 762 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | com.apple.InterfaceBuilder.CocoaPlugin 1017 | com.apple.InterfaceBuilder.CocoaPlugin 1018 | com.apple.InterfaceBuilder.CocoaPlugin 1019 | com.apple.InterfaceBuilder.CocoaPlugin 1020 | com.apple.InterfaceBuilder.CocoaPlugin 1021 | com.apple.InterfaceBuilder.CocoaPlugin 1022 | com.apple.InterfaceBuilder.CocoaPlugin 1023 | com.apple.InterfaceBuilder.CocoaPlugin 1024 | com.apple.InterfaceBuilder.CocoaPlugin 1025 | com.apple.InterfaceBuilder.CocoaPlugin 1026 | com.apple.InterfaceBuilder.CocoaPlugin 1027 | com.apple.InterfaceBuilder.CocoaPlugin 1028 | com.apple.InterfaceBuilder.CocoaPlugin 1029 | com.apple.InterfaceBuilder.CocoaPlugin 1030 | com.apple.InterfaceBuilder.CocoaPlugin 1031 | com.apple.InterfaceBuilder.CocoaPlugin 1032 | com.apple.InterfaceBuilder.CocoaPlugin 1033 | com.apple.InterfaceBuilder.CocoaPlugin 1034 | com.apple.InterfaceBuilder.CocoaPlugin 1035 | com.apple.InterfaceBuilder.CocoaPlugin 1036 | com.apple.InterfaceBuilder.CocoaPlugin 1037 | com.apple.InterfaceBuilder.CocoaPlugin 1038 | com.apple.InterfaceBuilder.CocoaPlugin 1039 | com.apple.InterfaceBuilder.CocoaPlugin 1040 | 1041 | com.apple.InterfaceBuilder.CocoaPlugin 1042 | com.apple.InterfaceBuilder.CocoaPlugin 1043 | 1044 | com.apple.InterfaceBuilder.CocoaPlugin 1045 | com.apple.InterfaceBuilder.CocoaPlugin 1046 | com.apple.InterfaceBuilder.CocoaPlugin 1047 | com.apple.InterfaceBuilder.CocoaPlugin 1048 | com.apple.InterfaceBuilder.CocoaPlugin 1049 | com.apple.InterfaceBuilder.CocoaPlugin 1050 | com.apple.InterfaceBuilder.CocoaPlugin 1051 | com.apple.InterfaceBuilder.CocoaPlugin 1052 | com.apple.InterfaceBuilder.CocoaPlugin 1053 | com.apple.InterfaceBuilder.CocoaPlugin 1054 | com.apple.InterfaceBuilder.CocoaPlugin 1055 | com.apple.InterfaceBuilder.CocoaPlugin 1056 | com.apple.InterfaceBuilder.CocoaPlugin 1057 | com.apple.InterfaceBuilder.CocoaPlugin 1058 | com.apple.InterfaceBuilder.CocoaPlugin 1059 | com.apple.InterfaceBuilder.CocoaPlugin 1060 | com.apple.InterfaceBuilder.CocoaPlugin 1061 | com.apple.InterfaceBuilder.CocoaPlugin 1062 | com.apple.InterfaceBuilder.CocoaPlugin 1063 | com.apple.InterfaceBuilder.CocoaPlugin 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 767 1070 | 1071 | 1072 | 1073 | 1074 | FMCIView 1075 | NSOpenGLView 1076 | 1077 | takeScaleValueFrom: 1078 | id 1079 | 1080 | 1081 | takeScaleValueFrom: 1082 | 1083 | takeScaleValueFrom: 1084 | id 1085 | 1086 | 1087 | 1088 | scaleField 1089 | NSTextField 1090 | 1091 | 1092 | scaleField 1093 | 1094 | scaleField 1095 | NSTextField 1096 | 1097 | 1098 | 1099 | IBProjectSource 1100 | ./Classes/FMCIView.h 1101 | 1102 | 1103 | 1104 | 1105 | 0 1106 | IBCocoaFramework 1107 | YES 1108 | 1109 | com.apple.InterfaceBuilder.CocoaPlugin.macosx 1110 | 1111 | 1112 | 1113 | com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 1114 | 1115 | 1116 | YES 1117 | 3 1118 | 1119 | {11, 11} 1120 | {10, 3} 1121 | {15, 15} 1122 | 1123 | 1124 | 1125 | -------------------------------------------------------------------------------- /CIMicroPaint/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: main.m 3 | Abstract: Standard main file. 4 | Version: 1.1 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2012 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import 49 | 50 | int main(int argc, char *argv[]) 51 | { 52 | return NSApplicationMain(argc, (const char **) argv); 53 | } 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FMMicroPaintPlus 2 | ================ 3 | 4 | A hacked up version of Apple's CIMicroPaint sample code adding a custom image accumulator, extra filter on the canvas, magnification, scrollbars, and a HUD. 5 | 6 | =========================================================================== 7 | 8 | KNOWN ISSUES: 9 | 10 | The CG HUD doesn't properly scroll with the canvas. 11 | 12 | =========================================================================== 13 | 14 | TODO: 15 | 16 | Move this to Metal some day. 17 | 18 | =========================================================================== 19 | 20 | BUILD REQUIREMENTS: 21 | 22 | Xcode 9 or later, MacOS v10.13 or later 23 | 24 | =========================================================================== 25 | 26 | Portions Copyright (C) 2009-2012 Apple Inc. All rights reserved. 27 | --------------------------------------------------------------------------------