mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-05 22:38:03 +02:00
611 lines
15 KiB
ObjectPascal
611 lines
15 KiB
ObjectPascal
unit mainunit;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Forms, Graphics, Dialogs, StdCtrls, Grids, IniFiles,
|
|
LCLType, LCLIntf, LazUTF8;
|
|
|
|
type
|
|
|
|
{ TfrmMain }
|
|
|
|
TfrmMain = class(TForm)
|
|
btnResetText: TButton;
|
|
btnApplyFilter: TButton;
|
|
btnFontDlg: TButton;
|
|
cbCharset: TComboBox;
|
|
cbPitch: TComboBox;
|
|
chkStrike: TCheckBox;
|
|
chkUnderLine: TCheckBox;
|
|
FontDialog1: TFontDialog;
|
|
lflFontFaceList: TLabel;
|
|
lblStyles: TLabel;
|
|
lblCharset: TLabel;
|
|
lblFilter: TLabel;
|
|
lblSizes: TLabel;
|
|
lbFamily: TListBox;
|
|
lbStyles: TListBox;
|
|
lbSizes: TListBox;
|
|
lbCharset: TListBox;
|
|
grid: TStringGrid;
|
|
procedure btnFontDlgClick(Sender: TObject);
|
|
procedure btnResetTextClick(Sender: TObject);
|
|
procedure btnApplyFilterClick(Sender: TObject);
|
|
procedure chkStrikeChange(Sender: TObject);
|
|
procedure chkUnderLineChange(Sender: TObject);
|
|
procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormShow(Sender: TObject);
|
|
procedure lbFamilyClick(Sender: TObject);
|
|
procedure lbCharsetClick(Sender: TObject);
|
|
procedure lbSizesClick(Sender: TObject);
|
|
procedure lbStylesClick(Sender: TObject);
|
|
private
|
|
FTime: LongWord;
|
|
FIniTime: LongWord;
|
|
FCurrentFamily,FCurrentStyle,FCurrentSize,FCurrentCharset: string;
|
|
procedure StartTimer;
|
|
Procedure EndTimer;
|
|
function GetCharSet: byte;
|
|
function GetPitch: integer;
|
|
procedure EnableEvents(Ok: boolean; Lb: TListbox = nil);
|
|
procedure SelectFont;
|
|
procedure ResetSampleText;
|
|
procedure SaveSelection;
|
|
procedure RestoreSelection(Sender: TListbox);
|
|
procedure LoadFontList;
|
|
procedure LoadFamilyFonts(Charset: integer);
|
|
procedure UpdateFont(F: TFont);
|
|
public
|
|
|
|
end;
|
|
|
|
var
|
|
frmMain: TfrmMain;
|
|
|
|
implementation
|
|
{.$define Debug}
|
|
|
|
{$R *.lfm}
|
|
|
|
{ TfrmMain }
|
|
var
|
|
LStyles,
|
|
LSizes: TStringList;
|
|
|
|
function EnumFontsNoDups(
|
|
var LogFont: TEnumLogFontEx;
|
|
var Metric: TNewTextMetricEx;
|
|
FontType: Longint;
|
|
Data: LParam):LongInt; stdcall;
|
|
var
|
|
L: TStringList;
|
|
S: String;
|
|
begin
|
|
L := TStringList(ptrint(Data));
|
|
S := LogFont.elfLogFont.lfFaceName;
|
|
if L.IndexOf(S)<0 then
|
|
L.Add(S);
|
|
result := 1;
|
|
end;
|
|
|
|
var
|
|
NeedTTF: boolean;
|
|
|
|
function EnumFamilyFonts(
|
|
var eLogFont: TEnumLogFontEx;
|
|
var Metric:TNewTextMetricEx;
|
|
FontType:longint;
|
|
Data:LParam):longint; stdcall;
|
|
var
|
|
s: string;
|
|
n: integer;
|
|
lcharsets: TStringList;
|
|
begin
|
|
LCharSets := TStringList(ptrint(Data));
|
|
if Lcharsets<>nil then begin
|
|
// collect charsets
|
|
// when collecting charsets no need to collect all other info
|
|
s :=CharSetToString(eLogFont.elfLogFont.lfCharSet);
|
|
if LCharsets.indexOf(s)<0 then
|
|
LCharsets.AddObject(s, TObject(ptrint(eLogFont.elfLogFont.lfCharSet)));
|
|
exit;
|
|
end;
|
|
|
|
// collect styles
|
|
s :=eLogFont.elfStyle;
|
|
if LStyles.IndexOf(s)<0 then begin
|
|
// encode bold (bit 0), italic (bit 1) -- see SelectFont
|
|
n := 0;
|
|
{$IF DEFINED(LCLWin32) or DEFINED(LCLCocoa) }
|
|
if (eLogFont.elfLogFont.lfItalic <> 0) then
|
|
n := n or 1;
|
|
if (eLogFont.elfLogFont.lfWeight > FW_MEDIUM) then
|
|
n := n or 2;
|
|
{$ENDIF}
|
|
{$IF DEFINED(LCLGtk2) or DEFINED(LCLGtk3) or DEFINED(LCLQt) or DEFINED(LCLQt5)}
|
|
s := Lowercase(s);
|
|
if (pos('italic', s) <> 0) or (pos('oblique', s) <> 0) then
|
|
n := n or 1;
|
|
if (pos('bold', s) <> 0) then
|
|
n := n or 2;
|
|
{$ENDIF}
|
|
LStyles.AddObject(eLogFont.elfStyle, TObject(ptrint(n)));
|
|
end;
|
|
|
|
// collect sizes
|
|
if FontType=TRUETYPE_FONTTYPE then
|
|
NeedTTF := True
|
|
else
|
|
with metric.ntmentm do
|
|
if tmDigitizedAspectY <> 0 then begin
|
|
n := (tmHeight-tmInternalLeading)*72+tmDigitizedAspectY shr 1;
|
|
n := n div tmDigitizedAspectY;
|
|
if n>0 then begin
|
|
s := IntToStr(n)+'*'; // font sizes with * indicate raster fonts
|
|
if LSizes.IndexOf(s)<0 then
|
|
LSizes.AddObject(s, TObject(ptrint(n)));
|
|
end;
|
|
end;
|
|
result := 1;
|
|
end;
|
|
|
|
procedure TfrmMain.btnFontDlgClick(Sender: TObject);
|
|
begin
|
|
if FontDialog1.Execute then
|
|
UpdateFont(FontDialog1.Font);
|
|
end;
|
|
|
|
procedure TfrmMain.btnResetTextClick(Sender: TObject);
|
|
begin
|
|
ResetSampleText;
|
|
end;
|
|
|
|
procedure TfrmMain.btnApplyFilterClick(Sender: TObject);
|
|
begin
|
|
LoadFontList;
|
|
end;
|
|
|
|
procedure TfrmMain.chkStrikeChange(Sender: TObject);
|
|
begin
|
|
SelectFont;
|
|
end;
|
|
|
|
procedure TfrmMain.chkUnderLineChange(Sender: TObject);
|
|
begin
|
|
SelectFont;
|
|
end;
|
|
|
|
procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: boolean);
|
|
var
|
|
Ini: TInifile;
|
|
begin
|
|
SaveSelection;
|
|
Ini := TIniFile.Create(UTF8ToSys(ChangeFileExt(Application.ExeName,'.ini')));
|
|
try
|
|
Ini.WriteString('General','CurrentFamily', FCurrentFamily);
|
|
Ini.WriteString('General','CurrentCharset',FCurrentCharset);
|
|
Ini.WriteString('General','CurrentStyle', FCurrentStyle);
|
|
Ini.WriteString('General','CurrentSize', FCurrentSize);
|
|
finally
|
|
Ini.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmMain.FormCreate(Sender: TObject);
|
|
procedure Add(Charset: Integer);
|
|
begin
|
|
cbCharset.Items.AddObject(CharSetToString(CharSet), TObject(ptrint(Charset)));
|
|
end;
|
|
var
|
|
Ini: TIniFile;
|
|
begin
|
|
// populate cbcharset
|
|
cbCharset.Items.clear;
|
|
Add(ANSI_CHARSET);
|
|
Add(DEFAULT_CHARSET);
|
|
Add(SYMBOL_CHARSET);
|
|
Add(MAC_CHARSET);
|
|
Add(SHIFTJIS_CHARSET);
|
|
Add(HANGEUL_CHARSET);
|
|
Add(JOHAB_CHARSET);
|
|
Add(GB2312_CHARSET);
|
|
Add(CHINESEBIG5_CHARSET);
|
|
Add(GREEK_CHARSET);
|
|
Add(TURKISH_CHARSET);
|
|
Add(VIETNAMESE_CHARSET);
|
|
Add(HEBREW_CHARSET);
|
|
Add(ARABIC_CHARSET);
|
|
Add(BALTIC_CHARSET);
|
|
Add(RUSSIAN_CHARSET);
|
|
Add(THAI_CHARSET);
|
|
Add(EASTEUROPE_CHARSET);
|
|
Add(OEM_CHARSET);
|
|
Add(FCS_ISO_10646_1);
|
|
Add(FCS_ISO_8859_1);
|
|
Add(FCS_ISO_8859_2);
|
|
Add(FCS_ISO_8859_3);
|
|
Add(FCS_ISO_8859_4);
|
|
Add(FCS_ISO_8859_5);
|
|
Add(FCS_ISO_8859_6);
|
|
Add(FCS_ISO_8859_7);
|
|
Add(FCS_ISO_8859_8);
|
|
Add(FCS_ISO_8859_9);
|
|
Add(FCS_ISO_8859_10);
|
|
Add(FCS_ISO_8859_15);
|
|
ResetSampleText;
|
|
|
|
Ini := TIniFile.Create(UTF8ToSys(ChangeFileExt(Application.ExeName,'.ini')));
|
|
try
|
|
FCurrentFamily := Ini.ReadString('General','CurrentFamily', '');
|
|
FCurrentCharset := Ini.ReadString('General','CurrentCharset','');
|
|
FCurrentStyle := Ini.ReadString('General','CurrentStyle', '');
|
|
FCurrentSize := Ini.ReadString('General','CurrentSize', '');
|
|
finally
|
|
Ini.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmMain.FormShow(Sender: TObject);
|
|
begin
|
|
LoadFontlist;
|
|
lbCharsetClick(nil);
|
|
SelectFont;
|
|
end;
|
|
|
|
procedure TfrmMain.lbFamilyClick(Sender: TObject);
|
|
begin
|
|
LoadFamilyFonts(-1);
|
|
lbCharsetClick(nil);
|
|
SelectFont;
|
|
end;
|
|
|
|
procedure TfrmMain.lbCharsetClick(Sender: TObject);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
i := lbCharset.ItemIndex;
|
|
if i<0 then exit;
|
|
i := ptrint(lbCharSet.Items.Objects[i]);
|
|
LoadFamilyFonts(byte(i));
|
|
end;
|
|
|
|
procedure TfrmMain.lbSizesClick(Sender: TObject);
|
|
begin
|
|
SelectFont;
|
|
end;
|
|
|
|
procedure TfrmMain.lbStylesClick(Sender: TObject);
|
|
begin
|
|
SelectFont;
|
|
end;
|
|
|
|
procedure TfrmMain.StartTimer;
|
|
begin
|
|
FIniTime := GetTickCount;
|
|
end;
|
|
|
|
procedure TfrmMain.EndTimer;
|
|
begin
|
|
FTime := GetTickCount-FIniTime;
|
|
end;
|
|
|
|
function TfrmMain.GetCharSet: Byte;
|
|
begin
|
|
if cbCharSet.Itemindex<0 then
|
|
result := ANSI_CHARSET
|
|
else
|
|
result := byte(ptrint(cbCharset.items.Objects[CbCharset.ItemIndex]));
|
|
end;
|
|
|
|
function TfrmMain.GetPitch: integer;
|
|
begin
|
|
case cbPitch.ItemIndex of
|
|
1: result := FIXED_PITCH;
|
|
2: result := VARIABLE_PITCH;
|
|
3: result := MONO_FONT;
|
|
else
|
|
result := DEFAULT_PITCH;
|
|
end;
|
|
btnApplyFilter.Caption := IntToStr(result);
|
|
end;
|
|
|
|
procedure TfrmMain.EnableEvents(Ok: boolean; Lb: TListbox = nil);
|
|
procedure SetEvent(L: TListbox);
|
|
var
|
|
Event: TNotifyEvent;
|
|
begin
|
|
Event := nil;
|
|
if ok then begin
|
|
if l=lbFamily then Event := @lbFamilyClick else
|
|
if l=lbStyles then Event := @LbStylesClick else
|
|
if l=lbCharset then Event := @lbCharsetClick else
|
|
if l=lbSizes then Event := @lbSizesClick;
|
|
end;
|
|
L.OnClick := Event;
|
|
end;
|
|
begin
|
|
if Lb<>nil then
|
|
SetEvent(Lb)
|
|
else begin
|
|
SetEvent(lbFamily);
|
|
SetEvent(lbStyles);
|
|
SetEvent(lbCharset);
|
|
SetEvent(lbSizes);
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmMain.SelectFont;
|
|
var
|
|
F: TFont;
|
|
i: integer;
|
|
function GetFontSize(s: string): Integer;
|
|
begin
|
|
i := pos('*',s);
|
|
if i<>0 then
|
|
result := StrToInt(Copy(S, 1, i-1))
|
|
else
|
|
result := StrToInt(s);
|
|
end;
|
|
begin
|
|
if lbFamily.ItemIndex>=0 then
|
|
if lbCharSet.ItemIndex>=0 then
|
|
if lbStyles.ItemIndex>=0 then
|
|
if lbSizes.ItemIndex>=0 then
|
|
begin
|
|
F := TFont.Create;
|
|
try
|
|
F.Name := lbFamily.Items[lbFamily.ItemIndex];
|
|
F.CharSet := TFontCharSet(ptrint(lbCharSet.Items.Objects[lbCharset.ItemIndex]));
|
|
F.Size := GetFontSize(lbSizes.Items[lbSizes.ItemIndex]);
|
|
i := ptrint(lbStyles.Items.Objects[lbStyles.ItemIndex]);
|
|
F.Style := [];
|
|
if i and 1 <> 0 then F.Style := F.Style + [fsItalic];
|
|
if i and 2 <> 0 then F.Style := F.Style + [fsBold];
|
|
if chkUnderLine.Checked then F.Style := F.Style + [fsUnderline];
|
|
if chkStrike.Checked then F.Style := F.Style + [fsStrikeOut];
|
|
UpdateFont(F);
|
|
SaveSelection;
|
|
finally
|
|
F.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmMain.ResetSampleText;
|
|
var
|
|
L: TStringList;
|
|
begin
|
|
L := TStringList.Create;
|
|
L.Add('abcdefghijklmnopqrstuvwxyz');
|
|
L.Add('ABCDEFGHIJKLMNOPQRSTUVWXYZ');
|
|
L.Add('01234567891 ўЈ¤Ґ§');
|
|
L.Add('абвгдежзийклмнопрстуфхцшщъыь');
|
|
L.add('АБВГДЕЖЗИЙКЛМНОПРСТУФХХШЩЪЫЬЭЯ');
|
|
grid.Cols[0] := L;
|
|
l.Free;
|
|
end;
|
|
|
|
procedure TfrmMain.SaveSelection;
|
|
function doGet(lb: TListbox): string;
|
|
begin
|
|
if lb.itemindex>=0 then
|
|
result := lb.Items[lb.ItemIndex]
|
|
else
|
|
result := '';
|
|
end;
|
|
begin
|
|
FCurrentFamily := doGet(LbFamily);
|
|
FCurrentCharset := doGet(LbCharset);
|
|
FCurrentStyle := doGet(LbStyles);
|
|
FCurrentSize := doGet(LbSizes);
|
|
end;
|
|
|
|
procedure TfrmMain.RestoreSelection(Sender: TListbox);
|
|
function GetSelection: string;
|
|
begin
|
|
if Sender.itemindex>=0 then
|
|
result := Sender.Items[Sender.ItemIndex]
|
|
else
|
|
result := '';
|
|
end;
|
|
function GetCurrent: string;
|
|
begin
|
|
if Sender=lbFamily then result := FCurrentFamily else
|
|
if Sender=lbCharset then result := FCurrentCharset else
|
|
if Sender=lbStyles then result := FCurrentStyle else
|
|
if Sender=lbSizes then result := FCurrentSize;
|
|
end;
|
|
var
|
|
i: Integer;
|
|
s: string;
|
|
begin
|
|
s := GetCurrent;
|
|
if GetSelection <> s then begin
|
|
i := Sender.Items.IndexOf(s);
|
|
if i>-1 then begin
|
|
{$ifdef debug}
|
|
debugln('RestoreSelection: listbox=',Sender.Name,' Old=',GetSelection,' New=',S);
|
|
{$endif}
|
|
if i<>Sender.ItemIndex then
|
|
Sender.ItemIndex := i;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmMain.LoadFontList;
|
|
var
|
|
DC: HDC;
|
|
lf: TLogFont;
|
|
L: TStringList;
|
|
i: Integer;
|
|
begin
|
|
// this could be have done also with screen.fonts
|
|
// but here, we have the list filtered by Charset
|
|
lf.lfCharSet := GetCharSet;
|
|
lf.lfFaceName := '';
|
|
case cbPitch.ItemIndex of
|
|
1: i:=FIXED_PITCH;
|
|
2: i:=VARIABLE_PITCH;
|
|
3: i:=MONO_FONT;
|
|
else
|
|
i:=DEFAULT_PITCH;
|
|
end;
|
|
lf.lfPitchAndFamily := i;
|
|
|
|
{$ifdef debug}
|
|
debugln('LoadFontList: for charset=',CharSetToString(lf.lfcharset));
|
|
{$endif}
|
|
|
|
L := TStringList.create;
|
|
lbStyles.Clear;
|
|
lbCharset.Clear;
|
|
lbSizes.Clear;
|
|
|
|
DC := GetDC(0);
|
|
EnableEvents(False, lbFamily);
|
|
try
|
|
StartTimer;
|
|
EnumFontFamiliesEX(DC, @lf, @EnumFontsNoDups, ptrint(L), 0);
|
|
EndTimer;
|
|
L.Sort;
|
|
lbFamily.Items.Assign(L);
|
|
lbFamily.Itemindex := -1;
|
|
|
|
RestoreSelection(lbFamily);
|
|
if lbFamily.ItemIndex<0 then begin
|
|
if lbFamily.Items.Count>0 then
|
|
lbFamily.ItemIndex := 0;
|
|
end;
|
|
LoadFamilyFonts(-1);
|
|
|
|
lflFontFaceList.Caption := format('Fontfaces, found %d, %d ms',[lbFamily.Items.Count, FTime]);
|
|
finally
|
|
EnableEvents(True, lbFamily);
|
|
ReleaseDC(0, DC);
|
|
L.Free;
|
|
end;
|
|
end;
|
|
|
|
function CompareSizes(List: TStringList; Index1, Index2: Integer): Integer;
|
|
begin
|
|
result := ptrint(List.Objects[Index1]) - ptrint(List.Objects[Index2]);
|
|
end;
|
|
|
|
procedure TfrmMain.LoadFamilyFonts(Charset: integer);
|
|
var
|
|
LCharset: TStringList;
|
|
dc: HDC;
|
|
Lf: TLogFont;
|
|
i: LongInt;
|
|
LoadingCharsets: boolean;
|
|
|
|
procedure AddScalableSizes;
|
|
procedure Add(Sz: Integer);
|
|
begin
|
|
if LSizes.IndexOfObject(TObject(ptrint(Sz)))<0 then
|
|
LSizes.AddObject(IntToStr(Sz), TObject(ptrint(Sz)));
|
|
end;
|
|
begin
|
|
add(8); add(9); add(10); add(11); add(12); add(14); add(16); add(18);
|
|
add(20); add(22); add(24); add(26); add(28); add(36); add(48); add(72);
|
|
end;
|
|
begin
|
|
i := lbFamily.ItemIndex;
|
|
if i<0 then exit;
|
|
|
|
LoadingCharsets := Charset<0;
|
|
{$ifdef debug}
|
|
Write('LoadFamilyFonts: for family=', lbFamily.Items[i],' and Charset=');
|
|
if LoadingCharsets then
|
|
debugln('ALL_CHARSETS')
|
|
else
|
|
debugln(CharsetToString(byte(Charset)));
|
|
{$endif}
|
|
|
|
// at the moment only global fonts are enumerated
|
|
// ie. fonts selected in a device context are not enumerated
|
|
DC := GetDC(0);
|
|
// create global variables, EnumFamilyFonts use them
|
|
if LoadingCharsets then begin
|
|
// need to fill charset listbox too
|
|
LCharset := TStringList.Create;
|
|
CharSet := DEFAULT_CHARSET;
|
|
end else begin
|
|
// charset listbox is already filled, so fill styles and sizes
|
|
LCharSet := nil;
|
|
LStyles := TStringList.Create;
|
|
LSizes := TStringList.Create;
|
|
end;
|
|
try
|
|
// enumerate fonts
|
|
Lf.lfFaceName := lbFamily.Items[i];
|
|
Lf.lfCharSet := byte(Charset);
|
|
Lf.lfPitchAndFamily := 0;
|
|
NeedTTF := False;
|
|
EnumFontFamiliesEX(DC, @Lf, @EnumFamilyFonts, ptrint(LCharset), 0);
|
|
// fill charset listbox if necessary
|
|
if LCharset<>nil then begin
|
|
LCharset.Sort;
|
|
EnableEvents(False, LbCharset);
|
|
LbCharset.Items.Assign(LCharset);
|
|
LbCharset.ItemIndex := -1;
|
|
EnableEvents(true, LbCharset);
|
|
end else begin
|
|
// fill styles listbox
|
|
LStyles.Sort;
|
|
EnableEvents(False, LbStyles);
|
|
LbStyles.Items.Assign(LStyles);
|
|
lbStyles.ItemIndex := -1;
|
|
EnableEvents(true, LbStyles);
|
|
RestoreSelection(lbStyles);
|
|
if lbStyles.ItemIndex<0 then begin
|
|
if LbStyles.Items.Count>0 then
|
|
LbStyles.ItemIndex := 0;
|
|
end;
|
|
// fill sizes listbox
|
|
// any raster font size is already there
|
|
if NeedTTF then
|
|
AddScalableSizes;
|
|
LSizes.CustomSort(@CompareSizes);
|
|
EnableEvents(False, lbSizes);
|
|
lbSizes.Items.Assign(LSizes);
|
|
lbSizes.ItemIndex := -1;
|
|
EnableEvents(true, LbSizes);
|
|
RestoreSelection(LbSizes);
|
|
if lbSizes.ItemIndex<0 then begin
|
|
if lbSizes.Items.Count>0 then
|
|
LbSizes.ItemIndex := 0;
|
|
end;
|
|
end;
|
|
finally
|
|
if LCharset=nil then begin
|
|
LSizes.Free;
|
|
LStyles.Free;
|
|
end else
|
|
LCharset.Free;
|
|
releaseDC(0, DC);
|
|
end;
|
|
|
|
if LoadingCharsets then begin
|
|
// make an initial charset selection
|
|
RestoreSelection(lbCharset);
|
|
if lbCharset.ItemIndex<0 then begin
|
|
if lbCharset.Items.Count>0 then
|
|
lbCharset.ItemIndex := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmMain.UpdateFont(F: TFont);
|
|
begin
|
|
grid.Font := F;
|
|
grid.DefaultRowHeight := grid.canvas.textHeight('Бj') + 5;
|
|
end;
|
|
|
|
end.
|
|
|