GR32_PolygonsAggLite.pas 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933
  1. unit GR32_PolygonsAggLite;
  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 a mixture of AggLite and the other polygon renderers of
  23. * Graphics32
  24. *
  25. * The Initial Developer is
  26. * Christian-W. Budde <[email protected]>
  27. *
  28. * Portions created by the Initial Developer are Copyright (C) 2008-2012
  29. * the Initial Developer. All Rights Reserved.
  30. *
  31. * AggLite is based on Anti-Grain Geometry (Version 2.0)
  32. * Copyright (C) 2002-2004 Maxim Shemanarev (McSeem)
  33. *
  34. * Permission to copy, use, modify, sell and distribute this software
  35. * is granted provided this copyright notice appears in all copies.
  36. * This software is provided "as is" without express or implied
  37. * warranty, and with no claim as to its suitability for any purpose.
  38. *
  39. * Contributor(s):
  40. *
  41. * ***** END LICENSE BLOCK ***** *)
  42. interface
  43. {$I GR32.inc}
  44. {$IFDEF FPC}
  45. {$DEFINE PUREPASCAL}
  46. {$ENDIF}
  47. uses
  48. Types, GR32, GR32_Polygons, GR32_Transforms;
  49. type
  50. TPolygonRenderer32AggLite = class(TPolygonRenderer32)
  51. protected
  52. procedure Render(CellsPtr: Pointer; MinX, MaxX: Integer);
  53. public
  54. procedure PolygonFS(const Points: TArrayOfFloatPoint;
  55. const ClipRect: TFloatRect); override;
  56. procedure PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint;
  57. const ClipRect: TFloatRect); override;
  58. end;
  59. procedure PolyPolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
  60. Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
  61. Transformation: TTransformation = nil); overload;
  62. procedure PolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  63. Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
  64. Transformation: TTransformation = nil); overload;
  65. procedure PolyPolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
  66. Filler: TCustomPolygonFiller; FillMode: TPolyFillMode = pfAlternate;
  67. Transformation: TTransformation = nil); overload;
  68. procedure PolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  69. Filler: TCustomPolygonFiller; FillMode: TPolyFillMode = pfAlternate;
  70. Transformation: TTransformation = nil); overload;
  71. procedure PolyPolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
  72. ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
  73. Transformation: TTransformation = nil); overload;
  74. procedure PolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  75. ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
  76. Transformation: TTransformation = nil); overload;
  77. procedure PolyPolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
  78. ClipRect: TRect; Filler: TCustomPolygonFiller; FillMode: TPolyFillMode = pfAlternate;
  79. Transformation: TTransformation = nil); overload;
  80. procedure PolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  81. ClipRect: TRect; Filler: TCustomPolygonFiller; FillMode: TPolyFillMode = pfAlternate;
  82. Transformation: TTransformation = nil); overload;
  83. procedure PolyPolylineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
  84. Color: TColor32; Closed: Boolean = False; StrokeWidth: TFloat = 1.0;
  85. JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
  86. MiterLimit: TFloat = 4.0; Transformation: TTransformation = nil); overload;
  87. procedure PolyPolylineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
  88. Filler: TCustomPolygonFiller; Closed: Boolean = False; StrokeWidth: TFloat = 1.0;
  89. JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
  90. MiterLimit: TFloat = 4.0; Transformation: TTransformation = nil); overload;
  91. procedure PolylineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  92. Color: TColor32; Closed: Boolean = False; StrokeWidth: TFloat = 1.0;
  93. JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
  94. MiterLimit: TFloat = 4.0; Transformation: TTransformation = nil); overload;
  95. procedure PolylineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  96. Filler: TCustomPolygonFiller; Closed: Boolean = False; StrokeWidth: TFloat = 1.0;
  97. JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
  98. MiterLimit: TFloat = 4.0; Transformation: TTransformation = nil); overload;
  99. procedure DashLineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  100. const Dashes: TArrayOfFloat; Color: TColor32;
  101. Closed: Boolean = False; Width: TFloat = 1.0); overload;
  102. procedure DashLineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  103. const Dashes: TArrayOfFloat; FillColor, StrokeColor: TColor32;
  104. Closed: Boolean; Width: TFloat; StrokeWidth: TFloat = 2.0); overload;
  105. procedure DashLineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  106. const Dashes: TArrayOfFloat; Filler: TCustomPolygonFiller;
  107. Closed: Boolean = False; Width: TFloat = 1.0); overload;
  108. procedure DashLineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  109. const Dashes: TArrayOfFloat; Filler: TCustomPolygonFiller; StrokeColor: TColor32;
  110. Closed: Boolean; Width: TFloat; StrokeWidth: TFloat = 2.0); overload;
  111. implementation
  112. uses
  113. Math, GR32_Blend, GR32_Gamma, GR32_LowLevel, GR32_System, GR32_Bindings,
  114. GR32_VectorUtils;
  115. procedure PolyPolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
  116. Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
  117. var
  118. Renderer: TPolygonRenderer32AggLite;
  119. begin
  120. Renderer := TPolygonRenderer32AggLite.Create;
  121. try
  122. Renderer.Bitmap := Bitmap;
  123. Renderer.Color := Color;
  124. Renderer.FillMode := FillMode;
  125. Renderer.PolyPolygonFS(Points, FloatRect(Bitmap.ClipRect), Transformation);
  126. finally
  127. Renderer.Free;
  128. end;
  129. end;
  130. procedure PolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  131. Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
  132. var
  133. Renderer: TPolygonRenderer32AggLite;
  134. begin
  135. Renderer := TPolygonRenderer32AggLite.Create;
  136. try
  137. Renderer.Bitmap := Bitmap;
  138. Renderer.Color := Color;
  139. Renderer.FillMode := FillMode;
  140. Renderer.PolygonFS(Points, FloatRect(Bitmap.ClipRect), Transformation);
  141. finally
  142. Renderer.Free;
  143. end;
  144. end;
  145. procedure PolyPolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
  146. Filler: TCustomPolygonFiller; FillMode: TPolyFillMode; Transformation: TTransformation);
  147. var
  148. Renderer: TPolygonRenderer32AggLite;
  149. begin
  150. if not Assigned(Filler) then Exit;
  151. Renderer := TPolygonRenderer32AggLite.Create;
  152. try
  153. Renderer.Bitmap := Bitmap;
  154. Renderer.Filler := Filler;
  155. Renderer.FillMode := FillMode;
  156. Renderer.PolyPolygonFS(Points, FloatRect(Bitmap.ClipRect), Transformation);
  157. finally
  158. Renderer.Free;
  159. end;
  160. end;
  161. procedure PolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  162. Filler: TCustomPolygonFiller; FillMode: TPolyFillMode; Transformation: TTransformation);
  163. var
  164. Renderer: TPolygonRenderer32AggLite;
  165. begin
  166. if not Assigned(Filler) then Exit;
  167. Renderer := TPolygonRenderer32AggLite.Create;
  168. try
  169. Renderer.Bitmap := Bitmap;
  170. Renderer.Filler := Filler;
  171. Renderer.FillMode := FillMode;
  172. Renderer.PolygonFS(Points, FloatRect(Bitmap.ClipRect), Transformation);
  173. finally
  174. Renderer.Free;
  175. end;
  176. end;
  177. procedure PolyPolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
  178. ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode;
  179. Transformation: TTransformation);
  180. var
  181. Renderer: TPolygonRenderer32AggLite;
  182. IntersectedClipRect: TRect;
  183. begin
  184. Renderer := TPolygonRenderer32AggLite.Create;
  185. try
  186. Renderer.Bitmap := Bitmap;
  187. Renderer.Color := Color;
  188. Renderer.FillMode := FillMode;
  189. GR32.IntersectRect(IntersectedClipRect, Bitmap.ClipRect, ClipRect);
  190. Renderer.PolyPolygonFS(Points, FloatRect(IntersectedClipRect), Transformation);
  191. finally
  192. Renderer.Free;
  193. end;
  194. end;
  195. procedure PolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  196. ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode;
  197. Transformation: TTransformation);
  198. var
  199. Renderer: TPolygonRenderer32AggLite;
  200. IntersectedClipRect: TRect;
  201. begin
  202. Renderer := TPolygonRenderer32AggLite.Create;
  203. try
  204. Renderer.Bitmap := Bitmap;
  205. Renderer.Color := Color;
  206. Renderer.FillMode := FillMode;
  207. GR32.IntersectRect(IntersectedClipRect, Bitmap.ClipRect, ClipRect);
  208. Renderer.PolygonFS(Points, FloatRect(IntersectedClipRect), Transformation);
  209. finally
  210. Renderer.Free;
  211. end;
  212. end;
  213. procedure PolyPolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
  214. ClipRect: TRect; Filler: TCustomPolygonFiller; FillMode: TPolyFillMode;
  215. Transformation: TTransformation);
  216. var
  217. Renderer: TPolygonRenderer32AggLite;
  218. IntersectedClipRect: TRect;
  219. begin
  220. if not Assigned(Filler) then Exit;
  221. Renderer := TPolygonRenderer32AggLite.Create;
  222. try
  223. Renderer.Bitmap := Bitmap;
  224. Renderer.Filler := Filler;
  225. Renderer.FillMode := FillMode;
  226. GR32.IntersectRect(IntersectedClipRect, Bitmap.ClipRect, ClipRect);
  227. Renderer.PolyPolygonFS(Points, FloatRect(IntersectedClipRect), Transformation);
  228. finally
  229. Renderer.Free;
  230. end;
  231. end;
  232. procedure PolygonFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  233. ClipRect: TRect; Filler: TCustomPolygonFiller; FillMode: TPolyFillMode;
  234. Transformation: TTransformation);
  235. var
  236. Renderer: TPolygonRenderer32AggLite;
  237. IntersectedClipRect: TRect;
  238. begin
  239. if not Assigned(Filler) then Exit;
  240. Renderer := TPolygonRenderer32AggLite.Create;
  241. try
  242. Renderer.Bitmap := Bitmap;
  243. Renderer.Filler := Filler;
  244. Renderer.FillMode := FillMode;
  245. GR32.IntersectRect(IntersectedClipRect, Bitmap.ClipRect, ClipRect);
  246. Renderer.PolygonFS(Points, FloatRect(IntersectedClipRect), Transformation);
  247. finally
  248. Renderer.Free;
  249. end;
  250. end;
  251. procedure PolyPolylineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
  252. Color: TColor32; Closed: Boolean; StrokeWidth: TFloat;
  253. JoinStyle: TJoinStyle; EndStyle: TEndStyle;
  254. MiterLimit: TFloat; Transformation: TTransformation);
  255. var
  256. Dst: TArrayOfArrayOfFloatPoint;
  257. begin
  258. Dst := BuildPolyPolyLine(Points, Closed, StrokeWidth, JoinStyle, EndStyle, MiterLimit);
  259. PolyPolygonFS_AggLite(Bitmap, Dst, Color, pfWinding, Transformation);
  260. end;
  261. procedure PolyPolylineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
  262. Filler: TCustomPolygonFiller; Closed: Boolean = False; StrokeWidth: TFloat = 1.0;
  263. JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
  264. MiterLimit: TFloat = 4.0; Transformation: TTransformation = nil);
  265. var
  266. Dst: TArrayOfArrayOfFloatPoint;
  267. begin
  268. Dst := BuildPolyPolyLine(Points, Closed, StrokeWidth, JoinStyle, EndStyle, MiterLimit);
  269. PolyPolygonFS(Bitmap, Dst, Filler, pfWinding, Transformation);
  270. end;
  271. procedure PolylineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  272. Color: TColor32; Closed: Boolean; StrokeWidth: TFloat;
  273. JoinStyle: TJoinStyle; EndStyle: TEndStyle;
  274. MiterLimit: TFloat; Transformation: TTransformation);
  275. begin
  276. PolyPolylineFS_AggLite(Bitmap, PolyPolygon(Points), Color, Closed, StrokeWidth,
  277. JoinStyle, EndStyle, MiterLimit, Transformation);
  278. end;
  279. procedure PolylineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  280. Filler: TCustomPolygonFiller; Closed: Boolean = False; StrokeWidth: TFloat = 1.0;
  281. JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
  282. MiterLimit: TFloat = 4.0; Transformation: TTransformation = nil);
  283. begin
  284. PolyPolylineFS_AggLite(Bitmap, PolyPolygon(Points), Filler, Closed, StrokeWidth,
  285. JoinStyle, EndStyle, MiterLimit, Transformation);
  286. end;
  287. procedure DashLineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  288. const Dashes: TArrayOfFloat; Color: TColor32;
  289. Closed: Boolean = False; Width: TFloat = 1.0);
  290. var
  291. MultiPoly: TArrayOfArrayOfFloatPoint;
  292. begin
  293. MultiPoly := GR32_VectorUtils.BuildDashedLine(Points, Dashes, 0, Closed);
  294. PolyPolylineFS_AggLite(Bitmap, MultiPoly, Color, False, Width);
  295. end;
  296. procedure DashLineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  297. const Dashes: TArrayOfFloat; FillColor, StrokeColor: TColor32;
  298. Closed: Boolean; Width: TFloat; StrokeWidth: TFloat = 2.0);
  299. var
  300. MultiPoly: TArrayOfArrayOfFloatPoint;
  301. begin
  302. MultiPoly := GR32_VectorUtils.BuildDashedLine(Points, Dashes, 0, Closed);
  303. MultiPoly := BuildPolyPolyLine(MultiPoly, False, Width);
  304. PolyPolygonFS_AggLite(Bitmap, MultiPoly, FillColor);
  305. PolyPolylineFS_AggLite(Bitmap, MultiPoly, StrokeColor, True, StrokeWidth);
  306. end;
  307. procedure DashLineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  308. const Dashes: TArrayOfFloat; Filler: TCustomPolygonFiller;
  309. Closed: Boolean = False; Width: TFloat = 1.0);
  310. var
  311. MultiPoly: TArrayOfArrayOfFloatPoint;
  312. begin
  313. MultiPoly := GR32_VectorUtils.BuildDashedLine(Points, Dashes, 0, Closed);
  314. PolyPolylineFS_AggLite(Bitmap, MultiPoly, Filler, False, Width);
  315. end;
  316. procedure DashLineFS_AggLite(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
  317. const Dashes: TArrayOfFloat; Filler: TCustomPolygonFiller; StrokeColor: TColor32;
  318. Closed: Boolean; Width: TFloat; StrokeWidth: TFloat = 2.0);
  319. var
  320. MultiPoly: TArrayOfArrayOfFloatPoint;
  321. begin
  322. MultiPoly := GR32_VectorUtils.BuildDashedLine(Points, Dashes, 0, Closed);
  323. MultiPoly := BuildPolyPolyLine(MultiPoly, False, Width);
  324. PolyPolygonFS_AggLite(Bitmap, MultiPoly, Filler);
  325. PolyPolylineFS_AggLite(Bitmap, MultiPoly, StrokeColor, True, StrokeWidth);
  326. end;
  327. const
  328. CPolyBaseShift = 8;
  329. CPolyBaseSize = 1 shl CPolyBaseShift;
  330. CPolyBaseMask = CPolyBaseSize - 1;
  331. CCellBlockShift = 12;
  332. CCellBlockSize = 1 shl CCellBlockShift;
  333. CCellBlockMask = CCellBlockSize - 1;
  334. CCellBlockPool = 256;
  335. CCellBlockLimit = 1024;
  336. type
  337. PPColor32 = ^PColor32;
  338. TPointWord = record
  339. case Byte of
  340. 0: (X, Y: SmallInt);
  341. 1: (PackedCoord: Integer);
  342. end;
  343. TCell = packed record
  344. Pnt: TPointWord;
  345. PackedCoord: Integer;
  346. Cover: Integer;
  347. Area: Integer;
  348. end;
  349. PCell = ^TCell;
  350. PPCell = ^PCell;
  351. TScanLine = class(TObject)
  352. private
  353. FCounts: PWord;
  354. FCovers: PColor32Array;
  355. FCurCount: PWord;
  356. FCurStartPtr: PPColor32;
  357. FLastX: Integer;
  358. FLastY: Integer;
  359. FMaxLen: Cardinal;
  360. FMinX: Integer;
  361. FNumSpans: Cardinal;
  362. FStartPtrs: PPColor32;
  363. public
  364. constructor Create(MinX, MaxX: Integer);
  365. destructor Destroy; override;
  366. procedure AddCell(X, Y: Integer; Cover: Cardinal);
  367. procedure AddSpan(X, Y: Integer; Len, Cover: Cardinal);
  368. function IsReady(Y: Integer): Integer;
  369. procedure ResetSpans;
  370. property BaseX: Integer read FMinX;
  371. property Y: Integer read FLastY;
  372. property NumSpans: Cardinal read FNumSpans;
  373. property CountsPtr: PWord read FCounts;
  374. property CoversPtr: PColor32Array read FCovers;
  375. property StartPtrs: PPColor32 read FStartPtrs;
  376. end;
  377. TOutlineFlag = (ofNotClosed, ofSortRequired);
  378. TOutlineFlags = set of TOutlineFlag;
  379. TOutline = class(TObject)
  380. private
  381. FCells: PPCell;
  382. FClose: TPoint;
  383. FCurBlock: Cardinal;
  384. FCurCell: TCell;
  385. FCurCellPtr: PCell;
  386. FCur: TPoint;
  387. FFlags: TOutlineFlags;
  388. FMaxBlocks: Cardinal;
  389. FMax: TPoint;
  390. FMin: TPoint;
  391. FNumBlocks: Cardinal;
  392. FNumCells: Cardinal;
  393. FSortedCells: PPCell;
  394. FSortedSize: Cardinal;
  395. procedure AddCurCell;
  396. procedure AllocateBlock;
  397. function GetCells: PPCell;
  398. procedure RenderLine(X1, Y1, X2, Y2: Integer);
  399. procedure RenderScanLine(EY, X1, Y1, X2, Y2: Integer);
  400. procedure SetCurCell(X, Y: Integer);
  401. procedure SortCells;
  402. procedure InternalReset;
  403. public
  404. constructor Create;
  405. destructor Destroy; override;
  406. procedure LineTo(X, Y: Integer);
  407. procedure MoveTo(X, Y: Integer);
  408. procedure Reset;
  409. property Cells: PPCell read GetCells;
  410. property MaxX: Integer read FMax.X;
  411. property MaxY: Integer read FMax.Y;
  412. property MinX: Integer read FMin.X;
  413. property MinY: Integer read FMin.Y;
  414. property NumCells: Cardinal read FNumCells;
  415. end;
  416. function Fixed8(C: TFloat): Integer; {$IFDEF USEINLINING} inline; {$ENDIF}
  417. begin
  418. Result := Trunc(C * CPolyBaseSize);
  419. end;
  420. { TCell }
  421. procedure SetCell(var Cell: TCell; CX, CY: Integer); {$IFDEF USEINLINING} inline; {$ENDIF}
  422. begin
  423. with Cell do
  424. begin
  425. Pnt.X := SmallInt(CX);
  426. Pnt.Y := SmallInt(CY);
  427. PackedCoord := (CY shl 16) + CX;
  428. Cover := 0;
  429. Area := 0;
  430. end;
  431. end;
  432. procedure PartSort(var A, B: PPCell; const Stop: PCell);
  433. {$IFDEF PUREPASCAL}
  434. {$IFDEF USEINLINING} inline; {$ENDIF}
  435. procedure SwapCells(A, B: PPCell); {$IFDEF USEINLINING} inline; {$ENDIF}
  436. var
  437. Temp: PCell;
  438. begin
  439. Temp := A^;
  440. A^ := B^;
  441. B^ := Temp;
  442. end;
  443. begin
  444. while True do
  445. begin
  446. repeat
  447. Inc(A)
  448. until (A^^.PackedCoord >= Stop^.PackedCoord);
  449. repeat
  450. Dec(B)
  451. until (B^^.PackedCoord <= Stop^.PackedCoord);
  452. {$IFDEF FPC}
  453. if PtrInt(A) > PtrInt(B) then
  454. Break;
  455. {$ELSE}
  456. {$IFDEF HAS_NATIVEINT}
  457. if NativeInt(A) > NativeInt(B) then
  458. Break;
  459. {$ELSE}
  460. if Integer(A) > Integer(B) then
  461. Break;
  462. {$ENDIF}
  463. {$ENDIF}
  464. SwapCells(A, B);
  465. end;
  466. {$ELSE}
  467. asm
  468. {$IFDEF CPUX86}
  469. PUSH EBX
  470. PUSH EDI
  471. PUSH ESI
  472. PUSH EBP
  473. MOV ECX, [ECX + 4]
  474. @0:
  475. MOV EDI, [EAX]
  476. @1:
  477. ADD EDI, $04
  478. MOV EBX, [EDI]
  479. CMP ECX, [EBX + 4]
  480. JG @1
  481. MOV [EAX], EDI
  482. MOV EDI, [EDX]
  483. @2:
  484. SUB EDI, $04
  485. MOV EBX, [EDI]
  486. CMP ECX, [EBX + 4]
  487. JL @2
  488. MOV [EDX], EDI
  489. CMP EDI, [EAX]
  490. JLE @3
  491. MOV EBX, [EAX]
  492. MOV ESI, [EBX]
  493. MOV EBP, [EDI]
  494. MOV [EDI], ESI
  495. MOV [EBX], EBP
  496. JMP @0
  497. @3:
  498. POP EBP
  499. POP ESI
  500. POP EDI
  501. POP EBX
  502. {$ENDIF}
  503. {$IFDEF CPUX64}
  504. MOV R8D, [R8 + 4]
  505. @0:
  506. MOV R9, [RCX]
  507. @1:
  508. ADD R9, $08
  509. MOV RAX, [R9]
  510. CMP R8D, [RAX + 4]
  511. JG @1
  512. MOV [RCX], R9
  513. MOV R9, [RDX]
  514. @2:
  515. SUB R9, $08
  516. MOV RAX, [R9]
  517. CMP R8D, [RAX + 4]
  518. JL @2
  519. MOV [RDX], R9
  520. CMP R9, [RCX]
  521. JLE @3
  522. MOV RAX, [RCX]
  523. MOV R10, [RAX]
  524. MOV R11, [R9]
  525. MOV [RAX], R11
  526. MOV [R9], R10
  527. JMP @0
  528. @3:
  529. {$ENDIF}
  530. {$ENDIF}
  531. end;
  532. procedure QSortCells(Start: PPCell; Num: Cardinal);
  533. const
  534. QSortThreshold = 9;
  535. var
  536. Stack: array [0 .. 79] of PPCell;
  537. Top: ^PPCell;
  538. Limit, Base, I, J, Pivot: PPCell;
  539. Len: Integer;
  540. procedure CheckCells(var A, B: PCell); {$IFDEF USEINLINING} inline; {$ENDIF}
  541. var
  542. Temp: PCell;
  543. begin
  544. if A^.PackedCoord < B^.PackedCoord then
  545. begin
  546. Temp := A;
  547. A := B;
  548. B := Temp;
  549. end;
  550. end;
  551. procedure SwapCells(A, B: PPCell); {$IFDEF USEINLINING} inline; {$ENDIF}
  552. var
  553. Temp: PCell;
  554. begin
  555. Temp := A^;
  556. A^ := B^;
  557. B^ := Temp;
  558. end;
  559. function LessThan(A, B: PPCell): Boolean; {$IFDEF USEINLINING} inline; {$ENDIF}
  560. begin
  561. Result := A^^.PackedCoord < B^^.PackedCoord;
  562. end;
  563. begin
  564. {$IFDEF FPC}
  565. Limit := PPCell(PtrInt(Start) + Num * SizeOf(PCell));
  566. {$ELSE}
  567. {$IFDEF HAS_NATIVEINT}
  568. Limit := PPCell(NativeUInt(Start) + Num * SizeOf(PCell));
  569. {$ELSE}
  570. Limit := PPCell(Cardinal(Start) + Num * SizeOf(PCell));
  571. {$ENDIF}
  572. {$ENDIF}
  573. Base := Start;
  574. Top := @Stack[0];
  575. while True do
  576. begin
  577. {$IFDEF FPC}
  578. Len := (PtrInt(Limit) - PtrInt(Base)) div SizeOf(PCell);
  579. {$ELSE}
  580. {$IFDEF HAS_NATIVEINT}
  581. Len := (NativeInt(Limit) - NativeInt(Base)) div SizeOf(PCell);
  582. {$ELSE}
  583. Len := (Integer(Limit) - Integer(Base)) div SizeOf(PCell);
  584. {$ENDIF}
  585. {$ENDIF}
  586. if Len > QSortThreshold then
  587. begin
  588. // we use Base + (Len div 2) as the pivot
  589. Pivot := Base;
  590. Inc(Pivot, Len div 2);
  591. SwapCells(Base, Pivot);
  592. I := Base;
  593. Inc(I);
  594. J := Limit;
  595. Dec(J);
  596. // now ensure that I^ <= Base^ <= J^
  597. CheckCells(J^, I^);
  598. CheckCells(Base^, I^);
  599. CheckCells(J^, Base^);
  600. PartSort(I, J, Base^);
  601. SwapCells(Base, J);
  602. // now, push the largest sub-array
  603. {$IFDEF FPC}
  604. if PtrInt(J) - PtrInt(Base) > PtrInt(Limit) - PtrInt(I) then
  605. {$ELSE}
  606. {$IFDEF HAS_NATIVEINT}
  607. if NativeInt(J) - NativeInt(Base) > NativeInt(Limit) - NativeInt(I) then
  608. {$ELSE}
  609. if Integer(J) - Integer(Base) > Integer(Limit) - Integer(I) then
  610. {$ENDIF}
  611. {$ENDIF}
  612. begin
  613. Top^ := Base;
  614. Inc(Top);
  615. Top^ := J;
  616. Base := I;
  617. end
  618. else
  619. begin
  620. Top^ := I;
  621. Inc(Top);
  622. Top^ := Limit;
  623. Limit := J;
  624. end;
  625. Inc(Top);
  626. end
  627. else
  628. begin
  629. // the sub-array is small, perform insertion sort
  630. J := Base;
  631. I := J;
  632. Inc(I);
  633. {$IFDEF FPC}
  634. while PtrInt(I) < PtrInt(Limit) do
  635. {$ELSE}
  636. {$IFDEF HAS_NATIVEINT}
  637. while NativeInt(I) < NativeInt(Limit) do
  638. {$ELSE}
  639. while Integer(I) < Integer(Limit) do
  640. {$ENDIF}
  641. {$ENDIF}
  642. begin
  643. {$IFDEF FPC}
  644. while LessThan(PPCell(PtrInt(J) + SizeOf(PCell)), J) do
  645. begin
  646. SwapCells(PPCell(PtrInt(J) + SizeOf(PCell)), J);
  647. {$ELSE}
  648. {$IFDEF HAS_NATIVEINT}
  649. while LessThan(PPCell(NativeUInt(J) + SizeOf(PCell)), J) do
  650. begin
  651. SwapCells(PPCell(NativeUInt(J) + SizeOf(PCell)), J);
  652. {$ELSE}
  653. while LessThan(PPCell(Cardinal(J) + SizeOf(PCell)), J) do
  654. begin
  655. SwapCells(PPCell(Cardinal(J) + SizeOf(PCell)), J);
  656. {$ENDIF}
  657. {$ENDIF}
  658. if J = Base then
  659. Break;
  660. Dec(J);
  661. end;
  662. J := I;
  663. Inc(I);
  664. end;
  665. {$IFDEF FPC}
  666. if PtrInt(Top) > PtrInt(@Stack[0]) then
  667. {$ELSE}
  668. {$IFDEF HAS_NATIVEINT}
  669. if NativeInt(Top) > NativeInt(@Stack[0]) then
  670. {$ELSE}
  671. if Integer(Top) > Integer(@Stack[0]) then
  672. {$ENDIF}
  673. {$ENDIF}
  674. begin
  675. Dec(Top, 2);
  676. Base := Top^;
  677. Limit := PPCell(Pointer(NativeInt(Top) + SizeOf(PPCell))^);
  678. end
  679. else
  680. Break;
  681. end;
  682. end;
  683. end;
  684. var
  685. FillSpan: procedure (Ptr: PColor32Array; Covers: PColor32; Count: Cardinal;
  686. const C: TColor32);
  687. procedure FillSpan_Pas(Ptr: PColor32Array; Covers: PColor32; Count: Cardinal;
  688. const C: TColor32);
  689. begin
  690. repeat
  691. BlendMemEx(C, PColor32(Ptr)^, Covers^);
  692. Inc(Covers);
  693. Inc(Ptr);
  694. Dec(Count);
  695. until Count = 0;
  696. end;
  697. {$IFNDEF PUREPASCAL}
  698. procedure FillSpan_ASM(Ptr: PColor32Array; Covers: PColor32; Count: Cardinal;
  699. const C: TColor32);
  700. asm
  701. {$IFDEF CPUX86}
  702. PUSH EBX
  703. PUSH ESI
  704. PUSH EDI
  705. LEA ESI, EDX + 4 * ECX // ESI = Covers
  706. LEA EDI, EAX + 4 * ECX // EDI = P
  707. NEG ECX
  708. @LoopStart:
  709. MOVZX EBX, [ESI + 4 * ECX]
  710. MOVZX EAX, [EBP + $0B] // EAX = C.A
  711. IMUL EBX, EAX // EBX = Alpha
  712. MOVZX EAX, [EDI + 4 * ECX]
  713. MOVZX EDX, [EBP + $08] // EDX = C.R
  714. SUB EDX, EAX
  715. IMUL EDX, EBX
  716. SHL EAX, $10
  717. ADD EDX, EAX
  718. SHR EDX, $10
  719. MOV [EDI + 4 * ECX], DL // store to pointer
  720. MOVZX EAX, [EDI + 4 * ECX + 1]
  721. MOVZX EDX, [EBP + $09] // EDX = C.G
  722. SUB EDX, EAX
  723. IMUL EDX, EBX
  724. SHL EAX, $10
  725. ADD EDX, EAX
  726. SHR EDX, $10
  727. MOV [EDI + 4 * ECX + 1], DL // store to pointer
  728. MOVZX EAX, [EDI + 4 * ECX + 2]
  729. MOVZX EDX, [EBP + $0A] // EDX = C.B
  730. SUB EDX, EAX
  731. IMUL EDX, EBX
  732. SHL EAX, $10
  733. ADD EDX, EAX
  734. SHR EDX, $10
  735. MOV [EDI + 4 * ECX + 2], DL // store to pointer
  736. MOVZX EAX, [EDI + 4 * ECX + 3]
  737. MOVZX EDX, [EBP + $0B] // EDX = C.A
  738. SUB EDX, EAX
  739. IMUL EDX, EBX
  740. SHL EAX, $10
  741. ADD EDX, EAX
  742. SHR EDX, $10
  743. MOV [EDI + 4 * ECX + 3], DL // store to pointer
  744. ADD ECX, 1
  745. JS @LoopStart
  746. POP EDI
  747. POP ESI
  748. POP EBX
  749. {$ENDIF}
  750. {$IFDEF CPUX64}
  751. LEA R10, [RDX + 4 * R8] // R10 = Covers
  752. LEA R11, [RCX + 4 * R8] // R11 = P
  753. NEG R8D
  754. @LoopStart:
  755. MOVZX R9D, [R10 + 4 * R8]
  756. MOVZX ECX, [EBP + $0B] // ECX = C.A
  757. IMUL R9D, ECX // R9D = Alpha
  758. MOVZX ECX, [R11 + 4 * R8]
  759. MOVZX EDX, [EBP + $08] // EDX = C.R
  760. SUB EDX, ECX
  761. IMUL EDX, R9D
  762. SHL ECX, $10
  763. ADD EDX, ECX
  764. SHR EDX, $10
  765. MOV [R11 + 4 * R8], DL // store to pointer
  766. MOVZX ECX, [R11 + 4 * R8 + 1]
  767. MOVZX EDX, [EBP + $09] // EDX = C.G
  768. SUB EDX, ECX
  769. IMUL EDX, R9D
  770. SHL ECX, $10
  771. ADD EDX, ECX
  772. SHR EDX, $10
  773. MOV [R11 + 4 * R8 + 1], DL // store to pointer
  774. MOVZX ECX, [R11 + 4 * R8 + 2]
  775. MOVZX EDX, [EBP + $0A] // EDX = C.B
  776. SUB EDX, ECX
  777. IMUL EDX, R9D
  778. SHL ECX, $10
  779. ADD EDX, ECX
  780. SHR EDX, $10
  781. MOV [R11 + 4 * R8 + 2], DL // store to pointer
  782. MOVZX ECX, [R11 + 4 * R8 + 3]
  783. MOVZX EDX, [EBP + $0B] // EDX = C.A
  784. SUB EDX, ECX
  785. IMUL EDX, R9D
  786. SHL ECX, $10
  787. ADD EDX, ECX
  788. SHR EDX, $10
  789. MOV [R11 + 4 * R8 + 3], DL // store to pointer
  790. ADD R8D, 1
  791. JS @LoopStart
  792. {$ENDIF}
  793. end;
  794. {$IFNDEF OMIT_MMX}
  795. {$IFDEF TARGET_X86}
  796. procedure FillSpan_MMX(Ptr: PColor32Array; Covers: PColor32; Count: Cardinal;
  797. const C: TColor32);
  798. asm
  799. JCXZ @3
  800. PUSH EBX
  801. PUSH ESI
  802. MOV ESI,EAX
  803. MOV EBX,C
  804. PXOR MM3,MM3 // MM3 = 0
  805. MOVD MM1,EBX // MM1 = C (Foreground)
  806. PUNPCKLBW MM1,MM3
  807. SHR EBX,24
  808. JZ @2
  809. INC EBX // 255:256 range bias
  810. @1:
  811. MOVD MM2,[ESI] // MM2 = Dest (Background)
  812. PUNPCKLBW MM2,MM3
  813. MOV EAX,[EDX] // EAX = Alpha
  814. IMUL EAX,EBX
  815. SHR EAX,8
  816. SHL EAX,4
  817. ADD EAX,alpha_ptr
  818. MOVQ MM0,MM1
  819. PSUBW MM0,MM2
  820. PMULLW MM0,[EAX]
  821. PSLLW MM2,8
  822. MOV EAX,bias_ptr
  823. PADDW MM2,[EAX]
  824. PADDW MM0,MM2
  825. PSRLW MM0,8
  826. PACKUSWB MM0,MM3
  827. MOVD [ESI],MM0
  828. ADD ESI,4
  829. ADD EDX,4
  830. DEC ECX
  831. JNZ @1
  832. @2: POP ESI
  833. POP EBX
  834. @3:
  835. end;
  836. {$ENDIF}
  837. {$ENDIF}
  838. {$IFNDEF OMIT_SSE2}
  839. procedure FillSpan_SSE2(Ptr: PColor32Array; Covers: PColor32; Count: Cardinal;
  840. const C: TColor32);
  841. asm
  842. {$IFDEF TARGET_X86}
  843. JCXZ @5
  844. PUSH EBX
  845. MOV EBX,C
  846. PXOR XMM7,XMM7 // XMM7 = 0
  847. MOVD XMM1,EBX // XMM1 = C (Foreground)
  848. PUNPCKLBW XMM1,XMM7
  849. SHR EBX,24
  850. JZ @4
  851. INC EBX // 255:256 range bias
  852. PUSH ESI
  853. MOV ESI,EAX
  854. @1: MOVQ XMM0,XMM1
  855. MOVD XMM2,[ESI] // XMM2 = Dest (Background)
  856. PUNPCKLBW XMM2,XMM7
  857. MOV EAX,[EDX] // EAX = Alpha
  858. IMUL EAX,EBX
  859. SHR EAX,8
  860. JZ @3
  861. CMP EAX,$FF
  862. JZ @2
  863. SHL EAX,4
  864. ADD EAX,alpha_ptr
  865. PSUBW XMM0,XMM2
  866. PMULLW XMM0,[EAX]
  867. PSLLW XMM2,8
  868. MOV EAX,bias_ptr
  869. PADDW XMM2,[EAX]
  870. PADDW XMM0,XMM2
  871. PSRLW XMM0,8
  872. @2: PACKUSWB XMM0,XMM7
  873. MOVD [ESI],XMM0
  874. @3: ADD ESI,4
  875. ADD EDX,4
  876. DEC ECX
  877. JNZ @1
  878. POP ESI
  879. @4: POP EBX
  880. @5:
  881. {$ENDIF}
  882. {$IFDEF TARGET_X64}
  883. TEST R8D,R8D
  884. JZ @4
  885. PXOR XMM7,XMM7 // XMM7 = 0
  886. MOVD XMM1,R9D // XMM1 = C (Foreground)
  887. PUNPCKLBW XMM1,XMM7
  888. SHR R9D,24
  889. JZ @2
  890. INC R9D // 255:256 range bias
  891. @1: MOVQ XMM0,XMM1
  892. MOVD XMM2,[RCX] // XMM2 = Dest (Background)
  893. PUNPCKLBW XMM2,XMM7
  894. MOV EAX,[RDX] // EAX = Alpha
  895. IMUL EAX,R9D
  896. SHR EAX,8
  897. JZ @3
  898. CMP EAX,$FF
  899. JZ @2
  900. SHL EAX,4
  901. ADD RAX,alpha_ptr
  902. PSUBW XMM0,XMM2
  903. PMULLW XMM0,[RAX]
  904. PSLLW XMM2,8
  905. MOV RAX,bias_ptr
  906. PADDW XMM2,[RAX]
  907. PADDW XMM0,XMM2
  908. PSRLW XMM0,8
  909. @2: PACKUSWB XMM0,XMM7
  910. MOVD [RCX],XMM0
  911. @3: ADD ECX,4
  912. ADD EDX,4
  913. DEC R8D
  914. JNZ @1
  915. @4:
  916. {$ENDIF}
  917. end;
  918. {$ENDIF}
  919. {$ENDIF}
  920. function CalculateAlpha(FillMode: TPolyFillMode; Area: Integer): Cardinal;
  921. var
  922. Cover: Integer;
  923. const
  924. CAAShift = 8;
  925. CAANum = 1 shl CAAShift;
  926. CAAMask = CAANum - 1;
  927. CAA2Num = CAANum shl 1;
  928. CAA2Mask = CAA2Num - 1;
  929. begin
  930. Cover := SAR_9(Area);
  931. if Cover < 0 then
  932. Cover := -Cover;
  933. if FillMode = pfEvenOdd then
  934. begin
  935. Cover := Cover and CAA2Mask;
  936. if Cover > CAANum then
  937. Cover := CAA2Num - Cover;
  938. end;
  939. if Cover > CAAMask then
  940. Cover := CAAMask;
  941. Result := Cover;
  942. end;
  943. { TScanLine }
  944. constructor TScanLine.Create(MinX, MaxX: Integer);
  945. begin
  946. inherited Create;
  947. FMaxLen := MaxX - MinX + 2;
  948. GetMem(FCovers, FMaxLen * SizeOf(TColor32));
  949. GetMem(FStartPtrs, FMaxLen * SizeOf(PColor32));
  950. GetMem(FCounts, FMaxLen * SizeOf(Word));
  951. FLastX := $7FFF;
  952. FLastY := $7FFF;
  953. FMinX := MinX;
  954. FCurCount := FCounts;
  955. FCurStartPtr := FStartPtrs;
  956. FNumSpans := 0;
  957. end;
  958. destructor TScanLine.Destroy;
  959. begin
  960. FreeMem(FCounts);
  961. FreeMem(FStartPtrs);
  962. FreeMem(FCovers);
  963. inherited Destroy;
  964. end;
  965. procedure TScanLine.AddCell(X, Y: Integer; Cover: Cardinal);
  966. begin
  967. Dec(X, FMinX);
  968. FCovers[X] := TColor32(Cover);
  969. if X = FLastX + 1 then
  970. Inc(FCurCount^)
  971. else
  972. begin
  973. Inc(FCurCount);
  974. FCurCount^ := 1;
  975. Inc(FCurStartPtr);
  976. FCurStartPtr^ := PColor32(@FCovers[X]);
  977. Inc(FNumSpans);
  978. end;
  979. FLastX := X;
  980. FLastY := Y;
  981. end;
  982. procedure TScanLine.AddSpan(X, Y: Integer; Len, Cover: Cardinal);
  983. begin
  984. Dec(X, FMinX);
  985. FillLongWord(FCovers[X], Len, Cover);
  986. if X = FLastX + 1 then
  987. Inc(FCurCount^, Word(Len))
  988. else
  989. begin
  990. Inc(FCurCount);
  991. FCurCount^ := Word(Len);
  992. Inc(FCurStartPtr);
  993. FCurStartPtr^ := PColor32(@FCovers[X]);
  994. Inc(FNumSpans);
  995. end;
  996. FLastX := X + Integer(Len) - 1;
  997. FLastY := Y;
  998. end;
  999. function TScanLine.IsReady(Y: Integer): Integer;
  1000. begin
  1001. Result := Ord((FNumSpans <> 0) and ((Y xor FLastY) <> 0));
  1002. end;
  1003. procedure TScanLine.ResetSpans;
  1004. begin
  1005. FLastX := $7FFF;
  1006. FLastY := $7FFF;
  1007. FCurCount := FCounts;
  1008. FCurStartPtr := FStartPtrs;
  1009. FNumSpans := 0;
  1010. end;
  1011. { TOutline }
  1012. constructor TOutline.Create;
  1013. begin
  1014. inherited Create;
  1015. FCurCellPtr := nil;
  1016. FMin.X := $7FFFFFFF;
  1017. FMin.Y := $7FFFFFFF;
  1018. FMax.X := -$7FFFFFFF;
  1019. FMax.Y := -$7FFFFFFF;
  1020. FFlags := [ofSortRequired];
  1021. SetCell(FCurCell, $7FFF, $7FFF);
  1022. end;
  1023. destructor TOutline.Destroy;
  1024. var
  1025. Ptr: PPCell;
  1026. begin
  1027. FreeMem(FSortedCells);
  1028. if FNumBlocks <> 0 then
  1029. begin
  1030. Ptr := PPCell(Cardinal(FCells) + (FNumBlocks - 1) * SizeOf(PCell));
  1031. while FNumBlocks <> 0 do
  1032. begin
  1033. FreeMem(Ptr^);
  1034. Dec(Ptr);
  1035. Dec(FNumBlocks);
  1036. end;
  1037. FreeMem(FCells);
  1038. end;
  1039. inherited Destroy;
  1040. end;
  1041. procedure TOutline.Reset;
  1042. begin
  1043. FNumCells := 0;
  1044. FCurBlock := 0;
  1045. InternalReset;
  1046. end;
  1047. procedure TOutline.InternalReset;
  1048. begin
  1049. FMin.X := $7FFFFFFF;
  1050. FMin.Y := $7FFFFFFF;
  1051. FMax.X := -$7FFFFFFF;
  1052. FMax.Y := -$7FFFFFFF;
  1053. FFlags := [ofSortRequired];
  1054. SetCell(FCurCell, $7FFF, $7FFF);
  1055. end;
  1056. procedure TOutline.AddCurCell;
  1057. begin
  1058. if FCurCell.Area or FCurCell.Cover <> 0 then
  1059. begin
  1060. if FNumCells and CCellBlockMask = 0 then
  1061. begin
  1062. if FNumBlocks >= CCellBlockLimit then
  1063. Exit;
  1064. AllocateBlock;
  1065. end;
  1066. FCurCellPtr^ := FCurCell;
  1067. Inc(FCurCellPtr);
  1068. Inc(FNumCells);
  1069. end;
  1070. end;
  1071. procedure TOutline.AllocateBlock;
  1072. var
  1073. NewCells: PPCell;
  1074. begin
  1075. if FCurBlock >= FNumBlocks then
  1076. begin
  1077. if FNumBlocks >= FMaxBlocks then
  1078. begin
  1079. GetMem(NewCells, (FMaxBlocks + CCellBlockPool) * SizeOf(PCell));
  1080. if Assigned(FCells) then
  1081. begin
  1082. Move(FCells^, NewCells^, FMaxBlocks * SizeOf(PCell));
  1083. FreeMem(FCells);
  1084. end;
  1085. FCells := NewCells;
  1086. Inc(FMaxBlocks, CCellBlockPool);
  1087. end;
  1088. GetMem(PPCell(Cardinal(FCells) + FNumBlocks * SizeOf(PCell))^,
  1089. Cardinal(CCellBlockSize) * SizeOf(TCell));
  1090. Inc(FNumBlocks);
  1091. end;
  1092. FCurCellPtr := PPCell(Cardinal(FCells) + FCurBlock * SizeOf(PCell))^;
  1093. Inc(FCurBlock);
  1094. end;
  1095. function TOutline.GetCells: PPCell;
  1096. begin
  1097. if ofNotClosed in FFlags then
  1098. begin
  1099. LineTo(FClose.X, FClose.Y);
  1100. FFlags := FFlags - [ofNotClosed];
  1101. end;
  1102. // Perform sort only the first time.
  1103. if ofSortRequired in FFlags then
  1104. begin
  1105. AddCurCell;
  1106. if FNumCells = 0 then
  1107. begin
  1108. Result := nil;
  1109. Exit;
  1110. end;
  1111. SortCells;
  1112. FFlags := FFlags - [ofSortRequired];
  1113. end;
  1114. Result := FSortedCells;
  1115. end;
  1116. procedure TOutline.LineTo(X, Y: Integer);
  1117. var
  1118. C: Integer;
  1119. begin
  1120. if (ofSortRequired in FFlags) and (((FCur.X xor X) or (FCur.Y xor Y)) <> 0) then
  1121. begin
  1122. C := SAR_8(FCur.X);
  1123. if C < FMin.X then FMin.X := C;
  1124. Inc(C);
  1125. if C > FMax.X then FMax.X := C;
  1126. C := SAR_8(X);
  1127. if C < FMin.X then FMin.X := C;
  1128. Inc(C);
  1129. if C > FMax.X then FMax.X := C;
  1130. RenderLine(FCur.X, FCur.Y, X, Y);
  1131. FCur.X := X;
  1132. FCur.Y := Y;
  1133. FFlags := FFlags + [ofNotClosed];
  1134. end;
  1135. end;
  1136. procedure TOutline.MoveTo(X, Y: Integer);
  1137. begin
  1138. if not (ofSortRequired in FFlags) then //-7468, -6124, -6124, -4836
  1139. Reset;
  1140. if ofNotClosed in FFlags then
  1141. LineTo(FClose.X, FClose.Y);
  1142. SetCurCell(SAR_8(X), SAR_8(Y));
  1143. FCur.X := X;
  1144. FClose.X := X;
  1145. FCur.Y := Y;
  1146. FClose.Y := Y;
  1147. end;
  1148. procedure TOutline.RenderLine(X1, Y1, X2, Y2: Integer);
  1149. var
  1150. EY1, EY2, FY1, FY2, Dx, Dy, XFrom, XTo, P, Rem, AMod, Lift: Integer;
  1151. Delta, First, Incr, EX, TwoFx, Area: Integer;
  1152. begin
  1153. EY1 := SAR_8(Y1);
  1154. EY2 := SAR_8(Y2);
  1155. FY1 := Y1 and CPolyBaseMask;
  1156. FY2 := Y2 and CPolyBaseMask;
  1157. if EY1 < FMin.Y then FMin.Y := EY1;
  1158. if EY1 >= FMax.Y then FMax.Y := EY1 + 1;
  1159. if EY2 < FMin.Y then FMin.Y := EY2;
  1160. if EY2 >= FMax.Y then FMax.Y := EY2 + 1;
  1161. Dx := X2 - X1;
  1162. Dy := Y2 - Y1;
  1163. // everything is on a single scanline
  1164. if EY1 = EY2 then
  1165. begin
  1166. RenderScanLine(EY1, X1, FY1, X2, FY2);
  1167. Exit;
  1168. end;
  1169. // Vertical line - we have to calculate start and end cells, and then -
  1170. // the common values of the area and coverage for all cells of the line.
  1171. // We know exactly there's only one cell, so, we don't have to call
  1172. // RenderScanline().
  1173. Incr := 1;
  1174. if Dx = 0 then
  1175. begin
  1176. EX := SAR_8(X1);
  1177. TwoFx := (X1 - (EX shl CPolyBaseShift)) shl 1;
  1178. First := CPolyBaseSize;
  1179. if Dy < 0 then
  1180. begin
  1181. First := 0;
  1182. Incr := -1;
  1183. end;
  1184. Delta := First - FY1;
  1185. Inc(FCurCell.Cover, Delta);
  1186. Inc(FCurCell.Area, TwoFx * Delta);
  1187. Inc(EY1, Incr);
  1188. SetCurCell(EX, EY1);
  1189. Delta := First + First - CPolyBaseSize;
  1190. Area := TwoFx * Delta;
  1191. while EY1 <> EY2 do
  1192. begin
  1193. FCurCell.Cover := Delta;
  1194. FCurCell.Area := Area;
  1195. Inc(EY1, Incr);
  1196. SetCurCell(EX, EY1);
  1197. end;
  1198. Delta := FY2 - CPolyBaseSize + First;
  1199. Inc(FCurCell.Cover, Delta);
  1200. Inc(FCurCell.Area, TwoFx * Delta);
  1201. Exit;
  1202. end;
  1203. // ok, we have to render several scanlines
  1204. P := (CPolyBaseSize - FY1) * Dx;
  1205. First := CPolyBaseSize;
  1206. if Dy < 0 then
  1207. begin
  1208. P := FY1 * Dx;
  1209. First := 0;
  1210. Incr := -1;
  1211. Dy := -Dy;
  1212. end;
  1213. Delta := P div Dy;
  1214. AMod := P mod Dy;
  1215. if AMod < 0 then
  1216. begin
  1217. Dec(Delta);
  1218. Inc(AMod, Dy);
  1219. end;
  1220. XFrom := X1 + Delta;
  1221. RenderScanLine(EY1, X1, FY1, XFrom, First);
  1222. Inc(EY1, Incr);
  1223. SetCurCell(SAR_8(XFrom), EY1);
  1224. if EY1 <> EY2 then
  1225. begin
  1226. P := CPolyBaseSize * Dx;
  1227. Lift := P div Dy;
  1228. Rem := P mod Dy;
  1229. if Rem < 0 then
  1230. begin
  1231. Dec(Lift);
  1232. Inc(Rem, Dy);
  1233. end;
  1234. Dec(AMod, Dy);
  1235. while EY1 <> EY2 do
  1236. begin
  1237. Delta := Lift;
  1238. Inc(AMod, Rem);
  1239. if AMod >= 0 then
  1240. begin
  1241. Dec(AMod, Dy);
  1242. Inc(Delta);
  1243. end;
  1244. XTo := XFrom + Delta;
  1245. RenderScanLine(EY1, XFrom, CPolyBaseSize - First, XTo, First);
  1246. XFrom := XTo;
  1247. Inc(EY1, Incr);
  1248. SetCurCell(SAR_8(XFrom), EY1);
  1249. end;
  1250. end;
  1251. RenderScanLine(EY1, XFrom, CPolyBaseSize - First, X2, FY2);
  1252. end;
  1253. procedure TOutline.RenderScanLine(EY, X1, Y1, X2, Y2: Integer);
  1254. var
  1255. EX1, EX2, FX1, FX2, Delta, P, First, Dx, Incr, Lift, AMod, Rem: Integer;
  1256. begin
  1257. EX1 := SAR_8(X1);
  1258. EX2 := SAR_8(X2);
  1259. FX1 := X1 and CPolyBaseMask;
  1260. FX2 := X2 and CPolyBaseMask;
  1261. // trivial case. Happens often
  1262. if Y1 = Y2 then
  1263. begin
  1264. SetCurCell(EX2, EY);
  1265. Exit;
  1266. end;
  1267. // everything is located in a single cell. That is easy!
  1268. if EX1 = EX2 then
  1269. begin
  1270. Delta := Y2 - Y1;
  1271. Inc(FCurCell.Cover, Delta);
  1272. Inc(FCurCell.Area, (FX1 + FX2) * Delta);
  1273. Exit;
  1274. end;
  1275. // ok, we'll have to render a run of adjacent cells on the same scanline...
  1276. P := (CPolyBaseSize - FX1) * (Y2 - Y1);
  1277. First := CPolyBaseSize;
  1278. Incr := 1;
  1279. Dx := X2 - X1;
  1280. if Dx < 0 then
  1281. begin
  1282. P := FX1 * (Y2 - Y1);
  1283. First := 0;
  1284. Incr := -1;
  1285. Dx := -Dx;
  1286. end;
  1287. Delta := P div Dx;
  1288. AMod := P mod Dx;
  1289. if AMod < 0 then
  1290. begin
  1291. Dec(Delta);
  1292. Inc(AMod, Dx);
  1293. end;
  1294. Inc(FCurCell.Cover, Delta);
  1295. Inc(FCurCell.Area, (FX1 + First) * Delta);
  1296. Inc(EX1, Incr);
  1297. SetCurCell(EX1, EY);
  1298. Inc(Y1, Delta);
  1299. if EX1 <> EX2 then
  1300. begin
  1301. P := CPolyBaseSize * (Y2 - Y1 + Delta);
  1302. Lift := P div Dx;
  1303. Rem := P mod Dx;
  1304. if Rem < 0 then
  1305. begin
  1306. Dec(Lift);
  1307. Inc(Rem, Dx);
  1308. end;
  1309. Dec(AMod, Dx);
  1310. while EX1 <> EX2 do
  1311. begin
  1312. Delta := Lift;
  1313. Inc(AMod, Rem);
  1314. if AMod >= 0 then
  1315. begin
  1316. Dec(AMod, Dx);
  1317. Inc(Delta);
  1318. end;
  1319. Inc(FCurCell.Cover, Delta);
  1320. Inc(FCurCell.Area, CPolyBaseSize * Delta);
  1321. Inc(Y1, Delta);
  1322. Inc(EX1, Incr);
  1323. SetCurCell(EX1, EY);
  1324. end;
  1325. end;
  1326. Delta := Y2 - Y1;
  1327. Inc(FCurCell.Cover, Delta);
  1328. Inc(FCurCell.Area, (FX2 + CPolyBaseSize - First) * Delta);
  1329. end;
  1330. procedure TOutline.SetCurCell(X, Y: Integer);
  1331. begin
  1332. if FCurCell.PackedCoord <> (Y shl 16) + X then
  1333. begin
  1334. AddCurCell;
  1335. SetCell(FCurCell, X, Y);
  1336. end;
  1337. end;
  1338. procedure TOutline.SortCells;
  1339. var
  1340. SortedPtr, BlockPtr: PPCell;
  1341. CellPtr: PCell;
  1342. NB, I: Cardinal;
  1343. begin
  1344. if FNumCells = 0 then
  1345. Exit;
  1346. if FNumCells > FSortedSize then
  1347. begin
  1348. FreeMem(FSortedCells);
  1349. FSortedSize := FNumCells;
  1350. GetMem(FSortedCells, (FNumCells + 1) * SizeOf(PCell));
  1351. end;
  1352. SortedPtr := FSortedCells;
  1353. BlockPtr := FCells;
  1354. NB := FNumCells shr CCellBlockShift;
  1355. while NB <> 0 do
  1356. begin
  1357. Dec(NB);
  1358. CellPtr := BlockPtr^;
  1359. Inc(BlockPtr);
  1360. I := CCellBlockSize;
  1361. while I <> 0 do
  1362. begin
  1363. Dec(I);
  1364. SortedPtr^ := CellPtr;
  1365. Inc(SortedPtr);
  1366. Inc(CellPtr);
  1367. end;
  1368. end;
  1369. CellPtr := BlockPtr^;
  1370. I := FNumCells and CCellBlockMask;
  1371. while I <> 0 do
  1372. begin
  1373. Dec(I);
  1374. SortedPtr^ := CellPtr;
  1375. Inc(SortedPtr);
  1376. Inc(CellPtr);
  1377. end;
  1378. PPCell(Cardinal(FSortedCells) + FNumCells * SizeOf(PCell))^ := nil;
  1379. QSortCells(FSortedCells, FNumCells);
  1380. end;
  1381. { TPolygonRenderer32AggLite }
  1382. procedure TPolygonRenderer32AggLite.Render(CellsPtr: Pointer; MinX, MaxX: Integer);
  1383. var
  1384. X, Y, Cover, Alpha, Area, Coord: Integer;
  1385. Cells: PPCell absolute CellsPtr;
  1386. CurCell, StartCell: PCell;
  1387. ScanLine: TScanLine;
  1388. procedure RenderSpan;
  1389. var
  1390. NumSpans: Cardinal;
  1391. BaseX: Integer;
  1392. Row: PColor32Array;
  1393. CurX: Integer;
  1394. Covers: PColor32;
  1395. NumPix: Integer;
  1396. BaseCovers: Pointer;
  1397. CurCount: PWord;
  1398. CurStartPtr: PPColor32;
  1399. begin
  1400. NumSpans := ScanLine.NumSpans;
  1401. BaseX := ScanLine.BaseX;
  1402. Row := Bitmap.ScanLine[ScanLine.Y];
  1403. BaseCovers := ScanLine.CoversPtr;
  1404. CurCount := ScanLine.CountsPtr;
  1405. CurStartPtr := ScanLine.StartPtrs;
  1406. if Assigned(Filler) then
  1407. repeat
  1408. Dec(NumSpans);
  1409. Inc(CurCount);
  1410. Inc(CurStartPtr);
  1411. {$IFDEF FPC}
  1412. CurX := (PtrInt(CurStartPtr^) - PtrInt(BaseCovers)) div SizeOf(TColor32) + BaseX;
  1413. {$ELSE}
  1414. {$IFDEF HAS_NATIVEINT}
  1415. CurX := (NativeInt(CurStartPtr^) - NativeInt(BaseCovers)) div SizeOf(TColor32) + BaseX;
  1416. {$ELSE}
  1417. CurX := (Integer(CurStartPtr^) - Integer(BaseCovers)) div SizeOf(TColor32) + BaseX;
  1418. {$ENDIF}
  1419. {$ENDIF}
  1420. Covers := CurStartPtr^;
  1421. NumPix := CurCount^;
  1422. if CurX < 0 then
  1423. begin
  1424. Inc(NumPix, CurX);
  1425. if NumPix <= 0 then
  1426. Continue;
  1427. Dec(Covers, CurX);
  1428. CurX := 0;
  1429. end;
  1430. if CurX + NumPix >= Bitmap.Width then
  1431. begin
  1432. NumPix := Bitmap.Width - CurX;
  1433. if NumPix <= 0 then
  1434. Continue;
  1435. end;
  1436. Filler.FillLine(@Row^[CurX], CurX, ScanLine.Y, NumPix, Covers, Bitmap.CombineMode);
  1437. until NumSpans = 0
  1438. else
  1439. repeat
  1440. Dec(NumSpans);
  1441. Inc(CurCount);
  1442. Inc(CurStartPtr);
  1443. {$IFDEF FPC}
  1444. CurX := (PtrInt(CurStartPtr^) - PtrInt(BaseCovers)) div SizeOf(TColor32) + BaseX;
  1445. {$ELSE}
  1446. {$IFDEF HAS_NATIVEINT}
  1447. CurX := (NativeInt(CurStartPtr^) - NativeInt(BaseCovers)) div SizeOf(TColor32) + BaseX;
  1448. {$ELSE}
  1449. CurX := (Integer(CurStartPtr^) - Integer(BaseCovers)) div SizeOf(TColor32) + BaseX;
  1450. {$ENDIF}
  1451. {$ENDIF}
  1452. Covers := CurStartPtr^;
  1453. NumPix := CurCount^;
  1454. if CurX < 0 then
  1455. begin
  1456. Inc(NumPix, CurX);
  1457. if NumPix <= 0 then
  1458. Continue;
  1459. Dec(Covers, CurX);
  1460. CurX := 0;
  1461. end;
  1462. if CurX + NumPix >= Bitmap.Width then
  1463. begin
  1464. NumPix := Bitmap.Width - CurX;
  1465. if NumPix <= 0 then
  1466. Continue;
  1467. end;
  1468. FillSpan(@Row^[CurX], PColor32(Covers), NumPix, Color);
  1469. until NumSpans = 0;
  1470. EMMS;
  1471. end;
  1472. begin
  1473. ScanLine := TScanLine.Create(MinX, MaxX); // -32, 64
  1474. try
  1475. Cover := 0;
  1476. CurCell := Cells^;
  1477. Inc(Cells);
  1478. while True do
  1479. begin
  1480. StartCell := CurCell;
  1481. Coord := CurCell^.Pnt.PackedCoord;
  1482. X := CurCell^.Pnt.X;
  1483. Y := CurCell^.Pnt.Y;
  1484. Area := StartCell^.Area;
  1485. Inc(Cover, StartCell^.Cover);
  1486. CurCell := Cells^;
  1487. Inc(Cells);
  1488. while Assigned(CurCell) do
  1489. begin
  1490. if CurCell^.Pnt.PackedCoord <> Coord then
  1491. Break;
  1492. Inc(Area, CurCell^.Area);
  1493. Inc(Cover, CurCell^.Cover);
  1494. CurCell := Cells^;
  1495. Inc(Cells);
  1496. end;
  1497. if Area <> 0 then
  1498. begin
  1499. Alpha := CalculateAlpha(Fillmode, (Cover shl (CPolyBaseShift + 1)) - Area);
  1500. if Alpha <> 0 then
  1501. begin
  1502. if ScanLine.IsReady(Y) <> 0 then
  1503. begin
  1504. if (ScanLine.Y >= 0) and (ScanLine.Y < Bitmap.Height) then
  1505. RenderSpan;
  1506. ScanLine.ResetSpans;
  1507. end;
  1508. ScanLine.AddCell(X, Y, GAMMA_ENCODING_TABLE[Alpha]);
  1509. end;
  1510. Inc(X);
  1511. end;
  1512. if not Assigned(CurCell) then
  1513. Break;
  1514. if CurCell^.Pnt.X > X then
  1515. begin
  1516. Alpha := CalculateAlpha(Fillmode, Cover shl (CPolyBaseShift + 1));
  1517. if Alpha <> 0 then
  1518. begin
  1519. if ScanLine.IsReady(Y) <> 0 then
  1520. begin
  1521. if (ScanLine.Y >= 0) and (ScanLine.Y < Bitmap.Height) then
  1522. RenderSpan;
  1523. ScanLine.ResetSpans;
  1524. end;
  1525. ScanLine.AddSpan(X, Y, CurCell^.Pnt.X - X, GAMMA_ENCODING_TABLE[Alpha]);
  1526. end;
  1527. end;
  1528. end;
  1529. with ScanLine do
  1530. if (NumSpans <> 0) and (Y >= 0) and (Y < Bitmap.Height) then
  1531. RenderSpan;
  1532. finally
  1533. ScanLine.Free;
  1534. end;
  1535. end;
  1536. type
  1537. TBitmap32Access = class(TBitmap32);
  1538. procedure TPolygonRenderer32AggLite.PolygonFS(
  1539. const Points: TArrayOfFloatPoint; const ClipRect: TFloatRect);
  1540. var
  1541. I: Integer;
  1542. Cells: PPCell;
  1543. OutLine: TOutline;
  1544. APoints: TArrayOfFloatPoint;
  1545. R: TFloatRect;
  1546. begin
  1547. R := ClipRect;
  1548. InflateRect(R, 0.05, 0.05);
  1549. APoints := ClipPolygon (Points, R);
  1550. OutLine := TOutline.Create;
  1551. try
  1552. OutLine.Reset;
  1553. OutLine.MoveTo(Fixed8(APoints[0].X), Fixed8(APoints[0].Y));
  1554. for I := 1 to High(APoints) do
  1555. OutLine.LineTo(Fixed8(APoints[I].X), Fixed8(APoints[I].Y));
  1556. // get cells and check count
  1557. Cells := OutLine.Cells;
  1558. if OutLine.NumCells = 0 then
  1559. Exit;
  1560. if Assigned(Filler) then
  1561. begin
  1562. // call begin rendering of assigned filler
  1563. Filler.BeginRendering;
  1564. Render(Cells, OutLine.MinX, OutLine.MaxX);
  1565. // rendering done, call end rendering of assigned filler
  1566. Filler.EndRendering;
  1567. end
  1568. else
  1569. Render(Cells, OutLine.MinX, OutLine.MaxX);
  1570. {$IFDEF CHANGENOTIFICATIONS}
  1571. if TBitmap32Access(Bitmap).UpdateCount = 0 then
  1572. if Length(APoints) > 0 then
  1573. Bitmap.Changed(MakeRect(OutLine.MinX, OutLine.MinY, OutLine.MaxX,
  1574. OutLine.MaxY));
  1575. {$ENDIF}
  1576. finally
  1577. SetLength(APoints, 0);
  1578. OutLine.Free;
  1579. end;
  1580. end;
  1581. procedure TPolygonRenderer32AggLite.PolyPolygonFS(
  1582. const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect);
  1583. var
  1584. I, J: Integer;
  1585. Cells: PPCell;
  1586. OutLine: TOutline;
  1587. Bounds: TRect;
  1588. APoints: TArrayOfArrayOfFloatPoint;
  1589. R: TFloatRect;
  1590. FirstValid: integer;
  1591. begin
  1592. if Length(Points) = 0 then
  1593. Exit;
  1594. APoints := Points;
  1595. // temporary fix for floating point rounding errors - corr. - to + by pws
  1596. R := ClipRect;
  1597. InflateRect(R, 0.05, 0.05);
  1598. FirstValid := -1;
  1599. for i := 0 to High(APoints) do
  1600. begin
  1601. APoints[i] := ClipPolygon(Points[I], R);
  1602. if (FirstValid = -1) and (Length(APoints[i]) > 0) then
  1603. FirstValid := i;
  1604. end;
  1605. if (FirstValid = -1) then
  1606. exit; // All were clipped
  1607. OutLine := TOutline.Create;
  1608. try
  1609. OutLine.Reset;
  1610. OutLine.MoveTo(Fixed8(APoints[FirstValid, 0].X), Fixed8(APoints[FirstValid, 0].Y));
  1611. for I := 1 to High(APoints[FirstValid]) do
  1612. OutLine.LineTo(Fixed8(APoints[FirstValid, I].X), Fixed8(APoints[FirstValid, I].Y));
  1613. Bounds := MakeRect(OutLine.MinX, OutLine.MinY, OutLine.MaxX, OutLine.MaxY);
  1614. for J := FirstValid+1 to High(APoints) do
  1615. begin
  1616. if (Length(APoints[J]) = 0) then
  1617. continue;
  1618. OutLine.MoveTo(Fixed8(APoints[J, 0].X), Fixed8(APoints[J, 0].Y));
  1619. for I := 1 to High(APoints[J]) do
  1620. OutLine.LineTo(Fixed8(APoints[J, I].X), Fixed8(APoints[J, I].Y));
  1621. Bounds.Left := Min(Bounds.Left, OutLine.MinX);
  1622. Bounds.Right := Max(Bounds.Right, OutLine.MaxX);
  1623. Bounds.Top := Min(Bounds.Top, OutLine.MinY);
  1624. Bounds.Bottom := Max(Bounds.Bottom, OutLine.MaxY);
  1625. end;
  1626. // get cells and check count
  1627. Cells := OutLine.Cells;
  1628. if OutLine.NumCells = 0 then
  1629. Exit;
  1630. if Assigned(Filler) then
  1631. begin
  1632. // call begin rendering of assigned filler
  1633. Filler.BeginRendering;
  1634. Render(Cells, Bounds.Left, Bounds.Right);
  1635. // rendering done, call end rendering of assigned filler
  1636. Filler.EndRendering;
  1637. end
  1638. else
  1639. Render(Cells, Bounds.Left, Bounds.Right);
  1640. {$IFDEF CHANGENOTIFICATIONS}
  1641. if TBitmap32Access(Bitmap).UpdateCount = 0 then
  1642. for I := 0 to High(APoints) do
  1643. if Length(APoints[I]) > 0 then
  1644. Bitmap.Changed(Bounds);
  1645. {$ENDIF}
  1646. finally
  1647. OutLine.Free;
  1648. SetLength(APoints, 0);
  1649. end;
  1650. end;
  1651. const
  1652. FID_FILLSPAN = 0;
  1653. const
  1654. FillSpanBindingFlagPascal = $0001;
  1655. const
  1656. FillSpanRegistryPriorityASM = -256;
  1657. FillSpanRegistryPriorityMMX = -512;
  1658. FillSpanRegistryPrioritySSE2 = -768;
  1659. var
  1660. FillSpanRegistry: TFunctionRegistry;
  1661. procedure RegisterBindings;
  1662. begin
  1663. FillSpanRegistry := NewRegistry('GR32_PolygonsAggLite bindings');
  1664. FillSpanRegistry.RegisterBinding(FID_FILLSPAN, @@FILLSPAN);
  1665. // pure pascal
  1666. FillSpanRegistry.Add(FID_FILLSPAN, @FILLSPAN_Pas, [], FillSpanBindingFlagPascal);
  1667. {$IFNDEF PUREPASCAL}
  1668. FillSpanRegistry.Add(FID_FILLSPAN, @FILLSPAN_ASM, [], 0, FillSpanRegistryPriorityASM);
  1669. {$IFNDEF OMIT_MMX}
  1670. FillSpanRegistry.Add(FID_FILLSPAN, @FILLSPAN_MMX, [ciMMX], 0, FillSpanRegistryPriorityMMX);
  1671. {$ENDIF}
  1672. {$IFNDEF OMIT_SSE2}
  1673. FillSpanRegistry.Add(FID_FILLSPAN, @FILLSPAN_SSE2, [ciSSE2], 0, FillSpanRegistryPrioritySSE2);
  1674. {$ENDIF}
  1675. {$ENDIF}
  1676. FillSpanRegistry.RebindAll;
  1677. end;
  1678. initialization
  1679. RegisterPolygonRenderer(TPolygonRenderer32AggLite);
  1680. RegisterBindings;
  1681. finalization
  1682. end.