Ellipses.pp 19 KB

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