frobozz@well.sf.ca.us (Jordan Bortz) (04/11/90)
I've been working on an animation package for the Tigre system, and have run into a lack of code as it were; before I write these routines, I was wondering: Does anyone have a routine that copies a Form into an OpaqueForm, but makes the inner white bits WHITE instead of transparent? (ala COPY MASK in resedit) Of course, that could easily be written with one of two routines, so: What about a routine to list all the bits enclosed by the larges single-closed-curve in a rectangle, or: A Better shape:fil routine that works faster and chews up less memory... Thanks, Jordan --- See you at MacWorld! :=)
phil@abccam.abcl.co.uk (Phillip Yelland) (04/12/90)
From: frobozz@well.sf.ca.us (Jordan Bortz) > A Better shape:fil (sic.) routine.... Well, here's something that might be of interest: `Fraid I put it together late one night after a party (what, pose?--me, pose?), so I can't attest to its quality---you should be able to improve it significantly.... --Phil P.S. The valueAt: hack is fairly specific to the monochrome, 32-bit Smalltalk that we use. ---Cut--- !Form methodsFor: 'image manipulation'! fillFrom: seed rule: rule mask: mask "Fill a bounded region encompassing seed with the rule and mask given" "Try: Form exampleSketch. Display fillFrom: Sensor waitClickButton rule: Form over mask: Form gray" | copy stack x y rightX lastTop lastBottom top bottom fillBitBlt blackBitBlt | copy _ self deepCopy. "To track filled regions" stack _ OrderedCollection new: 100. "For seeds" stack addLast: seed. fillBitBlt _ BitBlt destForm: self sourceForm: nil halftoneForm: mask combinationRule: rule destOrigin: 0@0 sourceOrigin: 0@0 extent: 0@0 clipRect: self boundingBox. blackBitBlt _ BitBlt destForm: copy sourceForm: nil halftoneForm: Form black combinationRule: Form over destOrigin: 0@0 sourceOrigin: 0@0 extent: 0@0 clipRect: self boundingBox. [stack isEmpty] whileFalse: [ "While lines still to be filled" x _ stack last x. y _ stack last y. stack removeLast. "Find the right-hand end of the scan-line" [x < self width and: [(copy valueAt: x@y) = 0]] whileTrue: [ x _ x+1]. rightX _ x. "Save the right-hand end" x _ x-1. "Go left; seed rightmost pixels of scan-lines above and below" lastTop _ lastBottom _ 1. [x >= 0 and: [(copy valueAt: x@y) = 0]] whileTrue: [ top _ y < 0 ifTrue: [1] ifFalse: [self valueAt: x@(y-1)]. bottom _ y > self height ifTrue: [1] ifFalse: [ self valueAt: x@(y+1)]. "Check for unfilled scan-lines top and bottom" (lastTop = 1 and: [top = 0]) ifTrue: [ stack addLast: x@(y-1)]. (lastBottom = 1 and: [bottom = 0]) ifTrue: [ stack addLast: x@(y+1)]. lastBottom _ bottom. lastTop _ top. x _ x-1]. "Fill this scan-line" x _ x+1. fillBitBlt destRect: (x@y corner: rightX@(y+1)); copyBits. blackBitBlt destRect: (x@y corner: rightX@(y+1)); copyBits]! ! !Form methodsFor: 'pattern'! valueAt: aPoint "Query whether a bit is on or off.... answer with 1 if the color at coordinate aPoint is black in the receiver and 0 if the color is white at coordinate aPoint" ^((bits at: aPoint y*(width + 31 // 32 * 2)+(aPoint x//16+1)) bitShift: 0-(aPoint x\\16)) bitAnd: 1! !