Recent

Author Topic: [SOLVED] Puzzling TBGRAlabelFX Autosizing Bug and Form Resizing Bug  (Read 3705 times)

evoshroom

  • Full Member
  • ***
  • Posts: 157
There is a bug with TBGRAlabelFX.  It took a while to track down and I'm still not sure exactly what causes it.

My initial setup was I had two forms, call them Form2 and Form3.  They have basically the same dialog and info on them, just arranged slightly differently.  Form2 has a button on it that hides Form2 and Form3 and updates a bunch of TBGRAlabelFX's with numbers.  If you click this button on Form2 everything works as expected.

Form3 has a button on it that does the same thing as Form2.  In fact this button simply calls the same code on the button of Form2.  Form3 and Form2 are hidden and it attempts to update the labels.  However, when this is attempted with Form3, instead an error is generated:

Error Project ProjectName raised exception class 'External: EXC_BAD_ACCESS'. At address 20858.

SYSTEM_TOBJECT_$__INHERITSFROM$TCLASS$$BOOLEAN
00020850 85d2                     test   %edx,%edx
00020852 7416                     je     0x2086a <SYSTEM_TOBJECT_$__INHERITSFROM$TCLASS$$BOOLEAN+26>
00020854 eb05                     jmp    0x2085b <SYSTEM_TOBJECT_$__INHERITSFROM$TCLASS$$BOOLEAN+11>
00020856 6690                     xchg   %ax,%ax
00020858 8b4008                   mov    0x8(%eax),%eax
0002085B 85c0                     test   %eax,%eax
0002085D 7404                     je     0x20863 <SYSTEM_TOBJECT_$__INHERITSFROM$TCLASS$$BOOLEAN+19>
0002085F 39d0                     cmp    %edx,%eax
00020861 75f5                     jne    0x20858 <SYSTEM_TOBJECT_$__INHERITSFROM$TCLASS$$BOOLEAN+8>
00020863 39d0                     cmp    %edx,%eax
00020865 0f94c0                   sete   %al
00020868 eb02                     jmp    0x2086c <SYSTEM_TOBJECT_$__INHERITSFROM$TCLASS$$BOOLEAN+28>
0002086A b000                     mov    $0x0,%al
0002086C c3                       ret   
0002086D 0f1f00                   nopl   (%eax)

Through a lot of testing I discovered this error is caused by the autosizing of BGRALabelFX.  The caption starts at '0' and is on Form1.  If you manually set the caption to '5' in the code, everything works fine.  If you set the caption to a two-digit number in the code, like '60,' so it has to resize, the error is generated.  Finally, if you put BGRALabelFX.DisableAutoSizing in the code, it also works fine.

If BGRALabelFX is your code circular, you might want to look the autosizing code over.  If you find a fix, let me know.  I'd love to use autosizing again.
« Last Edit: August 05, 2012, 01:48:45 am by evoshroom »

evoshroom

  • Full Member
  • ***
  • Posts: 157
Re: Puzzling TBGRAlabelFX Autosizing Bug and Form Resizing Bug
« Reply #1 on: August 04, 2012, 02:10:51 am »
This bug just got even worse.  So, I don't get how or why, but even after the workaround above the BGRALabelFX somehow destroys FormResize events entirely.  An error isn't even generated and this one applies to both Form2 and Form3. 

Essentially, the next day I noticed a bug where FormResize for Form1 (which I have code in) wasn't being called, but only after some code was executed.  It worked fine when the program opened.

I traced the code and it again led back to the exact same BGRALabelFX.Caption code.  For some reason setting a BGRALabelFX.Caption stops the program from using FormResize in Form1.  I don't even get how that could be, but that is what happens.

The form resizes fine on opening.  If the BGRALabelFX lines are commented out it still works fine.  If they aren't instead of calling FormResize on resizing the form, nothing is called.

Again, this is all on 1.0RC1-2 on OS X.  I can check if it affects Windows too.

circular

  • Hero Member
  • *****
  • Posts: 3082
    • Personal webpage
Re: Puzzling TBGRAlabelFX Autosizing Bug and Form Resizing Bug
« Reply #2 on: August 04, 2012, 05:52:40 pm »
If I remember well, lainz found a problem with BGRALabelFX resizing.

Oh think I know how to fix it.

Try with this code for BGRALabelFX. I don't know if it will prevent the bug you encounter, but at least, it will update correctly.
Code: [Select]
unit BGRALabelFX;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Controls, Graphics,
  BGRABitmap, BGRABitmapTypes, BGRATextFXTypes, BGRATextFX, types;

type

  { TBGRALabelFX }

  TBGRALabelFX = class(TGraphicControl)
  private
    FBGRA:    TBGRABitmap;
    FTextEffect: TBGRATextEffect;
    FOutline: TBGRATextEffectOutline;
    FShadow:  TBGRATextEffectShadow;
    FPreviousCaption: string;
    FPreviousFont: TFont;
  protected
    procedure Paint; override;
    procedure RealSetText(const Value: TCaption); override;
    procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer;
      WithThemeSpace: boolean); override;
    procedure UpdateTextEffect;
  public
    function Draw: TBGRABitmap;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Action;
    property Align;
    property AutoSize;
    property Caption;
    property Font;
    property PopupMenu;
    property Outline: TBGRATextEffectOutline Read FOutline Write FOutline;
    property Shadow: TBGRATextEffectShadow Read FShadow Write FShadow;
    property OnClick;
    property OnDblClick;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnMouseEnter;
    property OnMouseLeave;
  end;

procedure Register;

implementation

uses
  LResources;

procedure Register;
begin
  {$I bgralabelfx_icon.lrs}
  RegisterComponents('BGRA Controls', [TBGRALabelFX]);
end;

{ TBGRALabelFX }

procedure TBGRALabelFX.RealSetText(const Value: TCaption);
begin
  inherited RealSetText(Value);

  if Value <> FPreviousCaption then Invalidate;
  InvalidatePreferredSize;
  AdjustSize;
end;

procedure TBGRALabelFX.CalculatePreferredSize(var PreferredWidth,
  PreferredHeight: integer; WithThemeSpace: boolean);
var
  s: TSize;
  ax, ay: integer;
begin
  UpdateTextEffect;
  s.cx := FTextEffect.Width;
  s.cy := FTextEffect.Height;

  if FShadow.Visible then
  begin
    if FShadow.OffsetX < 0 then
      ax := (FShadow.OffsetX) - (FShadow.OffsetX * 2)
    else
      ax := FShadow.OffsetX;

    if FShadow.OffsetY < 0 then
      ay := (FShadow.OffsetY) - (FShadow.OffsetY * 2)
    else
      ay := FShadow.OffsetY;

    Inc(s.cx, 2 * ax + 2 * FShadow.Radius);
    Inc(s.cy, 2 * ay + 2 * FShadow.Radius);
  end;

  PreferredWidth := s.cx;
  PreferredHeight := s.cy;
end;

procedure TBGRALabelFX.UpdateTextEffect;
var NewCaption: string;
begin
  if FTextEffect = nil then exit;
  NewCaption := Caption;
  if (NewCaption <> FPreviousCaption) or
    (Font.Name <> FPreviousFont.Name) or
    (Font.Style <> FPreviousFont.Style) or
    (Font.Quality <> FPreviousFont.Quality) or
    (Font.Orientation <> FPreviousFont.Orientation) or
    (Font.Pitch <> FPreviousFont.Pitch) or
    (Font.Height <> FPreviousFont.Height) or
    (Font.CharSet <> FPreviousFont.CharSet) then
  begin
    FreeAndNil(FTextEffect);
    FTextEffect := TBGRATextEffect.Create(NewCaption, Font, True);
    FPreviousFont.Assign(Font);
    FPreviousCaption := NewCaption;
  end;
end;

procedure TBGRALabelFX.Paint;
var
  cx, cy, px, py: integer;
  ax, ay: integer;
  shx, shy: integer;
begin
  ax := 0;
  ay := 0;

  if FShadow.Visible then
  begin
    if FShadow.OffsetX < 0 then
      ax := (FShadow.OffsetX) - (FShadow.OffsetX * 2)
    else
      ax := FShadow.OffsetX;

    if FShadow.OffsetY < 0 then
      ay := (FShadow.OffsetY) - (FShadow.OffsetY * 2)
    else
      ay := FShadow.OffsetY;

    ax := 2 * ax + 2 * FShadow.Radius;
    ay := 2 * ay + 2 * FShadow.Radius;
  end;

  UpdateTextEffect;

  InvalidatePreferredSize;
  AdjustSize;

  FBGRA.Free;
  FBGRA := TBGRABitmap.Create(FTextEffect.Width + ax,
    FTextEffect.Height + ay);

  { taCenter }
  cx := trunc((FBGRA.Width - FTextEffect.Width) / 2);
  cy := trunc((FBGRA.Height - FTextEffect.Height) / 2);
  px := trunc((Width - FBGRA.Width) / 2);
  py := trunc((Height - FBGRA.Height) / 2);

  if FShadow.OffsetX < 0 then
    shx := - FShadow.OffsetX + FShadow.Radius
  else
    shx := 2 * FShadow.OffsetX + integer(FSHadow.Radius);

  if FShadow.OffsetY < 0 then
    shy := - FShadow.OffsetY + FShadow.Radius
  else
    shy := 2 * FShadow.OffsetY + integer(FShadow.Radius);

  if FShadow.Visible then
    FTextEffect.DrawShadow(FBGRA, shx,
      shy,
      FShadow.Radius, ColorToBGRA(FShadow.Color, FShadow.Alpha));

  if FOutline.Visible then
    FTextEffect.DrawOutline(FBGRA, cx + FOutline.OffsetX, cy + FOutline.OffsetY,
      ColorToBGRA(FOutline.Color, FOutline.Alpha));

  FTextEffect.Draw(FBGRA, cx, cy, ColorToBGRA(Font.Color, 255));

  FBGRA.Draw(Self.Canvas, px, py, False);
end;

function TBGRALabelFX.Draw: TBGRABitmap;
begin
  Result := FBGRA.Duplicate as TBGRABitmap;
end;

constructor TBGRALabelFX.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  SetInitialBounds(0, 0, 24, 24);
  Font.Height := 24;
  FBGRA := TBGRABitmap.Create;
  FTextEffect := TBGRATextEffect.Create(Caption, Font, True);
  FPreviousCaption:= Caption;
  FPreviousFont := TFont.Create;
  FPreviousFont.Assign(Font);
  FOutline := TBGRATextEffectOutline.Create(Self);
  FShadow := TBGRATextEffectShadow.Create(Self);
  //
  AutoSize := True;
  FShadow.OffsetX := 0;
  FShadow.OffsetY := 0;
  FShadow.Radius := 5;
end;

destructor TBGRALabelFX.Destroy;
begin
  FBGRA.Free;
  FTextEffect.Free;
  FPreviousFont.Free;
  FOutline.Free;
  FShadow.Free;
  inherited Destroy;
end;

end.
Conscience is the debugger of the mind

evoshroom

  • Full Member
  • ***
  • Posts: 157
Re: Puzzling TBGRAlabelFX Autosizing Bug and Form Resizing Bug
« Reply #3 on: August 04, 2012, 08:24:32 pm »
I tried it on Windows 7 and Lazarus .9.30.4 later that some night and it also affected those. 

Luckily, your new unit here doubly did the trick.  Resizing appears to be working and autosizing also appears to be working.

Thanks again circular!
« Last Edit: August 04, 2012, 08:31:36 pm by evoshroom »