Recent

Author Topic: Circle with antialising for RadioButton component  (Read 2316 times)

vercetti

  • Newbie
  • Posts: 4
Circle with antialising for RadioButton component
« on: September 21, 2023, 01:08:22 pm »
Hi guys. I'm trying to make my own crossplatform Radio Button component. It inherited from TCustomControl.

I have a problem with painting circle. Using Canvas.Ellipse(Rect) i've got ugly circle.

Adding "Canvas.AntialiasingMode := amOn;" doesn't change anything.

Is there an any way to make antialised circle without using third parties libraries ?

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1719
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Circle with antialising for RadioButton component
« Reply #1 on: September 21, 2023, 01:46:42 pm »
Your code is very confusing, I get a lot of errors with your provided code, so I show mine.
Code: Pascal  [Select][+][-]
  1. procedure DrawAntiAliasedCircleOnPanel(const AImage: TImage);
  2. var
  3.   Bitmap: TBitmap;
  4.   Radius, CenterX, CenterY: Double;
  5. begin
  6.   Bitmap := TBitmap.Create;
  7.   try
  8.     Bitmap.Width := AImage.ClientWidth;
  9.     Bitmap.Height := AImage.ClientHeight;
  10.  
  11.     SetStretchBltMode(Bitmap.Canvas.Handle, HALFTONE);
  12.     SetBrushOrgEx(Bitmap.Canvas.Handle, 0, 0, nil);
  13.  
  14.     Bitmap.Canvas.Pen.Width := 1;
  15.     Bitmap.Canvas.Pen.Style := psSolid;
  16.     Bitmap.Canvas.Pen.Color := clWhite;
  17.  
  18.     Bitmap.Canvas.Brush.Style := bsSolid;
  19.     Bitmap.Canvas.Brush.Color := clBlack;
  20.  
  21.     Radius := Min(Bitmap.Width, Bitmap.Height) / 2;
  22.  
  23.     CenterX := Bitmap.Width / 2;
  24.     CenterY := Bitmap.Height / 2;
  25.  
  26.     Bitmap.Canvas.Ellipse(Round(CenterX - Radius), Round(CenterY - Radius), Round(CenterX + Radius), Round(CenterY + Radius));
  27.     AImage.Picture.Assign(Bitmap);
  28.   finally
  29.     Bitmap.Free;
  30.   end;
  31. end;
« Last Edit: Tomorrow at 31:76:97 by KodeZwerg »

vercetti

  • Newbie
  • Posts: 4
Re: Circle with antialising for RadioButton component
« Reply #2 on: September 21, 2023, 02:45:42 pm »
Thanks, but result is almost the same. It looks like a Bresenham's algorithm, there are no smooth color transitions here.
It looks great when the circle is big, but not for small (filled)circle for RadioButton.
In theory this can be drawn using the Xiaolin Wu's algorithm. But maybe there are other solutions.

Code: Pascal  [Select][+][-]
  1. SetBrushOrgEx(Bitmap.Canvas.Handle, 0, 0, nil);
Does WinGdi work on Linux ? Or i confusing something ?

I need something like this.


paweld

  • Hero Member
  • *****
  • Posts: 844
Re: Circle with antialising for RadioButton component
« Reply #3 on: September 21, 2023, 03:08:34 pm »
use BGRABitmap. It is multiplatform.
You can download from: https://github.com/bgrabitmap/bgrabitmap or install from OPM
Code: Pascal  [Select][+][-]
  1. uses
  2.   BGRABitmap, BGRABitmapTypes;
  3.  
  4. procedure TForm1.Button1Click(Sender: TObject);
  5. var
  6.   bmp: TBGRABitmap;
  7. begin
  8.   bmp := TBGRABitmap.Create(40, 40, clBlack);
  9.   bmp.EllipseAntialias(19, 19, 7, 7, clWhite, 1);
  10.   bmp.EllipseAntialias(19, 19, 4, 4, clSkyBlue, 0, clSkyBlue);
  11.   bmp.Draw(Canvas, 0, 0);
  12.   bmp.Free;
  13. end;    
  14.  
Best regards / Pozdrawiam
paweld

lainz

  • Hero Member
  • *****
  • Posts: 4276
    • https://lainz.github.io/
Re: Circle with antialising for RadioButton component
« Reply #4 on: September 22, 2023, 01:57:57 am »
Try BGRAControls. We have high dpi / retina SVG radio button.

wp

  • Hero Member
  • *****
  • Posts: 11454
Re: Circle with antialising for RadioButton component
« Reply #5 on: September 22, 2023, 02:03:59 am »
"Poor man's" anti-aliasing: Draw the image at double size and then stretch-draw it back to original size.

Here is a version using a LazIntfImage und the FPBaseInterpolation which results in nicer results than the standard TCanvas.StretchDraw. No extra libraries required, everything needed comes with FPC/Lazarus:

Code: Pascal  [Select][+][-]
  1. uses
  2.   LclIntf, FPImage, FPCanvas, IntfGraphics, LazCanvas;
  3.  
  4. function CreateRadioButtonBitmap(ASize: Integer; Checked: Boolean): TBitmap;
  5. var
  6.   img1, img2: TLazIntfImage;
  7.   canvas1, canvas2: TLazCanvas;
  8.   R: TRect;
  9.   i, n: Integer;
  10. begin
  11.   Result := TBitmap.Create;
  12.   Result.PixelFormat := pf32Bit;
  13.   Result.SetSize(ASize, ASize);
  14.  
  15.   img1 := Result.CreateIntfImage;
  16.   try
  17.     img1.Width := 2*ASize;
  18.     img1.Height := 2*ASize;
  19.     canvas1 := TLazCanvas.Create(img1);
  20.     try
  21.       canvas1.Clear;
  22.       R := Rect(0, 0, img1.Width-1, img1.Height-1);
  23.       canvas1.Pen.Width := 1;
  24.       canvas1.Pen.FPColor := colGray;
  25.       canvas1.Brush.Style := bsClear;
  26.       canvas1.Brush.FPColor := colWhite;
  27.       n := ASize div 8;
  28.       for i:= 1 to n do
  29.       begin
  30.         if i = n then
  31.           canvas1.Brush.Style := bsSolid;
  32.         canvas1.Ellipse(R);
  33.         InflateRect(R, -1, -1);
  34.       end;
  35.       if Checked then
  36.       begin
  37.         InflateRect(R, -ASize div 4, -ASize div 4);  
  38.         canvas1.Brush.Style := bsSolid;
  39.         canvas1.Brush.FPColor := colBlue;
  40.         canvas1.Ellipse(R);
  41.       end;
  42.     finally
  43.       canvas1.Free;
  44.     end;
  45.  
  46.     img2 := Result.CreateIntfImage;
  47.     try
  48.       canvas2 := TLazCanvas.Create(img2);
  49.       try
  50.         canvas2.Interpolation := TFPBaseInterpolation.Create;
  51.         try
  52.           canvas2.StretchDraw(0, 0, ASize, ASize, img1);
  53.           Result.LoadFromIntfImage(img2);
  54.         finally
  55.           canvas2.Interpolation.Free;
  56.         end;
  57.       finally
  58.         canvas2.Free;
  59.       end;
  60.     finally
  61.       img2.Free;
  62.     end;
  63.   finally
  64.     img1.Free;
  65.   end;
  66. end;        
  67.  
  68. procedure TForm1.FormCreate(Sender: TObject);
  69. begin
  70.   RadioBtnChecked_Bmp := CreateRadioButtonBitmap(16, true);
  71.   RadioBtnUnchecked_Bmp := CreateRadioButtonBitmap(16, false);
  72. end;
  73.  
  74. procedure TForm1.FormDestroy(Sender: TObject);
  75. begin
  76.   RadioBtnChecked_Bmp.Free;
  77.   RadioBtnUnchecked_Bmp.Free;
  78. end;
  79.  
  80. procedure TForm1.FormPaint(Sender: TObject);
  81. begin
  82.   Canvas.Draw(10, 10, RadioBtnChecked_bmp);
  83.   Canvas.Draw(10, 50, RadioBtnUnchecked_bmp);
  84. end;  
« Last Edit: September 22, 2023, 02:11:45 am by wp »

440bx

  • Hero Member
  • *****
  • Posts: 3623
Re: Circle with antialising for RadioButton component
« Reply #6 on: September 22, 2023, 09:54:23 am »
@wp,

First, the following is totally off topic

A number of years ago you attached a little program that used SetWindowRgn to create a window in the shape of a Bugs Bunny image. 

I know I downloaded it but, I've lost it in a sea of other source code and I've tried to locate the post you attached it to,  to no avail.

I am hereby asking that if you can locate the post with that attachment, I would be very grateful if you would post its address so I can download it again.

Thank you in advance.
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 SP1 64bit.

balazsszekely

  • Guest
Re: Circle with antialising for RadioButton component
« Reply #7 on: September 22, 2023, 10:11:53 am »
@440bx
Quote
A number of years ago you attached a little program that used SetWindowRgn to create a window in the shape of a Bugs Bunny image. 
It was me who posted the program with the bunny.  :) Today I made it cross platform, you can find the attachment in the following post: https://forum.lazarus.freepascal.org/index.php/topic,64677.msg492064.html#msg492064

PS: I will try to locate the original post.

« Last Edit: September 22, 2023, 10:14:18 am by GetMem »

TRon

  • Hero Member
  • *****
  • Posts: 1849
Re: Circle with antialising for RadioButton component
« Reply #8 on: September 22, 2023, 10:19:09 am »
PS: I will try to locate the original post.
Here seems to be something hopping around ? Not sure if that was the one you two had in mind though.

balazsszekely

  • Guest
Re: Circle with antialising for RadioButton component
« Reply #9 on: September 22, 2023, 10:30:58 am »
PS: I will try to locate the original post.
Here seems to be something hopping around ? Not sure if that was the one you two had in mind though.
Yes. Thank you @TRon! That's the original one with alphablendig . In the meantime I found the other one, with CreateRectRgn/SetWindowRgn: https://forum.lazarus.freepascal.org/index.php/topic,44577.msg313713.html#msg313713 , but is windows only(PS: apparently it no longer works with the current version of laz/fpc) . The cross platform version is here: https://forum.lazarus.freepascal.org/index.php/topic,64677.msg492064.html#msg492064
« Last Edit: September 22, 2023, 10:41:46 am by GetMem »

440bx

  • Hero Member
  • *****
  • Posts: 3623
Re: Circle with antialising for RadioButton component
« Reply #10 on: September 22, 2023, 10:46:47 am »
@440bx
Quote
A number of years ago you attached a little program that used SetWindowRgn to create a window in the shape of a Bugs Bunny image. 
It was me who posted the program with the bunny.  :) Today I made it cross platform, you can find the attachment in the following post: https://forum.lazarus.freepascal.org/index.php/topic,64677.msg492064.html#msg492064

PS: I will try to locate the original post.
Thank you GetMem, my apologies for the mistaken credit.  Looks like what they say is true, memory does not get better with age ... chuckle.

Thank you for the updated/cross-platform version. 

It would be wonderful if you could locate the original post but... no rush... take your time... I don't want to impose and, thank you again.

ETA:

I think I found the old one, the one you mentioned in your reply to TRon
« Last Edit: September 22, 2023, 11:03:03 am by 440bx »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 SP1 64bit.

Fibonacci

  • Full Member
  • ***
  • Posts: 219
  • #PDK
Re: Circle with antialising for RadioButton component
« Reply #11 on: September 22, 2023, 11:47:28 am »
PS: apparently it no longer works with the current version of laz/fpc

It compiled and works.

Multiplatform version on the left.
Windows version on the right, much better.

Old example windows-only with button looks like multiplatform version, not great. Versions multiplatform + old windows cut window shape by color, newer windows version uses transparency of the PNG, looks better.

Maybe its little offtopic, but thanks, maybe I will use it for splash window for some of my projects :D

cdbc

  • Hero Member
  • *****
  • Posts: 715
    • http://www.cdbc.dk
Re: Circle with antialising for RadioButton component
« Reply #12 on: September 22, 2023, 12:18:05 pm »
Hi
Cool it works on Linux Qt5 too, but takes short of 3 minutes to show form...
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6

balazsszekely

  • Guest
Re: Circle with antialising for RadioButton component
« Reply #13 on: September 22, 2023, 01:03:24 pm »
@Fibonacci
Yes I agree. If you are on windows, the version with transparency looks much better. The cross platform version with regions also can be improoved.

@cdbc
On my linux mint machine with qt5 the application loads in 1-2 seconds. I don" t know why is so slow at your side. Did you try to debug it? Alternatively run the application outside the IDE.

PS: We should move the discussion to another thread. This one is about circles and anti aliasing. :)

cdbc

  • Hero Member
  • *****
  • Posts: 715
    • http://www.cdbc.dk
Re: Circle with antialising for RadioButton component
« Reply #14 on: September 22, 2023, 01:56:46 pm »
Hi
I just "LazBuild" it and clicked in "Dolphin", waited... thought [Nah, doesn't work] and forgot about it, and suddenly there it was, like a troll from a box  :D
Building it pulls in practically all of GTK... Maybe that's why.
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6

 

TinyPortal © 2005-2018