[bug] Premature GC of Brush

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[bug] Premature GC of Brush

Bill Dargel
Blair,

For some time I've seen an intermittent problem in the rendering of the
backcolor of StaticText. I just happened to run across a situation where
it was repeatable enough to get to what appears to be the cause. I've
supplied a hack that clears it up. I leave it to you to provide a more
palatable solution.

First, where it was showing up. Sometimes the background of a StaticText
would be rendered gray instead of the given backcolor. Obviously, it
only shows up on windows where the background is other than default. It
wouldn't happen too often, but occasionally a single label on a window
would be mis-rendered. After occluding part of it with another window,
it would show the correct backcolor when uncovered. I also found that by
waiving another window around over the colored window, that sometimes it
would, with fair regularity, leave temporary little gray rectangles
behind on the StaticText backgrounds.

I happened to run into a window with data such that the pattern of
button enables made the timing just right for the problem to show up
consistently on one particular StaticText when making a specific
selection in a list.

The problem appears to be similar to that where a Bitmap could be
finalized prematurely when used in a Brush passed to windows. You
responded to that 30 September 2002 in
http://www.google.com/groups?threadm=an95fe%24c0d0h%241%40ID-50941.news.dfncis.de
BTW, there you mentioned it would be "an enhancement in the next
release". Did that fall through cracks? Or did you mean 6.0 (rather than
5.1 or one of the patches)?

Today's problem seems to be due to a Brush being GC'd and finalized
before windows has a chance to use it. My hack was to put the brush into
a global variable (which keeps getting reused). That keeps it around
long enough to eliminate the rendering problem.

regards,
-Bill

-------------------------------
!ControlView methodsFor!

onColorRequired: aColorEvent
        "Colour event handler for aColorEvent. We set up the canvas provided by
the event
        with the appropriate foreground and background colours for the
receiver. Windows
        WM_CTLCOLORXXX messages require that we answer the background brush
handle"

        | canvas |
        (self backcolor isNil and: [self forecolor isNil]) ifTrue: [^nil].
        canvas := aColorEvent canvas.
        self forecolor notNil ifTrue: [canvas setTextColor: self forecolor].
        self backcolor notNil
                ifTrue:
                        [| bc |
                        bc := self backcolor.
                        canvas backcolor: bc.
                        canvas
                                brush:
(HackToKeepControlViewBackcolorBrushFromBeingGCedBeforeItIsUsedByWindows
:= bc
                                                                brush)].
        ^canvas brush asParameter! !
!ControlView categoriesFor: #onColorRequired:!event handling!public! !


-------------------------------------------
Bill Dargel            [hidden email]
Shoshana Technologies
100 West Joy Road, Ann Arbor, MI 48105  USA


Reply | Threaded
Open this post in threaded view
|

Re: [bug] Premature GC of Brush

Blair McGlashan
"Bill Dargel" <[hidden email]> wrote in message
news:[hidden email]...

> Blair,
>
> For some time I've seen an intermittent problem in the rendering of the
> backcolor of StaticText. I just happened to run across a situation where
> it was repeatable enough to get to what appears to be the cause. I've
> supplied a hack that clears it up. I leave it to you to provide a more
> palatable solution.
>
> First, where it was showing up. Sometimes the background of a StaticText
> would be rendered gray instead of the given backcolor. ... snip...
> The problem appears to be similar to that where a Bitmap could be
> finalized prematurely when used in a Brush passed to windows. You
> responded to that 30 September 2002 in
>
http://www.google.com/groups?threadm=an95fe%24c0d0h%241%40ID-50941.news.dfncis.de
> BTW, there you mentioned it would be "an enhancement in the next
> release". Did that fall through cracks? Or did you mean 6.0 (rather than
> 5.1 or one of the patches)?

It was recorded as defect #1052, and my triage comment indicates that I
concluded it should be deferred until the next major release (i.e. 6.0).
However more recently I looked at it again and found a simpler solution to
the problem for inclusion in 5.1.5. I've attached the patch below.

>
> Today's problem seems to be due to a Brush being GC'd and finalized
> before windows has a chance to use it. My hack was to put the brush into
> a global variable (which keeps getting reused). That keeps it around
> long enough to eliminate the rendering problem.

Yes, I would agree with your analysis. The only "proper" solution I can
think of right now is to add an instance variable to ControlView to hold the
background brush, if any. I would hope this can be sorted out for 5.1.5.

Thanks for the report,

Blair

------------------------
!LOGBRUSH class methodsFor!

defineFields
 "Define the fields of the LOGBRUSH structure.
  LOGBRUSH compileDefinition

  typedef
  struct tagLOGBRUSH {
   int lbStyle;
   long lbColor;
   long lbHatch;
  } LOGBRUSH;
"

 self
  defineField: #lbStyle type: SDWORDField new offset: 0;
  defineField: #lbColor type: SDWORDField new offset: 4;
  defineField: #lbHatch type: SDWORDField new offset: 8.
 self byteSize: 12!

stbConvertFrom: anSTBClassFormat
 "Version 1 adds hatch instance variables to hold Bitmap preventing it being
GC'd (#1052)."

 ^
 [:data |
 | newInstance |
  newInstance := self basicNew.
  1 to: data size do: [:i | newInstance instVarAt: i put: (data at: i)].
  newInstance]!

stbVersion
 ^1! !
!LOGBRUSH class categoriesFor: #defineFields!**auto
generated**!initializing!public! !
!LOGBRUSH class categoriesFor: #stbConvertFrom:!binary filing!public! !
!LOGBRUSH class categoriesFor: #stbVersion!binary filing!public! !


!LOGBRUSH methodsFor!

hatch
 "Answer the hatch object. This is either a bitmap, or one of a set of
standard integer constants."

 ^hatch
  ifNil:
   [self lbStyle = BS_PATTERN ifTrue: [hatch := Bitmap fromHandle: self
lbHatch] ifFalse: [self lbHatch]]!

hatch: aBitmapOrInteger
 hatch := aBitmapOrInteger.
 self lbHatch: aBitmapOrInteger asParameter!

lbColor
 "Answer the receiver's lbColor field as a Smalltalk object."

 ^(bytes sdwordAtOffset: 4)!

lbColor: anObject
 "Set the receiver's lbColor field to the value of anObject."

 bytes sdwordAtOffset: 4 put: anObject!

lbHatch
 "Answer the receiver's lbHatch field as a Smalltalk object."

 ^(bytes sdwordAtOffset: 8)!

lbHatch: anObject
 "Set the receiver's lbHatch field to the value of anObject."

 bytes sdwordAtOffset: 8 put: anObject!

lbStyle
 "Answer the receiver's lbStyle field as a Smalltalk object."

 ^(bytes sdwordAtOffset: 0)!

lbStyle: anObject
 "Set the receiver's lbStyle field to the value of anObject."

 bytes sdwordAtOffset: 0 put: anObject!

style
 ^self lbStyle!

style: anObject
 self lbStyle: anObject! !
!LOGBRUSH categoriesFor: #hatch!accessing!public! !
!LOGBRUSH categoriesFor: #hatch:!accessing!public! !
!LOGBRUSH categoriesFor: #lbColor!**compiled accessors**!public! !
!LOGBRUSH categoriesFor: #lbColor:!**compiled accessors**!public! !
!LOGBRUSH categoriesFor: #lbHatch!**compiled accessors**!public! !
!LOGBRUSH categoriesFor: #lbHatch:!**compiled accessors**!public! !
!LOGBRUSH categoriesFor: #lbStyle!**compiled accessors**!public! !
!LOGBRUSH categoriesFor: #lbStyle:!**compiled accessors**!public! !
!LOGBRUSH categoriesFor: #style!accessing!public! !
!LOGBRUSH categoriesFor: #style:!accessing!public! !

!Brush class methodsFor!

bitmap: aBitmap
 "Answer a new instance of the receiver for paiting the specified <Bitmap>
pattern."

 ^self
  withStyle: BS_PATTERN
  color: 0
  hatch: aBitmap!

color: aColour
 "Answer a new instance of the receiver for painting in the specified solid
colour."

 ^self
  withStyle: BS_SOLID
  color: aColour
  hatch: 0!

hatchedDiagonal
 "Answer a new instance of the receiver for painting diagonal hatching."

 ^self
  withStyle: BS_HATCHED
  color: 0
  hatch: HS_BDIAGONAL!

withStyle: styleFlags color: aColour hatch: hatchObject
 "Answer a new instance of the receiver with the specified style, colour and
hatching attributes."

 ^self fromLogBrush: ((LOGBRUSH new)
    style: styleFlags;
    color: aColour;
    hatch: hatchObject;
    yourself)! !
!Brush class categoriesFor: #bitmap:!instance creation!public! !
!Brush class categoriesFor: #color:!instance creation!public! !
!Brush class categoriesFor: #hatchedDiagonal!instance creation!public! !
!Brush class categoriesFor: #withStyle:color:hatch:!instance
creation!public! !