Dnes to bude o Delphi 1, nějaký Open Source pro syntézu řeči, kousek kódu z RTL, device drivers a Delphi nebo FPC, TMethod, GDI+ a vyhlazování a seminář bude nakonec v Olomouci atd.
Delphi 1 a lokalizace
Jelikož se blíží svátek Valentýna, neboli výročí uvedení Delphi 1 na trh - letos to bude už 17 let - je třeba vytáhnout něco historického:
Na EDN je Delphi Product Definition 3rd Draft - May 13, 1993 (tj. 2 roky před release) a tam mne zaujalo toto:
Původně se tedy předpokládalo, že Delphi 1 bude i v našem jazyku. Což je pro mne překvapení. Vím, že existoval překlad helpu k BP7, ale myslel jsem
si, že je to neofiko a uvedená tabulka mne překvapila (a potěšila). Ale asi se to nakonec nestalo. Nebo jo?
eSpeak
eSpeak je Open Source "text to speech" SAPI5 engine, které funguje i pro češtinu. Sice to zní jako když mluví Číslo 5, ale je to zadarmo. Upozornil mne na to jeden klient, kterému pomáhám a který se specializuje na pomůcky pro zrakově postižené. Kromě toho i existují samozřejmě i kvalitní syntézy, ale někdy tohle stačí.
Na stránce slibují i DLL knihovnu, ale tu jsem tam nenašel, jen SAPI5 verzi. Ale zato je pro více OS.
Pěkné je, že celkem má cca 2M.
TStream.Seek a XE2
Minule jsem tu rozebíral jak jsem ladil TinyDB a kde byl zakopaný pes (v přidané metodě Seek pro 64bit posun).
Jelikož Delphi je velmi o kompatibilitě, bylo nutno zařídit, aby případná 32bit verze Seek za určitých podmínek volala novou 64bit verzi a naopak. Přiznám se, že mne řešení překvapilo (a je to trochu hack). Zároveň pěkně ukazuje použití záznamu TMethod.
function TStream.Seek(Offset: Longint; Origin: Word): Longint;
procedure RaiseException;
begin
raise EStreamError.CreateResFmt(@sSeekNotImplemented, [Classname]);
end;
type
TSeek64 = function (const Offset: Int64; Origin: TSeekOrigin): Int64 of object;
var
Impl: TSeek64;
Base: TSeek64;
ClassTStream: TClass;
begin
{ Deflect 32 seek requests to the 64 bit seek, if 64 bit is implemented.
No existing TStream classes should call this method, since it was originally
abstract. Descendent classes MUST implement at least one of either
the 32 bit or the 64 bit version, and must not call the inherited
default implementation. }
Impl := Seek;
ClassTStream := Self.ClassType;
while (ClassTStream <> nil) and (ClassTStream <> TStream) do
ClassTStream := ClassTStream.ClassParent;
if ClassTStream = nil then RaiseException;
Base := TStream(@ClassTStream).Seek;
if TMethod(Impl).Code = TMethod(Base).Code then
RaiseException;
Result := Seek(Int64(Offset), TSeekOrigin(Origin));
end;
TMethod podruhé
No a když jsem to nakousl, tak TMethod se ve spolupráci s metodou MethodAddress dá použít pro vyvolání metody dle jména.
program Project2;
{$APPTYPE CONSOLE}
uses
System.SysUtils, Classes;
type
TDummy = class
published
procedure Print; virtual;
end;
procedure TDummy.Print;
begin
writeln('TDummy.Print');
end;
type
TMyMethod = procedure of object;
var
oDummy: TDummy;
proc: TMyMethod;
method: TMethod;
begin
oDummy := TDummy.Create;
method.Data := Pointer(oDummy);
method.Code := TDummy.MethodAddress('Print');
proc := TMyMethod(method);
proc;
oDummy.Free;
end.
Trochu zvláštní příklad, ale snad to demonstruje dobře. Když jsem si s tím hrál, tak mi to nechtělo fungovat do doby než byla metoda Print published. Což mne trošku překvapuje, protože jsem doufal že by to mohlo fungovat i pro virtuální metody - ale ne. Bez tak je lepší použít unit RTTI z RTL, jak jsem psal dříve.
Device Drivers v Delphi a FPC
Existoval projekt, který dokázal generoval SYS drivery psané v Delphi - Delphi Driver Development Kit (lokal copy). Je to v podstatě hack, kdy za pomocí thirdparty nástroje se upravují obj soubory a výsledný link se provede za pomocí MS Link.
Uvádím to jen protože to ukazuje, že i drivery se v Delphi dají psát. Když budete moc chtít.
Na druhou stranu Free Pascal jako jeden z cílů umožňuje NativeNT target - Target_NativeNT. Díky tomu by mělo jít psát ovladače.
GDI+ a vyhlazování
V diskuzi ohledně vyhlazování ve FireMonkey (resp. v GDI+ verzi) mne inspiroval zajímavý kousek kódu, který demonstruje různé způsoby vyhlazování GDI+.
uses
Winapi.GDIPOBJ, Winapi.GDIPAPI;
procedure DrawGdiPlus(dc: HDC);
var
LGraphics : TGPGraphics;
LFont: TGPFont;
LPointF: TGPPointF;
LBrush: TGPSolidBrush;
LHint: TextRenderingHint;
procedure Draw(y: Integer; hint:TextRenderingHint; const sName:string);
begin
LPointF.Y := y;
LGraphics.SetTextRenderingHint(hint);
LGraphics.DrawString(sName, Length(sName), LFont, LPointF, LBrush);
end;
begin
LGraphics := TGPGraphics.Create(dc);
LFont := TGPFont.Create('Arial', 10);
LPointF.X := 0; LPointF.Y := 0;
LBrush := TGPSolidBrush.Create(MakeColor(255, 0, 0, 0));
Draw(20, TextRenderingHintSystemDefault, 'TextRenderingHintSystemDefault');
Draw(40, TextRenderingHintSingleBitPerPixelGridFit, 'TextRenderingHintSingleBitPerPixelGridFit');
Draw(60, TextRenderingHintSingleBitPerPixel, 'TextRenderingHintSingleBitPerPixel');
Draw(80, TextRenderingHintAntiAliasGridFit, 'TextRenderingHintAntiAliasGridFit');
Draw(100, TextRenderingHintAntiAlias, 'TextRenderingHintAntiAlias');
Draw(120, TextRenderingHintClearTypeGridFit, 'TextRenderingHintClearTypeGridFit');
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DrawGdiPlus(GetDC(Handle));
end;
Seminář v Olomouci
Embarcadero CZ+SK chystá seminář o RAD Studiu XE2 dne 6.3.2012 a nakonec bude v Olomouci. Přednášet bude Pawel Glowacki. Registrace začne kolem 13.2.2012.
Oftopinka
je pro dnešní den jak udělat hodiny ze starého HDD.