Recent

Author Topic: Is Lazarus' Tool Palette DPI-aware?  (Read 1435 times)

Ed78z

  • Jr. Member
  • **
  • Posts: 82
Is Lazarus' Tool Palette DPI-aware?
« on: December 11, 2025, 10:37:03 am »
I prepared an icon set for my custom component to be visible smoothly in tool palette in any DPIs
I'm not sure my setup is wrong or it's Lazarus' issue?

Code: Pascal  [Select][+][-]
  1. .......
  2. procedure Register;
  3.  
  4. implementation
  5.  
  6. {$R tmycomponent.res}
  7. procedure Register;
  8. begin
  9.   RegisterComponents('TQ Controls', [TMyComponent]);
  10. end;
  11. .........

Ed78z

  • Jr. Member
  • **
  • Posts: 82
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #1 on: December 16, 2025, 07:50:39 am »
I found the answer! I'm sharing this here to save someone else's time in the future!

Based on a note by Ondrej Pokorny:
The Lazarus only supports these three even other scales provided in the res file:
tmycomponent.png (24×24) - 100%
tmycomponent_150.png (36×36) - 150%
tmycomponent_200.png (48×48) - 200%


I prepared a res file with 13 icon sizes as
tmycomponent.png   (base/default)
tmycomponent_125.png
tmycomponent_150.png
tmycomponent_175.png
tmycomponent_200.png
tmycomponent_225.png
tmycomponent_250.png
tmycomponent_275.png
tmycomponent_300.png
tmycomponent_325.png
tmycomponent_350.png
tmycomponent_375.png
tmycomponent_400.png

But all those other files (_125, _175, _225, _275, _300, _325, _350, _375, _400) are never looked at by Lazarus.
Lazarus has hardcoded to only check for _150 and _200 postfixes.

wp

  • Hero Member
  • *****
  • Posts: 13336
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #2 on: December 16, 2025, 11:30:33 am »
Looking at the Lazarus binary in a resource viewer I would guess that the IDE contains more than 1000 icons. Adding the additional icons that you propose would blow up the size of the binary tremendously...

Only the 100%, 150% and 200% sizes are registered. Intermediate images can be interpolated from these sizes. This works quite well für downscaling, but I don't know what images at >=300% look like.

AFAIK, however, there is no handler for the OnGetWidthForPPI event of the IDE imagelists, therefore, the IDE only uses the registered sizes. Maybe this should be changed.

domasz

  • Hero Member
  • *****
  • Posts: 615
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #3 on: December 16, 2025, 11:56:17 am »
well für downscaling
Oh, you are German. Didn't know. From the East?

wp

  • Hero Member
  • *****
  • Posts: 13336
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #4 on: December 16, 2025, 01:28:38 pm »
West.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12031
  • Debugger - SynEdit - and more
    • wiki
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #5 on: December 16, 2025, 02:01:17 pm »
but I don't know what images at >=300% look like.

Well, there is an issue. Normally they should look good, at least up to a certain size...

But, currently, even just scaling the image to double size (which should look really great), does not work well: https://gitlab.com/freepascal.org/fpc/source/-/issues/33978

wp

  • Hero Member
  • *****
  • Posts: 13336
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #6 on: December 16, 2025, 02:50:34 pm »
Not sure, but I though that LCLScaling utilizes the widgetset. But as for FPImage scaling, many of the FPInterpolations are buggy, among them the MitchelInterpolation used by FPCanvas.StretchDraw by default. If you replace it by a TFPBoxInterpolation your test image in the bug report scales correctly (it will look fine for line-drawings only, for "normal" images I think TFPBaseInterpolation looks best - see attachment:
Code: Pascal  [Select][+][-]
  1. ...
  2.   ScFI2 := TFPCompactImgRGBA8Bit.Create(90, 90);
  3.   ScCanvas := TFPImageCanvas.create(ScFI2);
  4.   ScIntp := TFPBoxInterpolation.Create;
  5.   ScCanvas.Interpolation := ScIntp;
  6.   ScCanvas.StretchDraw(0,0, 90, 90, scFI);
  7.   ScIntp.Free;  
  8. ...

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12031
  • Debugger - SynEdit - and more
    • wiki
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #7 on: December 16, 2025, 03:05:11 pm »
Not sure, but I though that LCLScaling utilizes the widgetset.
Not sure.

I had the issue with SynEdit (since it can be zoomed, and get higher scale factors than the rest of the IDE).
And afaik it uses the same multi-resolution image list as the rest of the IDE. (IIRC SynEdit include now some higher res images)

Though yes, defending on factors such as multi monitor dpi the IDE may not scale at all. But then it doesn't even use the 150 image... With system wide dpi setting the IDE should be doing the scaling, IIRC.

Ed78z

  • Jr. Member
  • **
  • Posts: 82
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #8 on: December 16, 2025, 09:34:17 pm »
@WP:
....The IDE contains more than 1000 icons. Adding the additional icons that you propose would blow up the size of the binary tremendously...

- No, I don't think so, a PNG icon size is ~1kB

@WP:
Intermediate images can be interpolated from these sizes.

- Unfortunately there is no interpolation! just 100%, 150% and 200%..... so, for the scale of 125%, Lazarus will use the base icon (100%)... for 175%, Lazarus will ignore the right icon and will use 150%...for any scale above 200%, Lazarus will use 200% only


Ed78z

  • Jr. Member
  • **
  • Posts: 82
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #9 on: December 16, 2025, 09:52:44 pm »
I developed a small utility code to create the res file... it may save your time a little bit....

wp

  • Hero Member
  • *****
  • Posts: 13336
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #10 on: December 16, 2025, 11:44:21 pm »
- No, I don't think so, a PNG icon size is ~1kB
I added all the sizes that you mentioned in your first post to the resource-builder utlity that you posted here and created a res file: with these 13 images it is larger by 36 kB than the original version with 3 images. Having 1000+ images in Lazarus this means a size increase of the binary by about 30-40 MB. The size of an original Lazarus.exe, however, already is about this size, too - so: size increase by about 100%. Yes, I would call this a "tremendous increase" for a feature which most users will not need.

@WP:
Intermediate images can be interpolated from these sizes.

- Unfortunately there is no interpolation! just 100%, 150% and 200%..... so, for the scale of 125%, Lazarus will use the base icon (100%)... for 175%, Lazarus will ignore the right icon and will use 150%...for any scale above 200%, Lazarus will use 200% only
I don't know why Ondrej did not provide such a wide-reaching handler for the OnGetWidthForPPI event, but please try it yourself: Open the file IDEImagesIntf.pas from folder "components/ideintf" of the Lazarus installation, find the implementation of procedure FImages_24_GetWidthForPPI and replace the code as follows:
Code: Pascal  [Select][+][-]
  1. procedure TIDEImages.FImages_24_GetWidthForPPI(Sender: TCustomImageList;
  2.   AImageWidth, APPI: Integer; var AResultWidth: Integer);
  3. begin
  4.   AResultWidth := AImageWidth * APPI div 96;
  5. end;
Then find the implementations of the functions TIDEImages.GetImages_12, .GetImages_16 and .GetImage_24 and assign the FImages_24_GetWidthForPPI to their OnGetWidthForPPI event. This tells these imagelists how they should interpolate to not registered sizes.
Code: Pascal  [Select][+][-]
  1. function TIDEImages.GetImages_12: TLCLGlyphs;
  2. begin
  3.   if FImages_12 = nil then
  4.   begin
  5.     FImages_12 := TLCLGlyphs.Create(nil);
  6.     FImages_12.Width := 12;
  7.     FImages_12.Height := FImages_12.Width;
  8.     FImages_12.RegisterResolutions([12, 16, 24]);
  9.     FImages_12.OnGetWidthForPPI := @FImages_24_GetWidthForPPI;
  10.   end;
  11.   Result := FImages_12;
  12. end;
  13.  
  14. function TIDEImages.GetImages_16: TLCLGlyphs;
  15. begin
  16.   if FImages_16 = nil then
  17.   begin
  18.     FImages_16 := TLCLGlyphs.Create(nil);
  19.     FImages_16.Width := 16;
  20.     FImages_16.Height := FImages_16.Width;
  21.     FImages_16.RegisterResolutions([16, 24, 32]);
  22.     FImages_16.OnGetWidthForPPI := @FImages_24_GetWidthForPPI;
  23.   end;
  24.   Result := FImages_16;
  25. end;
  26.  
  27. function TIDEImages.GetImages_24: TLCLGlyphs;
  28. begin
  29.   if FImages_24 = nil then
  30.   begin
  31.     FImages_24 := TLCLGlyphs.Create(nil);
  32.     FImages_24.Width := 24;
  33.     FImages_24.Height := FImages_24.Width;
  34.     FImages_24.RegisterResolutions([24, 36, 48]);
  35.     FImages_24.OnGetWidthForPPI := @FImages_24_GetWidthForPPI;
  36.   end;
  37.   Result := FImages_24;
  38. end;
The attached screenshots of the relevant IDE parts at 96 (100%), 120ppi (125%), 144ppi (150%), 168ppi (175%), and 192ppi (200%) demonstrates that now both toolbar icons (default size 16x16) and palette icons(default size 24x24) are scaled (12x12 icons are not shown on these screenshots). If you look carefully, however, you'll notice that the 125% and 175% images are not as crisp as the 100%, 150% and 200% icons. Maybe this is the reason why this feature is not activated by default? We should think about adding a configuration setting for it. What do you think, Martin?

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12031
  • Debugger - SynEdit - and more
    • wiki
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #11 on: December 17, 2025, 12:35:43 am »
The attached screenshots of the relevant IDE parts at 96 (100%), 120ppi (125%), 144ppi (150%), 168ppi (175%), and 192ppi (200%) demonstrates that now both toolbar icons (default size 16x16) and palette icons(default size 24x24) are scaled (12x12 icons are not shown on these screenshots). If you look carefully, however, you'll notice that the 125% and 175% images are not as crisp as the 100%, 150% and 200% icons. Maybe this is the reason why this feature is not activated by default? We should think about adding a configuration setting for it. What do you think, Martin?

Probably. We even do have the svg images (at least for many, maybe most of the icons). But most of the icons have been retouched, at least for the lower sizes. Because svg does not render perfect for all sizes either.

Scaling depends a lot on the algorithm. E.g. irfan view gives really good result. So if we can use the same algorithm....

Scaling would/should still have a list of predefined sizes. There is no point to scale for 16 to 18 (or 24 to 26, not even 28) => in that case really better to use the ever so slightly smaller image.
So that would mean for 16/24/32 images we could add scaling to  20 (well, I am not sure if that should be included, or 16 be used), then 28, 36, 44, ... And no idea if up or down sizing will be better.

I would definitely not add the image in more default sizes. If need we can include a script for people who want to build the IDE with them. However in that case the resources need to be searched for those sizes, or have a list of known sizes....


Ally

  • Jr. Member
  • **
  • Posts: 81
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #12 on: December 17, 2025, 09:22:06 am »
Hello Martin,

I completely agree with you.
Specifically, the idea of using an improved scaling algorithm would largely eliminate the problem.

Ed78z

  • Jr. Member
  • **
  • Posts: 82
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #13 on: December 17, 2025, 07:01:29 pm »
@WP, thank you for your detailed explanation.

I'm suggesting removing the limitation in Lazarus regarding hardcoded icon sizes (_150 & _200). There should be no limitation on the custom component's icon size. If a custom component provides different icon sizes for different DPIs, Lazarus should select and display the appropriate icon size provided by the custom component.

For Lazarus' own (internal) icons, it can use an optimum scaling algorithm, so there's no need to add thousands of internal icons in Lazarus.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12031
  • Debugger - SynEdit - and more
    • wiki
Re: Is Lazarus' Tool Palette DPI-aware?
« Reply #14 on: December 17, 2025, 07:33:26 pm »
I'm suggesting removing the limitation in Lazarus regarding hardcoded icon sizes (_150 & _200). There should be no limitation on the custom component's icon size. If a custom component provides different icon sizes for different DPIs, Lazarus should select and display the appropriate icon size provided by the custom component.

The "fixed size" in that case afaik is so the resources can be found. IIRC the image names are found by searching the component name + the suffix (or some rule like that).  I don't know what ways there are to find all available sizes, other than iterating all possible suffixes. If that is indeed currently the only way, then the above would require a way for such components to register their available sizes, and make them known. At least I don't think that iterating and trial and errors searching is a way to go.
And this isn't just about finding the exact needed size. The available may be off by 1. Or a source for scaling need to be found.
Well, if I am wrong and there already is a better way....

Also this IMHO only makes sense if other images are then scaled. Otherwise the display will look worse, as there will be a mix of all different sizes shown....

 

TinyPortal © 2005-2018