GR32_Polygons.GDI.pas 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. unit GR32_Polygons.GDI;
  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 GDI 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. Graphics,
  41. GR32,
  42. GR32_Polygons;
  43. //------------------------------------------------------------------------------
  44. //
  45. // TPolygonRenderer32GDI
  46. //
  47. //------------------------------------------------------------------------------
  48. // GDI polygon rasterizer.
  49. //------------------------------------------------------------------------------
  50. // Note: The Filler property of TPolygonRenderer32 is ignored; Fills are always
  51. // solid.
  52. // Semi-transparency is not supported; All fills are opaque.
  53. //------------------------------------------------------------------------------
  54. type
  55. TPolygonRenderer32GDI = class(TPolygonRenderer32)
  56. private
  57. FCanvas: TCanvas;
  58. protected
  59. procedure SetBitmap(const Value: TCustomBitmap32); override;
  60. procedure SetColor(const Value: TColor32); override;
  61. public
  62. constructor Create; override;
  63. destructor Destroy; override;
  64. procedure PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect); override;
  65. end;
  66. //------------------------------------------------------------------------------
  67. //------------------------------------------------------------------------------
  68. //------------------------------------------------------------------------------
  69. implementation
  70. uses
  71. Math,
  72. SysUtils,
  73. UITypes,
  74. Windows,
  75. GR32_VectorUtils,
  76. GR32_Backends;
  77. //------------------------------------------------------------------------------
  78. //
  79. // TPolygonRenderer32GDI
  80. //
  81. //------------------------------------------------------------------------------
  82. constructor TPolygonRenderer32GDI.Create;
  83. begin
  84. inherited Create;
  85. FCanvas := TCanvas.Create;
  86. FCanvas.Brush.Style := bsSolid;
  87. FCanvas.Pen.Style := psClear;
  88. end;
  89. destructor TPolygonRenderer32GDI.Destroy;
  90. begin
  91. FCanvas.Free;
  92. inherited;
  93. end;
  94. //------------------------------------------------------------------------------
  95. procedure TPolygonRenderer32GDI.SetBitmap(const Value: TCustomBitmap32);
  96. var
  97. DeviceContextSupport: IDeviceContextSupport;
  98. begin
  99. if (Value = Bitmap) then
  100. exit;
  101. FCanvas.Handle := 0;
  102. inherited;
  103. if (Bitmap <> nil) and (Supports(Bitmap.Backend, IDeviceContextSupport, DeviceContextSupport)) then
  104. FCanvas.Handle := DeviceContextSupport.Handle;
  105. end;
  106. //------------------------------------------------------------------------------
  107. procedure TPolygonRenderer32GDI.SetColor(const Value: TColor32);
  108. begin
  109. if (TColor(Value and $00FFFFFF) = FCanvas.Brush.Color) then
  110. exit;
  111. inherited;
  112. FCanvas.Brush.Color := Value and $00FFFFFF;
  113. end;
  114. //------------------------------------------------------------------------------
  115. type
  116. TBitmap32Access = class(TBitmap32);
  117. procedure TPolygonRenderer32GDI.PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect);
  118. const
  119. GdiFillMode: array[TPolyFillMode] of integer = (ALTERNATE, WINDING);
  120. var
  121. i, j: Integer;
  122. {$IFDEF CHANGENOTIFICATIONS}
  123. ChangeRect: TRect;
  124. {$ENDIF}
  125. PolyPoints: array of tagPoint;
  126. PolyCount: array of longint;
  127. n: integer;
  128. Counts: integer;
  129. begin
  130. if (Length(Points) = 0) then
  131. Exit;
  132. if (FCanvas = nil) then
  133. exit;
  134. if (not Bitmap.MeasuringMode) then
  135. begin
  136. n := 0;
  137. Counts := 0;
  138. for j := 0 to High(Points) do
  139. begin
  140. if (Length(Points[j]) = 0) then
  141. continue;
  142. Inc(Counts);
  143. Inc(n, Length(Points[j]));
  144. end;
  145. if (n = 0) then
  146. exit;
  147. SetLength(PolyPoints, n);
  148. SetLength(PolyCount, Counts);
  149. n := 0;
  150. Counts := 0;
  151. for j := 0 to High(Points) do
  152. begin
  153. if (Length(Points[j]) = 0) then
  154. continue;
  155. PolyCount[Counts] := Length(Points[j]);
  156. Inc(Counts);
  157. for i := 0 to High(Points[j]) do
  158. begin
  159. PolyPoints[n] := GR32.Point(Points[j, i]);
  160. Inc(n);
  161. end;
  162. end;
  163. SetPolyFillMode(FCanvas.Handle, GdiFillMode[FillMode]);
  164. if (not Windows.PolyPolygon(FCanvas.Handle, PolyPoints[0], PolyCount[0], Counts)) then
  165. RaiseLastOSError;
  166. end;
  167. {$IFDEF CHANGENOTIFICATIONS}
  168. if (TBitmap32Access(Bitmap).LockUpdateCount = 0) and
  169. ((Bitmap.MeasuringMode) or (TBitmap32Access(Bitmap).UpdateCount = 0)) then
  170. begin
  171. for i := 0 to High(Points) do
  172. if (Length(Points[i]) > 1) then
  173. begin
  174. if (GR32.IntersectRect(ChangeRect, MakeRect(ClipRect, rrOutside), MakeRect(PolygonBounds(Points[i])))) then
  175. Bitmap.Changed(ChangeRect);
  176. end;
  177. end;
  178. {$ENDIF}
  179. end;
  180. //------------------------------------------------------------------------------
  181. initialization
  182. RegisterPolygonRenderer(TPolygonRenderer32GDI);
  183. end.