123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 |
- unit UnitMain;
- (* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1 or LGPL 2.1 with linking exception
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * Alternatively, the contents of this file may be used under the terms of the
- * Free Pascal modified version of the GNU Lesser General Public License
- * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
- * of this license are applicable instead of those above.
- * Please see the file LICENSE.txt for additional information concerning this
- * license.
- *
- * The Original Code is Thick Line example for Graphics32
- *
- * The Initial Developer of the Original Code is
- * Anders Melander
- *
- * Portions created by the Initial Developer are Copyright (C) 2023
- * the Initial Developer. All Rights Reserved.
- *
- * ***** END LICENSE BLOCK ***** *)
- interface
- uses
- Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
- Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls,
- GR32_Image;
- type
- TFormThickLineTest = class(TForm)
- PaintBoxGDIThin: TPaintBox;
- PaintBox32_ThinAlpha: TPaintBox32;
- Label1: TLabel;
- Label2: TLabel;
- PaintBoxGDIThick: TPaintBox;
- PaintBox32_Thick: TPaintBox32;
- Label3: TLabel;
- Label4: TLabel;
- ButtonRedraw: TButton;
- Label5: TLabel;
- PaintBox32_ThickLine: TPaintBox32;
- Label6: TLabel;
- PaintBox32_Thin: TPaintBox32;
- procedure PaintBoxGDIThinPaint(Sender: TObject);
- procedure PaintBox32_ThinAlphaPaintBuffer(Sender: TObject);
- procedure PaintBoxGDIThickPaint(Sender: TObject);
- procedure PaintBox32_ThickPaintBuffer(Sender: TObject);
- procedure ButtonRedrawClick(Sender: TObject);
- procedure PaintBox32_ThickLinePaintBuffer(Sender: TObject);
- procedure PaintBoxClick(Sender: TObject);
- procedure PaintBox32Click(Sender: TObject);
- procedure PaintBox32_ThinPaintBuffer(Sender: TObject);
- private
- FDoPaint: boolean;
- procedure NotHung;
- public
- end;
- var
- FormThickLineTest: TFormThickLineTest;
- implementation
- {$R *.dfm}
- uses
- System.Types,
- System.Math,
- GR32_System,
- GR32.Lines.Thick,
- GR32,
- GR32_LowLevel,
- GR32_Paths,
- GR32_Brushes,
- GR32_Polygons;
- const
- MinLineCount = 200000;
- MinTestTime = 1000;
- MaxTestTime = 4500; // Windows will consider the application hung after 5 seconds
- ThickLineWidth = 10;
- //------------------------------------------------------------------------------
- procedure TFormThickLineTest.NotHung;
- var
- Msg: TMsg;
- begin
- // Pump WM_NULL so Windows doesn't consider application hung
- if PeekMessage(Msg, Handle, WM_NULL, WM_NULL, PM_NOREMOVE) and (Msg.message = WM_NULL) then
- PeekMessage(Msg, Handle, WM_NULL, WM_NULL, PM_REMOVE);
- end;
- //------------------------------------------------------------------------------
- procedure TFormThickLineTest.ButtonRedrawClick(Sender: TObject);
- begin
- ButtonRedraw.Enabled := False;
- ButtonRedraw.Update;
- FDoPaint := True;
- try
- Invalidate;
- PaintBox32_ThinAlpha.Invalidate;
- PaintBox32_Thin.Invalidate;
- PaintBox32_Thick.Invalidate;
- PaintBox32_ThickLine.Invalidate;
- Update;
- finally
- FDoPaint := False;
- ButtonRedraw.Enabled := True;
- end;
- end;
- procedure TFormThickLineTest.PaintBoxClick(Sender: TObject);
- begin
- FDoPaint := True;
- try
- TPaintBox(Sender).Invalidate;
- TPaintBox(Sender).Update;
- finally
- FDoPaint := False;
- end;
- end;
- procedure TFormThickLineTest.PaintBox32Click(Sender: TObject);
- begin
- FDoPaint := True;
- try
- TPaintBox32(Sender).Invalidate;
- TPaintBox32(Sender).Update;
- finally
- FDoPaint := False;
- end;
- end;
- //------------------------------------------------------------------------------
- procedure TFormThickLineTest.PaintBoxGDIThinPaint(Sender: TObject);
- var
- Stopwatch: TStopwatch;
- LineCount: integer;
- begin
- (*
- ** GDI, thin line. Aliased. No alpha blending.
- *)
- if (not FDoPaint) then
- exit;
- Screen.Cursor := crHourGlass;
- TPaintBox(Sender).Canvas.Brush.Color := clWhite;
- TPaintBox(Sender).Canvas.Brush.Style := bsSolid;
- TPaintBox(Sender).Canvas.FillRect(PaintBoxGDIThin.Canvas.ClipRect);
- TPaintBox(Sender).Canvas.Pen.Width := 1;
- TPaintBox(Sender).Canvas.MoveTo(0,0);
- RandSeed := 0;
- Stopwatch := TStopwatch.StartNew;
- LineCount := 0;
- while ((LineCount < MinLineCount) or (Stopwatch.ElapsedMilliseconds < MinTestTime)) and (Stopwatch.ElapsedMilliseconds < MaxTestTime) do
- begin
- Inc(LineCount);
- TPaintBox(Sender).Canvas.Pen.Color := Random($00FFFFFF);
- TPaintBox(Sender).Canvas.LineTo(Random(TPaintBox(Sender).Width), Random(TPaintBox(Sender).Height));
- end;
- Stopwatch.Stop;
- Label1.Caption := Format('TCanvas.LineTo, Width=1.'#13'Lines per second: %.0n', [LineCount / Stopwatch.ElapsedMilliseconds * 1000]);
- NotHung;
- Screen.Cursor := crDefault;
- end;
- //------------------------------------------------------------------------------
- procedure TFormThickLineTest.PaintBoxGDIThickPaint(Sender: TObject);
- var
- Stopwatch: TStopwatch;
- LineCount: integer;
- begin
- (*
- ** GDI, thick line. Aliased. No alpha blending.
- *)
- if (not FDoPaint) then
- exit;
- Screen.Cursor := crHourGlass;
- TPaintBox(Sender).Canvas.Pen.Width := ThickLineWidth;
- TPaintBox(Sender).Canvas.MoveTo(0,0);
- TPaintBox(Sender).Canvas.Brush.Color := clWhite;
- TPaintBox(Sender).Canvas.Brush.Style := bsSolid;
- TPaintBox(Sender).Canvas.FillRect(TPaintBox(Sender).Canvas.ClipRect);
- RandSeed := 0;
- Stopwatch := TStopwatch.StartNew;
- LineCount := 0;
- while ((LineCount < MinLineCount) or (Stopwatch.ElapsedMilliseconds < MinTestTime)) and (Stopwatch.ElapsedMilliseconds < MaxTestTime) do
- begin
- Inc(LineCount);
- TPaintBox(Sender).Canvas.Pen.Color := Random($00FFFFFF);
- TPaintBox(Sender).Canvas.LineTo(Random(TPaintBox(Sender).Width), Random(TPaintBox(Sender).Height));
- end;
- Stopwatch.Stop;
- Label3.Caption := Format('TCanvas.LineTo, Width=%d.'#13'Lines per second: %.0n', [ThickLineWidth, LineCount / Stopwatch.ElapsedMilliseconds * 1000]);
- NotHung;
- Screen.Cursor := crDefault;
- end;
- //------------------------------------------------------------------------------
- procedure TFormThickLineTest.PaintBox32_ThinAlphaPaintBuffer(Sender: TObject);
- var
- Stopwatch: TStopwatch;
- LineCount: integer;
- begin
- (*
- ** Graphics32, thin line. Anti-aliased & Alpha blended.
- *)
- if (not FDoPaint) then
- exit;
- Screen.Cursor := crHourGlass;
- TPaintBox32(Sender).Buffer.Clear(clWhite32);
- TPaintBox32(Sender).Buffer.DrawMode := dmOpaque;
- TPaintBox32(Sender).Buffer.CombineMode := cmBlend;
- TPaintBox32(Sender).Buffer.BeginLockUpdate; // No need for update handling, we will redraw everything
- TPaintBox32(Sender).Buffer.MoveTo(0, 0);
- RandSeed := 0;
- Stopwatch := TStopwatch.StartNew;
- LineCount := 0;
- while ((LineCount < MinLineCount) or (Stopwatch.ElapsedMilliseconds < MinTestTime)) and (Stopwatch.ElapsedMilliseconds < MaxTestTime) do
- begin
- Inc(LineCount);
- TPaintBox32(Sender).Buffer.PenColor := Color32(Random($00FFFFFF)); // Color32 to swap R and B
- TPaintBox32(Sender).Buffer.LineToAS(Random(TPaintBox32(Sender).Width), Random(TPaintBox32(Sender).Height));
- end;
- Stopwatch.Stop;
- TPaintBox32(Sender).Buffer.EndLockUpdate;
- Label2.Caption := Format('TBitmap32.LineToAS, Width=1.'#13'Lines per second: %.0n', [LineCount / Stopwatch.ElapsedMilliseconds * 1000]);
- NotHung;
- Screen.Cursor := crDefault;
- end;
- //------------------------------------------------------------------------------
- procedure TFormThickLineTest.PaintBox32_ThinPaintBuffer(Sender: TObject);
- var
- Stopwatch: TStopwatch;
- LineCount: integer;
- begin
- (*
- ** Graphics32, thin line. Aliased. No alpha blending.
- *)
- if (not FDoPaint) then
- exit;
- Screen.Cursor := crHourGlass;
- TPaintBox32(Sender).Buffer.Clear(clWhite32);
- TPaintBox32(Sender).Buffer.DrawMode := dmOpaque;
- TPaintBox32(Sender).Buffer.CombineMode := cmBlend;
- TPaintBox32(Sender).Buffer.BeginLockUpdate; // No need for update handling, we will redraw everything
- TPaintBox32(Sender).Buffer.MoveTo(0, 0);
- RandSeed := 0;
- Stopwatch := TStopwatch.StartNew;
- LineCount := 0;
- while ((LineCount < MinLineCount) or (Stopwatch.ElapsedMilliseconds < MinTestTime)) and (Stopwatch.ElapsedMilliseconds < MaxTestTime) do
- begin
- Inc(LineCount);
- TPaintBox32(Sender).Buffer.PenColor := Color32(Random($00FFFFFF)); // Color32 to swap R and B
- TPaintBox32(Sender).Buffer.LineToS(Random(TPaintBox32(Sender).Width), Random(TPaintBox32(Sender).Height));
- end;
- Stopwatch.Stop;
- TPaintBox32(Sender).Buffer.EndLockUpdate;
- Label6.Caption := Format('TBitmap32.LineToS, Width=1.'#13'Lines per second: %.0n', [LineCount / Stopwatch.ElapsedMilliseconds * 1000]);
- NotHung;
- Screen.Cursor := crDefault;
- end;
- //------------------------------------------------------------------------------
- procedure TFormThickLineTest.PaintBox32_ThickPaintBuffer(Sender: TObject);
- var
- Canvas: TCanvas32;
- Stroke: TStrokeBrush;
- LastPoint: TFloatPoint;
- Stopwatch: TStopwatch;
- LineCount: integer;
- begin
- (*
- ** Graphics32, thick line via TCanvas32. Anti-aliased & Alpha blended.
- *)
- if (not FDoPaint) then
- exit;
- Screen.Cursor := crHourGlass;
- TPaintBox32(Sender).Buffer.Clear(clWhite32);
- TPaintBox32(Sender).Buffer.DrawMode := dmOpaque;
- TPaintBox32(Sender).Buffer.CombineMode := cmBlend;
- TPaintBox32(Sender).Buffer.BeginLockUpdate; // No need for update handling, we will redraw everything
- Canvas := TCanvas32.Create(TPaintBox32(Sender).Buffer);
- try
- Stroke := TStrokeBrush(Canvas.Brushes.Add(TStrokeBrush));
- Stroke.StrokeWidth := ThickLineWidth;
- LastPoint := GR32.FloatPoint(0, 0);
- RandSeed := 0;
- Stopwatch := TStopwatch.StartNew;
- LineCount := 0;
- while ((LineCount < MinLineCount) or (Stopwatch.ElapsedMilliseconds < MinTestTime)) and (Stopwatch.ElapsedMilliseconds < MaxTestTime) do
- begin
- Inc(LineCount);
- Stroke.FillColor := Color32(Random($00FFFFFF)); // Color32 to swap R and B
- Canvas.MoveTo(LastPoint); // EndPath clears last point so we have to set it manually
- LastPoint := GR32.FloatPoint(Random(TPaintBox32(Sender).Width), Random(TPaintBox32(Sender).Height));
- Canvas.LineTo(LastPoint);
- Canvas.EndPath; // Each line must be its own path, with its own stroke color
- end;
- Stopwatch.Stop;
- TPaintBox32(Sender).Buffer.EndLockUpdate;
- finally
- Canvas.Free;
- end;
- Label4.Caption := Format('TCanvas32.LineTo, Width=%d.'#13'Lines per second: %.0n', [ThickLineWidth, LineCount / Stopwatch.ElapsedMilliseconds * 1000]);
- NotHung;
- Screen.Cursor := crDefault;
- end;
- //------------------------------------------------------------------------------
- procedure TFormThickLineTest.PaintBox32_ThickLinePaintBuffer(Sender: TObject);
- var
- LastPos, NewPos: TPoint;
- Stopwatch: TStopwatch;
- LineCount: integer;
- Color: TColor32;
- begin
- (*
- ** Graphics32, thick line via DrawThickLine. Aliased. No alpha blending.
- *)
- if (not FDoPaint) then
- exit;
- Screen.Cursor := crHourGlass;
- TPaintBox32(Sender).Buffer.Clear(clWhite32);
- TPaintBox32(Sender).Buffer.DrawMode := dmOpaque;
- TPaintBox32(Sender).Buffer.CombineMode := cmBlend;
- TPaintBox32(Sender).Buffer.BeginLockUpdate; // No need for update handling, we will redraw everything
- LastPos := GR32.Point(0, 0);
- RandSeed := 0;
- Stopwatch := TStopwatch.StartNew;
- LineCount := 0;
- while ((LineCount < MinLineCount) or (Stopwatch.ElapsedMilliseconds < MinTestTime)) and (Stopwatch.ElapsedMilliseconds < MaxTestTime) do
- begin
- Inc(LineCount);
- Color := Color32(Random($00FFFFFF)); // Color32 to swap R and B
- NewPos := GR32.Point(Random(TPaintBox32(Sender).Width), Random(TPaintBox32(Sender).Height));
- DrawThickLine(TPaintBox32(Sender).Buffer, LastPos.X, LastPos.Y, NewPos.X, NewPos.Y, ThickLineWidth, Color);
- LastPos := NewPos;
- end;
- Stopwatch.Stop;
- TPaintBox32(Sender).Buffer.EndLockUpdate;
- Label5.Caption := Format('Graphics32 DrawThickLine, Width=%d.'#13'Lines per second: %.0n', [ThickLineWidth, LineCount / Stopwatch.ElapsedMilliseconds * 1000]);
- NotHung;
- Screen.Cursor := crDefault;
- end;
- //------------------------------------------------------------------------------
- end.
|