193 lines
5.3 KiB
ObjectPascal
193 lines
5.3 KiB
ObjectPascal
unit umain;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
|
|
BCPanel, BCLabel, BCTrackbarUpdown, BGRAVirtualScreen, BGRABitmap,
|
|
BGRABitmapTypes;
|
|
|
|
type
|
|
|
|
{ TFMain }
|
|
|
|
TFMain = class(TForm)
|
|
BCLabel1: TBCLabel;
|
|
BCLabel2: TBCLabel;
|
|
BCPanel1: TBCPanel;
|
|
BCTrackbarZoom: TBCTrackbarUpdown;
|
|
BCTrackbarDiagonal: TBCTrackbarUpdown;
|
|
BGRAVirtualScreen1: TBGRAVirtualScreen;
|
|
CheckBoxIntermediate: TCheckBox;
|
|
procedure BCTrackbarChange(Sender: TObject; AByUser: boolean);
|
|
procedure BGRAVirtualScreen1MouseDown(Sender: TObject;
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
procedure BGRAVirtualScreen1MouseMove(Sender: TObject; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
procedure BGRAVirtualScreen1MouseUp(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
procedure BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);
|
|
procedure CheckBoxIntermediateChange(Sender: TObject);
|
|
procedure FormCreate(Sender: TObject);
|
|
private
|
|
|
|
function GetRawBitmap: TBGRABitmap;
|
|
function GetPosAt(X,Y: Integer): integer;
|
|
public
|
|
pos: array of TPoint;
|
|
pointMoving: integer;
|
|
pointMoveMouseStart, pointMoveCoordStart: TPoint;
|
|
end;
|
|
|
|
var
|
|
FMain: TFMain;
|
|
|
|
implementation
|
|
|
|
uses BGRAVectorize, BGRATransform;
|
|
|
|
{$R *.lfm}
|
|
|
|
{ TFMain }
|
|
|
|
procedure TFMain.BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);
|
|
var
|
|
bmp: TBGRABitmap;
|
|
pts: ArrayOfTPointF;
|
|
zoom, i: Integer;
|
|
radius: single;
|
|
m: TAffineMatrix;
|
|
begin
|
|
bmp := GetRawBitmap;
|
|
zoom := BCTrackbarZoom.Value;
|
|
Bitmap.StretchPutImage(rect(0,0,bmp.Width*zoom,bmp.Height*zoom), bmp, dmSet);
|
|
if zoom >= 4 then
|
|
begin
|
|
for i := 1 to bmp.Height-1 do
|
|
Bitmap.HorizLine(0,i*zoom-1,bmp.Width*zoom-1,BGRA(144,144,144,128), dmDrawWithTransparency);
|
|
for i := 1 to bmp.Width-1 do
|
|
Bitmap.VertLine(i*zoom-1,0,bmp.Height*zoom-1,BGRA(144,144,144,128), dmDrawWithTransparency);
|
|
end;
|
|
pts := VectorizeMonochrome(bmp, 1, true, true, BCTrackbarDiagonal.Value, CheckBoxIntermediate.Checked);
|
|
|
|
bmp.FillTransparent;
|
|
bmp.FillPolyAntialias(pts, BGRA(0,128,0,128));
|
|
Bitmap.StretchPutImage(rect(0,0,bmp.Width*zoom,bmp.Height*zoom), bmp, dmDrawWithTransparency);
|
|
|
|
m := AffineMatrixTranslation(-0.5,-0.5)*AffineMatrixScale(zoom,zoom)*AffineMatrixTranslation(0.5,0.5);
|
|
for i := 0 to high(pts) do pts[i] := m * pts[i];
|
|
|
|
Bitmap.DrawPolygonAntialias(pts, CSSRed, 2);
|
|
if zoom > 6 then
|
|
begin
|
|
radius := zoom/6;
|
|
if radius < 2.5 then radius := 2.5;
|
|
for i := 0 to high(pts) do
|
|
Bitmap.EllipseAntialias(pts[i].x,pts[i].y, radius,radius, BGRA(0,0,0,192),1,CSSOrange);
|
|
end;
|
|
for i := 0 to high(pos) do
|
|
begin
|
|
Bitmap.EllipseAntialias(pos[i].x*zoom,pos[i].y*zoom,8,8,BGRABlack,4);
|
|
Bitmap.EllipseAntialias(pos[i].x*zoom,pos[i].y*zoom,8,8,BGRAWhite,2);
|
|
end;
|
|
bmp.Free;
|
|
end;
|
|
|
|
procedure TFMain.CheckBoxIntermediateChange(Sender: TObject);
|
|
begin
|
|
BGRAVirtualScreen1.DiscardBitmap;
|
|
end;
|
|
|
|
procedure TFMain.FormCreate(Sender: TObject);
|
|
begin
|
|
setlength(pos, 4);
|
|
pos[0] := Point(10,10);
|
|
pos[1] := Point(60,10);
|
|
pos[2] := Point(10,20);
|
|
pos[3] := Point(60,60);
|
|
pointMoving := -1;
|
|
end;
|
|
|
|
procedure TFMain.BCTrackbarChange(Sender: TObject; AByUser: boolean);
|
|
begin
|
|
if AByUser then BGRAVirtualScreen1.DiscardBitmap;
|
|
end;
|
|
|
|
procedure TFMain.BGRAVirtualScreen1MouseDown(Sender: TObject;
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
idx: Integer;
|
|
begin
|
|
if Button = mbLeft then
|
|
begin
|
|
idx := GetPosAt(X,Y);
|
|
pointMoving := idx;
|
|
pointMoveMouseStart := Point(X,Y);
|
|
pointMoveCoordStart := pos[idx];
|
|
BGRAVirtualScreen1.Cursor := crHandPoint;
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TFMain.BGRAVirtualScreen1MouseMove(Sender: TObject;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
idx, zoom: Integer;
|
|
newPos: TPoint;
|
|
begin
|
|
if pointMoving <> -1 then
|
|
begin
|
|
zoom := BCTrackbarZoom.Value;
|
|
newPos := Point(pointMoveCoordStart.x + round((X-pointMoveMouseStart.x)/zoom),
|
|
pointMoveCoordStart.y + round((Y-pointMoveMouseStart.y)/zoom));
|
|
if (newPos.X <> pos[pointMoving].x) or (newPos.Y <> pos[pointMoving].y) then
|
|
begin
|
|
pos[pointMoving] := newPos;
|
|
BGRAVirtualScreen1.DiscardBitmap;
|
|
end;
|
|
end else
|
|
begin
|
|
idx := GetPosAt(X,Y);
|
|
if idx <> -1 then BGRAVirtualScreen1.Cursor := crHandPoint else BGRAVirtualScreen1.Cursor := crDefault;
|
|
end;
|
|
end;
|
|
|
|
procedure TFMain.BGRAVirtualScreen1MouseUp(Sender: TObject;
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if Button = mbLeft then pointMoving:= -1;
|
|
end;
|
|
|
|
function TFMain.GetRawBitmap: TBGRABitmap;
|
|
var
|
|
zoom: Integer;
|
|
begin
|
|
zoom := BCTrackbarZoom.Value;
|
|
result := TBGRABitmap.Create(BGRAVirtualScreen1.Width div zoom,BGRAVirtualScreen1.Height div zoom, BGRAWhite);
|
|
result.FillEllipseInRect(rect(pos[2].x,pos[2].y,pos[3].x,pos[3].y), BGRABlack, dmSet);
|
|
result.DrawLine(pos[0].x,pos[0].y,pos[1].x,pos[1].y, BGRABlack, true);
|
|
end;
|
|
|
|
function TFMain.GetPosAt(X, Y: Integer): integer;
|
|
var
|
|
minDist,dist, i, zoom: integer;
|
|
begin
|
|
minDist := sqr(8);
|
|
result := -1;
|
|
zoom := BCTrackbarZoom.Value;
|
|
for i := 0 to high(pos) do
|
|
begin
|
|
dist := sqr(X-pos[i].X*zoom)+sqr(Y-pos[i].Y*zoom);
|
|
if dist < minDist then
|
|
begin
|
|
minDist := dist;
|
|
result := i;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|