ellipse.ppi 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 by the Free Pascal development team.
  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. var
  12. ActArcCoords : ArcCoordsType;
  13. function CalcEllipse(x,y:Integer;XRadius,YRadius:word):Integer;
  14. var aq,bq,xq,yq,abq : Longint;
  15. xp,yp,count : integer;
  16. i : integer;
  17. begin
  18. {XRadius:=(XRadius*10000) div XAsp;
  19. YRadius:=(YRadius*10000) div YAsp; }
  20. { must be changed before !! }
  21. aq :=XRadius * XRadius;
  22. bq :=YRadius * YRadius;
  23. abq:=aq * bq;
  24. yp:=YRadius;
  25. xp:=0;
  26. count:=0;
  27. { Berechnung nach : X^2 / A^2 + Y^2 / B^2 = 1 }
  28. { umgestellt : X^2 * Y^2 * A^2 * B^2 = A^2*B^2 }
  29. { dadurch werden evtuelle Divisionen durch 0 vermieden }
  30. { und Integerarithmetik moeglich }
  31. { was buggy for B=0 !! }
  32. if YRadius=0 then
  33. begin
  34. for i:=0 to XRadius do
  35. begin
  36. PWord(buffermem)[count ]:=x + i;
  37. PWord(buffermem)[count+1]:=y;
  38. PWord(buffermem)[count+2]:=x - i;
  39. PWord(buffermem)[count+3]:=y;
  40. Count:=Count+4;
  41. end;
  42. for i:=Xradius-1 downto 1 do
  43. begin
  44. PWord(buffermem)[count ]:=x + i;
  45. PWord(buffermem)[count+1]:=y;
  46. PWord(buffermem)[count+2]:=x - i;
  47. PWord(buffermem)[count+3]:=y;
  48. Count:=Count+4;
  49. end;
  50. end
  51. else repeat
  52. PWord(buffermem)[count ]:=x + xp;
  53. PWord(buffermem)[count+1]:=y + yp;
  54. PWord(buffermem)[count+2]:=x - xp;
  55. PWord(buffermem)[count+3]:=y - yp;
  56. xq:=xp * xp; yq:=yp * yp;
  57. if xq * bq + yq * aq >= abq then yp:=yp-1 else xp:=xp+1;
  58. Count:=Count+4;
  59. until yp < 0;
  60. CalcEllipse:=Count;
  61. end;
  62. Procedure _Ellipse(Count:Integer);
  63. const aq:Integer=0;
  64. begin
  65. { Das Zeichnen der Ellipse erfolgt in zwei Schleifen, um systematisch }
  66. { von oben nach unten zu zeichnen und somit ein staendiges Bank- }
  67. { umschalten zu verhindern }
  68. while aq <> count do begin
  69. PutPixeli( PWord(buffermem)[aq] ,PWord(buffermem)[aq+3],aktcolor);
  70. PutPixeli( PWord(buffermem)[aq+2],PWord(buffermem)[aq+3],aktcolor);
  71. aq:=aq+4;
  72. end;
  73. while aq <> 0 do begin
  74. aq:=aq-4;
  75. PutPixeli( PWord(buffermem)[aq] ,PWord(buffermem)[aq+1],aktcolor);
  76. PutPixeli( PWord(buffermem)[aq+2],PWord(buffermem)[aq+1],aktcolor);
  77. end;
  78. end;
  79. Procedure Fillellipse(x,y:Integer;XRadius,YRadius:word);
  80. var Count,index:Word;
  81. Count8:Word;
  82. begin
  83. _graphresult:=grOk;
  84. if not isgraphmode then
  85. begin
  86. _graphresult:=grnoinitgraph;
  87. exit;
  88. end;
  89. XRadius:=(XRadius*10000) div XAsp;
  90. YRadius:=(YRadius*10000) div YAsp;
  91. Count:=CalcEllipse(x,y,XRadius,YRadius);
  92. if Count=0 then exit;
  93. Count8:=Count-8;
  94. index:=0;
  95. while index < count do begin
  96. while (PWord(buffermem)[index+1]=PWord(buffermem)[index+5]) and
  97. (index < count8) do Index:=Index+4;
  98. PatternLine(PWord(buffermem)[index],PWord(buffermem)[index+2],
  99. PWord(buffermem)[index+3]);
  100. Index:=Index+4;
  101. end;
  102. while index > 0 do begin
  103. index:=index-4;
  104. PatternLine(PWord(buffermem)[index],PWord(buffermem)[index+2],
  105. PWord(buffermem)[index+1]);
  106. while (PWord(buffermem)[index+1]=PWord(buffermem)[index-3]) and
  107. (index > 4 ) do Index:=Index-4;
  108. end;
  109. if (aktColor <> aktFillSettings.Color) or (aktFillSettings.Pattern<>1)
  110. then _Ellipse(Count);
  111. end;
  112. { allmost same code than Arc, should be squeezed together !! }
  113. procedure Ellipse(x,y,alpha,beta:Integer;XRad,YRad:word);
  114. const i:Array[0..20]of Byte=
  115. (0,3,0, 2,3,1, 2,1,0, 0,1,1, 0,3,0, 2,3,1, 2,1,0);
  116. var counter,index : integer;
  117. ofs,endofs : integer;
  118. xa,ya,xe,ye : Array[0..2] of Integer;
  119. xp,yp : integer;
  120. xradius,yradius : word;
  121. first,ready : Boolean;
  122. ofscount : byte;
  123. procedure DrawArc(index1,index2,index3:byte);
  124. var ende,incr:integer;
  125. begin
  126. if index3=0 then begin
  127. counter:=index;
  128. ende:=0;
  129. incr:=-4;
  130. end else begin
  131. counter:=-4;
  132. ende:=index-4;
  133. incr:=4;
  134. end;
  135. if first then begin
  136. repeat
  137. first:=false;
  138. counter:=counter+incr;
  139. xp:=PInteger(BufferMem)[counter+index1];
  140. yp:=PInteger(BufferMem)[counter+index2];
  141. until (counter=ende) or
  142. (((xp=xa[0]) or (xp=xa[1]) or (xp=xa[2])) and
  143. ((yp=ya[0]) or (yp=ya[1]) or (yp=ya[2])));
  144. if Counter=Ende then exit else putpixeli(xp,yp,aktcolor);
  145. end;
  146. repeat
  147. if (((xp=xe[0]) or (xp=xe[1]) or (xp=xe[2])) and
  148. ((yp=ye[0]) or (yp=ye[1]) or (yp=ye[2]))) and
  149. ((ofs mod 4)=endofs) then
  150. begin
  151. putpixeli(xp,yp,aktcolor);
  152. ready:=true;
  153. exit;
  154. end;
  155. counter:=counter+incr;
  156. xp:=PInteger(BufferMem)[counter+index1];
  157. yp:=PInteger(BufferMem)[counter+index2];
  158. putpixeli(xp,yp,aktcolor);
  159. until counter=Ende;
  160. end;
  161. begin
  162. first:=true; ready:=false;
  163. XRadius:=XRad; YRadius:=YRad;
  164. XRadius:=(XRadius*10000) div XAsp;
  165. YRadius:=(YRadius*10000) div YAsp;
  166. alpha:=alpha mod 360; beta:=beta mod 360;
  167. case alpha of
  168. 0.. 89 : ofs:=0;
  169. 90..179 : ofs:=1;
  170. 180..269 : ofs:=2;
  171. 270..359 : ofs:=3;
  172. end;
  173. case beta of
  174. 0.. 89 : endofs:=0;
  175. 90..179 : endofs:=1;
  176. 180..269 : endofs:=2;
  177. 270..359 : endofs:=3;
  178. end;
  179. xa[1]:=x+round(sin((alpha+90)*Pi/180) * XRadius);
  180. ya[1]:=y+round(cos((alpha+90)*Pi/180) * YRadius);
  181. xe[1]:=x+round(sin((beta+90)*Pi/180) * XRadius);
  182. ye[1]:=y+round(cos((beta+90)*Pi/180) * YRadius);
  183. ActArcCoords.x:=x;
  184. ActArcCoords.y:=y;
  185. ActArcCoords.xstart:=xa[1];
  186. ActArcCoords.ystart:=ya[1];
  187. ActArcCoords.xend:=xe[1];
  188. ActArcCoords.yend:=ye[1];
  189. xa[0]:=xa[1]-1; xa[2]:=xa[1]+1; ya[0]:=ya[1]-1; ya[2]:=ya[1]+1;
  190. xe[0]:=xe[1]-1; xe[2]:=xe[1]+1; ye[0]:=ye[1]-1; ye[2]:=ye[1]+1;
  191. index:=Calcellipse(x,y,XRadius,YRadius);
  192. ofscount:=0;
  193. repeat
  194. DrawArc(i[ofs*3],i[ofs*3+1],i[ofs*3+2]);
  195. ofs:=(ofs+1) mod 7;
  196. inc(ofscount);
  197. until ready or (ofscount>16);
  198. end;
  199. procedure Sector(X,Y,alpha,beta:integer;XRadius,YRadius: Word);
  200. var angle : real;
  201. stline : LineSettingsType;
  202. writemode : word;
  203. begin
  204. Ellipse(x,y,alpha,beta,XRadius,YRadius);
  205. GetLineSettings(stline);
  206. SetLineStyle(SolidLn,0,NormWidth);
  207. writemode:=aktwritemode;
  208. aktwritemode:=normalput;
  209. MoveTo(ActArcCoords.xstart,ActArcCoords.ystart);
  210. LineTo(x,y);
  211. LineTo(ActArcCoords.xend,ActArcCoords.yend);
  212. PutPixeli(ActArcCoords.xstart,ActArcCoords.ystart,aktcolor);
  213. PutPixeli(x,y,aktcolor);
  214. PutPixeli(ActArcCoords.xend,ActArcCoords.yend,aktcolor);
  215. alpha:=alpha mod 360; beta:=beta mod 360;
  216. if alpha<=beta then
  217. angle:=(alpha+beta)/2
  218. else
  219. angle:=(alpha-360+beta)/2;
  220. { fill from the point in the middle of the slice }
  221. XRadius:=(XRadius*10000) div XAsp;
  222. YRadius:=(YRadius*10000) div YAsp;
  223. {$ifdef GraphDebug}
  224. Writeln(stderr,'Sector Center ',x,' ',y);
  225. Writeln(stderr,'Radii ',xradius,' ',yradius);
  226. Writeln(stderr,'Start ',ActArcCoords.xstart,' ',ActArcCoords.ystart);
  227. if not ColorsEqual(truecolor,getpixel(ActArcCoords.xstart,ActArcCoords.ystart)) then
  228. Writeln('Start error not set');
  229. Writeln(stderr,'End ',ActArcCoords.xend,' ',ActArcCoords.yend);
  230. if not ColorsEqual(truecolor,getpixel(ActArcCoords.xend,ActArcCoords.yend)) then
  231. Writeln('End error not set');
  232. Writeln(stderr,'Fill start ',x+round(sin((angle+90)*Pi/180)*XRadius/2),' ',
  233. y+round(cos((angle+90)*Pi/180)*YRadius/2));
  234. {$endif GraphDebug}
  235. { avoid rounding errors }
  236. if abs(ActArcCoords.xstart-ActArcCoords.xend)
  237. +abs(ActArcCoords.ystart-ActArcCoords.yend)>2 then
  238. FloodFill(x+round(sin((angle+90)*Pi/180)*XRadius/2),
  239. y+round(cos((angle+90)*Pi/180)*YRadius/2),truecolor);
  240. aktwritemode:=writemode;
  241. aktlineinfo:=stline;
  242. end;
  243. procedure Circle(x,y:integer;radius:word);
  244. var
  245. xradius,yradius : word;
  246. begin
  247. _graphresult:=grOk;
  248. if not isgraphmode then
  249. begin
  250. _graphresult:=grnoinitgraph;
  251. exit;
  252. end;
  253. XRadius:=(Radius*10000) div XAsp;
  254. YRadius:=(Radius*10000) div YAsp;
  255. _Ellipse(CalcEllipse(x,y,xradius,yradius));
  256. end;
  257. {
  258. $Log$
  259. Revision 1.1 1998-12-21 13:07:03 peter
  260. * use -FE
  261. Revision 1.6 1998/11/23 10:04:18 pierre
  262. * pieslice and sector work now !!
  263. * bugs in text writing removed
  264. + scaling for defaultfont added
  265. + VertDir for default font added
  266. * RestoreCRTMode corrected
  267. Revision 1.5 1998/11/20 18:42:06 pierre
  268. * many bugs related to floodfill and ellipse fixed
  269. Revision 1.4 1998/11/19 15:09:36 pierre
  270. * several bugfixes for sector/ellipse/floodfill
  271. + graphic driver mode const in interface G800x600x256...
  272. + added backput mode as in linux graph.pp
  273. (clears the background of textoutput)
  274. Revision 1.3 1998/11/19 09:48:47 pierre
  275. + added some functions missing like sector ellipse getarccoords
  276. (the filling of sector and ellipse is still buggy
  277. I use floodfill but sometimes the starting point
  278. is outside !!)
  279. * fixed a bug in floodfill for patterns
  280. (still has problems !!)
  281. Revision 1.2 1998/11/18 09:31:32 pierre
  282. * changed color scheme
  283. all colors are in RGB format if more than 256 colors
  284. + added 24 and 32 bits per pixel mode
  285. (compile with -dDEBUG)
  286. 24 bit mode with banked still as problems on pixels across
  287. the bank boundary, but works in LinearFrameBufferMode
  288. Look at install/demo/nmandel.pp
  289. Revision 1.1.1.1 1998/03/25 11:18:42 root
  290. * Restored version
  291. Revision 1.3 1998/01/26 11:57:54 michael
  292. + Added log at the end
  293. Working file: rtl/dos/ppi/ellipse.ppi
  294. description:
  295. ----------------------------
  296. revision 1.2
  297. date: 1997/12/01 12:21:29; author: michael; state: Exp; lines: +13 -1
  298. + added copyright reference in header.
  299. ----------------------------
  300. revision 1.1
  301. date: 1997/11/27 08:33:51; author: michael; state: Exp;
  302. Initial revision
  303. ----------------------------
  304. revision 1.1.1.1
  305. date: 1997/11/27 08:33:51; author: michael; state: Exp; lines: +0 -0
  306. FPC RTL CVS start
  307. =============================================================================
  308. }