ellipses.pp 19 KB

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