ellipses.pp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2003 by the Free Pascal development team
  4. Drawing of ellipses and arcs, and filling ellipses and pies.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. unit Ellipses;
  13. interface
  14. uses classes, FPImage, FPCanvas;
  15. procedure DrawSolidEllipse (Canv:TFPCustomCanvas; const Bounds:TRect; c:TFPColor);
  16. procedure DrawSolidEllipse (Canv:TFPCustomCanvas; const Bounds:TRect; Width:integer; c:TFPColor);
  17. procedure DrawPatternEllipse (Canv:TFPCustomCanvas; const Bounds:TRect; Pattern:TPenPattern; c:TFPColor);
  18. procedure FillEllipseColor (Canv:TFPCustomCanvas; const Bounds:TRect; c:TFPColor);
  19. procedure FillEllipsePattern (Canv:TFPCustomCanvas; const Bounds:TRect; Pattern:TBrushPattern; c:TFPColor);
  20. procedure FillEllipseHashHorizontal (Canv:TFPCustomCanvas; const Bounds:TRect; width:integer; const c:TFPColor);
  21. procedure FillEllipseHashVertical (Canv:TFPCustomCanvas; const Bounds:TRect; width:integer; const c:TFPColor);
  22. procedure FillEllipseHashDiagonal (Canv:TFPCustomCanvas; const Bounds:TRect; width:integer; const c:TFPColor);
  23. procedure FillEllipseHashBackDiagonal (Canv:TFPCustomCanvas; const Bounds:TRect; width:integer; const c:TFPColor);
  24. procedure FillEllipseHashDiagCross (Canv:TFPCustomCanvas; const Bounds:TRect; width:integer; const c:TFPColor);
  25. procedure FillEllipseHashCross (Canv:TFPCustomCanvas; const Bounds:TRect; width:integer; const c:TFPColor);
  26. procedure FillEllipseImage (Canv:TFPCustomCanvas; const Bounds:TRect; const Image:TFPCustomImage);
  27. procedure FillEllipseImageRel (Canv:TFPCustomCanvas; const Bounds:TRect; const Image:TFPCustomImage);
  28. type
  29. PEllipseInfoData = ^TEllipseInfoData;
  30. TEllipseInfoData = record
  31. x, ytopmax, ytopmin, ybotmax, ybotmin : integer;
  32. OnlyTop : boolean;
  33. end;
  34. TEllipseInfo = class
  35. private
  36. fcx, fcy, frx,fry,
  37. fa1, fa2, frot : real;
  38. fx1,fy1, fx2,fy2 : integer;
  39. InfoList : TList;
  40. procedure FreeList;
  41. procedure ClearList;
  42. function FindXIndex (x:integer) : integer;
  43. procedure PrepareCalculation (var np:integer; var delta:real);
  44. function NewInfoRec (anX:integer) : PEllipseInfoData;
  45. procedure CalculateCircular (const b:TRect; var x,y,rx,ry:real);
  46. public
  47. constructor create;
  48. destructor destroy; override;
  49. function GetInfoForX (x:integer; var ytopmax,ytopmin,ybotmax,ybotmin:integer):boolean;
  50. function GetInfoForX (x:integer; var Info:PEllipseInfoData):boolean;
  51. procedure GatherEllipseInfo (const bounds:TRect);
  52. procedure GatherArcInfo (const bounds:TRect; alpha1,alpha2:real);
  53. property cx : real read fcx; // center point
  54. property cy : real read fcy;
  55. property rhor : real read frx; // radius
  56. property rver : real read fry;
  57. { only usable when created with GatherArcInfo }
  58. property a1 : real read fa1; // angle 1 and point on ellipse
  59. property x1 : integer read fx1;
  60. property y1 : integer read fy1;
  61. property a2 : real read fa2; // angle 2 and point on ellipse
  62. property x2 : integer read fx2;
  63. property y2 : integer read fy2;
  64. end;
  65. implementation
  66. constructor TEllipseInfo.Create;
  67. begin
  68. inherited;
  69. InfoList := TList.Create;
  70. end;
  71. destructor TEllipseInfo.Destroy;
  72. begin
  73. FreeList;
  74. inherited;
  75. end;
  76. procedure TEllipseInfo.ClearList;
  77. var r : integer;
  78. d : PEllipseInfoData;
  79. begin
  80. if assigned (InfoList) then
  81. begin
  82. for r := 0 to infolist.count-1 do
  83. begin
  84. d := PEllipseInfoData(InfoList[r]);
  85. dispose (d);
  86. end;
  87. InfoList.clear;
  88. end;
  89. end;
  90. procedure TEllipseInfo.FreeList;
  91. begin
  92. if assigned (InfoList) then
  93. begin
  94. ClearList;
  95. InfoList.Free;
  96. InfoList := nil;
  97. end;
  98. end;
  99. function TEllipseInfo.GetInfoForX (x:integer; var ytopmax,ytopmin,ybotmax,ybotmin:integer):boolean;
  100. var r : PEllipseInfoData;
  101. begin
  102. result := GetInfoForX (x, r);
  103. if assigned(r) then
  104. begin
  105. ytopmax := ytopmax;
  106. ytopmin := ytopmin;
  107. ybotmax := ybotmax;
  108. ybotmin := ybotmin;
  109. end;
  110. end;
  111. function TEllipseInfo.FindXIndex (x : integer) : integer;
  112. begin
  113. result := InfoList.Count;
  114. repeat
  115. dec (result);
  116. until (result < 0) or (x = PEllipseInfoData(InfoList[result])^.x);
  117. end;
  118. function TEllipseInfo.GetInfoForX (x:integer; var Info:PEllipseInfoData):boolean;
  119. var r : integer;
  120. begin
  121. r := FindXIndex (x);
  122. result := (r >= 0);
  123. if result then
  124. Info := PEllipseInfoData(InfoList[r])
  125. end;
  126. procedure TEllipseInfo.PrepareCalculation (var np:integer; var delta:real);
  127. begin
  128. np := round(1.5708 * sqrt(sqr(frx)+sqr(fry)) );
  129. // number of pixel in quarter circel to calculate without gaps in drawing
  130. delta := pi / (2 * np);
  131. end;
  132. function TEllipseInfo.NewInfoRec (anX:integer) : PEllipseInfoData;
  133. begin
  134. new (result);
  135. result^.x := anX;
  136. infolist.Add (result);
  137. with result^ do
  138. begin
  139. ytopmax := -1;
  140. ytopmin := maxint;
  141. ybotmax := -1;
  142. ybotmin := maxint;
  143. end;
  144. end;
  145. procedure TEllipseInfo.CalculateCircular (const b:TRect; var x,y,rx,ry:real);
  146. begin
  147. with b do
  148. begin
  149. x := (right+left) / 2;
  150. y := (top+bottom) / 2;
  151. rx := abs(right-left) / 2;
  152. ry := abs(bottom-top) / 2;
  153. end;
  154. end;
  155. procedure TEllipseInfo.GatherEllipseInfo (const bounds:TRect);
  156. var infoP, infoM : PEllipseInfoData;
  157. halfnumber,
  158. r, NumberPixels, xtemp,yt,yb : integer;
  159. pPy, pMy, x,y, rx,ry, xd,yd,ra, rdelta : real;
  160. begin
  161. ClearList;
  162. CalculateCircular (bounds, x,y,rx,ry);
  163. with bounds do
  164. fcx := x;
  165. fcy := y;
  166. frx := rx;
  167. fry := ry;
  168. if (rx < 0.5) and (ry < 0.5) then
  169. with NewInfoRec (round(x))^ do
  170. begin
  171. ytopmax := round(y);
  172. ytopmin := ytopmax;
  173. ybotmax := ytopmax;
  174. ybotmin := ytopmax;
  175. end
  176. else
  177. begin
  178. PrepareCalculation (NumberPixels, rdelta);
  179. halfnumber := NumberPixels div 2;
  180. pPy := maxint;
  181. pMy := maxint;
  182. ra := 0;
  183. infoP := NewInfoRec (round(x + rx));
  184. infoM := NewInfoRec (round(x - rx));
  185. for r := 0 to NumberPixels do
  186. begin
  187. xd := rx * cos(ra);
  188. yd := ry * sin(ra);
  189. // take all 4 quarters
  190. yt := round(y - yd);
  191. yb := round(y + yd);
  192. xtemp := round (x + xd);
  193. // quarter 1 and 4 at the same x line
  194. if infoP^.x <> xtemp then // has correct record ?
  195. begin
  196. with infoP^ do // ensure single width
  197. begin
  198. if r < halfnumber then
  199. begin
  200. if ytopmin = yt then
  201. begin
  202. inc (ytopmin);
  203. dec (ybotmax);
  204. end;
  205. end
  206. else
  207. begin
  208. if (ytopmax = pPy) and (ytopmax <> ytopmin) then
  209. begin
  210. dec (ytopmax);
  211. inc (ybotmin);
  212. end;
  213. end;
  214. pPy := ytopmin;
  215. end;
  216. if not GetInfoForX (xtemp, infoP) then // record exists already ?
  217. infoP := NewInfoRec (xtemp); // create a new recod
  218. end;
  219. // lower y is top, min is lowest
  220. with InfoP^ do
  221. begin
  222. if yt < ytopmin then
  223. ytopmin := yt;
  224. if yb < ybotmin then
  225. ybotmin := yb;
  226. if yt > ytopmax then
  227. ytopmax := yt;
  228. if yb > ybotmax then
  229. ybotmax := yb;
  230. end;
  231. // quarter 2 and 3 on the same x line
  232. xtemp := round(x - xd);
  233. if infoM^.x <> xtemp then // has correct record ?
  234. begin
  235. with infoM^ do // ensure single width
  236. begin
  237. if r < halfnumber then
  238. begin
  239. if ytopmin = yt then
  240. begin
  241. inc (ytopmin);
  242. dec (ybotmax);
  243. end;
  244. end
  245. else
  246. begin
  247. if (ytopmax = pMy) and (ytopmax <> ytopmin) then
  248. begin
  249. dec (ytopmax);
  250. inc (ybotmin);
  251. end;
  252. end;
  253. pMy := ytopmin;
  254. end;
  255. if not GetInfoForX (xtemp, infoM) then // record exists already ?
  256. infoM := NewInfoRec (xtemp); // create a new recod
  257. end;
  258. // lower y is top, min is lowest
  259. with InfoM^ do
  260. begin
  261. if yt < ytopmin then
  262. ytopmin := yt;
  263. if yb < ybotmin then
  264. ybotmin := yb;
  265. if yt > ytopmax then
  266. ytopmax := yt;
  267. if yb > ybotmax then
  268. ybotmax := yb;
  269. end;
  270. ra := ra + rdelta;
  271. end;
  272. end;
  273. end;
  274. procedure TEllipseInfo.GatherArcInfo (const bounds:TRect; alpha1,alpha2:real);
  275. var stAngle,endAngle:real;
  276. procedure CheckAngles;
  277. begin
  278. if a1 < a2 then
  279. begin
  280. stAngle := a1;
  281. endAngle := a2;
  282. end
  283. else
  284. begin
  285. stAngle := a2;
  286. endAngle := a1;
  287. end;
  288. end;
  289. begin
  290. end;
  291. { The drawing routines }
  292. type
  293. TPutPixelProc = procedure (Canv:TFPCustomCanvas; x,y:integer; color:TFPColor);
  294. TLinePoints = array[0..PatternBitCount-1] of boolean;
  295. PLinePoints = ^TLinePoints;
  296. procedure PatternToPoints (const APattern:TPenPattern; LinePoints:PLinePoints);
  297. var r : integer;
  298. i : longword;
  299. begin
  300. i := 1;
  301. for r := PatternBitCount-1 downto 1 do
  302. begin
  303. LinePoints^[r] := (APattern and i) <> 0;
  304. i := i shl 1;
  305. end;
  306. LinePoints^[0] := (APattern and i) <> 0;
  307. end;
  308. procedure PutPixelCopy(Canv:TFPCustomCanvas; x,y:integer; color:TFPColor);
  309. begin
  310. with Canv do
  311. Colors[x,y] := color;
  312. end;
  313. procedure PutPixelXor(Canv:TFPCustomCanvas; x,y:integer; color:TFPColor);
  314. begin
  315. with Canv do
  316. Colors[x,y] := Colors[x,y] xor color;
  317. end;
  318. procedure PutPixelOr(Canv:TFPCustomCanvas; x,y:integer; color:TFPColor);
  319. begin
  320. with Canv do
  321. Colors[x,y] := Colors[x,y] or color;
  322. end;
  323. procedure PutPixelAnd(Canv:TFPCustomCanvas; x,y:integer; color:TFPColor);
  324. begin
  325. with Canv do
  326. Colors[x,y] := Colors[x,y] and color;
  327. end;
  328. procedure DrawSolidEllipse (Canv:TFPCustomCanvas; const Bounds:TRect; c:TFPColor);
  329. var info : TEllipseInfo;
  330. r, y : integer;
  331. MyPutPix : TPutPixelProc;
  332. begin
  333. with canv.pen do
  334. case mode of
  335. pmMask : MyPutPix := @PutPixelAnd;
  336. pmMerge : MyPutPix := @PutPixelOr;
  337. pmXor : MyPutPix := @PutPixelXor;
  338. else MyPutPix := @PutPixelCopy;
  339. end;
  340. info := TEllipseInfo.Create;
  341. with Canv, info do
  342. try
  343. GatherEllipseInfo (bounds);
  344. for r := 0 to InfoList.count-1 do
  345. with PEllipseInfoData(InfoList[r])^ do
  346. begin
  347. for y := ytopmin to ytopmax do
  348. MyPutPix (Canv, x,y, c);
  349. for y := ybotmin to ybotmax do
  350. MyPutPix (Canv, x,y, c);
  351. end;
  352. finally
  353. info.Free;
  354. end;
  355. end;
  356. procedure DrawSolidEllipse (Canv:TFPCustomCanvas; const Bounds:TRect; Width:integer; c:TFPColor);
  357. var infoOut, infoIn : TEllipseInfo;
  358. r, y : integer;
  359. id : PEllipseInfoData;
  360. MyPutPix : TPutPixelProc;
  361. begin
  362. with canv.pen do
  363. case mode of
  364. pmMask : MyPutPix := @PutPixelAnd;
  365. pmMerge : MyPutPix := @PutPixelOr;
  366. pmXor : MyPutPix := @PutPixelXor;
  367. else MyPutPix := @PutPixelCopy;
  368. end;
  369. infoIn := TEllipseInfo.Create;
  370. infoOut := TEllipseInfo.Create;
  371. dec (width);
  372. try
  373. infoOut.GatherEllipseInfo(bounds);
  374. with bounds do
  375. infoIn.GatherEllipseInfo (Rect(left+width,top+width,right-width,bottom-width));
  376. with Canv do
  377. for r := 0 to infoOut.infolist.count-1 do
  378. with PEllipseInfoData (infoOut.infolist[r])^ do
  379. begin
  380. if infoIn.GetInfoForX (x, id) then
  381. begin
  382. for y := ytopmin to id^.ytopmax do
  383. MyPutPix (canv, x,y, c);
  384. for y := id^.ybotmin to ybotmax do
  385. MyPutPix (canv, x,y, c);
  386. end
  387. else
  388. begin // no inner circle found: draw all points between top and bottom
  389. for y := ytopmin to ybotmax do
  390. MyPutPix (canv, x,y, c);
  391. end;
  392. end;
  393. finally
  394. infoOut.Free;
  395. infoIn.Free;
  396. end;
  397. end;
  398. procedure DrawPatternEllipse (Canv:TFPCustomCanvas; const Bounds:TRect; Pattern:TPenPattern; c:TFPColor);
  399. var info : TEllipseInfo;
  400. xx, y : integer;
  401. LinePoints : TLinePoints;
  402. MyPutPix : TPutPixelProc;
  403. id : PEllipseInfoData;
  404. CountDown, CountUp, half : integer;
  405. begin
  406. with canv.pen do
  407. case mode of
  408. pmMask : MyPutPix := @PutPixelAnd;
  409. pmMerge : MyPutPix := @PutPixelOr;
  410. pmXor : MyPutPix := @PutPixelXor;
  411. else MyPutPix := @PutPixelCopy;
  412. end;
  413. PatternToPoints (pattern, @LinePoints);
  414. info := TEllipseInfo.Create;
  415. with Canv, info do
  416. try
  417. GatherEllipseInfo (bounds);
  418. CountUp := 0;
  419. CountDown := PatternBitCount - 1;
  420. half := round (cx);
  421. for xx := bounds.left to half do
  422. if GetInfoForX (xx, id) then
  423. begin
  424. with id^ do
  425. begin
  426. for y := ytopmax downto ytopmin do
  427. begin
  428. if LinePoints[CountUp mod PatternBitCount] then
  429. MyPutPix (Canv, xx,y, c);
  430. inc (CountUp);
  431. end;
  432. for y := ybotmin to ybotmax do
  433. begin
  434. if LinePoints[PatternBitCount - (CountDown mod PatternBitCount) - 1] then
  435. MyPutPix (Canv, xx,y, c);
  436. inc (CountDown);
  437. end;
  438. end;
  439. end;
  440. for xx := half+1 to bounds.right do
  441. if GetInfoForX (xx, id) then
  442. begin
  443. with id^ do
  444. begin
  445. for y := ytopmin to ytopmax do
  446. begin
  447. if LinePoints[CountUp mod PatternBitCount] then
  448. MyPutPix (Canv, xx,y, c);
  449. inc (CountUp);
  450. end;
  451. for y := ybotmax downto ybotmin do
  452. begin
  453. if LinePoints[Patternbitcount - (CountDown mod PatternBitCount) - 1] then
  454. MyPutPix (Canv, xx,y, c);
  455. inc (CountDown);
  456. end;
  457. end;
  458. end;
  459. finally
  460. info.Free;
  461. end;
  462. end;
  463. procedure FillEllipseColor (Canv:TFPCustomCanvas; const Bounds:TRect; c:TFPColor);
  464. var info : TEllipseInfo;
  465. r, y : integer;
  466. id : PEllipseInfoData;
  467. begin
  468. info := TEllipseInfo.Create;
  469. try
  470. info.GatherEllipseInfo(bounds);
  471. with Canv do
  472. for r := 0 to info.infolist.count-1 do
  473. with PEllipseInfoData (info.infolist[r])^ do
  474. for y := ytopmin to ybotmax do
  475. colors[x,y] := c;
  476. finally
  477. info.Free;
  478. end;
  479. end;
  480. procedure FillEllipsePattern (Canv:TFPCustomCanvas; const Bounds:TRect; Pattern:TBrushPattern; c:TFPColor);
  481. begin
  482. end;
  483. procedure FillEllipseHashHorizontal (Canv:TFPCustomCanvas; const Bounds:TRect; width:integer; const c:TFPColor);
  484. var info : TEllipseInfo;
  485. r, y : integer;
  486. id : PEllipseInfoData;
  487. begin
  488. info := TEllipseInfo.Create;
  489. try
  490. info.GatherEllipseInfo(bounds);
  491. for r := 0 to info.infolist.count-1 do
  492. with PEllipseInfoData (info.infolist[r])^ do
  493. for y := ytopmin to ybotmax do
  494. if (y mod width) = 0 then
  495. canv.colors[x,y] := c;
  496. finally
  497. info.Free;
  498. end;
  499. end;
  500. procedure FillEllipseHashVertical (Canv:TFPCustomCanvas; const Bounds:TRect; width:integer; const c:TFPColor);
  501. var info : TEllipseInfo;
  502. r, y : integer;
  503. id : PEllipseInfoData;
  504. begin
  505. info := TEllipseInfo.Create;
  506. try
  507. info.GatherEllipseInfo(bounds);
  508. for r := 0 to info.infolist.count-1 do
  509. with PEllipseInfoData (info.infolist[r])^ do
  510. if (x mod width) = 0 then
  511. for y := ytopmin to ybotmax do
  512. canv.colors[x,y] := c;
  513. finally
  514. info.Free;
  515. end;
  516. end;
  517. procedure FillEllipseHashDiagonal (Canv:TFPCustomCanvas; const Bounds:TRect; width:integer; const c:TFPColor);
  518. var info : TEllipseInfo;
  519. r, y : integer;
  520. id : PEllipseInfoData;
  521. w : integer;
  522. begin
  523. info := TEllipseInfo.Create;
  524. try
  525. info.GatherEllipseInfo(bounds);
  526. for r := 0 to info.infolist.count-1 do
  527. with PEllipseInfoData (info.infolist[r])^ do
  528. begin
  529. w := width - 1 - (x mod width);
  530. for y := ytopmin to ybotmax do
  531. if (y mod width) = w then
  532. canv.colors[x,y] := c;
  533. end;
  534. finally
  535. info.Free;
  536. end;
  537. end;
  538. procedure FillEllipseHashBackDiagonal (Canv:TFPCustomCanvas; const Bounds:TRect; width:integer; const c:TFPColor);
  539. var info : TEllipseInfo;
  540. r, y : integer;
  541. id : PEllipseInfoData;
  542. w : integer;
  543. begin
  544. info := TEllipseInfo.Create;
  545. try
  546. info.GatherEllipseInfo(bounds);
  547. for r := 0 to info.infolist.count-1 do
  548. with PEllipseInfoData (info.infolist[r])^ do
  549. begin
  550. w := (x mod width);
  551. for y := ytopmin to ybotmax do
  552. if (y mod width) = w then
  553. canv.colors[x,y] := c;
  554. end;
  555. finally
  556. info.Free;
  557. end;
  558. end;
  559. procedure FillEllipseHashDiagCross (Canv:TFPCustomCanvas; const Bounds:TRect; width:integer; const c:TFPColor);
  560. var info : TEllipseInfo;
  561. r, y : integer;
  562. id : PEllipseInfoData;
  563. wy,w1,w2 : integer;
  564. begin
  565. info := TEllipseInfo.Create;
  566. try
  567. info.GatherEllipseInfo(bounds);
  568. for r := 0 to info.infolist.count-1 do
  569. with PEllipseInfoData (info.infolist[r])^ do
  570. begin
  571. w1 := (x mod width);
  572. w2 := width - 1 - (x mod width);
  573. for y := ytopmin to ybotmax do
  574. begin
  575. wy := y mod width;
  576. if (wy = w1) or (wy = w2) then
  577. canv.colors[x,y] := c;
  578. end;
  579. end;
  580. finally
  581. info.Free;
  582. end;
  583. end;
  584. procedure FillEllipseHashCross (Canv:TFPCustomCanvas; const Bounds:TRect; width:integer; const c:TFPColor);
  585. var info : TEllipseInfo;
  586. r, y : integer;
  587. id : PEllipseInfoData;
  588. begin
  589. info := TEllipseInfo.Create;
  590. try
  591. info.GatherEllipseInfo(bounds);
  592. for r := 0 to info.infolist.count-1 do
  593. with PEllipseInfoData (info.infolist[r])^ do
  594. if (x mod width) = 0 then
  595. for y := ytopmin to ybotmax do
  596. canv.colors[x,y] := c
  597. else
  598. for y := ytopmin to ybotmax do
  599. if (y mod width) = 0 then
  600. canv.colors[x,y] := c;
  601. finally
  602. info.Free;
  603. end;
  604. end;
  605. procedure FillEllipseImage (Canv:TFPCustomCanvas; const Bounds:TRect; const Image:TFPCustomImage);
  606. var info : TEllipseInfo;
  607. r, y : integer;
  608. id : PEllipseInfoData;
  609. w : integer;
  610. begin
  611. info := TEllipseInfo.Create;
  612. try
  613. info.GatherEllipseInfo(bounds);
  614. for r := 0 to info.infolist.count-1 do
  615. with PEllipseInfoData (info.infolist[r])^ do
  616. begin
  617. w := (x mod image.width);
  618. for y := ytopmin to ybotmax do
  619. canv.colors[x,y] := Image.colors[w, (y mod image.height)];
  620. end;
  621. finally
  622. info.Free;
  623. end;
  624. end;
  625. procedure FillEllipseImageRel (Canv:TFPCustomCanvas; const Bounds:TRect; const Image:TFPCustomImage);
  626. var info : TEllipseInfo;
  627. r, y : integer;
  628. id : PEllipseInfoData;
  629. xo,yo, xi,yi : integer;
  630. begin
  631. info := TEllipseInfo.Create;
  632. try
  633. with info do
  634. begin
  635. GatherEllipseInfo(bounds);
  636. xo := round(cx) - (image.width div 2);
  637. yo := round(cy) - (image.height div 2);
  638. end;
  639. for r := 0 to info.infolist.count-1 do
  640. with PEllipseInfoData (info.infolist[r])^ do
  641. begin
  642. xi := (x - xo) mod image.width;
  643. if xi < 0 then
  644. inc (xi, image.width);
  645. for y := ytopmin to ybotmax do
  646. begin
  647. yi := (y - yo) mod image.height;
  648. if yi < 0 then
  649. inc (yi, image.height);
  650. canv.colors[x,y] := Image.colors[xi, yi];
  651. end;
  652. end;
  653. finally
  654. info.Free;
  655. end;
  656. end;
  657. end.