diff --git a/Source/editor/simba.editor_autocomplete.pas b/Source/editor/simba.editor_autocomplete.pas index 4b9a8507e..768bf0636 100644 --- a/Source/editor/simba.editor_autocomplete.pas +++ b/Source/editor/simba.editor_autocomplete.pas @@ -12,7 +12,7 @@ interface uses - Classes, SysUtils, Graphics, StdCtrls, Controls, Forms, LCLType, + Classes, SysUtils, Graphics, Controls, Forms, LCLType, SynEdit, SynEditTypes, SynEditKeyCmds, SynEditHighlighter, SynCompletion_Simba, simba.mufasatypes, simba.settings, diff --git a/Source/image/simba.image.pas b/Source/image/simba.image.pas index ce01c8d0a..5ae8619ea 100644 --- a/Source/image/simba.image.pas +++ b/Source/image/simba.image.pas @@ -40,6 +40,9 @@ TSimbaImage = class(TSimbaBaseClass) FTextDrawer: TSimbaTextDrawer; + procedure _DrawTPA(const TPA: TPointArray; Color: TColor); + procedure _DrawTPAAlpha(const TPA: TPointArray; Color: TColor; Alpha: Byte); + procedure _DrawBoxFilled(Box: TBox; Color: TColor); procedure _DrawBoxFilledAlpha(Box: TBox; Color: TColor; Alpha: Byte); @@ -126,8 +129,8 @@ TSimbaImage = class(TSimbaBaseClass) procedure SetExternalData(AData: PColorBGRA; AWidth, AHeight: Integer); procedure ResetExternalData; - procedure DrawATPA(ATPA: T2DPointArray; Color: TColor = -1); - procedure DrawTPA(Points: TPointArray; Color: TColor); + procedure DrawATPA(const ATPA: T2DPointArray; Color: TColor = -1; Alpha: Byte = 0); + procedure DrawTPA(const TPA: TPointArray; Color: TColor; Alpha: Byte = 0); // Line procedure DrawCrosshairs(ACenter: TPoint; Size: Integer; Color: TColor); @@ -251,17 +254,6 @@ implementation simba.image_lazbridge, simba.image_integral, simba.image_gaussblur, simba.image_bitmaparealoader, simba.image_utils; -function GetDistinctColor(const Color, Index: Integer): Integer; inline; -const - // Distinct colors - https://sashamaps.net/docs/resources/20-colors/ - DISTINCT_COLORS: TIntegerArray = ($4B19E6, $4BB43C, $19E1FF, $D86343, $3182F5, $B41E91, $F4D442, $E632F0, $45EFBF, $D4BEFA, $909946, $FFBEDC, $24639A, $C8FAFF, $000080, $C3FFAA, $008080, $B1D8FF, $750000, $A9A9A9); -begin - if (Color > -1) then - Result := Color - else - Result := DISTINCT_COLORS[Index mod Length(DISTINCT_COLORS)]; -end; - function TSimbaImage.SaveToFile(FileName: String; OverwriteIfExists: Boolean): Boolean; var Stream: TFileStream; @@ -752,31 +744,20 @@ procedure TSimbaImage.LoadFromImage(Image: TSimbaImage); Move(Image.FData^, FData^, FWidth * FHeight * SizeOf(TColorBGRA)); end; -procedure TSimbaImage.DrawATPA(ATPA: T2DPointArray; Color: TColor); -var - I: Integer; +procedure TSimbaImage.DrawTPA(const TPA: TPointArray; Color: TColor; Alpha: Byte); begin - for I := 0 to High(ATPA) do - DrawTPA(ATPA[I], GetDistinctColor(Color, I)); + if (Alpha = 0) then + _DrawTPA(TPA, Color) + else + _DrawTPAAlpha(TPA, Color, Alpha); end; -procedure TSimbaImage.DrawTPA(Points: TPointArray; Color: TColor); +procedure TSimbaImage.DrawATPA(const ATPA: T2DPointArray; Color: TColor; Alpha: Byte); var I: Integer; - P: TPoint; - BGR: TColorBGRA; begin - if (Length(Points) = 0) then - Exit; - - BGR := ColorToBGRA(Color); - - for I := 0 to High(Points) do - begin - P := Points[I]; - if (P.X >= 0) and (P.Y >= 0) and (P.X < FWidth) and (P.Y < FHeight) then - FData[P.Y * FWidth + P.X] := BGR; - end; + for I := 0 to High(ATPA) do + DrawTPA(ATPA[I], GetDistinctColor(Color, I), Alpha); end; procedure TSimbaImage.DrawCrosshairs(ACenter: TPoint; Size: Integer; Color: TColor); @@ -1229,20 +1210,6 @@ procedure TSimbaImage.ReplaceColors(OldColors, NewColors: TColorArray); end; end; -function GetRotatedSize(W, H: Integer; Angle: Single): TBox; -var - B: TPointArray; -begin - B := [ - TSimbaGeometry.RotatePoint(Point(0, H), Angle, W div 2, H div 2), - TSimbaGeometry.RotatePoint(Point(W, H), Angle, W div 2, H div 2), - TSimbaGeometry.RotatePoint(Point(W, 0), Angle, W div 2, H div 2), - TSimbaGeometry.RotatePoint(Point(0, 0), Angle, W div 2, H div 2) - ]; - - Result := B.Bounds(); -end; - function TSimbaImage.RotateNN(Radians: Single; Expand: Boolean): TSimbaImage; var CosAngle, SinAngle: Single; @@ -2252,6 +2219,40 @@ procedure TSimbaImage.Pad(Amount: Integer); end; end; +procedure TSimbaImage._DrawTPA(const TPA: TPointArray; Color: TColor); +var + BGRA: TColorBGRA; + Point: TPoint; +begin + BGRA := Color.ToBGRA(); + + for Point in TPA do + if (Point.X >= 0) and (Point.Y >= 0) and (Point.X < FWidth) and (Point.Y < FHeight) then + FData[Point.Y * FWidth + Point.X] := BGRA; +end; + +procedure TSimbaImage._DrawTPAAlpha(const TPA: TPointArray; Color: TColor; Alpha: Byte); +var + R,G,B,A: Byte; + Point: TPoint; + Ptr: PColorBGRA; +begin + R := (Color.R * (255 - Alpha + 1)) shr 8; + G := (Color.G * (255 - Alpha + 1)) shr 8; + B := (Color.B * (255 - Alpha + 1)) shr 8; + A := Alpha + 1; + + for Point in TPA do + if (Point.X >= 0) and (Point.Y >= 0) and (Point.X < FWidth) and (Point.Y < FHeight) then + begin + Ptr := @FData[Point.Y * FWidth + Point.X]; + Ptr^.R := R + Ptr^.R * A shr 8; + Ptr^.G := G + Ptr^.G * A shr 8; + Ptr^.B := B + Ptr^.B * A shr 8; + Ptr^.A := Alpha; + end; +end; + procedure TSimbaImage._DrawBoxFilled(Box: TBox; Color: TColor); var BGRA: TColorBGRA; diff --git a/Source/image/simba.image_utils.pas b/Source/image/simba.image_utils.pas index c3bce91bb..9866a0d69 100644 --- a/Source/image/simba.image_utils.pas +++ b/Source/image/simba.image_utils.pas @@ -8,10 +8,49 @@ interface Classes, SysUtils, simba.mufasatypes; -procedure FillData(Data: PColorBGRA; count: SizeInt; value: TColorBGRA); +// https://sashamaps.net/docs/resources/20-colors/ +const + DISTINCT_COLORS: TIntegerArray = ($4B19E6, $4BB43C, $19E1FF, $D86343, $3182F5, $B41E91, $F4D442, $E632F0, $45EFBF, $D4BEFA, $909946, $FFBEDC, $24639A, $C8FAFF, $000080, $C3FFAA, $008080, $B1D8FF, $750000, $A9A9A9); + +function GetDistinctColor(const Index: Integer): Integer; overload; inline; +function GetDistinctColor(const Color, Index: Integer): Integer; overload; inline; + +function GetRotatedSize(W, H: Integer; Angle: Single): TBox; + +procedure FillData(const Data: PColorBGRA; const count: SizeInt; const value: TColorBGRA); implementation +uses + simba.tpa, simba.geometry; + +function GetDistinctColor(const Index: Integer): Integer; +begin + Result := DISTINCT_COLORS[Index mod Length(DISTINCT_COLORS)]; +end; + +function GetDistinctColor(const Color, Index: Integer): Integer; +begin + if (Color > -1) then + Result := Color + else + Result := DISTINCT_COLORS[Index mod Length(DISTINCT_COLORS)]; +end; + +function GetRotatedSize(W, H: Integer; Angle: Single): TBox; +var + B: TPointArray; +begin + B := [ + TSimbaGeometry.RotatePoint(Point(0, H), Angle, W div 2, H div 2), + TSimbaGeometry.RotatePoint(Point(W, H), Angle, W div 2, H div 2), + TSimbaGeometry.RotatePoint(Point(W, 0), Angle, W div 2, H div 2), + TSimbaGeometry.RotatePoint(Point(0, 0), Angle, W div 2, H div 2) + ]; + + Result := B.Bounds(); +end; + // in FPC trunk {$IFDEF CPUX86_64} procedure FillXxxx_MoreThanTwoXmms; assembler; nostackframe; @@ -136,7 +175,7 @@ procedure FillDWord(var x;count:SizeInt;value:DWord);assembler;nostackframe; end; {$ENDIF} -procedure FillData(Data: PColorBGRA; count: SizeInt; value: TColorBGRA); +procedure FillData(const Data: PColorBGRA; const count: SizeInt; const value: TColorBGRA); begin FillDWord(Data^, Count, DWord(Value)); end; diff --git a/Source/script/imports/simbaclasses/simba.import_class_image.pas b/Source/script/imports/simbaclasses/simba.import_class_image.pas index d8f93ddc0..4fbe871e8 100644 --- a/Source/script/imports/simbaclasses/simba.import_class_image.pas +++ b/Source/script/imports/simbaclasses/simba.import_class_image.pas @@ -25,8 +25,15 @@ implementation ===== TImage is a data type that holds an image. -This is used anipulate and process an image such as resizing, rotating, bluring and much more. +This is used manipulate and process an image such as resizing, rotating, bluring and much more. Or simply get/set a pixel color at a given (x,y) coord. + +Note: + + | For methods with a `Alpha` parameter "real" alpha blending is not performed. + | The background of the pixel is just mixed in. + | If `Alpha=127` half of the background will be blended in. + *) (* @@ -182,21 +189,25 @@ procedure _LapeImage_LoadFromFileEx(const Params: PParamArray); LAPE_WRAPPER_CAL (* TImage.DrawATPA ~~~~~~~~~~~~~~~ -> procedure TImage.DrawATPA(ATPA: T2DPointArray; Color: TColor = -1); +> procedure TImage.DrawATPA(const ATPA: T2DPointArray; Color: TColor = -1; Alpha: Byte = 0); + +Draws every TPA in the ATPA. Color by default is -1 which will display each TPA in a different color. *) procedure _LapeImage_DrawATPA(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin - PSimbaImage(Params^[0])^.DrawATPA(P2DPointArray(Params^[1])^, PColor(Params^[2])^); + PSimbaImage(Params^[0])^.DrawATPA(P2DPointArray(Params^[1])^, PColor(Params^[2])^, PByte(Params^[3])^); end; (* TImage.DrawTPA ~~~~~~~~~~~~~~ -> procedure TImage.DrawTPA(TPA: TPointArray; Color: TColor); +> procedure TImage.DrawTPA(const Points: TPointArray; Color: TColor; Alpha: Byte = 0); + +Draws a TPA the same color. *) procedure _LapeImage_DrawTPA(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin - PSimbaImage(Params^[0])^.DrawTPA(PPointArray(Params^[1])^, PColor(Params^[2])^); + PSimbaImage(Params^[0])^.DrawTPA(PPointArray(Params^[1])^, PColor(Params^[2])^, PByte(Params^[3])^); end; (* @@ -1238,16 +1249,31 @@ procedure _LapeImage_RowPtrs(const Params: PParamArray; const Result: Pointer); TSimbaImageRowPtrs(Result^) := PSimbaImage(Params^[0])^.RowPtrs(); end; +(* +TImage.DrawLineAA +~~~~~~~~~~~~~~~~~~~~ +> procedure TImage.DrawLineAA(Start, Stop: TPoint; Color: TColor; Thickness: Single = 1.5); +*) procedure _LapeImage_DrawLineAA(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin PSimbaImage(Params^[0])^.DrawLineAA(PPoint(Params^[1])^, PPoint(Params^[2])^, PColor(Params^[3])^, PSingle(Params^[4])^); end; +(* +TImage.DrawEllipseAA +~~~~~~~~~~~~~~~~~~~~ +> procedure TImage.DrawEllipseAA(ACenter: TPoint; XRadius, YRadius: Integer; Color: TColor; Thickness: Single = 1.5); +*) procedure _LapeImage_DrawEllipseAA(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin PSimbaImage(Params^[0])^.DrawEllipseAA(PPoint(Params^[1])^, Pinteger(Params^[2])^, PInteger(Params^[3])^, PColor(Params^[4])^, PSingle(Params^[5])^); end; +(* +TImage.DrawCircleAA +~~~~~~~~~~~~~~~~~~~~ +> procedure TImage.DrawCircleAA(ACenter: TPoint; Radius: Integer; Color: TColor; Thickness: Single = 1.5); +*) procedure _LapeImage_DrawCircleAA(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin PSimbaImage(Params^[0])^.DrawCircleAA(PPoint(Params^[1])^, Pinteger(Params^[2])^, PColor(Params^[3])^, PSingle(Params^[4])^); @@ -1255,7 +1281,7 @@ procedure _LapeImage_DrawCircleAA(const Params: PParamArray); LAPE_WRAPPER_CALLI (* TImage.Finder -~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~ > function TImage.Finder: TSimbaFinder; Returns a TSimbaFinder which is targetted to the image. @@ -1362,8 +1388,8 @@ procedure ImportSimbaImage(Compiler: TSimbaScript_Compiler); addGlobalFunc('procedure TImage.DrawText(Text: String; Box: TBox; Center: Boolean; Color: TColor); overload', @_LapeImage_DrawTextEx); addGlobalFunc('procedure TImage.DrawTextLines(Text: TStringArray; Position: TPoint; Color: TColor);', @_LapeImage_DrawTextLines); - addGlobalFunc('procedure TImage.DrawATPA(ATPA: T2DPointArray; Color: TColor = -1)', @_LapeImage_DrawATPA); - addGlobalFunc('procedure TImage.DrawTPA(TPA: TPointArray; Color: TColor);', @_LapeImage_DrawTPA); + addGlobalFunc('procedure TImage.DrawATPA(const ATPA: T2DPointArray; Color: TColor = -1; Alpha: Byte = 0);', @_LapeImage_DrawATPA); + addGlobalFunc('procedure TImage.DrawTPA(const TPA: TPointArray; Color: TColor; Alpha: Byte = 0);', @_LapeImage_DrawTPA); addGlobalFunc('procedure TImage.DrawCrosshairs(ACenter: TPoint; Size: Integer; Color: TColor);', @_LapeImage_DrawCrosshairs); addGlobalFunc('procedure TImage.DrawCross(ACenter: TPoint; Radius: Integer; Color: TColor);', @_LapeImage_DrawCross); diff --git a/Source/simba.env.pas b/Source/simba.env.pas index 74479305b..bb9949ede 100644 --- a/Source/simba.env.pas +++ b/Source/simba.env.pas @@ -10,7 +10,7 @@ interface uses - classes, sysutils, + Classes, SysUtils, simba.mufasatypes; function FindInclude(var FileName: String; ExtraSearchDirs: TStringArray): Boolean; diff --git a/Source/simba.tpa.pas b/Source/simba.tpa.pas index afe096eb3..6636b7160 100644 --- a/Source/simba.tpa.pas +++ b/Source/simba.tpa.pas @@ -690,23 +690,23 @@ function TPointArrayHelper.Skeleton(FMin: Integer; FMax: Integer): TPointArray; Change, PTS: TPointArray; Matrix: TByteMatrix; iter: Boolean; - Area: TBox; + B: TBox; begin Result := Default(TPointArray); H := High(Self); if (H > 0) then begin - Area := Self.Bounds; - Area.x1 := Area.x1 - 2; - Area.y1 := Area.y1 - 2; - Matrix.SetSize(Area.Height + 2, Area.Width + 2); + B := Self.Bounds; + B.x1 := B.x1 - 2; + B.y1 := B.y1 - 2; + Matrix.SetSize(B.Height + 2, B.Width + 2); SetLength(PTS, H + 1); for i:=0 to H do begin - x := (Self[i].x-Area.x1); - y := (Self[i].y-Area.y1); + x := (Self[i].x-B.x1); + y := (Self[i].y-B.y1); PTS[i].x := X; PTS[i].y := Y; Matrix[y][x] := 1; @@ -770,7 +770,7 @@ function TPointArrayHelper.Skeleton(FMin: Integer; FMax: Integer): TPointArray; SetLength(Result, (MarkHigh + 1)); for i := 0 to MarkHigh do - Result[i] := TPoint.Create(PTS[i].x+Area.x1, PTS[i].y+Area.y1); + Result[i] := TPoint.Create(PTS[i].x+B.x1, PTS[i].y+B.y1); end; end;