ellipse.ppi 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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.6 1998-11-23 10:04:18 pierre
  260. * pieslice and sector work now !!
  261. * bugs in text writing removed
  262. + scaling for defaultfont added
  263. + VertDir for default font added
  264. * RestoreCRTMode corrected
  265. Revision 1.5 1998/11/20 18:42:06 pierre
  266. * many bugs related to floodfill and ellipse fixed
  267. Revision 1.4 1998/11/19 15:09:36 pierre
  268. * several bugfixes for sector/ellipse/floodfill
  269. + graphic driver mode const in interface G800x600x256...
  270. + added backput mode as in linux graph.pp
  271. (clears the background of textoutput)
  272. Revision 1.3 1998/11/19 09:48:47 pierre
  273. + added some functions missing like sector ellipse getarccoords
  274. (the filling of sector and ellipse is still buggy
  275. I use floodfill but sometimes the starting point
  276. is outside !!)
  277. * fixed a bug in floodfill for patterns
  278. (still has problems !!)
  279. Revision 1.2 1998/11/18 09:31:32 pierre
  280. * changed color scheme
  281. all colors are in RGB format if more than 256 colors
  282. + added 24 and 32 bits per pixel mode
  283. (compile with -dDEBUG)
  284. 24 bit mode with banked still as problems on pixels across
  285. the bank boundary, but works in LinearFrameBufferMode
  286. Look at install/demo/nmandel.pp
  287. Revision 1.1.1.1 1998/03/25 11:18:42 root
  288. * Restored version
  289. Revision 1.3 1998/01/26 11:57:54 michael
  290. + Added log at the end
  291. Working file: rtl/dos/ppi/ellipse.ppi
  292. description:
  293. ----------------------------
  294. revision 1.2
  295. date: 1997/12/01 12:21:29; author: michael; state: Exp; lines: +13 -1
  296. + added copyright reference in header.
  297. ----------------------------
  298. revision 1.1
  299. date: 1997/11/27 08:33:51; author: michael; state: Exp;
  300. Initial revision
  301. ----------------------------
  302. revision 1.1.1.1
  303. date: 1997/11/27 08:33:51; author: michael; state: Exp; lines: +0 -0
  304. FPC RTL CVS start
  305. =============================================================================
  306. }