1049 lines
28 KiB
ObjectPascal
1049 lines
28 KiB
ObjectPascal
unit Unit1;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Spin,
|
|
ExtCtrls, StdCtrls, BGRAVirtualScreen, BGRABitmap, BGRABitmapTypes,
|
|
BGRACanvas2D;
|
|
|
|
const
|
|
timeGrain = 15/1000/60/60/24;
|
|
|
|
type
|
|
|
|
{ TForm1 }
|
|
|
|
TForm1 = class(TForm)
|
|
Button_toDataURL: TButton;
|
|
CheckBox_Antialiasing: TCheckBox;
|
|
CheckBox_PixelCentered: TCheckBox;
|
|
Panel1: TPanel;
|
|
SaveDialog1: TSaveDialog;
|
|
SpinEdit1: TSpinEdit;
|
|
VirtualScreen: TBGRAVirtualScreen;
|
|
Timer1: TTimer;
|
|
procedure Button_toDataURLClick(Sender: TObject);
|
|
procedure CheckBox_AntialiasingChange(Sender: TObject);
|
|
procedure CheckBox_PixelCenteredChange(Sender: TObject);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormDestroy(Sender: TObject);
|
|
procedure FormMouseLeave(Sender: TObject);
|
|
procedure FormMouseMove(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
|
|
procedure FormPaint(Sender: TObject);
|
|
procedure SpinEdit1Change(Sender: TObject);
|
|
procedure Timer1Timer(Sender: TObject);
|
|
procedure VirtualScreenMouseLeave(Sender: TObject);
|
|
procedure VirtualScreenMouseMove(Sender: TObject; {%H-}Shift: TShiftState; X,
|
|
Y: Integer);
|
|
procedure VirtualScreenRedraw(Sender: TObject; Bitmap: TBGRABitmap);
|
|
private
|
|
{ private declarations }
|
|
mx,my: integer;
|
|
lastTime: TDateTime;
|
|
timeGrainAcc: double;
|
|
test4pos, test5pos, Test13pos, test16pos, test17pos, test18pos, test19pos, test23pos: integer;
|
|
img,abelias: TBGRABitmap;
|
|
procedure UpdateIn(ms: integer);
|
|
procedure UseVectorizedFont(ctx: TBGRACanvas2D; AUse: boolean);
|
|
public
|
|
{ public declarations }
|
|
procedure Test1(ctx: TBGRACanvas2D);
|
|
procedure Test2(ctx: TBGRACanvas2D);
|
|
procedure Test3(ctx: TBGRACanvas2D);
|
|
procedure Test4(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
procedure Test5(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
procedure Test6(ctx: TBGRACanvas2D);
|
|
procedure Test7(ctx: TBGRACanvas2D);
|
|
procedure Test8(ctx: TBGRACanvas2D);
|
|
procedure Test9(ctx: TBGRACanvas2D);
|
|
procedure Test10(ctx: TBGRACanvas2D);
|
|
procedure Test11(ctx: TBGRACanvas2D);
|
|
procedure Test12(ctx: TBGRACanvas2D);
|
|
procedure Test13(ctx: TBGRACanvas2D);
|
|
procedure Test14(ctx: TBGRACanvas2D);
|
|
procedure Test15(ctx: TBGRACanvas2D);
|
|
procedure Test16(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
procedure Test17(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
procedure Test18(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
procedure Test19(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
procedure Test20(ctx: TBGRACanvas2D; AVectorizedFont: boolean);
|
|
procedure Test22(ctx: TBGRACanvas2D);
|
|
procedure Test23(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
end;
|
|
|
|
var
|
|
Form1: TForm1;
|
|
|
|
implementation
|
|
|
|
uses BGRAGradientScanner, Math, BGRASVG, BGRAVectorize;
|
|
|
|
{$R *.lfm}
|
|
|
|
{ TForm1 }
|
|
|
|
procedure TForm1.FormPaint(Sender: TObject);
|
|
begin
|
|
end;
|
|
|
|
procedure TForm1.FormCreate(Sender: TObject);
|
|
begin
|
|
img := TBGRABitmap.Create(ExtractFilePath(Application.ExeName)+'pteRaz.jpg');
|
|
abelias := TBGRABitmap.Create(ExtractFilePath(Application.ExeName)+'abelias.png');
|
|
mx := -1000;
|
|
my := -1000;
|
|
lastTime := Now;
|
|
VirtualScreen.Color := $d0d0d0;
|
|
end;
|
|
|
|
procedure TForm1.CheckBox_PixelCenteredChange(Sender: TObject);
|
|
begin
|
|
VirtualScreen.DiscardBitmap;
|
|
end;
|
|
|
|
procedure TForm1.Button_toDataURLClick(Sender: TObject);
|
|
var html: string;
|
|
t: textfile;
|
|
begin
|
|
if SaveDialog1.Execute then
|
|
begin
|
|
html := '<html><body><img src="';
|
|
html += VirtualScreen.Bitmap.Canvas2D.toDataURL;
|
|
html += '"/></body></html>';
|
|
assignfile(t,SaveDialog1.FileName);
|
|
rewrite(t);
|
|
write(t,html);
|
|
closefile(t);
|
|
MessageDlg('toDataURL','Output: '+ SaveDialog1.FileName,mtInformation,[mbOK],0);
|
|
end;
|
|
end;
|
|
|
|
procedure TForm1.CheckBox_AntialiasingChange(Sender: TObject);
|
|
begin
|
|
VirtualScreen.DiscardBitmap;
|
|
end;
|
|
|
|
procedure TForm1.FormDestroy(Sender: TObject);
|
|
begin
|
|
img.Free;
|
|
abelias.free;
|
|
end;
|
|
|
|
procedure TForm1.FormMouseLeave(Sender: TObject);
|
|
begin
|
|
|
|
end;
|
|
|
|
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
|
|
Y: Integer);
|
|
begin
|
|
|
|
end;
|
|
|
|
procedure TForm1.SpinEdit1Change(Sender: TObject);
|
|
begin
|
|
VirtualScreen.DiscardBitmap;
|
|
end;
|
|
|
|
procedure TForm1.Timer1Timer(Sender: TObject);
|
|
begin
|
|
Timer1.Enabled := false;
|
|
VirtualScreen.DiscardBitmap;
|
|
end;
|
|
|
|
procedure TForm1.VirtualScreenMouseLeave(Sender: TObject);
|
|
begin
|
|
mx := -1000;
|
|
my := -1000;
|
|
end;
|
|
|
|
procedure TForm1.VirtualScreenMouseMove(Sender: TObject; Shift: TShiftState; X,
|
|
Y: Integer);
|
|
begin
|
|
mx := X;
|
|
my := Y;
|
|
if (SpinEdit1.Value = 1) and not Timer1.Enabled then UpdateIn(10);
|
|
end;
|
|
|
|
procedure TForm1.VirtualScreenRedraw(Sender: TObject; Bitmap: TBGRABitmap);
|
|
var ctx: TBGRACanvas2D;
|
|
grainElapse: integer;
|
|
newTime: TDateTime;
|
|
begin
|
|
newTime := Now;
|
|
timeGrainAcc += (newTime - lastTime)/timeGrain;
|
|
lastTime := newTime;
|
|
if timeGrainAcc < 1 then timeGrainAcc := 1;
|
|
if timeGrainAcc > 50 then timeGrainAcc := 50;
|
|
grainElapse := trunc(timeGrainAcc);
|
|
timeGrainAcc -= grainElapse;
|
|
|
|
ctx := Bitmap.Canvas2D;
|
|
ctx.antialiasing := CheckBox_Antialiasing.Checked;
|
|
ctx.pixelCenteredCoordinates := CheckBox_PixelCentered.Checked;
|
|
ctx.save;
|
|
case SpinEdit1.Value of
|
|
1: Test1(ctx);
|
|
2: Test2(ctx);
|
|
3: Test3(ctx);
|
|
4: Test4(ctx, grainElapse);
|
|
5: Test5(ctx, grainElapse);
|
|
6: Test6(ctx);
|
|
7: Test7(ctx);
|
|
8: Test8(ctx);
|
|
9: Test9(ctx);
|
|
10: Test10(ctx);
|
|
11: Test11(ctx);
|
|
12: Test12(ctx);
|
|
13: Test13(ctx);
|
|
14: Test14(ctx);
|
|
15: Test15(ctx);
|
|
16: Test16(ctx, grainElapse);
|
|
17: Test17(ctx, grainElapse);
|
|
18: Test18(ctx, grainElapse);
|
|
19: Test19(ctx, grainElapse);
|
|
20: Test20(ctx,false);
|
|
21: Test20(ctx,true);
|
|
22: Test22(ctx);
|
|
23: Test23(ctx,grainElapse);
|
|
end;
|
|
ctx.restore;
|
|
end;
|
|
|
|
procedure TForm1.UpdateIn(ms: integer);
|
|
begin
|
|
Timer1.Interval := ms;
|
|
Timer1.Enabled := false;
|
|
Timer1.Enabled := true;
|
|
end;
|
|
|
|
procedure TForm1.UseVectorizedFont(ctx: TBGRACanvas2D; AUse: boolean);
|
|
begin
|
|
if AUse and not (ctx.fontRenderer is TBGRAVectorizedFontRenderer) then
|
|
ctx.fontRenderer := TBGRAVectorizedFontRenderer.Create;
|
|
if not AUse and (ctx.fontRenderer is TBGRAVectorizedFontRenderer) then
|
|
ctx.fontRenderer := nil;
|
|
end;
|
|
|
|
procedure TForm1.Test1(ctx: TBGRACanvas2D);
|
|
|
|
procedure DrawShape(colors: TBGRACustomGradient);
|
|
begin
|
|
ctx.fillStyle('rgb(1000,1000,1000)'); //out of bounds so it is saturated to 255,255,255
|
|
ctx.fillRect (0, 0, ctx.Width, ctx.Height);
|
|
ctx.fillStyle(ctx.createLinearGradient(0,0,20,0,colors));
|
|
ctx.shadowOffset := PointF(10,10);
|
|
ctx.shadowColor('rgba(0,0,0,0.5)');
|
|
ctx.shadowBlur := 4;
|
|
ctx.fillRect (mx-100, my-100, 200, 200);
|
|
end;
|
|
|
|
var
|
|
colors: TBGRACustomGradient;
|
|
|
|
|
|
begin
|
|
if (mx < 0) or (my < 0) then
|
|
begin
|
|
mx := ctx.Width div 2;
|
|
my := ctx.height div 2;
|
|
end;
|
|
|
|
ctx.save;
|
|
ctx.beginPath;
|
|
ctx.moveTo(0,0);
|
|
ctx.lineTo(ctx.Width,0);
|
|
ctx.lineTo(0,ctx.Height);
|
|
ctx.clip;
|
|
colors := TBGRAMultiGradient.Create([BGRA(0,255,0),BGRA(0,192,128),BGRA(0,255,0)],[0,0.5,1],True,True);
|
|
DrawShape(colors);
|
|
colors.Free;
|
|
ctx.restore;
|
|
|
|
ctx.save;
|
|
ctx.beginPath;
|
|
ctx.moveTo(ctx.Width,ctx.Height);
|
|
ctx.lineTo(0,ctx.Height);
|
|
ctx.lineTo(ctx.Width,0);
|
|
ctx.clip;
|
|
colors := TBGRAMultiGradient.Create([BGRA(0,255,255),BGRA(0,192,128),BGRA(0,255,255)],[0,0.5,1],True,True);
|
|
DrawShape(colors);
|
|
colors.Free;
|
|
ctx.restore;
|
|
end;
|
|
|
|
procedure TForm1.Test2(ctx: TBGRACanvas2D);
|
|
var layer: TBGRABitmap;
|
|
begin
|
|
layer := TBGRABitmap.Create(ctx.width,ctx.height);
|
|
with layer.Canvas2D do
|
|
begin
|
|
pixelCenteredCoordinates:= ctx.pixelCenteredCoordinates;
|
|
antialiasing:= ctx.antialiasing;
|
|
|
|
fillStyle('rgb(1000,0,0)'); // fond de couleur rouge
|
|
beginPath;
|
|
roundRect(25,25,Width-50,Height-50,25); // remplissage d un carré 250x250
|
|
fill;
|
|
|
|
clearRect(Width-mx-25,Height-my-25,50,50); // effacement d un carré
|
|
|
|
beginPath;
|
|
arc(mx,my,30,0,2*Pi);
|
|
clearPath;
|
|
|
|
strokeStyle ('rgb(0,0,1000)'); // contour de couleur bleue
|
|
strokeRect(100,100,20,20); // contour d un carré
|
|
|
|
shadowOffset := PointF(3,3);
|
|
shadowColor('rgba(0,0,0,0.5)');
|
|
shadowBlur := 4;
|
|
|
|
beginPath;
|
|
lineWidth := 3;
|
|
moveTo(20,160);
|
|
lineTo(200,160);
|
|
lineStyle([3,1]);
|
|
stroke;
|
|
|
|
beginPath;
|
|
moveTo(20,180);
|
|
lineTo(220,180);
|
|
lineTo(240,160);
|
|
lineStyle([1,1,2,2]);
|
|
stroke;
|
|
end;
|
|
ctx.surface.PutImage(0,0,layer,dmDrawWithTransparency);
|
|
layer.Free;
|
|
UpdateIn(10);
|
|
end;
|
|
|
|
procedure TForm1.Test3(ctx: TBGRACanvas2D);
|
|
begin
|
|
ctx.fillStyle ('rgb(1000,1000,1000)');
|
|
ctx.fillRect (0, 0, ctx.width, ctx.height);
|
|
// Triangle plein sans bordure
|
|
ctx.beginPath();
|
|
ctx.moveTo(100,100);
|
|
ctx.lineTo(150,30);
|
|
ctx.lineTo(230,150);
|
|
ctx.closePath();
|
|
if ctx.isPointInPath(mx+0.5,my+0.5) then
|
|
ctx.fillStyle ('rgb(1000,192,192)')
|
|
else
|
|
ctx.fillStyle ('rgb(1000,0,0)');
|
|
ctx.fill();
|
|
// Triangle plein avec bordure
|
|
ctx.fillStyle ('rgb(0,1000,0)');
|
|
ctx.strokeStyle ('rgb(0,0,1000)');
|
|
ctx.lineWidth := 8;
|
|
ctx.beginPath();
|
|
ctx.moveTo(50,100);
|
|
ctx.lineTo(50,220);
|
|
ctx.lineTo(210,200);
|
|
ctx.closePath();
|
|
if ctx.isPointInPath(mx+0.5,my+0.5) then
|
|
ctx.fillStyle ('rgb(192,1000,192)')
|
|
else
|
|
ctx.fillStyle ('rgb(0,1000,0)');
|
|
ctx.fill();
|
|
ctx.stroke();
|
|
// Triangle plein avec bordure
|
|
UpdateIn(50);
|
|
end;
|
|
|
|
procedure TForm1.Test4(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
var angle: single;
|
|
p0,p1,p2: TPointF;
|
|
begin
|
|
inc(test4pos, grainElapse);
|
|
angle := test4pos*2*Pi/400;
|
|
ctx.translate((ctx.Width-300)/2,(ctx.height-300)/2);
|
|
ctx.skewx( sin(angle) );
|
|
|
|
ctx.beginPath;
|
|
ctx.rect (0, 0, 300, 300);
|
|
ctx.fillStyle (CSSYellow);
|
|
ctx.strokeStyle(CSSRed);
|
|
ctx.lineWidth := 5;
|
|
ctx.strokeOverFill;
|
|
|
|
ctx.beginPath();
|
|
// coord. centre 150,150 rayon : 50 angle départ 0 fin 2Pi, sens
|
|
ctx.arc(150,150,50,0,PI*2,true); // Cercle
|
|
ctx.moveTo(100,150); // aller au pt de départ de l arc
|
|
ctx.arc(100,100,50,PI/2,PI,false); // Arc sens aig. montre
|
|
ctx.moveTo(150,150); // aller au pt de départ de l arc
|
|
ctx.arc(200,150,50,2*PI/2,0,false); // Autre cercle
|
|
ctx.lineWidth := 1;
|
|
ctx.strokeStyle(BGRABlack);
|
|
ctx.stroke();
|
|
|
|
ctx.lineJoin := 'round';
|
|
|
|
angle := test4pos*2*Pi/180;
|
|
p0 := PointF(150,50);
|
|
p1 := pointF(150+50,50);
|
|
p2 := pointF(150+50+cos(sin(angle)*Pi/2)*40,50+sin(sin(angle)*Pi/2)*40);
|
|
ctx.beginPath;
|
|
ctx.moveTo(p0);
|
|
ctx.arcTo(p1, p2, 30);
|
|
ctx.lineTo(p2);
|
|
ctx.lineWidth := 5;
|
|
ctx.strokeStyle( BGRA(240,170,0) );
|
|
ctx.stroke();
|
|
|
|
ctx.beginPath;
|
|
ctx.moveTo(p0);
|
|
ctx.lineTo(p1);
|
|
ctx.lineTo(p2);
|
|
ctx.strokeStyle( BGRA(0,0,255) );
|
|
ctx.lineWidth := 2;
|
|
ctx.stroke();
|
|
|
|
UpdateIn(10);
|
|
end;
|
|
|
|
procedure TForm1.Test5(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
var svg: TBGRASVG;
|
|
begin
|
|
inc(test5pos, grainElapse);
|
|
|
|
svg := TBGRASVG.Create;
|
|
svg.LoadFromFile(ExtractFilePath(Application.ExeName)+'Amsterdammertje-icoon.svg');
|
|
svg.StretchDraw(ctx, taCenter,tlCenter, 0,0,ctx.Width/3,ctx.Height);
|
|
|
|
svg.LoadFromFile(ExtractFilePath(Application.ExeName)+'BespectacledMaleUser.svg');
|
|
svg.StretchDraw(ctx, ctx.Width/3,0,ctx.Width*2/3,ctx.Height/2);
|
|
|
|
ctx.save;
|
|
ctx.beginPath;
|
|
ctx.rect(ctx.Width/3,ctx.Height/2,ctx.Width*2/3,ctx.Height/2);
|
|
ctx.clip;
|
|
svg.LoadFromFile(ExtractFilePath(Application.ExeName)+'Blue_gyroelongated_pentagonal_pyramid.svg');
|
|
svg.Draw(ctx, taCenter,tlCenter, ctx.Width*2/3,ctx.Height*3/4);
|
|
ctx.restore;
|
|
|
|
svg.Free;
|
|
|
|
ctx.beginPath;
|
|
ctx.lineWidth:= 1;
|
|
ctx.strokeStyle(BGRABlack);
|
|
ctx.moveTo(ctx.Width/3,0);
|
|
ctx.lineTo(ctx.Width/3,ctx.Height);
|
|
ctx.moveTo(ctx.Width/3,ctx.Height/2);
|
|
ctx.lineTo(ctx.Width,ctx.Height/2);
|
|
ctx.stroke;
|
|
|
|
UpdateIn(20);
|
|
end;
|
|
|
|
procedure TForm1.Test6(ctx: TBGRACanvas2D);
|
|
begin
|
|
ctx.fillStyle ('rgb(1000,1000,1000)');
|
|
ctx.fillRect (0, 0, 300, 300);
|
|
// Exemple de courbes de Bézier
|
|
ctx.fillStyle ( 'yellow');
|
|
ctx.lineWidth := 15;
|
|
ctx.lineCap := 'round'; // round butt square
|
|
ctx.lineJoin := 'miter'; // round miter bevel
|
|
ctx.strokeStyle ('rgb(200,200,1000)');
|
|
ctx.beginPath();
|
|
ctx.moveTo(50,150);
|
|
ctx.bezierCurveTo(50,80,100,60,130,60);
|
|
ctx.bezierCurveTo(180,60,250,50,260,130);
|
|
ctx.bezierCurveTo(150,150,150,150,120,280);
|
|
ctx.bezierCurveTo(50,250,100,200,50,150);
|
|
ctx.fill();
|
|
ctx.stroke();
|
|
end;
|
|
|
|
procedure TForm1.Test7(ctx: TBGRACanvas2D);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
ctx.fillStyle('black');
|
|
ctx.fillRect(0, 0, 300, 300);
|
|
// Dessin du fond
|
|
ctx.fillStyle ('red');
|
|
ctx.fillRect(0, 0, 150, 150);
|
|
ctx.fillStyle ('blue');
|
|
ctx.fillRect(150, 0, 150, 150);
|
|
ctx.fillStyle ('yellow');
|
|
ctx.fillRect(0, 150, 150, 150);
|
|
ctx.fillStyle ('green');
|
|
ctx.fillRect(150, 150, 150, 150);
|
|
ctx.fillStyle ('#FFF');
|
|
// Définition de la valeur de transparence
|
|
ctx.globalAlpha := 0.1;
|
|
// Dessin de carrés semi transparents
|
|
for i := 0 to 9 do
|
|
begin
|
|
ctx.beginPath();
|
|
ctx.fillRect(10*i, 10*i, 300-20*i, 300-20*i);
|
|
ctx.fill();
|
|
end;
|
|
end;
|
|
|
|
procedure TForm1.Test8(ctx: TBGRACanvas2D);
|
|
begin
|
|
ctx.drawImage(img, 0, 0);
|
|
ctx.globalAlpha:= 0.5;
|
|
ctx.drawImage(img, 100, 100);
|
|
ctx.globalAlpha := 0.9;
|
|
ctx.translate(100,100);
|
|
ctx.beginPath;
|
|
ctx.moveTo(50,50);
|
|
ctx.lineTo(300,50);
|
|
ctx.lineTo(500,200);
|
|
ctx.lineTo(50,200);
|
|
ctx.fillStyle(img);
|
|
ctx.fill;
|
|
end;
|
|
|
|
procedure TForm1.Test9(ctx: TBGRACanvas2D);
|
|
var
|
|
i: Integer;
|
|
j: Integer;
|
|
begin
|
|
ctx.translate(ctx.Width/2 -15*10, ctx.Height/2 -15*10);
|
|
ctx.strokeStyle ('#000');
|
|
ctx.lineWidth :=4;
|
|
for i := 0 to 14 do
|
|
for j := 0 to 14 do
|
|
begin
|
|
ctx.fillStyle (BGRA ( 255-18*i, 255-18*j, 0) );
|
|
ctx.strokeStyle (BGRA( 20+10*j, 20+8*i, 0) );
|
|
ctx.fillRect(j*20, i*20, 20, 20);
|
|
ctx.strokeRect(j*20, i*20, 20, 20)
|
|
end;
|
|
end;
|
|
|
|
procedure TForm1.Test10(ctx: TBGRACanvas2D);
|
|
var
|
|
i: Integer;
|
|
j: Integer;
|
|
begin
|
|
ctx.translate(ctx.Width/2, ctx.Height/2); // centre 0 0 maintenant en position centrale
|
|
for i := 1 to 9 do
|
|
begin
|
|
ctx.save(); // contrebalancé par un restore
|
|
ctx.fillStyle ( BGRA(25*i,255-25*i,255) );
|
|
for j := 0 to i*5 do
|
|
begin
|
|
ctx.rotate(PI*2/(1+i*5)); //
|
|
ctx.beginPath();
|
|
ctx.arc(0, i*16, 6, 0, PI*2, true);
|
|
ctx.fill();
|
|
end;
|
|
ctx.restore();
|
|
end;
|
|
end;
|
|
|
|
procedure TForm1.Test11(ctx: TBGRACanvas2D);
|
|
const sc=20; // nb de pixels pour une unité
|
|
|
|
var
|
|
H: LongInt;
|
|
W: LongInt;
|
|
i: Integer;
|
|
x,u: Single;
|
|
|
|
function f(x: single): single; // fonction à tracer
|
|
begin
|
|
result := 3*sin(x)*(cos(x)+1/2*cos(x/2)+1/3*cos(x/3)+1/4*cos(x/4));
|
|
end;
|
|
begin
|
|
H := ctx.height;
|
|
W := ctx.width;
|
|
// tracé du quadrillage
|
|
ctx.strokeStyle ('#666');
|
|
ctx.beginPath();
|
|
ctx.lineWidth:=0.5;
|
|
// lignes horizontales
|
|
for i := -trunc(H/2/sc) to trunc(H/2/sc) do
|
|
begin
|
|
ctx.moveTo(0, H/2-sc*i);
|
|
ctx.lineTo(W, H/2-sc*i);
|
|
end;
|
|
// lignes verticales
|
|
for i := 0 to trunc(W/sc) do
|
|
begin
|
|
ctx.moveTo(sc*i,H-0);
|
|
ctx.lineTo(sc*i, H-H);
|
|
end;
|
|
ctx.stroke();
|
|
// tracé de la fonction
|
|
ctx.strokeStyle ('#ff0000');
|
|
ctx.lineWidth:=1.5;
|
|
ctx.beginPath();
|
|
x:=0;
|
|
u:=f(x);
|
|
ctx.moveTo(0, H/2-u*sc);
|
|
while x < W/sc do
|
|
begin
|
|
u := f(x);
|
|
ctx.lineTo(x*sc, H/2-u*sc);
|
|
x += 1/sc;
|
|
end;
|
|
ctx.stroke();
|
|
end;
|
|
|
|
procedure TForm1.Test12(ctx: TBGRACanvas2D);
|
|
var
|
|
W: LongInt;
|
|
H: LongInt;
|
|
i: Integer;
|
|
j: Integer;
|
|
|
|
function color(): TBGRAPixel;
|
|
begin
|
|
result := BGRA(random(256),random(256),random(256));
|
|
end;
|
|
|
|
procedure drawSpirograph(R2: single; r: single; O: single);
|
|
var
|
|
x0,x1,x2: single;
|
|
y0,y1,y2: single;
|
|
i: integer;
|
|
begin
|
|
x0 := R2-O;
|
|
y0 := 0;
|
|
i := 1;
|
|
ctx.beginPath();
|
|
x1 := x0;
|
|
y1 := y0;
|
|
ctx.moveTo(x1, y1);
|
|
repeat
|
|
if (i > 1000) then break;
|
|
x2 := (R2+r)*cos(i*PI/72) - (r+O)*cos(((R2+r)/r)*(i*PI/72));
|
|
y2 := (R2+r)*sin(i*PI/72) - (r+O)*sin(((R2+r)/r)*(i*PI/72));
|
|
ctx.lineTo(x2, y2);
|
|
x1 := x2;
|
|
y1 := y2;
|
|
inc(i);
|
|
until (abs(x2-x0) < 1e-6) and (abs(y2-y0) < 1e-6);
|
|
ctx.stroke();
|
|
end;
|
|
|
|
begin
|
|
W := ctx.width;
|
|
H := ctx.height;
|
|
ctx.fillRect(0, 0, W, H);
|
|
for i := 0 to 1 do
|
|
for j := 0 to 2 do
|
|
begin
|
|
ctx.save();
|
|
ctx.strokeStyle ( color() );
|
|
ctx.translate(110+j*200, 100+i*160);
|
|
drawSpirograph(40*(j+2)/(j+1), -(3+random(11))*(i+3)/(i+1), 35);
|
|
ctx.restore();
|
|
end;
|
|
|
|
UpdateIn(3000);
|
|
end;
|
|
|
|
procedure TForm1.Test13(ctx: TBGRACanvas2D);
|
|
const vitesse = 1;
|
|
begin
|
|
ctx.fillStyle ('#000');
|
|
ctx.fillRect (0, 0, 800, 400);
|
|
ctx.clearRect(0, 0, 800, 400);
|
|
ctx.fillRect (0, 0, 800, 400);
|
|
ctx.setTransform(-0.55, 0.85, -1, 0.10, 100, 50+img.width*0.5);
|
|
ctx.rotate(PI*2*(Test13pos/360)*vitesse );
|
|
ctx.drawImage(img, img.width*(-0.5)-200, img.height*(-0.8));
|
|
inc(Test13pos);
|
|
if (Test13pos=360) then Test13pos := 0;
|
|
UpdateIn(10);
|
|
end;
|
|
|
|
procedure TForm1.Test14(ctx: TBGRACanvas2D);
|
|
procedure pave();
|
|
begin
|
|
ctx.save();
|
|
ctx.fillStyle ('rgb(130,100,800)');
|
|
ctx.strokeStyle ('rgb(0,0,300)');
|
|
ctx.beginPath();
|
|
ctx.lineWidth:=2;
|
|
ctx.moveTo(5,5);ctx.lineTo(20,10);ctx.lineTo(55,5);ctx.lineTo(45,18);ctx.lineTo(30,50);
|
|
ctx.closePath();
|
|
ctx.stroke();
|
|
ctx.fill();
|
|
ctx.fillStyle ('rgb(300,300,100)');
|
|
ctx.lineWidth:=5;
|
|
ctx.strokeStyle ('rgb(0,300,0)');
|
|
ctx.beginPath();
|
|
ctx.moveTo(20,18);ctx.lineTo(40,16);ctx.lineTo(35,26); ctx.lineTo(25,30);
|
|
ctx.closePath();
|
|
ctx.stroke();
|
|
ctx.fill();
|
|
ctx.restore();
|
|
end;
|
|
// dessins d un hexagone à partir de six pavés par rotation
|
|
procedure six();
|
|
var
|
|
i: Integer;
|
|
begin
|
|
ctx.save();
|
|
for i := 0 to 5 do
|
|
begin
|
|
ctx.rotate(2*PI/6);
|
|
pave();
|
|
end;
|
|
ctx.restore();
|
|
end;
|
|
// pavage utilisant des translations selon deux vecteurs non colinéaires
|
|
// 0,60*Math.sqrt(3) et 60*3/2, 60*Math.sqrt(3)/2
|
|
procedure draw();
|
|
var
|
|
i: Integer;
|
|
j: Integer;
|
|
begin
|
|
ctx.fillStyle ('rgb(800,100,50)');
|
|
ctx.fillRect (0, 0, ctx.Width, ctx.Height);
|
|
for j := 0 to (ctx.Width+60) div 90 do
|
|
begin
|
|
ctx.save();
|
|
ctx.translate(0,(-j div 2)*60*sqrt(3));
|
|
for i := 0 to round(ctx.Height / (60*sqrt(3))) do
|
|
begin
|
|
six();
|
|
ctx.translate(0,60*sqrt(3));
|
|
end;
|
|
|
|
ctx.restore();
|
|
ctx.translate(90, sqrt(3)*60/2);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
draw();
|
|
end;
|
|
|
|
procedure TForm1.Test15(ctx: TBGRACanvas2D);
|
|
const cote = 190;
|
|
|
|
procedure pave();
|
|
begin
|
|
ctx.drawImage(abelias,0,0);
|
|
end;
|
|
|
|
procedure refl();
|
|
begin
|
|
ctx.save();
|
|
pave();
|
|
ctx.transform(1,0,0,-1, 0, 0);
|
|
pave();
|
|
ctx.restore();
|
|
end;
|
|
|
|
// dessins d un hexagone à partir de six pavés par rotation
|
|
procedure trois();
|
|
var
|
|
i: Integer;
|
|
begin
|
|
ctx.save();
|
|
for i := 0 to 2 do
|
|
begin
|
|
ctx.rotate(4*PI/6);
|
|
refl();
|
|
end;
|
|
ctx.restore();
|
|
end;
|
|
|
|
// pavage utilisant des translations selon deux vecteurs non colinéaires
|
|
// 0,cote*Math.sqrt(3) et cote*3/2, cote*Math.sqrt(3)/2
|
|
procedure draw();
|
|
var
|
|
i: Integer;
|
|
j: Integer;
|
|
begin
|
|
ctx.fillStyle ('#330055');
|
|
ctx.fillRect (0, 0, ctx.width, ctx.height);
|
|
ctx.translate(140,140);
|
|
for j := 0 to trunc(ctx.Width /(cote*3/2)) do
|
|
begin
|
|
ctx.save();
|
|
ctx.translate(0,-(1/2 + j div 2)*cote*sqrt(3));
|
|
for i := 0 to trunc(ctx.Height / (cote*sqrt(3)))+1 do
|
|
begin
|
|
trois();
|
|
ctx.translate(0,cote*sqrt(3));
|
|
end;
|
|
ctx.restore();
|
|
ctx.translate(cote*3/2, sqrt(3)*cote/2);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
draw();
|
|
end;
|
|
|
|
procedure TForm1.Test16(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
var center: TPointF;
|
|
angle,zoom: single;
|
|
begin
|
|
inc(test16pos, grainElapse);
|
|
center := pointf(ctx.width/2,ctx.height/2);
|
|
angle := test16pos*2*Pi/300;
|
|
zoom := (sin(test16pos*2*Pi/400)+1.1)*min(ctx.width,ctx.height)/300;
|
|
with ctx do
|
|
begin
|
|
translate(center.X,center.Y);
|
|
scale(zoom,zoom);
|
|
rotate(angle);
|
|
translate(-93,-83);
|
|
beginPath();
|
|
moveTo(89.724698,11.312043);
|
|
bezierCurveTo(95.526308,14.494575,100.52322000000001,18.838808,102.75144,24.966412);
|
|
bezierCurveTo(114.24578,26.586847,123.07072,43.010127999999995,118.71826,54.504664);
|
|
bezierCurveTo(114.77805000000001,64.910473,93.426098,68.10145299999999,89.00143800000001,59.252123);
|
|
bezierCurveTo(86.231818,53.712894999999996,90.877898,48.213108999999996,88.853498,42.139906999999994);
|
|
bezierCurveTo(87.401408,37.78364299999999,82.208048,33.87411899999999,85.595888,27.098436999999993);
|
|
bezierCurveTo(87.071858,24.146481999999992,94.76621800000001,25.279547999999995,94.863658,23.444067999999994);
|
|
bezierCurveTo(95.066728,19.618834999999994,92.648878,18.165403999999995,90.221828,15.326465999999995);
|
|
closePath();
|
|
moveTo(53.024288,20.876975);
|
|
bezierCurveTo(50.128958,26.827119000000003,48.561707999999996,33.260252,50.284608,39.548662);
|
|
bezierCurveTo(41.840728,47.513997,44.130318,66.017003,54.325338,72.88213300000001);
|
|
bezierCurveTo(63.554708000000005,79.09700300000002,82.823918,69.36119300000001,81.320528,59.58223300000001);
|
|
bezierCurveTo(80.379498,53.461101000000006,73.409408,51.65791100000001,71.551608,45.53168800000001);
|
|
bezierCurveTo(70.219018,41.13739400000001,72.197818,34.94548700000001,65.517188,31.373877000000007);
|
|
bezierCurveTo(62.606638000000004,29.817833000000007,56.98220800000001,35.18931200000001,55.841908000000004,33.74771500000001);
|
|
bezierCurveTo(53.465478000000004,30.743354000000007,54.598668,28.159881000000006,54.938648,24.44039800000001);
|
|
closePath();
|
|
moveTo(16.284108,78.650993);
|
|
bezierCurveTo(16.615938,85.259863,18.344168,91.651623,22.885208,96.330453);
|
|
bezierCurveTo(19.327327999999998,107.37975,30.253377999999998,122.48687000000001,42.495058,123.58667);
|
|
bezierCurveTo(53.577238,124.58229,65.765908,106.76307,59.734438,98.920263);
|
|
bezierCurveTo(55.959047999999996,94.01106300000001,48.983098,95.791453,44.402058,91.319753);
|
|
bezierCurveTo(41.116108,88.112233,39.864737999999996,81.73340300000001,32.289848,81.824883);
|
|
bezierCurveTo(28.989708,81.864783,26.651538,89.282293,24.957518,88.569003);
|
|
bezierCurveTo(21.427108,87.08246299999999,21.174458,84.272723,19.679208,80.85010299999999);
|
|
closePath();
|
|
moveTo(152.77652,37.616125);
|
|
bezierCurveTo(156.68534,42.955439,159.37334,49.006564,158.79801,55.501293);
|
|
bezierCurveTo(168.5256,61.835313,169.5682,80.450283,160.75895,89.021463);
|
|
bezierCurveTo(152.78409,96.780823,132.08894,90.63274299999999,131.82654,80.742363);
|
|
bezierCurveTo(131.6623,74.551503,138.19976,71.535693,138.93671,65.17653299999999);
|
|
bezierCurveTo(139.46532,60.615162999999995,136.41531,54.87470199999999,142.35299,50.170306999999994);
|
|
bezierCurveTo(144.93985,48.12074299999999,151.43107,52.404562999999996,152.29636,50.78291599999999);
|
|
bezierCurveTo(154.09968999999998,47.403324999999995,152.52446999999998,45.062994999999994,151.52745,41.463536999999995);
|
|
closePath();
|
|
moveTo(139.65359,109.38478);
|
|
bezierCurveTo(179.13505,123.79982000000001,142.51298,146.31478,119.19800000000001,151.55864);
|
|
bezierCurveTo(95.883018,156.8025,41.93790800000001,157.82316,75.508908,123.02183);
|
|
bezierCurveTo(78.980078,119.42344999999999,79.61785800000001,104.19731999999999,82.074898,99.283253);
|
|
bezierCurveTo(86.361158,93.329663,106.23528,86.908083,113.13709,88.929193);
|
|
bezierCurveTo(128.23085,93.960443,125.96716,106.89633,139.65359,109.38478);
|
|
closePath();
|
|
if isPointInPath(mx+0.5,my+0.5) then
|
|
fillStyle ('#6faed9')
|
|
else
|
|
fillStyle ('#3f5e99');
|
|
fill();
|
|
end;
|
|
UpdateIn(10);
|
|
end;
|
|
|
|
procedure TForm1.Test17(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
var
|
|
grad: IBGRACanvasGradient2D;
|
|
angle: single;
|
|
begin
|
|
inc(test17pos, grainElapse);
|
|
angle := test17pos*2*Pi/1000;
|
|
|
|
ctx.translate(ctx.Width/2,ctx.Height/2);
|
|
ctx.scale(min(ctx.Width,ctx.Height)/2-10);
|
|
ctx.rotate(angle);
|
|
|
|
grad := ctx.createLinearGradient(-1,-1,1,1);
|
|
grad.addColorStop(0.3, '#ff0000');
|
|
grad.addColorStop(0.6, '#0000ff');
|
|
ctx.fillStyle(grad);
|
|
|
|
grad := ctx.createLinearGradient(-1,-1,1,1);
|
|
grad.addColorStop(0.3, '#ffffff');
|
|
grad.addColorStop(0.6, '#000000');
|
|
ctx.strokeStyle(grad);
|
|
ctx.lineWidth := 5;
|
|
|
|
ctx.beginPath;
|
|
ctx.moveto(0,0);
|
|
ctx.arc(0,0,1,Pi/6,-Pi/6,false);
|
|
ctx.fill();
|
|
ctx.stroke();
|
|
|
|
UpdateIn(10);
|
|
end;
|
|
|
|
procedure TForm1.Test18(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
var pat: TBGRABitmap;
|
|
begin
|
|
inc(test18pos, grainElapse);
|
|
ctx.translate(ctx.width div 2, ctx.height div 2);
|
|
ctx.rotate(test18pos*2*Pi/360);
|
|
ctx.scale(3,3);
|
|
pat := TBGRABitmap.Create(8,8);
|
|
pat.GradientFill(0,0,8,8,BGRABlack,BGRAWhite,gtLinear,PointF(0,0),PointF(8,8),dmSet);
|
|
// ctx.surface.CreateBrushTexture(bsDiagCross,BGRA(255,255,0),BGRA(255,0,0)) as TBGRABitmap;
|
|
ctx.fillStyle(ctx.createPattern(pat,'repeat-x'));
|
|
ctx.fillRect(pat.width,0,ctx.width,pat.height);
|
|
ctx.fillStyle(ctx.createPattern(pat,'repeat-y'));
|
|
ctx.fillRect(0,0,pat.width,ctx.height);
|
|
|
|
ctx.rotate(Pi);
|
|
ctx.globalAlpha:= 0.25;
|
|
ctx.fillStyle(ctx.createPattern(pat,'repeat-x'));
|
|
ctx.fillRect(0,0,ctx.width,ctx.height);
|
|
ctx.fillStyle(ctx.createPattern(pat,'repeat-y'));
|
|
ctx.fillRect(0,0,ctx.width,ctx.height);
|
|
pat.free;
|
|
|
|
UpdateIn(10);
|
|
end;
|
|
|
|
procedure TForm1.Test19(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
var i: integer;
|
|
tx,ty: single;
|
|
begin
|
|
inc(test19pos, grainElapse);
|
|
ctx.save;
|
|
ctx.translate(ctx.width div 2, ctx.height div 2);
|
|
ctx.rotate(test19pos*2*Pi/500);
|
|
ctx.scale(ctx.height / 2,ctx.height / 2);
|
|
ctx.beginPath;
|
|
ctx.moveto(1,0);
|
|
for i := 1 to 8 do
|
|
begin
|
|
ctx.rotate(2*Pi/8);
|
|
ctx.lineto(1,0);
|
|
end;
|
|
ctx.restore;
|
|
ctx.clip;
|
|
|
|
tx := ctx.width div 2;
|
|
ty := ctx.height div 2;
|
|
ctx.fillStyle ('red');
|
|
ctx.fillRect(0, 0, tx, ty);
|
|
ctx.fillStyle ('blue');
|
|
ctx.fillRect(tx, 0, tx, ty);
|
|
|
|
ctx.globalAlpha := 0.75;
|
|
ctx.fillStyle ('yellow');
|
|
ctx.fillRect(0, ty, tx, ty);
|
|
ctx.fillStyle ('green');
|
|
ctx.fillRect(tx, ty, tx, ty);
|
|
|
|
test18(ctx, grainElapse);
|
|
end;
|
|
|
|
procedure TForm1.Test20(ctx: TBGRACanvas2D; AVectorizedFont: boolean);
|
|
var
|
|
i: Integer;
|
|
grad: IBGRACanvasGradient2D;
|
|
begin
|
|
UseVectorizedFont(ctx,AVectorizedFont);
|
|
ctx.save;
|
|
|
|
ctx.fontName:= 'default';
|
|
ctx.fontEmHeight:= ctx.height/10;
|
|
ctx.textBaseline:= 'alphabetic';
|
|
|
|
ctx.shadowBlur:= 5;
|
|
ctx.shadowOffset := PointF(5,5);
|
|
ctx.shadowColor(BGRABlack);
|
|
|
|
ctx.beginPath;
|
|
if AVectorizedFont then
|
|
ctx.text('Vectorized font',ctx.fontEmHeight*0.2,ctx.fontEmHeight)
|
|
else
|
|
ctx.text('Raster font',ctx.fontEmHeight*0.2,ctx.fontEmHeight);
|
|
ctx.lineWidth := 5;
|
|
ctx.lineJoin:= 'round';
|
|
ctx.strokeStyle(BGRA(0,192,0));
|
|
ctx.fillStyle(clBlack);
|
|
ctx.fillOverStroke;
|
|
|
|
ctx.shadowNone;
|
|
|
|
grad := ctx.createLinearGradient(0,0,ctx.width,ctx.height);
|
|
grad.addColorStop(0.3, '#000080');
|
|
grad.addColorStop(0.7, '#00a0a0');
|
|
ctx.fillStyle(grad);
|
|
|
|
ctx.translate(ctx.width/2, ctx.height/2);
|
|
|
|
for i := 0 to 11 do
|
|
begin
|
|
ctx.beginPath;
|
|
ctx.moveTo(0,0);
|
|
ctx.lineTo(ctx.width+ctx.height,0);
|
|
ctx.strokeStyle(clRed);
|
|
ctx.lineWidth := 1;
|
|
ctx.stroke;
|
|
|
|
ctx.beginPath;
|
|
ctx.text('hello',ctx.width/10,0);
|
|
ctx.fill;
|
|
ctx.rotate(Pi/6);
|
|
end;
|
|
ctx.restore;
|
|
ctx.fontRenderer := nil;
|
|
end;
|
|
|
|
procedure TForm1.Test22(ctx: TBGRACanvas2D);
|
|
var layer: TBGRABitmap;
|
|
begin
|
|
layer := TBGRABitmap.Create(ctx.width,ctx.height, CSSRed);
|
|
UseVectorizedFont(layer.Canvas2D,true);
|
|
with layer.Canvas2D do
|
|
begin
|
|
pixelCenteredCoordinates:= ctx.pixelCenteredCoordinates;
|
|
antialiasing:= ctx.antialiasing;
|
|
fontName:= 'default';
|
|
fontStyle := [fsBold];
|
|
fontEmHeight:= min(ctx.height/2, ctx.width/4);
|
|
textBaseline:= 'middle';
|
|
textAlign := 'center';
|
|
|
|
beginPath;
|
|
text('hole', width/2,height/2);
|
|
clearPath;
|
|
end;
|
|
ctx.surface.DrawCheckers(rect(0,0,ctx.width,ctx.height), CSSWhite,CSSSilver);
|
|
ctx.surface.PutImage(0,0,layer,dmDrawWithTransparency);
|
|
end;
|
|
|
|
procedure TForm1.Test23(ctx: TBGRACanvas2D; grainElapse: integer);
|
|
begin
|
|
UseVectorizedFont(ctx,true);
|
|
with ctx do
|
|
begin
|
|
save;
|
|
fontName:= 'default';
|
|
fontStyle := [fsBold];
|
|
fontEmHeight:= min(height/2, width/6);
|
|
textBaseline:= 'middle';
|
|
textAlign := 'center';
|
|
|
|
translate(width/2,height/2);
|
|
transform(cos(test23pos*Pi/60),sin(test23pos*Pi/60),0,1,0,0);
|
|
beginPath;
|
|
text('distort', 0,0);
|
|
fillStyle(clBlack);
|
|
fill;
|
|
restore;
|
|
end;
|
|
inc(test23pos, grainElapse);
|
|
UpdateIn(10);
|
|
end;
|
|
|
|
end.
|
|
|