123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- {
- $Id$
- This file is part of the Free Pascal run time library.
- Copyright (c) 1993,97 by the Free Pascal development team.
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- var
- ActArcCoords : ArcCoordsType;
- function CalcEllipse(x,y:Integer;XRadius,YRadius:word):Integer;
- var aq,bq,xq,yq,abq : Longint;
- xp,yp,count : integer;
- i : integer;
- begin
- {XRadius:=(XRadius*10000) div XAsp;
- YRadius:=(YRadius*10000) div YAsp; }
- { must be changed before !! }
- aq :=XRadius * XRadius;
- bq :=YRadius * YRadius;
- abq:=aq * bq;
- yp:=YRadius;
- xp:=0;
- count:=0;
-
- { Berechnung nach : X^2 / A^2 + Y^2 / B^2 = 1 }
- { umgestellt : X^2 * Y^2 * A^2 * B^2 = A^2*B^2 }
- { dadurch werden evtuelle Divisionen durch 0 vermieden }
- { und Integerarithmetik moeglich }
- { was buggy for B=0 !! }
- if YRadius=0 then
- begin
- for i:=0 to XRadius do
- begin
- PWord(buffermem)[count ]:=x + i;
- PWord(buffermem)[count+1]:=y;
- PWord(buffermem)[count+2]:=x - i;
- PWord(buffermem)[count+3]:=y;
- Count:=Count+4;
- end;
- for i:=Xradius-1 downto 1 do
- begin
- PWord(buffermem)[count ]:=x + i;
- PWord(buffermem)[count+1]:=y;
- PWord(buffermem)[count+2]:=x - i;
- PWord(buffermem)[count+3]:=y;
- Count:=Count+4;
- end;
- end
- else repeat
- PWord(buffermem)[count ]:=x + xp;
- PWord(buffermem)[count+1]:=y + yp;
- PWord(buffermem)[count+2]:=x - xp;
- PWord(buffermem)[count+3]:=y - yp;
- xq:=xp * xp; yq:=yp * yp;
- if xq * bq + yq * aq >= abq then yp:=yp-1 else xp:=xp+1;
- Count:=Count+4;
- until yp < 0;
- CalcEllipse:=Count;
- end;
-
- Procedure _Ellipse(Count:Integer);
- const aq:Integer=0;
- begin
-
- { Das Zeichnen der Ellipse erfolgt in zwei Schleifen, um systematisch }
- { von oben nach unten zu zeichnen und somit ein staendiges Bank- }
- { umschalten zu verhindern }
-
- while aq <> count do begin
- PutPixeli( PWord(buffermem)[aq] ,PWord(buffermem)[aq+3],aktcolor);
- PutPixeli( PWord(buffermem)[aq+2],PWord(buffermem)[aq+3],aktcolor);
- aq:=aq+4;
- end;
- while aq <> 0 do begin
- aq:=aq-4;
- PutPixeli( PWord(buffermem)[aq] ,PWord(buffermem)[aq+1],aktcolor);
- PutPixeli( PWord(buffermem)[aq+2],PWord(buffermem)[aq+1],aktcolor);
- end;
- end;
- Procedure Fillellipse(x,y:Integer;XRadius,YRadius:word);
- var Count,index:Word;
- Count8:Word;
- begin
- _graphresult:=grOk;
- if not isgraphmode then
- begin
- _graphresult:=grnoinitgraph;
- exit;
- end;
- XRadius:=(XRadius*10000) div XAsp;
- YRadius:=(YRadius*10000) div YAsp;
- Count:=CalcEllipse(x,y,XRadius,YRadius);
- if Count=0 then exit;
- Count8:=Count-8;
- index:=0;
-
- while index < count do begin
- while (PWord(buffermem)[index+1]=PWord(buffermem)[index+5]) and
- (index < count8) do Index:=Index+4;
- PatternLine(PWord(buffermem)[index],PWord(buffermem)[index+2],
- PWord(buffermem)[index+3]);
- Index:=Index+4;
- end;
-
- while index > 0 do begin
- index:=index-4;
- PatternLine(PWord(buffermem)[index],PWord(buffermem)[index+2],
- PWord(buffermem)[index+1]);
- while (PWord(buffermem)[index+1]=PWord(buffermem)[index-3]) and
- (index > 4 ) do Index:=Index-4;
- end;
- if (aktColor <> aktFillSettings.Color) or (aktFillSettings.Pattern<>1)
- then _Ellipse(Count);
- end;
- { allmost same code than Arc, should be squeezed together !! }
- procedure Ellipse(x,y,alpha,beta:Integer;XRad,YRad:word);
- const i:Array[0..20]of Byte=
- (0,3,0, 2,3,1, 2,1,0, 0,1,1, 0,3,0, 2,3,1, 2,1,0);
- var counter,index : integer;
- ofs,endofs : integer;
- xa,ya,xe,ye : Array[0..2] of Integer;
- xp,yp : integer;
- xradius,yradius : word;
- first,ready : Boolean;
- ofscount : byte;
- procedure DrawArc(index1,index2,index3:byte);
- var ende,incr:integer;
- begin
- if index3=0 then begin
- counter:=index;
- ende:=0;
- incr:=-4;
- end else begin
- counter:=-4;
- ende:=index-4;
- incr:=4;
- end;
- if first then begin
- repeat
- first:=false;
- counter:=counter+incr;
- xp:=PInteger(BufferMem)[counter+index1];
- yp:=PInteger(BufferMem)[counter+index2];
- until (counter=ende) or
- (((xp=xa[0]) or (xp=xa[1]) or (xp=xa[2])) and
- ((yp=ya[0]) or (yp=ya[1]) or (yp=ya[2])));
- if Counter=Ende then exit else putpixeli(xp,yp,aktcolor);
- end;
- repeat
- if (((xp=xe[0]) or (xp=xe[1]) or (xp=xe[2])) and
- ((yp=ye[0]) or (yp=ye[1]) or (yp=ye[2]))) and
- ((ofs mod 4)=endofs) then
- begin
- putpixeli(xp,yp,aktcolor);
- ready:=true;
- exit;
- end;
- counter:=counter+incr;
- xp:=PInteger(BufferMem)[counter+index1];
- yp:=PInteger(BufferMem)[counter+index2];
- putpixeli(xp,yp,aktcolor);
- until counter=Ende;
- end;
- begin
- first:=true; ready:=false;
- XRadius:=XRad; YRadius:=YRad;
- XRadius:=(XRadius*10000) div XAsp;
- YRadius:=(YRadius*10000) div YAsp;
- alpha:=alpha mod 360; beta:=beta mod 360;
- case alpha of
- 0.. 89 : ofs:=0;
- 90..179 : ofs:=1;
- 180..269 : ofs:=2;
- 270..359 : ofs:=3;
- end;
- case beta of
- 0.. 89 : endofs:=0;
- 90..179 : endofs:=1;
- 180..269 : endofs:=2;
- 270..359 : endofs:=3;
- end;
- xa[1]:=x+round(sin((alpha+90)*Pi/180) * XRadius);
- ya[1]:=y+round(cos((alpha+90)*Pi/180) * YRadius);
- xe[1]:=x+round(sin((beta+90)*Pi/180) * XRadius);
- ye[1]:=y+round(cos((beta+90)*Pi/180) * YRadius);
- ActArcCoords.x:=x;
- ActArcCoords.y:=y;
- ActArcCoords.xstart:=xa[1];
- ActArcCoords.ystart:=ya[1];
- ActArcCoords.xend:=xe[1];
- ActArcCoords.yend:=ye[1];
- xa[0]:=xa[1]-1; xa[2]:=xa[1]+1; ya[0]:=ya[1]-1; ya[2]:=ya[1]+1;
- xe[0]:=xe[1]-1; xe[2]:=xe[1]+1; ye[0]:=ye[1]-1; ye[2]:=ye[1]+1;
- index:=Calcellipse(x,y,XRadius,YRadius);
- ofscount:=0;
- repeat
- DrawArc(i[ofs*3],i[ofs*3+1],i[ofs*3+2]);
- ofs:=(ofs+1) mod 7;
- inc(ofscount);
- until ready or (ofscount>16);
- end;
- procedure Sector(X,Y,alpha,beta:integer;XRadius,YRadius: Word);
- var angle : real;
- stline : LineSettingsType;
- writemode : word;
- begin
- Ellipse(x,y,alpha,beta,XRadius,YRadius);
- GetLineSettings(stline);
- SetLineStyle(SolidLn,0,NormWidth);
- writemode:=aktwritemode;
- aktwritemode:=normalput;
- MoveTo(ActArcCoords.xstart,ActArcCoords.ystart);
- LineTo(x,y);
- LineTo(ActArcCoords.xend,ActArcCoords.yend);
- PutPixeli(ActArcCoords.xstart,ActArcCoords.ystart,aktcolor);
- PutPixeli(x,y,aktcolor);
- PutPixeli(ActArcCoords.xend,ActArcCoords.yend,aktcolor);
- alpha:=alpha mod 360; beta:=beta mod 360;
- if alpha<=beta then
- angle:=(alpha+beta)/2
- else
- angle:=(alpha-360+beta)/2;
- { fill from the point in the middle of the slice }
- XRadius:=(XRadius*10000) div XAsp;
- YRadius:=(YRadius*10000) div YAsp;
- {$ifdef GraphDebug}
- Writeln(stderr,'Sector Center ',x,' ',y);
- Writeln(stderr,'Radii ',xradius,' ',yradius);
- Writeln(stderr,'Start ',ActArcCoords.xstart,' ',ActArcCoords.ystart);
- if not ColorsEqual(truecolor,getpixel(ActArcCoords.xstart,ActArcCoords.ystart)) then
- Writeln('Start error not set');
- Writeln(stderr,'End ',ActArcCoords.xend,' ',ActArcCoords.yend);
- if not ColorsEqual(truecolor,getpixel(ActArcCoords.xend,ActArcCoords.yend)) then
- Writeln('End error not set');
- Writeln(stderr,'Fill start ',x+round(sin((angle+90)*Pi/180)*XRadius/2),' ',
- y+round(cos((angle+90)*Pi/180)*YRadius/2));
- {$endif GraphDebug}
- { avoid rounding errors }
- if abs(ActArcCoords.xstart-ActArcCoords.xend)
- +abs(ActArcCoords.ystart-ActArcCoords.yend)>2 then
- FloodFill(x+round(sin((angle+90)*Pi/180)*XRadius/2),
- y+round(cos((angle+90)*Pi/180)*YRadius/2),truecolor);
- aktwritemode:=writemode;
- aktlineinfo:=stline;
- end;
- procedure Circle(x,y:integer;radius:word);
- var
- xradius,yradius : word;
- begin
- _graphresult:=grOk;
- if not isgraphmode then
- begin
- _graphresult:=grnoinitgraph;
- exit;
- end;
- XRadius:=(Radius*10000) div XAsp;
- YRadius:=(Radius*10000) div YAsp;
- _Ellipse(CalcEllipse(x,y,xradius,yradius));
- end;
-
- {
- $Log$
- Revision 1.6 1998-11-23 10:04:18 pierre
- * pieslice and sector work now !!
- * bugs in text writing removed
- + scaling for defaultfont added
- + VertDir for default font added
- * RestoreCRTMode corrected
- Revision 1.5 1998/11/20 18:42:06 pierre
- * many bugs related to floodfill and ellipse fixed
- Revision 1.4 1998/11/19 15:09:36 pierre
- * several bugfixes for sector/ellipse/floodfill
- + graphic driver mode const in interface G800x600x256...
- + added backput mode as in linux graph.pp
- (clears the background of textoutput)
- Revision 1.3 1998/11/19 09:48:47 pierre
- + added some functions missing like sector ellipse getarccoords
- (the filling of sector and ellipse is still buggy
- I use floodfill but sometimes the starting point
- is outside !!)
- * fixed a bug in floodfill for patterns
- (still has problems !!)
- Revision 1.2 1998/11/18 09:31:32 pierre
- * changed color scheme
- all colors are in RGB format if more than 256 colors
- + added 24 and 32 bits per pixel mode
- (compile with -dDEBUG)
- 24 bit mode with banked still as problems on pixels across
- the bank boundary, but works in LinearFrameBufferMode
- Look at install/demo/nmandel.pp
- Revision 1.1.1.1 1998/03/25 11:18:42 root
- * Restored version
- Revision 1.3 1998/01/26 11:57:54 michael
- + Added log at the end
-
- Working file: rtl/dos/ppi/ellipse.ppi
- description:
- ----------------------------
- revision 1.2
- date: 1997/12/01 12:21:29; author: michael; state: Exp; lines: +13 -1
- + added copyright reference in header.
- ----------------------------
- revision 1.1
- date: 1997/11/27 08:33:51; author: michael; state: Exp;
- Initial revision
- ----------------------------
- revision 1.1.1.1
- date: 1997/11/27 08:33:51; author: michael; state: Exp; lines: +0 -0
- FPC RTL CVS start
- =============================================================================
- }
|