Andy/Blair or anyone else,
I've uncovered some issues with finalization and freeing of graphic
objects when creating a Brush from a Bitmap. I've finally gotten a
workaround, but wonder if something shouldn't be changed in the base
system.
I have an application class that draws various patterns. It had a
method:
patternBrush
^Brush bitmap: self patternBitmap
where patternBitmap creates a Bitmap with:
Bitmap displayCompatibleWithExtent: anExtent
and fills it in using #pixelAt:put:.
This seemed to work okay at first, but when using a number of patterns,
there were occasionally times when the #fillRectangle:brush: call didn't
paint anything. I could get it repeatable, but it was very dependent on
what other tests were run at the same time. I got all the expected
patterns to display by changing it to:
^Brush bitmap: self patternBitmap detachHandle
But, as I found out later, this creates a memory leak of GDI objects,
since the Bitmap never gets freed.
I think the original problem is that the Smalltalk Bitmap object has no
reference once the Brush is created. The Bitmap will get GCed, and then
when it's finalized the GDI bitmap gets freed. This was sometimes
apparently happening before the Brush got used.
The workaround I made was to create a BitmapBrush subclass of Brush with
an instance variable for 'bitmap'. I overrode the Brush class>>bitmap:
method to set the instance variable after doing "super bitmap:". The
Bitmap won't be GCed as long as the BitmapBrush sticks around. When the
brush goes, the Bitmap goes and all the GDI objects get freed. No more
leaks! :-)
An alternative, of course, would be to just cache the Bitmaps in my
application class. I might do that in any case, but it seems like the
Brush class>>bitmap: method should take the reference problem into
account.
Regards,
-Bill
-------------------------------------------
Bill Dargel
[hidden email]
Shoshana Technologies
100 West Joy Road, Ann Arbor, MI 48105 USA