1from Cocoa import * 2from Quartz import * 3 4from SampleCIView import SampleCIView 5 6import objc 7 8class CIMicroPaintView (SampleCIView): 9 imageAccumulator = objc.ivar() 10 brushFilter = objc.ivar() 11 compositeFilter = objc.ivar() 12 color = objc.ivar() 13 brushSize = objc.ivar(objc._C_FLT) 14 15 16 def initWithFrame_(self, frame): 17 self = super(CIMicroPaintView, self).initWithFrame_(frame) 18 if self is None: 19 return None 20 21 self.brushSize = 25.0 22 self.color = NSColor.colorWithDeviceRed_green_blue_alpha_( 23 0.0, 0.0, 0.0, 1.0) 24 25 self.brushFilter = CIFilter.filterWithName_("CIRadialGradient") 26 self.brushFilter.setDefaults() 27 for k, v in ( 28 ("inputColor1", CIColor.colorWithRed_green_blue_alpha_( 29 0.0, 0.0, 0.0, 0.0)), 30 ("inputRadius0", 0.0), 31 ): 32 33 self.brushFilter.setValue_forKey_(v, k) 34 35 self.compositeFilter = CIFilter.filterWithName_("CISourceOverCompositing") 36 self.compositeFilter.setDefaults() 37 38 return self 39 40 def viewBoundsDidChange_(self, bounds): 41 if self.imageAccumulator is not None and \ 42 bounds == self.imageAccumulator.extent(): 43 print "Nothing changed" 44 return 45 46 # Create a new accumulator and composite the old one over the it. 47 48 c = CIImageAccumulator.alloc( 49 ).initWithExtent_format_(bounds, kCIFormatRGBA16) 50 f = CIFilter.filterWithName_("CIConstantColorGenerator") 51 f.setDefaults() 52 f.setValue_forKey_( 53 CIColor.colorWithRed_green_blue_alpha_(1.0, 1.0, 1.0, 1.0), 54 "inputColor") 55 56 if self.imageAccumulator is not None: 57 f = CIFilter.filterWithName_("CISourceOverCompositing") 58 f.setDefaults() 59 f.setValue_forKey_(self.imageAccumulator.image(), "inputImage") 60 f.setValue_forKey_(c.image(), "inputBackgroundImage") 61 c.setImage_(f.valueForKey_("outputImage")) 62 63 self.imageAccumulator = c 64 self.setImage_(self.imageAccumulator.image()) 65 66 def mouseDragged_(self, event): 67 loc = self.convertPoint_fromView_(event.locationInWindow(), None) 68 69 rect = CGRectMake(loc.x-self.brushSize, loc.y-self.brushSize, 70 2.0*self.brushSize, 2.0*self.brushSize) 71 self.brushFilter.setValue_forKey_(self.brushSize, "inputRadius1") 72 73 cicolor = CIColor.alloc().initWithColor_(self.color) 74 self.brushFilter.setValue_forKey_(cicolor, "inputColor0") 75 76 self.brushFilter.setValue_forKey_( 77 CIVector.vectorWithX_Y_(loc.x, loc.y), 78 "inputCenter") 79 80 self.compositeFilter.setValue_forKey_( 81 self.brushFilter.valueForKey_("outputImage"), "inputImage") 82 self.compositeFilter.setValue_forKey_( 83 self.imageAccumulator.image(), "inputBackgroundImage") 84 85 self.imageAccumulator.setImage_dirtyRect_( 86 self.compositeFilter.valueForKey_("outputImage"), rect) 87 88 self.setImage_dirtyRect_(self.imageAccumulator.image(), rect) 89 90 def mouseDown_(self, event): 91 self.mouseDragged_(event) 92