Hi Mattias,
while inspecting the code of the benchmark tool I restructured it quite a bit. Maybe this is useful as I applied some minor optimizations as well and completed the unique naming scheme you were using (pnl as prefix for panels ans such).
Attached you can find the patch to your VPR project's benchmark example.
Kind regards,
Christian
Index: MainUnit.dfm =================================================================== --- MainUnit.dfm (Revision 4) +++ MainUnit.dfm (Arbeitskopie) @@ -1,4 +1,4 @@ -object Form1: TForm1 +object MainForm: TMainForm Left = 616 Top = 132 Caption = 'GR32 / AggPas / GDI+ benchmark tool' @@ -12,12 +12,11 @@ Font.Style = [] OldCreateOrder = False Position = poScreenCenter - WindowState = wsMinimized OnCreate = FormCreate OnDestroy = FormDestroy PixelsPerInch = 96 TextHeight = 13 - object Panel1: TPanel + object pnlControl: TPanel Left = 0 Top = 496 Width = 791 @@ -25,8 +24,7 @@ Align = alBottom BevelOuter = bvNone TabOrder = 0 - ExplicitWidth = 807 - object Label1: TLabel + object lblSeed: TLabel Left = 152 Top = 75 Width = 61 @@ -89,14 +87,14 @@ '2k text output') TabOrder = 2 end - object GroupBox1: TGroupBox + object gbResults: TGroupBox Left = 344 Top = 8 Width = 433 Height = 233 Caption = 'Benchmark Results' TabOrder = 3 - object Memo1: TMemo + object meResults: TMemo Left = 8 Top = 16 Width = 417 @@ -168,7 +166,7 @@ TabOrder = 9 end end - object Panel2: TPanel + object pnlImage: TPanel Left = 0 Top = 0 Width = 791 Index: MainUnit.pas =================================================================== --- MainUnit.pas (Revision 4) +++ MainUnit.pas (Arbeitskopie) @@ -38,7 +38,7 @@ // undefine to disable library {$DEFINE GDIPLUS} -{$DEFINE AGGPAS} +{.$DEFINE AGGPAS} {$DEFINE AGGLITE} {$DEFINE LIBART} {$DEFINE CAIRO} @@ -67,34 +67,31 @@ {$IFDEF CAIRO}, Cairo, CairoWin32 {$ENDIF}; + type - TForm1 = class(TForm) - Panel1: TPanel; + TMainForm = class(TForm) btnBenchmark: TButton; - Panel2: TPanel; + cbAllRasterizers: TCheckBox; + cbAllTests: TCheckBox; + cbOpaque: TCheckBox; + cbStroke: TCheckBox; + gbResults: TGroupBox; + gbSeed: TGaugeBar; Img: TImage32; + lblSeed: TLabel; + meResults: TMemo; + pnlControl: TPanel; + pnlImage: TPanel; + pnlSeed: TPanel; rgRasterizer: TRadioGroup; rgTest: TRadioGroup; - GroupBox1: TGroupBox; - Memo1: TMemo; - cbStroke: TCheckBox; - cbOpaque: TCheckBox; - cbAllTests: TCheckBox; - cbAllRasterizers: TCheckBox; - gbSeed: TGaugeBar; - Label1: TLabel; - pnlSeed: TPanel; - procedure btnBenchmarkClick(Sender: TObject); - procedure rgRasterizerClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); - procedure ImgPaintStage(Sender: TObject; Buffer: TBitmap32; - StageNum: Cardinal); + procedure btnBenchmarkClick(Sender: TObject); procedure gbSeedChange(Sender: TObject); - private - { Private declarations }
+ procedure rgRasterizerClick(Sender: TObject); public - { Public declarations } Polygon: TArrayOfArrayOfFloatPoint; TextPolygon: array [0..5] of TArrayOfArrayOfFloatPoint; AAMode: TAntialiasMode; @@ -130,7 +127,7 @@ end; var - Form1: TForm1; + MainForm: TMainForm; const XSIZE = 640; @@ -154,8 +151,8 @@ 'aliqua. Ut enim ad minim veniam, quis nostrud exercitation' + #13#10 + 'ullamco laboris nisi ut aliquip ex ea commodo consequat.', 'The quick brown fox jumps over the lazy dog.', - 'Jackdaws love my big sphinx of quartz.' - ); + 'Jackdaws love my big sphinx of quartz.'); + ONE255TH : Double = 1 / 255; type TFontEntry = record @@ -174,9 +171,47 @@ (Name: 'Garamond'; Size: 12; Style: []) ); -function RandColor: TColor32; +procedure SinCos(const Argument: TFloat; var Sin, Cos: TFloat); +asm + fld Argument + fsincos + fstp edx.TFloat // Cos + fstp eax.TFloat // Sin +end; + +function Ellipse(const X, Y, Rx, Ry: TFloat): TArrayOfFloatPoint; +const + M : TFloat = 2 * System.Pi / 100; +var + I: Integer; + t: TFloat; + Data : array [0..3] of TFloat; begin - Result := Random($ffffffff) and $ff777777 + $333333; + SetLength(Result, 100); + + // first item + Result[0].X := Rx + X; + Result[0].Y := Y; + + // calculate complex offset + SinCos(M, Data[0], Data[1]); + Data[2] := Data[0]; + Data[3] := Data[1]; + + // second item + Result[1].X := Rx * Data[3] + X; + Result[1].Y := Ry * Data[2] + Y; + + // other items + for I := 2 to 99 do + begin + t := Data[3]; + Data[3] := Data[3] * Data[1] - Data[2] * Data[0]; + Data[2] := Data[2] * Data[1] + t * Data[0]; + + Result[I].X := Rx * Data[3] + X; + Result[I].Y := Ry * Data[2] + Y; + end; end; function CreateLine(x1, y1, x2, y2, width: TFloat): TArrayOfFloatPoint; @@ -185,7 +220,7 @@ begin dx := x2 - x1; dy := y2 - y1; - d := sqrt(dx*dx + dy*dy); + d := Sqrt(Sqr(dx) + Sqr(dy)); if d <> 0 then begin dx := width * (y2 - y1) / d; @@ -204,39 +239,150 @@ end; end; -function Ellipse(const X, Y, Rx, Ry: TFloat): TArrayOfFloatPoint; +function MakeCurve(const Points: TArrayOfFloatPoint; Kernel: TCustomKernel; + Closed: Boolean; StepSize: Integer): TArrayOfFloatPoint; +var + I, J, F, H, Index, LastIndex, Steps, R: Integer; + K, V, W, dx, dy, X, Y: TFloat; + Filter: TFilterMethod; + WrapProc: TWrapProc; + PPoint: PFloatPoint; const - M: TFloat = 1/100*2*System.Pi; -var - I: Integer; - t: TFloat; + WRAP_PROC: array[Boolean] of TWrapProc = (Clamp, Wrap); begin - SetLength(Result, 100); - for I := 0 to 99 do + WrapProc := Wrap_PROC[Closed]; + Filter := Kernel.Filter; + R := Ceil(Kernel.GetWidth); + H := High(Points); + + LastIndex := H - Ord(not Closed); + Steps := 0; + for I := 0 to LastIndex do begin - t := I * M; - Result[I].X := Rx * Cos(t) + X; - Result[I].Y := Ry * Sin(t) + Y; + Index := WrapProc(I + 1, H); + dx := Points[Index].X - Points[I].X; + dy := Points[Index].Y - Points[I].Y; + Inc(Steps, Floor(Hypot(dx, dy) / StepSize) + 1); end; + + SetLength(Result, Steps); + PPoint := @Result[0]; + + for I := 0 to LastIndex do + begin + Index := WrapProc(I + 1, H); + dx := Points[Index].X - Points[I].X; + dy := Points[Index].Y - Points[I].Y; + Steps := Floor(Hypot(dx, dy) / StepSize); + if Steps > 0 then + begin + K := 1 / Steps; + V := 0; + for J := 0 to Steps do + begin + X := 0; Y := 0; + for F := -R to R do + begin + Index := WrapProc(I - F, H); + W := Filter(F + V); + X := X + W * Points[Index].X; + Y := Y + W * Points[Index].Y; + end; + PPoint^ := FloatPoint(X, Y); + Inc(PPoint); + V := V + K; + end; + end; + end; end; -function EllipseX(const X, Y, Rx, Ry: TFloat): TArrayOfFixedPoint; -const - M: TFloat = 1/100*2*System.Pi; +function RandColor: TColor32; +begin + Result := Random($FFFFFFFF) and $FF777777 + $333333; +end; + + +{ TForm1 } + +procedure TMainForm.FormCreate(Sender: TObject); var - I: Integer; - t: TFloat; + P: PPaintStage; begin - SetLength(Result, 100); - for I := 0 to 99 do + SetPriorityClass(GetCurrentProcess, HIGH_PRIORITY_CLASS); + SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_HIGHEST); + with Img.PaintStages[0]^ do begin - t := I * M; - Result[I].X := Fixed(Rx * Cos(t) + X); - Result[I].Y := Fixed(Ry * Sin(t) + Y); + if Stage = PST_CLEAR_BACKGND then Stage := PST_CUSTOM; end; + + P := Img.PaintStages.Add; + P.Stage := PST_CUSTOM; + P.Parameter := 1; + + CreateTextPolygons; + Img.BufferOversize := 0; + Img.Bitmap.SetSize(XSIZE, YSIZE); + Img.Bitmap.Clear(clWhite32); + +{$IFDEF AGGPAS} + Agg2D := TAgg2D.Create; + Agg2D.Attach32(Img.Bitmap); + Agg2D.LineWidth(1.0); +{$ENDIF} + +{$IFDEF AGGLITE}
+ + // Create the renderer and the rasterizer + Ren := TRenderer.Create(RBuf); + Ren.SpanType := stRGBA32; + Ras := TRasterizer.Create; + Ras.Gamma(1.0); + + // Setup the rasterizer + Ras.FillingRule := frFillNonZero; +{$ENDIF} + +{$IFDEF GDIPLUS} + // initialize GDI plus + GPGraphics := TGPGraphics.Create(Img.Bitmap.Handle); + GPPen := TGPPen.Create(Color); + GPPen.SetWidth(1.0); + GPBrush := TGPSolidBrush.Create(Color); +{$ENDIF} + +{$IFDEF CAIRO} + // initialize cairo + surface := cairo_win32_surface_create(Img.Bitmap.Handle); + cr := cairo_create(surface); + cairo_set_line_width(cr, 1.0); + //cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); +{$ENDIF} end; -procedure TForm1.btnBenchmarkClick(Sender: TObject); +procedure TMainForm.FormDestroy(Sender: TObject); +begin +{$IFDEF AGGPAS} + Agg2D.Free; +{$ENDIF} +{$IFDEF AGGLITE} + Ras.Free; + Ren.Free; + RBuf.Free; +{$ENDIF} +{$IFDEF GDIPLUS} + GPGraphics.Free; + GPPen.Free; + GPBrush.Free; +{$ENDIF} +{$IFDEF CAIRO} + cairo_destroy(cr); + cairo_surface_destroy(surface); +{$ENDIF} +end; + + +procedure TMainForm.btnBenchmarkClick(Sender: TObject); var I, J: Integer; begin @@ -255,7 +401,7 @@ end; end; -procedure TForm1.Benchmark; +procedure TMainForm.Benchmark; var I, Iter: Integer; Dst: TBitmap32; @@ -274,7 +420,7 @@ Screen.Cursor := crDefault; end; -procedure TForm1.BuildPolygon; +procedure TMainForm.BuildPolygon; begin SetLength(Polygon, 1); case rgTest.ItemIndex of @@ -286,9 +432,9 @@ end; end; +{$IFDEF LIBART}
-{$IFDEF LIBART} procedure LibArtCallback(data: Pointer; y, start: Integer; steps: PArtSVPRenderAAStep; n_steps: Integer); cdecl; var @@ -338,7 +484,7 @@ end; {$ENDIF} -procedure TForm1.RenderPolygon(Dst: TBitmap32); +procedure TMainForm.RenderPolygon(Dst: TBitmap32); var Color: TColor32; Poly: TArrayOfArrayOfFixedPoint; @@ -353,9 +499,9 @@ Agg2D.ResetPath; for J := 0 to High(Polygon) do begin - Agg2D.MoveTo(Polygon[J][0].X, Polygon[J][0].Y); + Agg2D.MoveTo(Polygon[J, 0].X, Polygon[J, 0].Y); for I := 1 to High(Polygon[J]) do - Agg2D.LineTo(Polygon[J][I].X, Polygon[J][I].Y); + Agg2D.LineTo(Polygon[J, I].X, Polygon[J, I].Y); Agg2D.ClosePolygon; end; if cbStroke.Checked then @@ -375,9 +521,9 @@ for J := 0 to High(Polygon) do begin - Ras.MoveToD(Polygon[J][0].X, Polygon[J][0].Y); + Ras.MoveToD(Polygon[J, 0].X, Polygon[J, 0].Y); for I := 1 to High(Polygon[J]) do - Ras.LineToD(Polygon[J][I].X, Polygon[J][I].Y); + Ras.LineToD(Polygon[J, I].X, Polygon[J, I].Y); //Agg2D.ClosePolygon; end; with TColor32Entry(Color) do @@ -405,7 +551,7 @@ begin Path.StartFigure; for I := 0 to High(Polygon[J]) - 1 do - Path.AddLine(TGPPointF(Polygon[J][I]), TGPPointF(Polygon[J][I + 1])); + Path.AddLine(TGPPointF(Polygon[J, I]), TGPPointF(Polygon[J, I + 1])); Path.CloseFigure; end; if cbStroke.Checked then @@ -440,18 +586,18 @@ begin N := Length(Polygon[J]); path[K].Code := ART_MOVETO; - path[K].X := Polygon[J][0].X; - path[K].Y := Polygon[J][0].Y; + path[K].X := Polygon[J, 0].X; + path[K].Y := Polygon[J, 0].Y; Inc(K); for I := 1 to N - 1 do begin path[K].Code := ART_LINETO; - path[K].X := Polygon[J][I].X; - path[K].Y := Polygon[J][I].Y; + path[K].X := Polygon[J, I].X; + path[K].Y := Polygon[J, I].Y; Inc(K); end; - path[K].X := Polygon[J][0].X; - path[K].Y := Polygon[J][0].Y; + path[K].X := Polygon[J, 0].X; + path[K].Y := Polygon[J, 0].Y; path[K].Code := ART_LINETO; Inc(K); end; @@ -468,23 +614,19 @@ I, J: Integer; begin with TColor32Entry(Color) do - cairo_set_source_rgba(cr, r/255, g/255, b/255, a/255);
cairo_new_path(cr); for J := 0 to High(Polygon) do begin - cairo_move_to(cr, Polygon[J][0].X, Polygon[J][0].Y); + cairo_move_to(cr, Polygon[J, 0].X, Polygon[J, 0].Y); for I := 1 to High(Polygon[J]) do - cairo_line_to(cr, Polygon[J][I].X, Polygon[J][I].Y); + cairo_line_to(cr, Polygon[J, I].X, Polygon[J, I].Y); end; cairo_close_path(cr); if cbStroke.Checked then - begin - cairo_stroke(cr); - end + cairo_stroke(cr) else - begin cairo_fill(cr); - end; end; {$ENDIF} @@ -531,40 +673,15 @@ end; end; -function TForm1.GetIterations: Integer; +function TMainForm.GetIterations: Integer; const Iterations: array [0..4] of Integer = (5000, 20000, 20000, 5000, 2000); begin Result := Iterations[rgTest.ItemIndex]; end; -function TForm1.RandomEllipse: TArrayOfFloatPoint; -const - MAXRADIUS = 200; +function TMainForm.GetFixedPolygon: TArrayOfArrayOfFixedPoint; var - X, Y, Rx, Ry: TFloat; -begin - X := Random(XSIZE); - Y := Random(YSIZE); - Rx := Random(MAXRADIUS); - Ry := Random(MAXRADIUS); - - Result := Ellipse(X, Y, Rx, Ry); -end; - -function TForm1.RandomLine: TArrayOfFloatPoint; -var - X1, Y1, X2, Y2: TFloat; -begin - X1 := Random(XSIZE); - X2 := Random(XSIZE); - Y1 := Random(YSIZE); - Y2 := Random(YSIZE); - Result := CreateLine(X1, Y1, X2, Y2, 5); -end; - -function TForm1.GetFixedPolygon: TArrayOfArrayOfFixedPoint; -var I, J, L, N: Integer; begin L := Length(Polygon); @@ -575,22 +692,22 @@ SetLength(Result[J], N); for I := 0 to N - 1 do begin - Result[J][I] := FixedPoint(Polygon[J][I]); + Result[J, I] := FixedPoint(Polygon[J, I]); end; end; end; -procedure TForm1.StopTimer; +procedure TMainForm.StopTimer; var S1, S2, S3: string; begin S3 := GlobalPerfTimer.ReadMilliseconds; with rgTest do S1 := Items[ItemIndex]; with rgRasterizer do S2 := Items[ItemIndex]; - Memo1.Lines.Add(Format('[%s, %s]: %s ms', [S1, S2, S3])); + meResults.Lines.Add(Format('[%s, %s]: %s ms', [S1, S2, S3])); end; -procedure TForm1.rgRasterizerClick(Sender: TObject); +procedure TMainForm.rgRasterizerClick(Sender: TObject); const Modes: array [0..5] of TAntialiasMode = (am32times, am16times, am8times, am4times, am2times, amNone); @@ -598,76 +715,33 @@ AAMode := Modes[rgRasterizer.ItemIndex - 8]; end; -function TForm1.RandomLine2: TArrayOfFloatPoint; +function TMainForm.RandomEllipse: TArrayOfFloatPoint; +const + MAXRADIUS = 200; var - X1, Y1, X2, Y2: TFloat; + X, Y, Rx, Ry: TFloat; begin - X1 := Random(XSIZE); - X2 := Random(XSIZE); - Y1 := Random(YSIZE); - Y2 := Random(YSIZE); - Result := CreateLine(X1, Y1, X2, Y2, 0.5); + X := Random(XSIZE); + Y := Random(YSIZE); + Rx := Random(MAXRADIUS); + Ry := Random(MAXRADIUS); + + Result := Ellipse(X, Y, Rx, Ry); end; +function TMainForm.RandomLine: TArrayOfFloatPoint; +begin + Result := CreateLine(Random(XSIZE), Random(YSIZE), Random(XSIZE), + Random(YSIZE), 5); +end; -function MakeCurve(const Points: TArrayOfFloatPoint; Kernel: TCustomKernel; - Closed: Boolean; StepSize: Integer): TArrayOfFloatPoint; -var - I, J, F, H, Index, LastIndex, Steps, R: Integer; - K, V, W, dx, dy, X, Y: TFloat; - Filter: TFilterMethod; - WrapProc: TWrapProc; - PPoint: PFloatPoint; -const - WRAP_PROC: array[Boolean] of TWrapProc = (Clamp, Wrap); +function TMainForm.RandomLine2: TArrayOfFloatPoint; begin - WrapProc := Wrap_PROC[Closed]; - Filter := Kernel.Filter; - R := Ceil(Kernel.GetWidth); - H := High(Points); - - LastIndex := H - Ord(not Closed); - Steps := 0; - for I := 0 to LastIndex do - begin - Index := WrapProc(I + 1, H); - dx := Points[Index].X - Points[I].X; - dy := Points[Index].Y - Points[I].Y; - Inc(Steps, Floor(Hypot(dx, dy) / StepSize) + 1); - end; - - SetLength(Result, Steps); - PPoint := @Result[0]; - - for I := 0 to LastIndex do - begin - Index := WrapProc(I + 1, H); - dx := Points[Index].X - Points[I].X; - dy := Points[Index].Y - Points[I].Y; - Steps := Floor(Hypot(dx, dy) / StepSize); - if Steps > 0 then - begin - K := 1 / Steps; - V := 0; - for J := 0 to Steps do - begin - X := 0; Y := 0; - for F := -R to R do - begin - Index := WrapProc(I - F, H); - W := Filter(F + V); - X := X + W * Points[Index].X; - Y := Y + W * Points[Index].Y; - end; - PPoint^ := FloatPoint(X, Y); - Inc(PPoint); - V := V + K; - end; - end; - end; + Result := CreateLine(Random(XSIZE), Random(YSIZE), Random(XSIZE), + Random(YSIZE), 0.5); end; -function TForm1.RandomSpline: TArrayOfFloatPoint; +function TMainForm.RandomSpline: TArrayOfFloatPoint; var Input: TArrayOfFloatPoint; I: Integer; @@ -687,79 +761,8 @@ end; end; -procedure TForm1.FormCreate(Sender: TObject); +procedure TMainForm.CreateTextPolygons; var - P: PPaintStage; -begin - SetPriorityClass(GetCurrentProcess, HIGH_PRIORITY_CLASS); - SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_HIGHEST); - with Img.PaintStages[0]^ do - begin - if Stage = PST_CLEAR_BACKGND then Stage := PST_CUSTOM; - end; - - P := Img.PaintStages.Add; - P.Stage := PST_CUSTOM; - P.Parameter := 1; - - CreateTextPolygons; - Img.BufferOversize := 0; - Img.Bitmap.SetSize(XSIZE, YSIZE); - Img.Bitmap.Clear(clWhite32); -{$IFDEF AGGPAS} - Agg2D := TAgg2D.Create; - Agg2D.Attach32(Img.Bitmap); - Agg2D.LineWidth(1.0); -{$ENDIF} -{$IFDEF AGGLITE}
- - // Create the renderer and the rasterizer - Ren := TRenderer.Create(RBuf); - Ren.SpanType := stRGBA32; - Ras := TRasterizer.Create; - Ras.Gamma(1.0); - - // Setup the rasterizer - Ras.FillingRule := frFillNonZero; -{$ENDIF} -{$IFDEF GDIPLUS} - GPGraphics := TGPGraphics.Create(Img.Bitmap.Handle); - GPPen := TGPPen.Create(Color); - GPPen.SetWidth(1.0); - GPBrush := TGPSolidBrush.Create(Color); -{$ENDIF} -{$IFDEF CAIRO} - surface := cairo_win32_surface_create(Img.Bitmap.Handle); - cr := cairo_create(surface); - cairo_set_line_width(cr, 1.0); - //cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); -{$ENDIF} -end; - -procedure TForm1.FormDestroy(Sender: TObject); -begin -{$IFDEF AGGPAS} - Agg2D.Free; -{$ENDIF} -{$IFDEF AGGLITE} - Ras.Free; - Ren.Free; - RBuf.Free; -{$ENDIF} -{$IFDEF GDIPLUS} - GPGraphics.Free; - GPPen.Free; - GPBrush.Free; -{$ENDIF} -{$IFDEF CAIRO} - cairo_destroy(cr); - cairo_surface_destroy(surface); -{$ENDIF} -end; - -procedure TForm1.CreateTextPolygons; -var I: Integer; Tmp: TBitmap32; begin @@ -778,7 +781,7 @@ Tmp.Free; end; -function TForm1.RandomText: TArrayOfArrayOfFloatPoint; +function TMainForm.RandomText: TArrayOfArrayOfFloatPoint; var I, J: Integer; L: Integer; @@ -796,13 +799,13 @@ Result[J] := Copy(Src[J]); for I := 0 to High(Result[J]) do begin - Result[J][I].X := Result[J][I].X + Dx; - Result[J][I].Y := Result[J][I].Y + Dy; + Result[J, I].X := Result[J, I].X + Dx; + Result[J, I].Y := Result[J, I].Y + Dy; end; end; end; -procedure TForm1.ImgPaintStage(Sender: TObject; Buffer: TBitmap32; +procedure TMainForm.ImgPaintStage(Sender: TObject; Buffer: TBitmap32; StageNum: Cardinal); const Colors: array [0..1] of TColor32 = ($FFFFFFFF, $FFB0B0B0); @@ -842,7 +845,7 @@ end; end; -procedure TForm1.gbSeedChange(Sender: TObject); +procedure TMainForm.gbSeedChange(Sender: TObject); begin pnlSeed.Caption := IntToStr(gbSeed.Position); end; Index: VPR_Benchmark.dpr =================================================================== --- VPR_Benchmark.dpr (Revision 4) +++ VPR_Benchmark.dpr (Arbeitskopie) @@ -4,13 +4,13 @@ FastMM4, FastMove, Forms, - MainUnit in 'MainUnit.pas' {Form1}; + MainUnit in 'MainUnit.pas' {MainForm}; {$R *.res} begin Application.Initialize; Application.Title := 'GR32_PolygonEx Benchmark Tool'; - Application.CreateForm(TForm1, Form1); + Application.CreateForm(TMainForm, MainForm); Application.Run; end.
Message source