123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2000 by the Free Pascal development team
- Graph unit implementation part
- 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
- ExitSave: pointer;
- const
- firstCallOfInitGraph: boolean = true;
- {$ifdef logging}
- var debuglog: text;
- function strf(l: longint): string;
- begin
- str(l, strf)
- end;
- Procedure Log(Const s: String);
- Begin
- Append(debuglog);
- Write(debuglog, s);
- Close(debuglog);
- End;
- Procedure LogLn(Const s: string);
- Begin
- Append(debuglog);
- Writeln(debuglog,s);
- Close(debuglog);
- End;
- {$endif logging}
- const
- StdBufferSize = 4096; { Buffer size for FloodFill }
- type
- tinttable = array[0..16383] of smallint;
- pinttable = ^tinttable;
- WordArray = Array [0..StdbufferSize] Of word;
- PWordArray = ^WordArray;
- const
- { Mask for each bit in byte used to determine pattern }
- BitArray: Array[0..7] of byte =
- ($01,$02,$04,$08,$10,$20,$40,$80);
- RevbitArray: Array[0..7] of byte =
- ($80,$40,$20,$10,$08,$04,$02,$01);
- { pre expanded line patterns }
- { 0 = LSB of byte pattern }
- { 15 = MSB of byte pattern }
- LinePatterns: Array[0..15] of BOOLEAN =
- (TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,
- TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE);
- const
- BGIPath : string = '.';
- { Default font 8x8 system from IBM PC }
- {$i fontdata.inc}
- var
- CurrentColor: Word;
- CurrentBkColor: Word;
- CurrentX : smallint; { viewport relative }
- CurrentY : smallint; { viewport relative }
- ClipPixels: Boolean; { Should cliiping be enabled }
- CurrentWriteMode: smallint;
- _GraphResult : smallint;
- LineInfo : LineSettingsType;
- FillSettings: FillSettingsType;
- { information for Text Output routines }
- CurrentTextInfo : TextSettingsType;
- CurrentXRatio, CurrentYRatio: graph_float;
- installedfonts: longint; { Number of installed fonts }
- StartXViewPort: smallint; { absolute }
- StartYViewPort: smallint; { absolute }
- ViewWidth : smallint;
- ViewHeight: smallint;
- IsGraphMode : Boolean; { Indicates if we are in graph mode or not }
- ArcCall: ArcCoordsType; { Information on the last call to Arc or Ellipse }
- var
- { ******************** HARDWARE INFORMATION ********************* }
- { Should be set in InitGraph once only. }
- IntCurrentMode : smallint;
- IntCurrentDriver : smallint; { Currently loaded driver }
- IntCurrentNewDriver: smallint;
- XAspect : word;
- YAspect : word;
- MaxX : smallint; { Maximum resolution - ABSOLUTE }
- MaxY : smallint; { Maximum resolution - ABSOLUTE }
- MaxColor : Longint;
- PaletteSize : longint; { Maximum palette entry we can set, usually equal}
- { maxcolor. }
- HardwarePages : byte; { maximum number of hardware visual pages }
- DriverName: String;
- DirectColor : Boolean ; { Is it a direct color mode? }
- ModeList : PModeInfo;
- newModeList: TNewModeInfo;
- DirectVideo : Boolean; { Direct access to video memory? }
- {--------------------------------------------------------------------------}
- { }
- { LINE AND LINE RELATED ROUTINES }
- { }
- {--------------------------------------------------------------------------}
- {$i clip.inc}
- procedure HLineDefault(x,x2,y: smallint); {$ifndef fpc}far;{$endif fpc}
- var
- xtmp: smallint;
- Begin
- { must we swap the values? }
- if x >= x2 then
- Begin
- xtmp := x2;
- x2 := x;
- x:= xtmp;
- end;
- { First convert to global coordinates }
- X := X + StartXViewPort;
- X2 := X2 + StartXViewPort;
- Y := Y + StartYViewPort;
- if ClipPixels then
- Begin
- if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
- StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
- exit;
- end;
- for x:= x to x2 do
- DirectPutPixel(X,Y);
- end;
- procedure VLineDefault(x,y,y2: smallint); {$ifndef fpc}far;{$endif fpc}
- var
- ytmp: smallint;
- Begin
- { must we swap the values? }
- if y >= y2 then
- Begin
- ytmp := y2;
- y2 := y;
- y:= ytmp;
- end;
- { First convert to global coordinates }
- X := X + StartXViewPort;
- Y2 := Y2 + StartYViewPort;
- Y := Y + StartYViewPort;
- if ClipPixels then
- Begin
- if LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort,
- StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
- exit;
- end;
- for y := y to y2 do Directputpixel(x,y)
- End;
- Procedure DirectPutPixelClip(x,y: smallint);
- { for thickwidth lines, because they may call DirectPutPixel for coords }
- { outside the current viewport (bug found by CEC) }
- Begin
- If (Not ClipPixels) Or
- ((X >= StartXViewPort) And (X <= (StartXViewPort + ViewWidth)) And
- (Y >= StartYViewPort) And (Y <= (StartYViewPort + ViewHeight))) then
- Begin
- DirectPutPixel(x,y)
- End
- End;
- procedure LineDefault(X1, Y1, X2, Y2: smallint); {$ifndef fpc}far;{$endif fpc}
- var X, Y : smallint;
- deltax, deltay : smallint;
- d, dinc1, dinc2: smallint;
- xinc1 : smallint;
- xinc2 : smallint;
- yinc1 : smallint;
- yinc2 : smallint;
- i : smallint;
- Flag : Boolean; { determines pixel direction in thick lines }
- NumPixels : smallint;
- PixelCount : smallint;
- OldCurrentColor: Word;
- swtmp : smallint;
- TmpNumPixels : smallint;
- begin
- {******************************************}
- { SOLID LINES }
- {******************************************}
- if lineinfo.LineStyle = SolidLn then
- Begin
- { we separate normal and thick width for speed }
- { and because it would not be 100% compatible }
- { with the TP graph unit otherwise }
- if y1 = y2 then
- Begin
- {******************************************}
- { SOLID LINES HORIZONTAL }
- {******************************************}
- if lineinfo.Thickness=NormWidth then
- hline(x1,x2,y2)
- else
- begin
- { thick width }
- hline(x1,x2,y2-1);
- hline(x1,x2,y2);
- hline(x2,x2,y2+1);
- end;
- end
- else
- if x1 = x2 then
- Begin
- {******************************************}
- { SOLID LINES VERTICAL }
- {******************************************}
- if lineinfo.Thickness=NormWidth then
- vline(x1,y1,y2)
- else
- begin
- { thick width }
- vline(x1-1,y1,y2);
- vline(x1,y1,y2);
- vline(x1+1,y1,y2);
- end;
- end
- else
- begin
- { Convert to global coordinates. }
- x1 := x1 + StartXViewPort;
- x2 := x2 + StartXViewPort;
- y1 := y1 + StartYViewPort;
- y2 := y2 + StartYViewPort;
- { if fully clipped then exit... }
- if ClipPixels then
- begin
- if LineClipped(x1,y1,x2,y2,StartXViewPort, StartYViewPort,
- StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
- exit;
- end;
- {******************************************}
- { SLOPED SOLID LINES }
- {******************************************}
- oldCurrentColor :=
- CurrentColor;
- { Calculate deltax and deltay for initialisation }
- deltax := abs(x2 - x1);
- deltay := abs(y2 - y1);
- { Initialize all vars based on which is the independent variable }
- if deltax >= deltay then
- begin
- Flag := FALSE;
- { x is independent variable }
- numpixels := deltax + 1;
- d := (2 * deltay) - deltax;
- dinc1 := deltay Shl 1;
- dinc2 := (deltay - deltax) shl 1;
- xinc1 := 1;
- xinc2 := 1;
- yinc1 := 0;
- yinc2 := 1;
- end
- else
- begin
- Flag := TRUE;
- { y is independent variable }
- numpixels := deltay + 1;
- d := (2 * deltax) - deltay;
- dinc1 := deltax Shl 1;
- dinc2 := (deltax - deltay) shl 1;
- xinc1 := 0;
- xinc2 := 1;
- yinc1 := 1;
- yinc2 := 1;
- end;
- { Make sure x and y move in the right directions }
- if x1 > x2 then
- begin
- xinc1 := - xinc1;
- xinc2 := - xinc2;
- end;
- if y1 > y2 then
- begin
- yinc1 := - yinc1;
- yinc2 := - yinc2;
- end;
- { Start drawing at <x1, y1> }
- x := x1;
- y := y1;
- If LineInfo.Thickness=NormWidth then
- Begin
- { Draw the pixels }
- for i := 1 to numpixels do
- begin
- DirectPutPixel(x, y);
- if d < 0 then
- begin
- d := d + dinc1;
- x := x + xinc1;
- y := y + yinc1;
- end
- else
- begin
- d := d + dinc2;
- x := x + xinc2;
- y := y + yinc2;
- end;
- CurrentColor := OldCurrentColor;
- end;
- end
- else
- { Thick width lines }
- begin
- { Draw the pixels }
- for i := 1 to numpixels do
- begin
- { all depending on the slope, we can determine }
- { in what direction the extra width pixels will be put }
- If Flag then
- Begin
- DirectPutPixelClip(x-1,y);
- DirectPutPixelClip(x,y);
- DirectPutPixelClip(x+1,y);
- end
- else
- Begin
- DirectPutPixelClip(x, y-1);
- DirectPutPixelClip(x, y);
- DirectPutPixelClip(x, y+1);
- end;
- if d < 0 then
- begin
- d := d + dinc1;
- x := x + xinc1;
- y := y + yinc1;
- end
- else
- begin
- d := d + dinc2;
- x := x + xinc2;
- y := y + yinc2;
- end;
- CurrentColor := OldCurrentColor;
- end;
- end;
- end;
- end
- else
- {******************************************}
- { begin patterned lines }
- {******************************************}
- Begin
- { Convert to global coordinates. }
- x1 := x1 + StartXViewPort;
- x2 := x2 + StartXViewPort;
- y1 := y1 + StartYViewPort;
- y2 := y2 + StartYViewPort;
- { if fully clipped then exit... }
- if ClipPixels then
- begin
- if LineClipped(x1,y1,x2,y2,StartXViewPort, StartYViewPort,
- StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
- exit;
- end;
- OldCurrentColor := CurrentColor;
- PixelCount:=0;
- if y1 = y2 then
- Begin
- { Check if we must swap }
- if x1 >= x2 then
- Begin
- swtmp := x1;
- x1 := x2;
- x2 := swtmp;
- end;
- if LineInfo.Thickness = NormWidth then
- Begin
- for PixelCount:=x1 to x2 do
- { optimization: PixelCount mod 16 }
- if LinePatterns[PixelCount and 15] = TRUE then
- begin
- DirectPutPixel(PixelCount,y2);
- end;
- end
- else
- Begin
- for i:=-1 to 1 do
- Begin
- for PixelCount:=x1 to x2 do
- { Optimization from Thomas - mod 16 = and 15 }
- {this optimization has been performed by the compiler
- for while as well (JM)}
- if LinePatterns[PixelCount and 15] = TRUE then
- begin
- DirectPutPixelClip(PixelCount,y2+i);
- end;
- end;
- end;
- end
- else
- if x1 = x2 then
- Begin
- { Check if we must swap }
- if y1 >= y2 then
- Begin
- swtmp := y1;
- y1 := y2;
- y2 := swtmp;
- end;
- if LineInfo.Thickness = NormWidth then
- Begin
- for PixelCount:=y1 to y2 do
- { compare if we should plot a pixel here , compare }
- { with predefined line patterns... }
- if LinePatterns[PixelCount and 15] = TRUE then
- begin
- DirectPutPixel(x1,PixelCount);
- end;
- end
- else
- Begin
- for i:=-1 to 1 do
- Begin
- for PixelCount:=y1 to y2 do
- { compare if we should plot a pixel here , compare }
- { with predefined line patterns... }
- if LinePatterns[PixelCount and 15] = TRUE then
- begin
- DirectPutPixelClip(x1+i,PixelCount);
- end;
- end;
- end;
- end
- else
- Begin
- oldCurrentColor := CurrentColor;
- { Calculate deltax and deltay for initialisation }
- deltax := abs(x2 - x1);
- deltay := abs(y2 - y1);
- { Initialize all vars based on which is the independent variable }
- if deltax >= deltay then
- begin
- Flag := FALSE;
- { x is independent variable }
- numpixels := deltax + 1;
- d := (2 * deltay) - deltax;
- dinc1 := deltay Shl 1;
- dinc2 := (deltay - deltax) shl 1;
- xinc1 := 1;
- xinc2 := 1;
- yinc1 := 0;
- yinc2 := 1;
- end
- else
- begin
- Flag := TRUE;
- { y is independent variable }
- numpixels := deltay + 1;
- d := (2 * deltax) - deltay;
- dinc1 := deltax Shl 1;
- dinc2 := (deltax - deltay) shl 1;
- xinc1 := 0;
- xinc2 := 1;
- yinc1 := 1;
- yinc2 := 1;
- end;
- { Make sure x and y move in the right directions }
- if x1 > x2 then
- begin
- xinc1 := - xinc1;
- xinc2 := - xinc2;
- end;
- if y1 > y2 then
- begin
- yinc1 := - yinc1;
- yinc2 := - yinc2;
- end;
- { Start drawing at <x1, y1> }
- x := x1;
- y := y1;
- If LineInfo.Thickness=ThickWidth then
- Begin
- TmpNumPixels := NumPixels-1;
- { Draw the pixels }
- for i := 0 to TmpNumPixels do
- begin
- { all depending on the slope, we can determine }
- { in what direction the extra width pixels will be put }
- If Flag then
- Begin
- { compare if we should plot a pixel here , compare }
- { with predefined line patterns... }
- if LinePatterns[i and 15] = TRUE then
- begin
- DirectPutPixelClip(x-1,y);
- DirectPutPixelClip(x,y);
- DirectPutPixelClip(x+1,y);
- end;
- end
- else
- Begin
- { compare if we should plot a pixel here , compare }
- { with predefined line patterns... }
- if LinePatterns[i and 15] = TRUE then
- begin
- DirectPutPixelClip(x,y-1);
- DirectPutPixelClip(x,y);
- DirectPutPixelClip(x,y+1);
- end;
- end;
- if d < 0 then
- begin
- d := d + dinc1;
- x := x + xinc1;
- y := y + yinc1;
- end
- else
- begin
- d := d + dinc2;
- x := x + xinc2;
- y := y + yinc2;
- end;
- end;
- end
- else
- Begin
- { instead of putting in loop , substract by one now }
- TmpNumPixels := NumPixels-1;
- { NormWidth }
- for i := 0 to TmpNumPixels do
- begin
- if LinePatterns[i and 15] = TRUE then
- begin
- DirectPutPixel(x,y);
- end;
- if d < 0 then
- begin
- d := d + dinc1;
- x := x + xinc1;
- y := y + yinc1;
- end
- else
- begin
- d := d + dinc2;
- x := x + xinc2;
- y := y + yinc2;
- end;
- end;
- end
- end;
- {******************************************}
- { end patterned lines }
- {******************************************}
- { restore color }
- CurrentColor:=OldCurrentColor;
- end;
- end; { Line }
- {********************************************************}
- { Procedure DummyPatternLine() }
- {--------------------------------------------------------}
- { This is suimply an procedure that does nothing which }
- { can be passed as a patternlineproc for non-filled }
- { ellipses }
- {********************************************************}
- Procedure DummyPatternLine(x1, x2, y: smallint); {$ifdef tp} far; {$endif tp}
- begin
- end;
- {********************************************************}
- { Procedure InternalEllipse() }
- {--------------------------------------------------------}
- { This routine first calculates all points required to }
- { draw a circle to the screen, and stores the points }
- { to display in a buffer before plotting them. The }
- { aspect ratio of the screen is taken into account when }
- { calculating the values. }
- {--------------------------------------------------------}
- { INPUTS: X,Y : Center coordinates of Ellipse. }
- { XRadius - X-Axis radius of ellipse. }
- { YRadius - Y-Axis radius of ellipse. }
- { stAngle, EndAngle: Start angle and end angles of the }
- { ellipse (used for partial ellipses and circles) }
- { pl: procedure which either draws a patternline (for }
- { FillEllipse) or does nothing (arc etc) }
- {--------------------------------------------------------}
- { NOTE: - }
- { - }
- {********************************************************}
- Procedure InternalEllipseDefault(X,Y: smallint;XRadius: word;
- YRadius:word; stAngle,EndAngle: word; pl: PatternLineProc); {$ifndef fpc}far;{$endif fpc}
- Const ConvFac = Pi/180.0;
- var
- j, Delta, DeltaEnd: graph_float;
- NumOfPixels: longint;
- TempTerm: graph_float;
- xtemp, ytemp, xp, yp, xm, ym, xnext, ynext,
- plxpyp, plxmyp, plxpym, plxmym: smallint;
- BackupColor, TmpAngle, OldLineWidth: word;
- Begin
- If LineInfo.ThickNess = ThickWidth Then
- { first draw the two outer ellipses using normwidth and no filling (JM) }
- Begin
- OldLineWidth := LineInfo.Thickness;
- LineInfo.Thickness := NormWidth;
- InternalEllipseDefault(x,y,XRadius,YRadius,StAngle,EndAngle,
- {$ifdef fpc}@{$endif fpc}DummyPatternLine);
- InternalEllipseDefault(x,y,XRadius+1,YRadius+1,StAngle,EndAngle,
- {$ifdef fpc}@{$endif fpc}DummyPatternLine);
- If (XRadius > 0) and (YRadius > 0) Then
- { draw the smallest ellipse last, since that one will use the }
- { original pl, so it could possibly draw patternlines (JM) }
- Begin
- Dec(XRadius);
- Dec(YRadius);
- End
- Else Exit;
- { restore line thickness }
- LineInfo.Thickness := OldLineWidth;
- End;
- If xradius = 0 then inc(xradius);
- if yradius = 0 then inc(yradius);
- { check for an ellipse with negligable x and y radius }
- If (xradius <= 1) and (yradius <= 1) then
- begin
- putpixel(x,y,CurrentColor);
- ArcCall.X := X;
- ArcCall.Y := Y;
- ArcCall.XStart := X;
- ArcCall.YStart := Y;
- ArcCall.XEnd := X;
- ArcCall.YEnd := Y;
- exit;
- end;
- { check if valid angles }
- stangle := stAngle mod 361;
- EndAngle := EndAngle mod 361;
- { if impossible angles then swap them! }
- if Endangle < StAngle then
- Begin
- TmpAngle:=EndAngle;
- EndAngle:=StAngle;
- Stangle:=TmpAngle;
- end;
- { approximate the number of pixels required by using the circumference }
- { equation of an ellipse. }
- { Changed this formula a it (trial and error), but the net result is that }
- { less pixels have to be calculated now }
- NumOfPixels:=Round(Sqrt(3)*sqrt(sqr(XRadius)+sqr(YRadius)));
- { Calculate the angle precision required }
- Delta := 90.0 / NumOfPixels;
- { for restoring after PatternLine }
- BackupColor := CurrentColor;
- { removed from inner loop to make faster }
- { store some arccall info }
- ArcCall.X := X;
- ArcCall.Y := Y;
- TempTerm := (StAngle)*ConvFac;
- ArcCall.XStart := round(XRadius*Cos(TempTerm)) + X;
- ArcCall.YStart := round(YRadius*Sin(TempTerm+Pi)) + Y;
- TempTerm := (EndAngle)*ConvFac;
- ArcCall.XEnd := round(XRadius*Cos(TempTerm)) + X;
- ArcCall.YEnd := round(YRadius*Sin(TempTerm+Pi)) + Y;
- { Always just go over the first 90 degrees. Could be optimized a }
- { bit if StAngle and EndAngle lie in the same quadrant, left as an }
- { exercise for the reader :) (JM) }
- j := 0;
- { calculate stop position, go 1 further than 90 because otherwise }
- { 1 pixel is sometimes not drawn (JM) }
- DeltaEnd := 91;
- { Calculate points }
- xnext := XRadius;
- ynext := 0;
- Repeat
- xtemp := xnext;
- ytemp := ynext;
- { this is used by both sin and cos }
- TempTerm := (j+Delta)*ConvFac;
- { Calculate points }
- xnext := round(XRadius*Cos(TempTerm));
- ynext := round(YRadius*Sin(TempTerm+Pi));
- xp := x + xtemp;
- xm := x - xtemp;
- yp := y + ytemp;
- ym := y - ytemp;
- plxpyp := maxsmallint;
- plxmyp := -maxsmallint-1;
- plxpym := maxsmallint;
- plxmym := -maxsmallint-1;
- If (j >= StAngle) and (j <= EndAngle) then
- begin
- plxpyp := xp;
- PutPixel(xp,yp,CurrentColor);
- end;
- If ((180-j) >= StAngle) and ((180-j) <= EndAngle) then
- begin
- plxmyp := xm;
- PutPixel(xm,yp,CurrentColor);
- end;
- If ((j+180) >= StAngle) and ((j+180) <= EndAngle) then
- begin
- plxmym := xm;
- PutPixel(xm,ym,CurrentColor);
- end;
- If ((360-j) >= StAngle) and ((360-j) <= EndAngle) then
- begin
- plxpym := xp;
- PutPixel(xp,ym,CurrentColor);
- end;
- If (ynext <> ytemp) and
- (xp - xm >= 1) then
- begin
- CurrentColor := FillSettings.Color;
- pl(plxmyp+1,plxpyp-1,yp);
- pl(plxmym+1,plxpym-1,ym);
- CurrentColor := BackupColor;
- end;
- j:=j+Delta;
- Until j > (DeltaEnd);
- end;
- procedure PatternLineDefault(x1,x2,y: smallint); {$ifndef fpc}far;{$endif fpc}
- {********************************************************}
- { Draws a horizontal patterned line according to the }
- { current Fill Settings. }
- {********************************************************}
- { Important notes: }
- { - CurrentColor must be set correctly before entering }
- { this routine. }
- {********************************************************}
- var
- NrIterations: smallint;
- i : smallint;
- j : smallint;
- TmpFillPattern : byte;
- OldWriteMode : word;
- OldCurrentColor : word;
- begin
- { convert to global coordinates ... }
- x1 := x1 + StartXViewPort;
- x2 := x2 + StartXViewPort;
- y := y + StartYViewPort;
- { if line was fully clipped then exit...}
- if LineClipped(x1,y,x2,y,StartXViewPort,StartYViewPort,
- StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
- exit;
- OldWriteMode := CurrentWriteMode;
- CurrentWriteMode := NormalPut;
- { Get the current pattern }
- TmpFillPattern := FillPatternTable
- [FillSettings.Pattern][(y and $7)+1];
- Case TmpFillPattern Of
- 0:
- begin
- OldCurrentColor := CurrentColor;
- CurrentColor := CurrentBkColor;
- { hline converts the coordinates to global ones, but that has been done }
- { already here!!! Convert them back to local ones... (JM) }
- HLine(x1-StartXViewPort,x2-StartXViewPort,y-StartYViewPort);
- CurrentColor := OldCurrentColor;
- end;
- $ff:
- begin
- OldCurrentColor := CurrentColor;
- CurrentColor := FillSettings.Color;
- HLine(x1-StartXViewPort,x2-StartXViewPort,y-StartYViewPort);
- CurrentColor := OldCurrentColor;
- end;
- else
- begin
- { number of times to go throuh the 8x8 pattern }
- NrIterations := abs(x2 - x1+8) div 8;
- For i:= 0 to NrIterations do
- Begin
- for j:=0 to 7 do
- Begin
- { x1 mod 8 }
- if RevBitArray[x1 and 7] and TmpFillPattern <> 0 then
- begin
- OldCurrentColor := CurrentColor;
- CurrentColor := FillSettings.Color;
- DirectPutpixel(x1,y);
- CurrentColor := OldCurrentColor;
- end
- else
- begin
- { According to the TP graph manual, we overwrite everything }
- { which is filled up - checked against VGA and CGA drivers }
- { of TP. }
- OldCurrentColor := CurrentColor;
- CurrentColor := CurrentBkColor;
- DirectPutPixel(x1,y);
- CurrentColor := OldCurrentColor;
- end;
- Inc(x1);
- if x1 > x2 then
- begin
- CurrentWriteMode := OldWriteMode;
- exit;
- end;
- end;
- end;
- end;
- End;
- CurrentWriteMode := OldWriteMode;
- end;
- procedure LineRel(Dx, Dy: smallint);
- Begin
- Line(CurrentX, CurrentY, CurrentX + Dx, CurrentY + Dy);
- CurrentX := CurrentX + Dx;
- CurrentY := CurrentY + Dy;
- end;
- procedure LineTo(x,y : smallint);
- Begin
- Line(CurrentX, CurrentY, X, Y);
- CurrentX := X;
- CurrentY := Y;
- end;
- procedure Rectangle(x1,y1,x2,y2:smallint);
- begin
- { Do not draw the end points }
- Line(x1,y1,x2-1,y1);
- Line(x1,y1+1,x1,y2);
- Line(x2,y1,x2,y2-1);
- Line(x1+1,y2,x2,y2);
- end;
- procedure GetLineSettings(var ActiveLineInfo : LineSettingsType);
- begin
- Activelineinfo:=Lineinfo;
- end;
- procedure SetLineStyle(LineStyle: word; Pattern: word; Thickness: word);
- var
- i: byte;
- j: byte;
- Begin
- if (LineStyle > UserBitLn) or ((Thickness <> Normwidth) and (Thickness <> ThickWidth)) then
- _GraphResult := grError
- else
- begin
- LineInfo.Thickness := Thickness;
- LineInfo.LineStyle := LineStyle;
- case LineStyle of
- UserBitLn: Lineinfo.Pattern := pattern;
- SolidLn: Lineinfo.Pattern := $ffff; { ------- }
- DashedLn : Lineinfo.Pattern := $F8F8; { -- -- --}
- DottedLn: LineInfo.Pattern := $CCCC; { - - - - }
- CenterLn: LineInfo.Pattern := $FC78; { -- - -- }
- end; { end case }
- { setup pattern styles }
- j:=16;
- for i:=0 to 15 do
- Begin
- dec(j);
- { bitwise mask for each bit in the word }
- if (word($01 shl i) AND LineInfo.Pattern) <> 0 then
- LinePatterns[j]:=TRUE
- else
- LinePatterns[j]:=FALSE;
- end;
- end;
- end;
- {--------------------------------------------------------------------------}
- { }
- { VIEWPORT RELATED ROUTINES }
- { }
- {--------------------------------------------------------------------------}
- Procedure ClearViewPortDefault; {$ifndef fpc}far;{$endif fpc}
- var
- j: smallint;
- OldWriteMode, OldCurColor: word;
- LineSets : LineSettingsType;
- Begin
- { CP is always RELATIVE coordinates }
- CurrentX := 0;
- CurrentY := 0;
- { Save all old settings }
- OldCurColor := CurrentColor;
- CurrentColor:=CurrentBkColor;
- OldWriteMode:=CurrentWriteMode;
- CurrentWriteMode:=NormalPut;
- GetLineSettings(LineSets);
- { reset to normal line style...}
- SetLineStyle(SolidLn, 0, NormWidth);
- { routines are relative here...}
- { ViewHeight is Height-1 ! }
- for J:=0 to ViewHeight do
- HLine(0, ViewWidth , J);
- { restore old settings...}
- SetLineStyle(LineSets.LineStyle, LineSets.Pattern, LineSets.Thickness);
- CurrentColor := OldCurColor;
- CurrentWriteMode := OldWriteMode;
- end;
- Procedure SetViewPort(X1, Y1, X2, Y2: smallint; Clip: Boolean);
- Begin
- if (X1 > GetMaxX) or (X2 > GetMaxX) or (X1 > X2) or (X1 < 0) then
- Begin
- {$ifdef logging}
- logln('invalid setviewport parameters: ('
- +strf(x1)+','+strf(y1)+'), ('+strf(x2)+','+strf(y2)+')');
- logln('maxx = '+strf(getmaxx)+', maxy = '+strf(getmaxy));
- {$endif logging}
- _GraphResult := grError;
- exit;
- end;
- if (Y1 > GetMaxY) or (Y2 > GetMaxY) or (Y1 > Y2) or (Y1 < 0) then
- Begin
- {$ifdef logging}
- logln('invalid setviewport parameters: ('
- +strf(x1)+','+strf(y1)+'), ('+strf(x2)+','+strf(y2)+')');
- logln('maxx = '+strf(getmaxx)+', maxy = '+strf(getmaxy));
- {$endif logging}
- _GraphResult := grError;
- exit;
- end;
- { CP is always RELATIVE coordinates }
- CurrentX := 0;
- CurrentY := 0;
- StartXViewPort := X1;
- StartYViewPort := Y1;
- ViewWidth := X2-X1;
- ViewHeight:= Y2-Y1;
- ClipPixels := Clip;
- end;
- procedure GetViewSettings(var viewport : ViewPortType);
- begin
- ViewPort.X1 := StartXViewPort;
- ViewPort.Y1 := StartYViewPort;
- ViewPort.X2 := ViewWidth + StartXViewPort;
- ViewPort.Y2 := ViewHeight + StartYViewPort;
- ViewPort.Clip := ClipPixels;
- end;
- procedure ClearDevice;
- var
- ViewPort: ViewPortType;
- begin
- { Reset the CP }
- CurrentX := 0;
- CurrentY := 0;
- { save viewport }
- ViewPort.X1 := StartXviewPort;
- ViewPort.X2 := ViewWidth - StartXViewPort;
- ViewPort.Y1 := StartYViewPort;
- ViewPort.Y2 := ViewHeight - StartYViewPort;
- ViewPort.Clip := ClipPixels;
- { put viewport to full screen }
- StartXViewPort := 0;
- ViewHeight := MaxY;
- StartYViewPort := 0;
- ViewWidth := MaxX;
- ClipPixels := TRUE;
- ClearViewPort;
- { restore old viewport }
- StartXViewPort := ViewPort.X1;
- ViewWidth := ViewPort.X2-ViewPort.X1;
- StartYViewPort := ViewPort.Y1;
- ViewHeight := ViewPort.Y2-ViewPort.Y1;
- ClipPixels := ViewPort.Clip;
- end;
- {--------------------------------------------------------------------------}
- { }
- { BITMAP PUT/GET ROUTINES }
- { }
- {--------------------------------------------------------------------------}
- Procedure GetScanlineDefault (X1, X2, Y : smallint; Var Data); {$ifndef fpc}far;{$endif fpc}
- {**********************************************************}
- { Procedure GetScanLine() }
- {----------------------------------------------------------}
- { Returns the full scanline of the video line of the Y }
- { coordinate. The values are returned in a WORD array }
- { each WORD representing a pixel of the specified scanline }
- { note: we only need the pixels inside the ViewPort! (JM) }
- { note2: extended so you can specify start and end X coord }
- { so it is usable for GetImage too (JM) }
- {**********************************************************}
- Var
- x : smallint;
- Begin
- For x:=X1 to X2 Do
- WordArray(Data)[x-x1]:=GetPixel(x, y);
- End;
- Function DefaultImageSize(X1,Y1,X2,Y2: smallint): longint; {$ifndef fpc}far;{$endif fpc}
- Begin
- { each pixel uses two bytes, to enable modes with colors up to 64K }
- { to work. }
- DefaultImageSize := 12 + (((X2-X1+1)*(Y2-Y1+1))*2);
- end;
- Procedure DefaultPutImage(X,Y: smallint; var Bitmap; BitBlt: Word); {$ifndef fpc}far;{$endif fpc}
- type
- pt = array[0..$fffffff] of word;
- ptw = array[0..2] of longint;
- var
- k: longint;
- oldCurrentColor: word;
- oldCurrentWriteMode, i, j, y1, x1, deltaX, deltaX1, deltaY: smallint;
- Begin
- {$ifdef logging}
- LogLn('putImage at ('+strf(x)+','+strf(y)+') with width '+strf(ptw(Bitmap)[0])+
- ' and height '+strf(ptw(Bitmap)[1]));
- deltaY := 0;
- {$endif logging}
- inc(x,startXViewPort);
- inc(y,startYViewPort);
- { width/height are 1-based, coordinates are zero based }
- x1 := ptw(Bitmap)[0]+x-1; { get width and adjust end coordinate accordingly }
- y1 := ptw(Bitmap)[1]+y-1; { get height and adjust end coordinate accordingly }
- deltaX := 0;
- deltaX1 := 0;
- k := 3 * sizeOf(Longint) div sizeOf(Word); { Three reserved longs at start of bitmap }
- { check which part of the image is in the viewport }
- if clipPixels then
- begin
- if y < startYViewPort then
- begin
- deltaY := startYViewPort - y;
- inc(k,(x1-x+1)*deltaY);
- y := startYViewPort;
- end;
- if y1 > startYViewPort+viewHeight then
- y1 := startYViewPort+viewHeight;
- if x < startXViewPort then
- begin
- deltaX := startXViewPort-x;
- x := startXViewPort;
- end;
- if x1 > startXViewPort + viewWidth then
- begin
- deltaX1 := x1 - (startXViewPort + viewWidth);
- x1 := startXViewPort + viewWidth;
- end;
- end;
- {$ifdef logging}
- LogLn('deltax: '+strf(deltax)+', deltax1: '+strf(deltax1)+',deltay: '+strf(deltay));
- {$endif logging}
- oldCurrentColor := currentColor;
- oldCurrentWriteMode := currentWriteMode;
- currentWriteMode := bitBlt;
- for j:=Y to Y1 do
- Begin
- inc(k,deltaX);
- for i:=X to X1 do
- begin
- currentColor := pt(bitmap)[k];
- directPutPixel(i,j);
- inc(k);
- end;
- inc(k,deltaX1);
- end;
- currentWriteMode := oldCurrentWriteMode;
- currentColor := oldCurrentColor;
- end;
- Procedure DefaultGetImage(X1,Y1,X2,Y2: smallint; Var Bitmap); {$ifndef fpc}far;{$endif fpc}
- type
- pt = array[0..$fffffff] of word;
- ptw = array[0..2] of longint;
- var
- i,j: smallint;
- k: longint;
- Begin
- k:= 3 * Sizeof(longint) div sizeof(word); { Three reserved longs at start of bitmap }
- i := x2 - x1 + 1;
- for j:=Y1 to Y2 do
- Begin
- GetScanLine(x1,x2,j,pt(Bitmap)[k]);
- inc(k,i);
- end;
- ptw(Bitmap)[0] := X2-X1+1; { First longint is width }
- ptw(Bitmap)[1] := Y2-Y1+1; { Second longint is height }
- ptw(bitmap)[2] := 0; { Third longint is reserved}
- end;
- Procedure GetArcCoords(var ArcCoords: ArcCoordsType);
- Begin
- ArcCoords.X := ArcCall.X;
- ArcCoords.Y := ArcCall.Y;
- ArcCoords.XStart := ArcCall.XStart;
- ArcCoords.YStart := ArcCall.YStart;
- ArcCoords.XEnd := ArcCall.XEnd;
- ArcCoords.YEnd := ArcCall.YEnd;
- end;
- procedure SetVisualPageDefault(page : word); {$ifndef fpc}far;{$endif fpc}
- begin
- end;
- procedure SetActivePageDefault(page : word); {$ifndef fpc}far;{$endif fpc}
- begin
- end;
- procedure DirectPutPixelDefault(X,Y: smallint);
- begin
- Writeln(stderr,'Error: Not in graphics mode (use InitGraph and test GraphResult afterwards)');
- Halt(1);
- end;
- function GetPixelDefault(X,Y: smallint): word;
- begin
- Writeln(stderr,'Error: Not in graphics mode (use InitGraph and test GraphResult afterwards)');
- Halt(1);
- exit(0); { avoid warning }
- end;
- procedure PutPixelDefault(X,Y: smallint; Color: Word);
- begin
- Writeln(stderr,'Error: Not in graphics mode (use InitGraph and test GraphResult afterwards)');
- Halt(1);
- end;
- procedure SetRGBPaletteDefault(ColorNum, RedValue, GreenValue, BlueValue: smallint);
- begin
- Writeln(stderr,'Error: Not in graphics mode (use InitGraph and test GraphResult afterwards)');
- Halt(1);
- end;
- procedure GetRGBPaletteDefault(ColorNum: smallint; var
- RedValue, GreenValue, BlueValue: smallint);
- begin
- Writeln(stderr,'Error: Not in graphics mode (use InitGraph and test GraphResult afterwards)');
- Halt(1);
- end;
- procedure OutTextXYDefault(x,y : smallint;const TextString : string);forward;
- procedure CircleDefault(X, Y: smallint; Radius:Word);forward;
- {$i palette.inc}
- Procedure DefaultHooks;
- {********************************************************}
- { Procedure DefaultHooks() }
- {--------------------------------------------------------}
- { Resets all hookable routine either to nil for those }
- { which need overrides, and others to defaults. }
- { This is called each time SetGraphMode() is called. }
- {********************************************************}
- Begin
- { All default hooks procedures }
- { required...}
- DirectPutPixel := {$ifdef fpc}@{$endif}DirectPutPixelDefault;
- PutPixel := {$ifdef fpc}@{$endif}PutPixelDefault;
- GetPixel := {$ifdef fpc}@{$endif}GetPixelDefault;
- SetRGBPalette := {$ifdef fpc}@{$endif}SetRGBPaletteDefault;
- GetRGBPalette := {$ifdef fpc}@{$endif}GetRGBPaletteDefault;
- { optional...}
- SetAllPalette := {$ifdef fpc}@{$endif}SetAllPaletteDefault;
- SetActivePage := {$ifdef fpc}@{$endif}SetActivePageDefault;
- SetVisualPage := {$ifdef fpc}@{$endif}SetVisualPageDefault;
- ClearViewPort := {$ifdef fpc}@{$endif}ClearViewportDefault;
- PutImage := {$ifdef fpc}@{$endif}DefaultPutImage;
- GetImage := {$ifdef fpc}@{$endif}DefaultGetImage;
- ImageSize := {$ifdef fpc}@{$endif}DefaultImageSize;
- GraphFreeMemPtr := nil;
- GraphGetMemPtr := nil;
- GetScanLine := {$ifdef fpc}@{$endif}GetScanLineDefault;
- Line := {$ifdef fpc}@{$endif}LineDefault;
- InternalEllipse := {$ifdef fpc}@{$endif}InternalEllipseDefault;
- PatternLine := {$ifdef fpc}@{$endif}PatternLineDefault;
- HLine := {$ifdef fpc}@{$endif}HLineDefault;
- VLine := {$ifdef fpc}@{$endif}VLineDefault;
- OuttextXY := {$ifdef fpc}@{$endif}OuttextXYDefault;
- Circle := {$ifdef fpc}@{$endif}CircleDefault;
- end;
- Procedure InitVars;
- {********************************************************}
- { Procedure InitVars() }
- {--------------------------------------------------------}
- { Resets all internal variables, and resets all }
- { overridable routines. }
- {********************************************************}
- Begin
- DirectVideo := TRUE; { By default use fastest access possible }
- ArcCall.X := 0;
- ArcCall.Y := 0;
- ArcCall.XStart := 0;
- ArcCall.YStart := 0;
- ArcCall.XEnd := 0;
- ArcCall.YEnd := 0;
- { Reset to default values }
- IntCurrentMode := 0;
- IntCurrentDriver := 0;
- IntCurrentNewDriver := 0;
- XAspect := 0;
- YAspect := 0;
- MaxX := 0;
- MaxY := 0;
- MaxColor := 0;
- PaletteSize := 0;
- DirectColor := FALSE;
- HardwarePages := 0;
- if hardwarepages=0 then; { remove note }
- DefaultHooks;
- end;
- {$i modes.inc}
- function InstallUserDriver(Name: string; AutoDetectPtr: Pointer): smallint;
- begin
- _graphResult := grError;
- InstallUserDriver:=grError;
- end;
- function RegisterBGIDriver(driver: pointer): smallint;
- begin
- _graphResult := grError;
- RegisterBGIDriver:=grError;
- end;
- { ----------------------------------------------------------------- }
- Procedure Arc(X,Y : smallint; StAngle,EndAngle,Radius: word);
- { var
- OldWriteMode: word;}
- Begin
- { Only if we are using thickwidths lines do we accept }
- { XORput write modes. }
- { OldWriteMode := CurrentWriteMode;
- if (LineInfo.Thickness = NormWidth) then
- CurrentWriteMode := NormalPut;}
- InternalEllipse(X,Y,Radius,Radius,StAngle,Endangle,{$ifdef fpc}@{$endif}DummyPatternLine);
- { CurrentWriteMode := OldWriteMode;}
- end;
- procedure Ellipse(X,Y : smallint; stAngle, EndAngle: word; XRadius,YRadius: word);
- Begin
- InternalEllipse(X,Y,XRadius,YRadius,StAngle,Endangle,{$ifdef fpc}@{$endif}DummyPatternLine);
- end;
- procedure FillEllipse(X, Y: smallint; XRadius, YRadius: Word);
- {********************************************************}
- { Procedure FillEllipse() }
- {--------------------------------------------------------}
- { Draws a filled ellipse using (X,Y) as a center point }
- { and XRadius and YRadius as the horizontal and vertical }
- { axes. The ellipse is filled with the current fill color}
- { and fill style, and is bordered with the current color.}
- {********************************************************}
- begin
- InternalEllipse(X,Y,XRadius,YRadius,0,360,PatternLine)
- end;
- procedure CircleDefault(X, Y: smallint; Radius:Word);
- {********************************************************}
- { Draws a circle centered at X,Y with the given Radius. }
- {********************************************************}
- { Important notes: }
- { - Thickwidth circles use the current write mode, while}
- { normal width circles ALWAYS use CopyPut/NormalPut }
- { mode. (Tested against VGA BGI driver -CEC 13/Aug/99 }
- {********************************************************}
- var OriginalArcInfo: ArcCoordsType;
- OldWriteMode: word;
- begin
- if (Radius = 0) then
- Exit;
- if (Radius = 1) then
- begin
- { only normal put mode is supported by a call to PutPixel }
- PutPixel(X, Y, CurrentColor);
- Exit;
- end;
- { save state of arc information }
- { because it is not needed for }
- { a circle call. }
- System.move(ArcCall,OriginalArcInfo, sizeof(ArcCall));
- if LineInfo.Thickness = Normwidth then
- begin
- OldWriteMode := CurrentWriteMode;
- CurrentWriteMode := CopyPut;
- end;
- { Adjust for screen aspect ratio }
- InternalEllipse(X,Y,Radius,(longint(Radius)*XAspect) div YAspect,0,360,{$ifdef fpc}@{$endif}DummyPatternLine);
- if LineInfo.Thickness = Normwidth then
- CurrentWriteMode := OldWriteMode;
- { restore arc information }
- System.move(OriginalArcInfo, ArcCall,sizeof(ArcCall));
- end;
- procedure SectorPL(x1,x2,y: smallint); {$ifndef fpc}far;{$endif fpc}
- var plx1, plx2: smallint;
- begin
- If (x1 = -maxsmallint) Then
- If (x2 = maxsmallint-1) Then
- { no ellipse points drawn on this line }
- If (((Y < ArcCall.Y) and (Y > ArcCall.YStart)) or
- ((Y > ArcCall.Y) and (Y < ArcCall.YStart))) Then
- { there is a part of the sector at this y coordinate, but no }
- { ellips points are plotted on this line, so draw a patternline }
- { between the lines connecting (arccall.x,arccall.y) with }
- { the start and the end of the arc (JM) }
- { use: y-y1=(y2-y1)/(x2-x1)*(x-x1) => }
- { x = (y-y1)/(y2-y1)*(x2-x1)+x1 }
- Begin
- plx1 := (y-ArcCall.Y)*(ArcCall.XStart-ArcCall.X)
- div (ArcCall.YStart-ArcCall.Y)+ArcCall.X;
- plx2 := (y-ArcCall.Y)*(ArcCall.XEnd-ArcCall.X)
- div (ArcCall.YEnd-ArcCall.Y)+ArcCall.X;
- If plx1 > plx2 then
- begin
- plx1 := plx1 xor plx2;
- plx2 := plx1 xor plx2;
- plx1 := plx1 xor plx2;
- end;
- End
- { otherwise two points which have nothing to do with the sector }
- Else exit
- Else
- { the arc is plotted at the right side, but not at the left side, }
- { fill till the line between (ArcCall.X,ArcCall.Y) and }
- { (ArcCall.XStart,ArcCall.YStart) }
- Begin
- If (y < ArcCall.Y) then
- begin
- plx1 := (y-ArcCall.Y)*(ArcCall.XEnd-ArcCall.X)
- div (ArcCall.YEnd-ArcCall.Y)+ArcCall.X
- end
- else if (y > ArcCall.Y) then
- begin
- plx1 := (y-ArcCall.Y)*(ArcCall.XStart-ArcCall.X)
- div (ArcCall.YStart-ArcCall.Y)+ArcCall.X
- end
- else plx1 := ArcCall.X;
- plx2 := x2;
- End
- Else
- If (x2 = maxsmallint-1) Then
- { the arc is plotted at the left side, but not at the rigth side. }
- { the right limit can be either the first or second line. Just take }
- { the closest one, but watch out for division by zero! }
- Begin
- If (y < ArcCall.Y) then
- begin
- plx2 := (y-ArcCall.Y)*(ArcCall.XStart-ArcCall.X)
- div (ArcCall.YStart-ArcCall.Y)+ArcCall.X
- end
- else if (y > ArcCall.Y) then
- begin
- plx2 := (y-ArcCall.Y)*(ArcCall.XEnd-ArcCall.X)
- div (ArcCall.YEnd-ArcCall.Y)+ArcCall.X
- end
- else plx2 := ArcCall.X;
- plx1 := x1;
- End
- Else
- { the arc is plotted at both sides }
- Begin
- plx1 := x1;
- plx2 := x2;
- End;
- If plx2 > plx1 then
- Begin
- PatternLine(plx1,plx2,y);
- end;
- end;
- procedure Sector(x, y: smallint; StAngle,EndAngle, XRadius, YRadius: Word);
- begin
- internalellipse(x,y,XRadius, YRadius, StAngle, EndAngle, {$ifdef fpc}@{$endif}SectorPL);
- Line(ArcCall.XStart, ArcCall.YStart, x,y);
- Line(x,y,ArcCall.Xend,ArcCall.YEnd);
- end;
- procedure SetFillStyle(Pattern : word; Color: word);
- begin
- { on invalid input, the current fill setting will be }
- { unchanged. }
- if (Pattern > UserFill) or (Color > GetMaxColor) then
- begin
- {$ifdef logging}
- logln('invalid fillstyle parameters');
- {$endif logging}
- _GraphResult := grError;
- exit;
- end;
- FillSettings.Color := Color;
- FillSettings.Pattern := Pattern;
- end;
- procedure SetFillPattern(Pattern: FillPatternType; Color: word);
- {********************************************************}
- { Changes the Current FillPattern to a user defined }
- { pattern and changes also the current fill color. }
- { The FillPattern is saved in the FillPattern array so }
- { it can still be used with SetFillStyle(UserFill,Color) }
- {********************************************************}
- var
- i: smallint;
- begin
- if Color > GetMaxColor then
- begin
- {$ifdef logging}
- logln('invalid fillpattern parameters');
- {$endif logging}
- _GraphResult := grError;
- exit;
- end;
- FillSettings.Color := Color;
- FillSettings.Pattern := UserFill;
- { Save the pattern in the buffer }
- For i:=1 to 8 do
- FillPatternTable[UserFill][i] := Pattern[i];
- end;
- procedure Bar(x1,y1,x2,y2:smallint);
- {********************************************************}
- { Important notes for compatibility with BP: }
- { - WriteMode is always CopyPut }
- { - No contour is drawn for the lines }
- {********************************************************}
- var y : smallint;
- origcolor : longint;
- origlinesettings: Linesettingstype;
- origwritemode : smallint;
- begin
- origlinesettings:=lineinfo;
- origcolor:=CurrentColor;
- if y1>y2 then
- begin
- y:=y1;
- y1:=y2;
- y2:=y;
- end;
- { Always copy mode for Bars }
- origwritemode := CurrentWriteMode;
- CurrentWriteMode := CopyPut;
- { All lines used are of this style }
- Lineinfo.linestyle:=solidln;
- Lineinfo.thickness:=normwidth;
- case Fillsettings.pattern of
- EmptyFill :
- begin
- Currentcolor:=CurrentBkColor;
- for y:=y1 to y2 do
- Hline(x1,x2,y);
- end;
- SolidFill :
- begin
- CurrentColor:=FillSettings.color;
- for y:=y1 to y2 do
- Hline(x1,x2,y);
- end;
- else
- Begin
- CurrentColor:=FillSettings.color;
- for y:=y1 to y2 do
- patternline(x1,x2,y);
- end;
- end;
- CurrentColor:= Origcolor;
- LineInfo := OrigLineSettings;
- CurrentWriteMode := OrigWritemode;
- end;
- procedure bar3D(x1, y1, x2, y2 : smallint;depth : word;top : boolean);
- var
- origwritemode : smallint;
- OldX, OldY : smallint;
- begin
- origwritemode := CurrentWriteMode;
- CurrentWriteMode := CopyPut;
- Bar(x1,y1,x2,y2);
- Rectangle(x1,y1,x2,y2);
- { Current CP should not be updated in Bar3D }
- { therefore save it and then restore it on }
- { exit. }
- OldX := CurrentX;
- OldY := CurrentY;
- if top then begin
- Moveto(x1,y1);
- Lineto(x1+depth,y1-depth);
- Lineto(x2+depth,y1-depth);
- Lineto(x2,y1);
- end;
- if Depth <> 0 then
- Begin
- Moveto(x2+depth,y1-depth);
- Lineto(x2+depth,y2-depth);
- Lineto(x2,y2);
- end;
- { restore CP }
- CurrentX := OldX;
- CurrentY := OldY;
- CurrentWriteMode := origwritemode;
- end;
- {--------------------------------------------------------------------------}
- { }
- { COLOR AND PALETTE ROUTINES }
- { }
- {--------------------------------------------------------------------------}
- procedure SetColor(Color: Word);
- Begin
- CurrentColor := Color;
- end;
- function GetColor: Word;
- Begin
- GetColor := CurrentColor;
- end;
- function GetBkColor: Word;
- Begin
- GetBkColor := CurrentBkColor;
- end;
- procedure SetBkColor(ColorNum: Word);
- { Background color means background screen color in this case, and it is }
- { INDEPENDANT of the viewport settings, so we must clear the whole screen }
- { with the color. }
- var
- ViewPort: ViewportType;
- Begin
- GetViewSettings(Viewport);
- {$ifdef logging}
- logln('calling setviewport from setbkcolor');
- {$endif logging}
- SetViewPort(0,0,MaxX,MaxY,FALSE);
- {$ifdef logging}
- logln('calling setviewport from setbkcolor done');
- {$endif logging}
- CurrentBkColor := ColorNum;
- {ClearViewPort;}
- if not DirectColor and (ColorNum<256) then
- SetRGBPalette(0,
- DefaultColors[ColorNum].Red,
- DefaultColors[ColorNum].Green,
- DefaultColors[ColorNum].Blue);
- SetViewport(ViewPort.X1,Viewport.Y1,Viewport.X2,Viewport.Y2,Viewport.Clip);
- end;
- function GetMaxColor: word;
- { Checked against TP VGA driver - CEC }
- begin
- GetMaxColor:=MaxColor-1; { based on an index of zero so subtract one }
- end;
- Procedure MoveRel(Dx, Dy: smallint);
- Begin
- CurrentX := CurrentX + Dx;
- CurrentY := CurrentY + Dy;
- end;
- Procedure MoveTo(X,Y: smallint);
- {********************************************************}
- { Procedure MoveTo() }
- {--------------------------------------------------------}
- { Moves the current pointer in VIEWPORT relative }
- { coordinates to the specified X,Y coordinate. }
- {********************************************************}
- Begin
- CurrentX := X;
- CurrentY := Y;
- end;
- function GraphErrorMsg(ErrorCode: smallint): string;
- Begin
- GraphErrorMsg:='';
- case ErrorCode of
- grOk,grFileNotFound,grInvalidDriver: exit;
- grNoInitGraph: GraphErrorMsg:='Graphics driver not installed';
- grNotDetected: GraphErrorMsg:='Graphics hardware not detected';
- grNoLoadMem,grNoScanMem,grNoFloodMem: GraphErrorMsg := 'Not enough memory for graphics';
- grNoFontMem: GraphErrorMsg := 'Not enough memory to load font';
- grFontNotFound: GraphErrorMsg:= 'Font file not found';
- grInvalidMode: GraphErrorMsg := 'Invalid graphics mode';
- grError: GraphErrorMsg:='Graphics error';
- grIoError: GraphErrorMsg:='Graphics I/O error';
- grInvalidFont,grInvalidFontNum: GraphErrorMsg := 'Invalid font';
- grInvalidVersion: GraphErrorMsg:='Invalid driver version';
- end;
- end;
- Function GetMaxX: smallint;
- { Routine checked against VGA driver - CEC }
- Begin
- GetMaxX := MaxX;
- end;
- Function GetMaxY: smallint;
- { Routine checked against VGA driver - CEC }
- Begin
- GetMaxY := MaxY;
- end;
- Function GraphResult: smallint;
- Begin
- GraphResult := _GraphResult;
- _GraphResult := grOk;
- end;
- Function GetX: smallint;
- Begin
- GetX := CurrentX;
- end;
- Function GetY: smallint;
- Begin
- GetY := CurrentY;
- end;
- Function GetDriverName: string;
- begin
- GetDriverName:=DriverName;
- end;
- procedure graphdefaults;
- { PS: GraphDefaults does not ZERO the ArcCall structure }
- { so a call to GetArcCoords will not change even the }
- { returned values even if GraphDefaults is called in }
- { between. }
- var
- i: smallint;
- begin
- lineinfo.linestyle:=solidln;
- lineinfo.thickness:=normwidth;
- { reset line style pattern }
- for i:=0 to 15 do
- LinePatterns[i] := TRUE;
- { By default, according to the TP prog's reference }
- { the default pattern is solid, and the default }
- { color is the maximum color in the palette. }
- fillsettings.color:=GetMaxColor;
- fillsettings.pattern:=solidfill;
- { GraphDefaults resets the User Fill pattern to $ff }
- { checked with VGA BGI driver - CEC }
- for i:=1 to 8 do
- FillPatternTable[UserFill][i] := $ff;
- CurrentColor:=white;
- ClipPixels := TRUE;
- { Reset the viewport }
- StartXViewPort := 0;
- StartYViewPort := 0;
- ViewWidth := MaxX;
- ViewHeight := MaxY;
- { Reset CP }
- CurrentX := 0;
- CurrentY := 0;
- SetBkColor(Black);
- { normal write mode }
- CurrentWriteMode := CopyPut;
- { set font style }
- CurrentTextInfo.font := DefaultFont;
- CurrentTextInfo.direction:=HorizDir;
- CurrentTextInfo.charsize:=1;
- CurrentTextInfo.horiz:=LeftText;
- CurrentTextInfo.vert:=TopText;
- XAspect:=10000; YAspect:=10000;
- end;
- procedure GetAspectRatio(var Xasp,Yasp : word);
- begin
- XAsp:=XAspect;
- YAsp:=YAspect;
- end;
- procedure SetAspectRatio(Xasp, Yasp : word);
- begin
- Xaspect:= XAsp;
- YAspect:= YAsp;
- end;
- procedure SetWriteMode(WriteMode : smallint);
- { TP sets the writemodes according to the following scheme (JM) }
- begin
- Case writemode of
- xorput, andput: CurrentWriteMode := XorPut;
- notput, orput, copyput: CurrentWriteMode := CopyPut;
- End;
- end;
- procedure GetFillSettings(var Fillinfo:Fillsettingstype);
- begin
- Fillinfo:=Fillsettings;
- end;
- procedure GetFillPattern(var FillPattern:FillPatternType);
- begin
- FillPattern:=FillpatternTable[UserFill];
- end;
- procedure DrawPoly(numpoints : word;var polypoints);
- type
- ppointtype = ^pointtype;
- pt = array[0..16000] of pointtype;
- var
- i : longint;
- begin
- if numpoints < 2 then
- begin
- _GraphResult := grError;
- exit;
- end;
- for i:=0 to numpoints-2 do
- line(pt(polypoints)[i].x,
- pt(polypoints)[i].y,
- pt(polypoints)[i+1].x,
- pt(polypoints)[i+1].y);
- end;
- procedure PieSlice(X,Y,stangle,endAngle:smallint;Radius: Word);
- begin
- Sector(x,y,stangle,endangle,radius,radius);
- end;
- {$i fills.inc}
- {$i gtext.inc}
- procedure internDetectGraph(var GraphDriver, GraphMode:smallint;
- calledFromInitGraph: boolean);
- var LoMode, HiMode: smallint;
- CpyMode: smallint;
- CpyDriver: smallint;
- begin
- HiMode := -1;
- LoMode := -1;
- if not calledFromInitGraph or
- (graphDriver < lowNewDriver) or
- (graphDriver > highNewDriver) then
- begin
- { Search lowest supported bitDepth }
- graphdriver := D1bit;
- while (graphDriver <= highNewDriver) and
- (hiMode = -1) do
- begin
- getModeRange(graphDriver,loMode,hiMode);
- inc(graphDriver);
- end;
- dec(graphdriver);
- if hiMode = -1 then
- begin
- _GraphResult := grNotDetected;
- exit;
- end;
- CpyMode := 0;
- repeat
- GetModeRange(GraphDriver,LoMode,HiMode);
- { save the highest mode possible...}
- {$ifdef logging}
- logln('Found driver '+strf(graphdriver)+' with modes '+
- strf(lomode)+' - '+strf(himode));
- {$endif logging}
- if HiMode <> -1 then
- begin
- CpyMode:=HiMode;
- CpyDriver:=GraphDriver;
- end;
- { go to next driver if it exists...}
- Inc(graphDriver);
- until (graphDriver > highNewDriver);
- end
- else
- begin
- cpyMode := 0;
- getModeRange(graphDriver,loMode,hiMode);
- if hiMode <> -1 then
- begin
- cpyDriver := graphDriver;
- cpyMode := hiMode;
- end;
- end;
- if cpyMode = 0 then
- begin
- _GraphResult := grNotDetected;
- exit;
- end;
- _GraphResult := grOK;
- GraphDriver := CpyDriver;
- GraphMode := CpyMode;
- end;
- procedure detectGraph(var GraphDriver: smallint; var GraphMode:smallint);
- begin
- internDetectGraph(graphDriver,graphMode,false);
- end;
- procedure InitGraph(var GraphDriver:smallint;var GraphMode:smallint;
- const PathToDriver:String);
- const
- dirchar = System.DirectorySeparator;
- begin
- InitVars;
- { path to the fonts (where they will be searched)...}
- bgipath:=PathToDriver;
- if (Length(bgipath) > 0) and (bgipath[length(bgipath)]<>dirchar) then
- bgipath:=bgipath+dirchar;
- if not assigned(SaveVideoState) then
- RunError(216);
- DriverName:=InternalDriverName; { DOS Graphics driver }
- if (Graphdriver=Detect)
- or (GraphMode = detectMode) then
- begin
- internDetectGraph(GraphDriver,GraphMode,true);
- If _GraphResult = grNotDetected then Exit;
- { _GraphResult is now already set to grOK by DetectGraph }
- IntCurrentDriver := GraphDriver;
- if (graphDriver >= lowNewDriver) and
- (graphDriver <= highNewDriver) then
- IntCurrentNewDriver := GraphDriver
- else IntCurrentNewDriver := -1;
- { Actually set the graph mode...}
- if firstCallOfInitgraph then
- begin
- SaveVideoState;
- firstCallOfInitgraph := false;
- end;
- SetGraphMode(GraphMode);
- end
- else
- begin
- { Search if that graphics modec actually exists...}
- if SearchMode(GraphDriver,GraphMode) = nil then
- begin
- _GraphResult := grInvalidMode;
- exit;
- end
- else
- begin
- _GraphResult := grOK;
- IntCurrentDriver := GraphDriver;
- if (graphDriver >= lowNewDriver) and
- (graphDriver <= highNewDriver) then
- IntCurrentNewDriver := GraphDriver
- else IntCurrentNewDriver := -1;
- if firstCallOfInitgraph then
- begin
- SaveVideoState;
- firstCallOfInitgraph := false;
- end;
- SetGraphMode(GraphMode);
- end;
- end;
- end;
- procedure SetDirectVideo(DirectAccess: boolean);
- begin
- DirectVideo := DirectAccess;
- end;
- function GetDirectVideo: boolean;
- begin
- GetDirectVideo := DirectVideo;
- end;
- procedure GraphExitProc; {$ifndef fpc} far; {$endif fpc}
- { deallocates all memory allocated by the graph unit }
- var
- list: PModeInfo;
- tmp : PModeInfo;
- c: longint;
- begin
- { restore old exitproc! }
- exitproc := exitsave;
- if IsGraphMode and ((errorcode<>0) or (erroraddr<>nil)) then
- CloseGraph;
- { release memory allocated for fonts }
- for c := 1 to installedfonts do
- with fonts[c] Do
- If assigned(instr) Then
- System.Freemem(instr,instrlength);
- { release memory allocated for modelist }
- list := ModeList;
- while assigned(list) do
- begin
- tmp := list;
- list:=list^.next;
- dispose(tmp);
- end;
- for c := lowNewDriver to highNewDriver do
- begin
- list := newModeList.modeinfo[c];
- while assigned(list) do
- begin
- tmp := list;
- list:=list^.next;
- dispose(tmp);
- end;
- end;
- {$IFDEF DPMI}
- { We had copied the buffer of mode information }
- { and allocated it dynamically... now free it }
- { Warning: if GetVESAInfo returned false, this buffer is not allocated! (JM)}
- If hasVesa then
- Dispose(VESAInfo.ModeList);
- {$ENDIF}
- end;
- procedure InitializeGraph;
- begin
- {$ifdef logging}
- assign(debuglog,'grlog.txt');
- rewrite(debuglog);
- close(debuglog);
- {$endif logging}
- isgraphmode := false;
- ModeList := nil;
- fillChar(newModeList.modeinfo,sizeof(newModeList.modeinfo),#0);
- { lo and hi modenumber are -1 currently (no modes supported) }
- fillChar(newModeList.loHiModeNr,sizeof(newModeList.loHiModeNr),#255);
- SaveVideoState := nil;
- RestoreVideoState := nil;
- { This must be called at startup... because GetGraphMode may }
- { be called even when not in graph mode. }
- {$ifdef logging}
- LogLn('Calling QueryAdapterInfo...');
- {$endif logging}
- QueryAdapterInfo;
- { Install standard fonts }
- { This is done BEFORE startup... }
- InstalledFonts := 0;
- InstallUserFont('TRIP');
- InstallUserFont('LITT');
- InstallUserFont('SANS');
- InstallUserFont('GOTH');
- InstallUserFont('SCRI');
- InstallUserFont('SIMP');
- InstallUserFont('TSCR');
- InstallUserFont('LCOM');
- InstallUserFont('EURO');
- InstallUserFont('BOLD');
- { This installs an exit procedure which cleans up the mode list...}
- ExitSave := ExitProc;
- ExitProc := @GraphExitProc;
- {$if defined(win32) and not defined(sdlgraph)}
- charmessagehandler:=nil;
- {$endif win32 and not sdlgraph}
- end;
|