[Lazarus] Transparent (key color based) drawing questions

Max Vlasov max.vlasov at gmail.com
Fri Jul 15 09:54:53 CEST 2011


2011/7/14 Flávio Etrusco <flavio.etrusco at gmail.com>:
> On Thu, Jul 14, 2011 at 7:37 AM, Max Vlasov <max.vlasov at gmail.com> wrote:
>> 1. At least on linux gtk the order of assignments should be reverse
>>
>> On the site
>>  bmp.Transparent := True;
>>  bmp.TransparentColor := clFuchsia;
>>
>> But the correct order is
>>  bmp.TransparentColor := clFuchsia;
>>  bmp.Transparent := True;
>>
>
> What's the exact code? Can you debug and check TGraphic.Changed is
> being called after TransparentColor is invoked in the first example?
> Looking at the TRasterImage code, SetTransparent always invoke
> Changed, but SetTransparentColor has a more complex handling.
> Anyway I agree it's worth changing the wiki; the mask generation is
> delayed until it's needed, so the order won't make a difference in the
> example, but depending on what's done in OnChange it can easily
> trigger the mask generation twice.
>


I tried to look deeper,

for general usage the order is really doesn't matter
So

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  fBmp.Transparent:=true;
  fBmp.TransparentColor:=clBlack;
  PaintBox1.Canvas.Draw(0, 0, fBmp);
end;

works.
But in my case during the internal actions the handle of the bitmap
was required before the first drawing, so changing the sequence to
...
  fBmp.Handle;
  fBmp.Transparent:=true;
  fBmp.TransparentColor:=clBlack;
  PaintBox1.Canvas.Draw(0, 0, fBmp);
...
triggers the problem. The next calls work because Transparent:=
returns the mask and TransparentColor:= does nothing since the color
is the same.

I looked and walked at the sources, the fragment from
TRasterImage.SetTransparentColor is

  if MaskHandleAllocated
  then MaskHandle := 0
  else Changed(Self);

then part is called (because the mask was allocated before as the
result of handle requesting) and because of this 'then' part
MaskHandle:= 0 changes fMasked property to false. So the drawing is
now non-transparent. The quick patch is to change it to

  if MaskHandleAllocated then
  begin
     svMasked:=Masked;
     MaskHandle := 0;
     Masked:=svMasked;
  end
  else Changed(Self);

But the property itself (Masked) currently is already hard to track
since it's depends on several states:
- can be changed directly with Transparent:=
- indirectly changed by MaskHandle:=

So I don't know whether it's better to do such quick hack or maybe
rethink the internal logic a littel.

Max




More information about the Lazarus mailing list