GR32_Polygons.GDIPlus.pas 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. unit GR32_Polygons.GDIPlus;
  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. GDIPAPI,
  41. GDIPOBJ,
  42. GR32,
  43. GR32_Polygons;
  44. //------------------------------------------------------------------------------
  45. //
  46. // TCustomPolygonRenderer32GDIPlus
  47. //
  48. //------------------------------------------------------------------------------
  49. // GDI+ polygon rasterizer base class.
  50. //------------------------------------------------------------------------------
  51. // Note: The Filler property of TPolygonRenderer32 is ignored; Fills are always
  52. // solid.
  53. //------------------------------------------------------------------------------
  54. type
  55. TGDIPlusQuality = (gdipQualityLow, gdipQualityHigh);
  56. TCustomPolygonRenderer32GDIPlus = class(TPolygonRenderer32)
  57. private
  58. FGPGraphics: TGPGraphics;
  59. FPath: TGPGraphicsPath;
  60. FBrush: TGPSolidBrush;
  61. FQuality: TGDIPlusQuality;
  62. protected
  63. procedure SetBitmap(const Value: TCustomBitmap32); override;
  64. procedure SetColor(const Value: TColor32); override;
  65. procedure ApplyQualitySetting;
  66. procedure SetQuality(const Value: TGDIPlusQuality);
  67. property Quality: TGDIPlusQuality read FQuality write SetQuality;
  68. public
  69. constructor Create; override;
  70. destructor Destroy; override;
  71. procedure PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect); override;
  72. end;
  73. //------------------------------------------------------------------------------
  74. //
  75. // TPolygonRenderer32GDIPlus
  76. //
  77. //------------------------------------------------------------------------------
  78. // GDI+ polygon rasterizer. Quality can be set through the Quality property.
  79. // This rasterizer isn't registered in the global rasterizer registry.
  80. //------------------------------------------------------------------------------
  81. type
  82. TPolygonRenderer32GDIPlus = class(TCustomPolygonRenderer32GDIPlus)
  83. public
  84. property Quality;
  85. end;
  86. //------------------------------------------------------------------------------
  87. //
  88. // TPolygonRenderer32GDIPlusLowQuality
  89. //
  90. //------------------------------------------------------------------------------
  91. // Fast GDI+ polygon rasterizer.
  92. // Does not perform anti-aliasing.
  93. // "Fast" means faster the the slow GDI+ rasterizer.
  94. //------------------------------------------------------------------------------
  95. type
  96. TPolygonRenderer32GDIPlusLowQuality = class(TCustomPolygonRenderer32GDIPlus)
  97. public
  98. constructor Create; override;
  99. end;
  100. //------------------------------------------------------------------------------
  101. //
  102. // TPolygonRenderer32GDIPlusHighQuality
  103. //
  104. //------------------------------------------------------------------------------
  105. // High quality GDI+ polygon rasterizer.
  106. // Performs anti-aliasing (16 levels I think).
  107. // Slower than the "fast" GDI+ rasterizer.
  108. //------------------------------------------------------------------------------
  109. type
  110. TPolygonRenderer32GDIPlusHighQuality = class(TCustomPolygonRenderer32GDIPlus)
  111. public
  112. constructor Create; override;
  113. end;
  114. //------------------------------------------------------------------------------
  115. //------------------------------------------------------------------------------
  116. //------------------------------------------------------------------------------
  117. implementation
  118. uses
  119. Math,
  120. SysUtils,
  121. GR32_VectorUtils,
  122. GR32_Backends;
  123. //------------------------------------------------------------------------------
  124. //
  125. // TCustomPolygonRenderer32GDIPlus
  126. //
  127. //------------------------------------------------------------------------------
  128. constructor TCustomPolygonRenderer32GDIPlus.Create;
  129. begin
  130. inherited Create;
  131. FPath := TGPGraphicsPath.Create;
  132. FBrush := TGPSolidBrush.Create(Color);
  133. end;
  134. destructor TCustomPolygonRenderer32GDIPlus.Destroy;
  135. begin
  136. FGPGraphics.Free;
  137. FPath.Free;
  138. FBrush.Free;
  139. inherited;
  140. end;
  141. //------------------------------------------------------------------------------
  142. procedure TCustomPolygonRenderer32GDIPlus.SetBitmap(const Value: TCustomBitmap32);
  143. var
  144. DeviceContextSupport: IDeviceContextSupport;
  145. begin
  146. FGPGraphics.Free;
  147. FGPGraphics := nil;
  148. inherited;
  149. if (Bitmap <> nil) and (Supports(Bitmap.Backend, IDeviceContextSupport, DeviceContextSupport)) then
  150. begin
  151. FGPGraphics := TGPGraphics.Create(DeviceContextSupport.Handle);
  152. ApplyQualitySetting;
  153. end;
  154. end;
  155. //------------------------------------------------------------------------------
  156. procedure TCustomPolygonRenderer32GDIPlus.ApplyQualitySetting;
  157. begin
  158. if (FGPGraphics = nil) then
  159. exit;
  160. case FQuality of
  161. gdipQualityLow:
  162. FGPGraphics.SetSmoothingMode(SmoothingModeHighSpeed);
  163. gdipQualityHigh:
  164. FGPGraphics.SetSmoothingMode(SmoothingModeHighQuality);
  165. end;
  166. end;
  167. //------------------------------------------------------------------------------
  168. procedure TCustomPolygonRenderer32GDIPlus.SetColor(const Value: TColor32);
  169. begin
  170. inherited;
  171. FBrush.SetColor(Color);
  172. end;
  173. //------------------------------------------------------------------------------
  174. procedure TCustomPolygonRenderer32GDIPlus.SetQuality(const Value: TGDIPlusQuality);
  175. begin
  176. FQuality := Value;
  177. ApplyQualitySetting;
  178. end;
  179. //------------------------------------------------------------------------------
  180. type
  181. TBitmap32Access = class(TBitmap32);
  182. procedure TCustomPolygonRenderer32GDIPlus.PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect);
  183. const
  184. gdipFillMode: array[TPolyFillMode] of GDIPAPI.TFillMode = (FillModeAlternate, FillModeWinding);
  185. var
  186. i, j: Integer;
  187. {$IFDEF CHANGENOTIFICATIONS}
  188. ChangeRect: TRect;
  189. {$ENDIF}
  190. begin
  191. if (Length(Points) = 0) then
  192. Exit;
  193. if (FGPGraphics = nil) then
  194. exit;
  195. if (not Bitmap.MeasuringMode) then
  196. begin
  197. // FPath.Reset clears the fillmode (to Alternate), so we have to apply it every time
  198. FPath.SetFillMode(gdipFillMode[FillMode]);
  199. for j := 0 to High(Points) do
  200. if (Length(Points[j]) > 0) then
  201. FPath.AddPolygon(PGPPointF(@Points[j, 0]), Length(Points[j]));
  202. FGPGraphics.FillPath(FBrush, FPath);
  203. FPath.Reset;
  204. end;
  205. {$IFDEF CHANGENOTIFICATIONS}
  206. if (TBitmap32Access(Bitmap).LockUpdateCount = 0) and
  207. ((Bitmap.MeasuringMode) or (TBitmap32Access(Bitmap).UpdateCount = 0)) then
  208. begin
  209. for i := 0 to High(Points) do
  210. if (Length(Points[i]) > 0) then
  211. begin
  212. if (GR32.IntersectRect(ChangeRect, MakeRect(ClipRect, rrOutside), MakeRect(PolygonBounds(Points[i])))) then
  213. Bitmap.Changed(ChangeRect);
  214. end;
  215. end;
  216. {$ENDIF}
  217. end;
  218. //------------------------------------------------------------------------------
  219. //
  220. // TPolygonRenderer32GDIPlusLowQuality
  221. //
  222. //------------------------------------------------------------------------------
  223. constructor TPolygonRenderer32GDIPlusLowQuality.Create;
  224. begin
  225. inherited;
  226. SetQuality(gdipQualityLow);
  227. end;
  228. //------------------------------------------------------------------------------
  229. //
  230. // TPolygonRenderer32GDIPlusHighQuality
  231. //
  232. //------------------------------------------------------------------------------
  233. constructor TPolygonRenderer32GDIPlusHighQuality.Create;
  234. begin
  235. inherited;
  236. SetQuality(gdipQualityHigh);
  237. end;
  238. //------------------------------------------------------------------------------
  239. initialization
  240. RegisterPolygonRenderer(TPolygonRenderer32GDIPlusLowQuality);
  241. RegisterPolygonRenderer(TPolygonRenderer32GDIPlusHighQuality);
  242. end.