GR32_Polygons.Blend2D.pas 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. unit GR32_Polygons.Blend2D;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Blend2D Polygon Rasterizer for Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Anders Melander
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2025
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * Contributor(s):
  31. *
  32. * ***** END LICENSE BLOCK ***** *)
  33. interface
  34. {$include GR32.inc}
  35. {$IFDEF FPC}
  36. {$DEFINE PUREPASCAL}
  37. {$ENDIF}
  38. uses
  39. Types,
  40. // Requires DelphiBlend2D
  41. // https://github.com/neslib/DelphiBlend2D
  42. Blend2D,
  43. GR32,
  44. GR32_Polygons;
  45. //------------------------------------------------------------------------------
  46. //
  47. // TPolygonRenderer32Blend2D
  48. //
  49. //------------------------------------------------------------------------------
  50. // Blend2D polygon rasterizer.
  51. //------------------------------------------------------------------------------
  52. // Note: The Filler property of TPolygonRenderer32 is ignored; Fills are always
  53. // solid.
  54. //------------------------------------------------------------------------------
  55. type
  56. // TPolygonRenderer32Blend2D = class(TPolygonRenderer32)
  57. TPolygonRenderer32Blend2D = class(TPolygonRenderer32, IPolygonRendererBatching)
  58. private
  59. FImage: IBLImage;
  60. FContext: IBLContext;
  61. FBatchLevel: integer;
  62. FInnerBatchLevel: integer;
  63. private
  64. procedure InnerBeginDraw;
  65. procedure InnerEndDraw;
  66. protected
  67. procedure SetBitmap(const Value: TCustomBitmap32); override;
  68. procedure SetColor(const Value: TColor32); override;
  69. procedure SetFillMode(const Value: TPolyFillMode); override;
  70. public
  71. constructor Create; override;
  72. destructor Destroy; override;
  73. procedure BeginDraw;
  74. procedure EndDraw;
  75. procedure PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect); override;
  76. end;
  77. //------------------------------------------------------------------------------
  78. //------------------------------------------------------------------------------
  79. //------------------------------------------------------------------------------
  80. implementation
  81. uses
  82. Math,
  83. SysUtils,
  84. GR32_VectorUtils,
  85. GR32_Backends;
  86. //------------------------------------------------------------------------------
  87. //
  88. // TPolygonRenderer32Blend2D
  89. //
  90. //------------------------------------------------------------------------------
  91. constructor TPolygonRenderer32Blend2D.Create;
  92. begin
  93. inherited Create;
  94. FContext := TBLContext.Create;
  95. end;
  96. destructor TPolygonRenderer32Blend2D.Destroy;
  97. begin
  98. FImage := nil;
  99. FContext := nil;
  100. inherited;
  101. end;
  102. //------------------------------------------------------------------------------
  103. procedure TPolygonRenderer32Blend2D.BeginDraw;
  104. begin
  105. Inc(FBatchLevel);
  106. if (FBatchLevel = 1) and (FImage <> nil) then
  107. FContext.Start(FImage);
  108. end;
  109. procedure TPolygonRenderer32Blend2D.EndDraw;
  110. begin
  111. Dec(FBatchLevel);
  112. if (FBatchLevel = 0) and (FImage <> nil) then
  113. FContext.Finish;
  114. end;
  115. //------------------------------------------------------------------------------
  116. procedure TPolygonRenderer32Blend2D.InnerBeginDraw;
  117. const
  118. b2dFillMode: array[TPolyFillMode] of TBLFillRule = (TBLFillRule.EvenOdd, TBLFillRule.NonZero);
  119. begin
  120. BeginDraw;
  121. Inc(FInnerBatchLevel);
  122. if (FInnerBatchLevel = 1) then
  123. begin
  124. FContext.FillColor := Color;
  125. FContext.FillRule := b2dFillMode[FillMode];
  126. end;
  127. end;
  128. procedure TPolygonRenderer32Blend2D.InnerEndDraw;
  129. begin
  130. Dec(FInnerBatchLevel);
  131. EndDraw;
  132. end;
  133. //------------------------------------------------------------------------------
  134. procedure TPolygonRenderer32Blend2D.SetBitmap(const Value: TCustomBitmap32);
  135. begin
  136. if (Value = Bitmap) then
  137. exit;
  138. Assert(FInnerBatchLevel = 0, 'Cannot alter state inside InnerBeginDraw/InnerEndDraw');
  139. if (FImage <> nil) then
  140. begin
  141. if (FBatchLevel > 0) then
  142. FContext.Finish;
  143. FImage := nil;
  144. end;
  145. inherited;
  146. if (Bitmap <> nil) then
  147. begin
  148. FImage := TBLImage.Create;
  149. FImage.InitializeFromData(Bitmap.Width, Bitmap.Height, TBLFormat.PRGB32, Bitmap.Bits, Bitmap.Width*SizeOf(TColor32));
  150. if (FBatchLevel > 0) then
  151. FContext.Start(FImage);
  152. end;
  153. end;
  154. //------------------------------------------------------------------------------
  155. procedure TPolygonRenderer32Blend2D.SetColor(const Value: TColor32);
  156. begin
  157. if (Value = Color) then
  158. exit;
  159. Assert(FInnerBatchLevel = 0, 'Cannot alter state inside InnerBeginDraw/InnerEndDraw');
  160. inherited;
  161. end;
  162. procedure TPolygonRenderer32Blend2D.SetFillMode(const Value: TPolyFillMode);
  163. begin
  164. if (Value = FillMode) then
  165. exit;
  166. Assert(FInnerBatchLevel = 0, 'Cannot alter state inside InnerBeginDraw/InnerEndDraw');
  167. inherited;
  168. end;
  169. //------------------------------------------------------------------------------
  170. type
  171. TBitmap32Access = class(TBitmap32);
  172. procedure TPolygonRenderer32Blend2D.PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect);
  173. var
  174. i, j: Integer;
  175. Path: IBLPath;
  176. {$IFDEF CHANGENOTIFICATIONS}
  177. ChangeRect: TRect;
  178. {$ENDIF}
  179. begin
  180. if (Length(Points) = 0) then
  181. Exit;
  182. if (FImage = nil) then
  183. exit;
  184. if (not Bitmap.MeasuringMode) then
  185. begin
  186. InnerBeginDraw;
  187. Path := TBLPath.Create;
  188. for j := 0 to High(Points) do
  189. if (Length(Points[j]) > 1) then
  190. begin
  191. Path.MoveTo(Points[j, 0].X, Points[j, 0].Y);
  192. for i := 1 to High(Points[j]) do
  193. Path.LineTo(Points[j, i].X, Points[j, i].Y);
  194. Path.Close;
  195. end;
  196. FContext.FillPath(Path);
  197. Path := nil;
  198. InnerEndDraw;
  199. end;
  200. {$IFDEF CHANGENOTIFICATIONS}
  201. if (TBitmap32Access(Bitmap).LockUpdateCount = 0) and
  202. ((Bitmap.MeasuringMode) or (TBitmap32Access(Bitmap).UpdateCount = 0)) then
  203. begin
  204. for i := 0 to High(Points) do
  205. if (Length(Points[i]) > 1) then
  206. begin
  207. if (GR32.IntersectRect(ChangeRect, MakeRect(ClipRect, rrOutside), MakeRect(PolygonBounds(Points[i])))) then
  208. Bitmap.Changed(ChangeRect);
  209. end;
  210. end;
  211. {$ENDIF}
  212. end;
  213. //------------------------------------------------------------------------------
  214. initialization
  215. RegisterPolygonRenderer(TPolygonRenderer32Blend2D);
  216. end.