lcscaledpi.pas 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // SPDX-License-Identifier: GPL-3.0-only
  2. unit LCScaleDPI;
  3. {$mode objfpc}{$H+}
  4. interface
  5. uses
  6. Forms, Graphics, Controls, ComCtrls;
  7. procedure ScaleForms(FromDPI: Integer);
  8. procedure ScaleControl(Control: TControl; FromDPI: Integer;
  9. ToDPI_X: Integer = 0; ToDPI_Y: Integer = 0; ScaleToolbar: boolean = false);
  10. procedure ScaleImageList(SourceList: TImageList; newWidth, newHeight: Integer; TargetList: TImageList);
  11. function DoScaleX(Size: Integer; FromDPI: Integer; ToDPI: Integer = 0): integer;
  12. function DoScaleY(Size: Integer; FromDPI: Integer; ToDPI: Integer = 0): integer;
  13. function DoScaleXF(Size: single; FromDPI: Integer; ToDPI: Integer = 0): single;
  14. function DoScaleYF(Size: single; FromDPI: Integer; ToDPI: Integer = 0): single;
  15. implementation
  16. uses BGRABitmap, BGRABitmapTypes, LCLType;
  17. procedure ScaleForms(FromDPI: Integer);
  18. var
  19. i: Integer;
  20. begin
  21. for i:=0 to Screen.FormCount-1 do begin
  22. ScaleControl(Screen.Forms[i],FromDPI);
  23. end;
  24. end;
  25. procedure ScaleImageList(SourceList: TImageList; newWidth, newHeight: Integer; TargetList: TImageList);
  26. var
  27. TempBmp: TBitmap;
  28. TempBGRA: array of TBGRABitmap;
  29. i: Integer;
  30. begin
  31. if (TargetList = SourceList) and (newWidth = SourceList.Width) and
  32. (newHeight = SourceList.Height) then exit;
  33. setlength(TempBGRA, SourceList.Count);
  34. TempBmp := TBitmap.Create;
  35. for i := 0 to SourceList.Count-1 do
  36. begin
  37. SourceList.GetBitmap(i,TempBmp);
  38. TempBGRA[i] := TBGRABitmap.Create(TempBmp);
  39. TempBGRA[i].ResampleFilter := rfBestQuality;
  40. if (TempBGRA[i].width=0) or (TempBGRA[i].height=0) then continue;
  41. while (TempBGRA[i].Width < NewWidth) or (TempBGRA[i].Height < NewHeight) do
  42. BGRAReplace(TempBGRA[i], TempBGRA[i].FilterSmartZoom3(moLowSmooth));
  43. BGRAReplace(TempBGRA[i], TempBGRA[i].Resample(NewWidth,NewHeight));
  44. BGRAReplace(TempBGRA[i], TempBGRA[i].FilterSharpen(0.50));
  45. end;
  46. TempBmp.Free;
  47. TargetList.Clear;
  48. TargetList.Width:= NewWidth;
  49. TargetList.Height:= NewHeight;
  50. for i := 0 to high(TempBGRA) do
  51. begin
  52. {$IFDEF LCLWin32}
  53. If TBGRAPixel_RGBAOrder then TempBGRA[i].SwapRedBlue;
  54. {$ENDIF}
  55. TargetList.Add(TempBGRA[i].Bitmap,nil);
  56. TempBGRA[i].Free;
  57. end;
  58. end;
  59. function DoScaleX(Size: Integer; FromDPI: Integer; ToDPI: Integer): integer;
  60. begin
  61. if ToDPI = 0 then ToDPI := ScreenInfo.PixelsPerInchX;
  62. if ToDPI <= FromDPI then
  63. result := Size
  64. else
  65. Result := MulDiv(Size, ToDPI, FromDPI);
  66. end;
  67. function DoScaleY(Size: Integer; FromDPI: Integer; ToDPI: Integer): integer;
  68. begin
  69. if ToDPI = 0 then ToDPI := ScreenInfo.PixelsPerInchY;
  70. if ToDPI <= FromDPI then
  71. result := Size
  72. else
  73. Result := MulDiv(Size, ToDPI, FromDPI);
  74. end;
  75. function DoScaleXF(Size: single; FromDPI: Integer; ToDPI: Integer): single;
  76. begin
  77. if ToDPI = 0 then ToDPI := ScreenInfo.PixelsPerInchX;
  78. if ToDPI <= FromDPI then
  79. result := Size
  80. else
  81. Result := Size * ToDPI / FromDPI;
  82. end;
  83. function DoScaleYF(Size: single; FromDPI: Integer; ToDPI: Integer): single;
  84. begin
  85. if ToDPI = 0 then ToDPI := ScreenInfo.PixelsPerInchY;
  86. if ToDPI <= FromDPI then
  87. result := Size
  88. else
  89. Result := Size * ToDPI / FromDPI;
  90. end;
  91. procedure ScaleControl(Control: TControl; FromDPI: Integer; ToDPI_X: Integer;
  92. ToDPI_Y: Integer; ScaleToolbar: boolean);
  93. var
  94. n: Integer;
  95. WinControl: TWinControl;
  96. ToolBarControl: TToolBar;
  97. begin
  98. if ToDPI_X = 0 then ToDPI_X := ScreenInfo.PixelsPerInchX;
  99. if ToDPI_Y = 0 then ToDPI_Y := ScreenInfo.PixelsPerInchY;
  100. if ToDPI_X < FromDPI then ToDPI_X := FromDPI;
  101. if ToDPI_Y < FromDPI then ToDPI_Y := FromDPI;
  102. if (ToDPI_X = FromDPI) and (ToDPI_Y = FromDPI) then exit;
  103. with Control do begin
  104. Left:=DoScaleX(Left,FromDPI,ToDPI_X);
  105. Top:=DoScaleY(Top,FromDPI,ToDPI_Y);
  106. Width:=DoScaleX(Width,FromDPI,ToDPI_X);
  107. Height:=DoScaleY(Height,FromDPI,ToDPI_Y);
  108. if not IsParentFont then
  109. begin
  110. if Font.Size = 0 then
  111. Font.Height := -DoScaleY(12,FromDPI,ToDPI_Y)
  112. else
  113. Font.Size:= round(Font.Size * ToDPI_Y / FromDPI);
  114. end;
  115. end;
  116. if Control is TToolBar then begin
  117. if not ScaleToolbar then exit;
  118. ToolBarControl:=TToolBar(Control);
  119. with ToolBarControl do begin
  120. ButtonWidth:=DoScaleX(ButtonWidth,FromDPI,ToDPI_X);
  121. ButtonHeight:=DoScaleY(ButtonHeight,FromDPI,ToDPI_Y);
  122. end;
  123. exit;
  124. end;
  125. if Control is TWinControl then begin
  126. WinControl:=TWinControl(Control);
  127. with WinControl.ChildSizing do
  128. begin
  129. HorizontalSpacing := DoScaleX(HorizontalSpacing, FromDPI, ToDPI_X);
  130. LeftRightSpacing := DoScaleX(LeftRightSpacing, FromDPI, ToDPI_X);
  131. TopBottomSpacing := DoScaleY(TopBottomSpacing, FromDPI, ToDPI_Y);
  132. VerticalSpacing := DoScaleY(VerticalSpacing, FromDPI, ToDPI_Y);
  133. end;
  134. if WinControl.ControlCount > 0 then begin
  135. for n:=0 to WinControl.ControlCount-1 do begin
  136. if WinControl.Controls[n] is TControl then begin
  137. ScaleControl(WinControl.Controls[n],FromDPI,ToDPI_X,ToDPI_Y,
  138. ScaleToolbar);
  139. end;
  140. end;
  141. end;
  142. end;
  143. end;
  144. end.