2
This file is part of the Free Pascal run time library.
3
Copyright (c) 1999-2000 by the Free Pascal development team
5
Graph unit implementation part
7
See the file COPYING.FPC, included in this distribution,
8
for details about the copyright.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
**********************************************************************}
20
firstCallOfInitGraph: boolean = true;
26
function strf(l: longint): string;
31
Procedure Log(Const s: String);
38
Procedure LogLn(Const s: string);
47
StdBufferSize = 4096; { Buffer size for FloodFill }
50
tinttable = array[0..16383] of smallint;
51
pinttable = ^tinttable;
53
WordArray = Array [0..StdbufferSize] Of word;
54
PWordArray = ^WordArray;
58
{ Mask for each bit in byte used to determine pattern }
59
BitArray: Array[0..7] of byte =
60
($01,$02,$04,$08,$10,$20,$40,$80);
61
RevbitArray: Array[0..7] of byte =
62
($80,$40,$20,$10,$08,$04,$02,$01);
64
{ pre expanded line patterns }
65
{ 0 = LSB of byte pattern }
66
{ 15 = MSB of byte pattern }
67
LinePatterns: Array[0..15] of BOOLEAN =
68
(TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,
69
TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE);
72
BGIPath : string = '.';
75
{ Default font 8x8 system from IBM PC }
83
CurrentX : smallint; { viewport relative }
84
CurrentY : smallint; { viewport relative }
86
ClipPixels: Boolean; { Should cliiping be enabled }
89
CurrentWriteMode: smallint;
92
_GraphResult : smallint;
95
LineInfo : LineSettingsType;
96
FillSettings: FillSettingsType;
98
{ information for Text Output routines }
99
CurrentTextInfo : TextSettingsType;
100
CurrentXRatio, CurrentYRatio: graph_float;
101
installedfonts: longint; { Number of installed fonts }
104
StartXViewPort: smallint; { absolute }
105
StartYViewPort: smallint; { absolute }
106
ViewWidth : smallint;
107
ViewHeight: smallint;
110
IsGraphMode : Boolean; { Indicates if we are in graph mode or not }
113
ArcCall: ArcCoordsType; { Information on the last call to Arc or Ellipse }
118
{ ******************** HARDWARE INFORMATION ********************* }
119
{ Should be set in InitGraph once only. }
120
IntCurrentMode : smallint;
121
IntCurrentDriver : smallint; { Currently loaded driver }
122
IntCurrentNewDriver: smallint;
125
MaxX : smallint; { Maximum resolution - ABSOLUTE }
126
MaxY : smallint; { Maximum resolution - ABSOLUTE }
128
PaletteSize : longint; { Maximum palette entry we can set, usually equal}
130
HardwarePages : byte; { maximum number of hardware visual pages }
132
DirectColor : Boolean ; { Is it a direct color mode? }
133
ModeList : PModeInfo;
134
newModeList: TNewModeInfo;
135
DirectVideo : Boolean; { Direct access to video memory? }
140
{--------------------------------------------------------------------------}
142
{ LINE AND LINE RELATED ROUTINES }
144
{--------------------------------------------------------------------------}
148
procedure HLineDefault(x,x2,y: smallint); {$ifndef fpc}far;{$endif fpc}
154
{ must we swap the values? }
161
{ First convert to global coordinates }
162
X := X + StartXViewPort;
163
X2 := X2 + StartXViewPort;
164
Y := Y + StartYViewPort;
167
if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
168
StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
176
procedure VLineDefault(x,y,y2: smallint); {$ifndef fpc}far;{$endif fpc}
181
{ must we swap the values? }
188
{ First convert to global coordinates }
189
X := X + StartXViewPort;
190
Y2 := Y2 + StartYViewPort;
191
Y := Y + StartYViewPort;
194
if LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort,
195
StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
198
for y := y to y2 do Directputpixel(x,y)
201
Procedure DirectPutPixelClip(x,y: smallint);
202
{ for thickwidth lines, because they may call DirectPutPixel for coords }
203
{ outside the current viewport (bug found by CEC) }
205
If (Not ClipPixels) Or
206
((X >= StartXViewPort) And (X <= (StartXViewPort + ViewWidth)) And
207
(Y >= StartYViewPort) And (Y <= (StartYViewPort + ViewHeight))) then
213
procedure LineDefault(X1, Y1, X2, Y2: smallint); {$ifndef fpc}far;{$endif fpc}
216
deltax, deltay : smallint;
217
d, dinc1, dinc2: smallint;
223
Flag : Boolean; { determines pixel direction in thick lines }
224
NumPixels : smallint;
225
PixelCount : smallint;
226
OldCurrentColor: Word;
228
TmpNumPixels : smallint;
230
{******************************************}
232
{******************************************}
233
if lineinfo.LineStyle = SolidLn then
235
{ we separate normal and thick width for speed }
236
{ and because it would not be 100% compatible }
237
{ with the TP graph unit otherwise }
240
{******************************************}
241
{ SOLID LINES HORIZONTAL }
242
{******************************************}
243
if lineinfo.Thickness=NormWidth then
256
{******************************************}
257
{ SOLID LINES VERTICAL }
258
{******************************************}
259
if lineinfo.Thickness=NormWidth then
271
{ Convert to global coordinates. }
272
x1 := x1 + StartXViewPort;
273
x2 := x2 + StartXViewPort;
274
y1 := y1 + StartYViewPort;
275
y2 := y2 + StartYViewPort;
276
{ if fully clipped then exit... }
279
if LineClipped(x1,y1,x2,y2,StartXViewPort, StartYViewPort,
280
StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
283
{******************************************}
284
{ SLOPED SOLID LINES }
285
{******************************************}
288
{ Calculate deltax and deltay for initialisation }
289
deltax := abs(x2 - x1);
290
deltay := abs(y2 - y1);
292
{ Initialize all vars based on which is the independent variable }
293
if deltax >= deltay then
297
{ x is independent variable }
298
numpixels := deltax + 1;
299
d := (2 * deltay) - deltax;
300
dinc1 := deltay Shl 1;
301
dinc2 := (deltay - deltax) shl 1;
311
{ y is independent variable }
312
numpixels := deltay + 1;
313
d := (2 * deltax) - deltay;
314
dinc1 := deltax Shl 1;
315
dinc2 := (deltax - deltay) shl 1;
322
{ Make sure x and y move in the right directions }
334
{ Start drawing at <x1, y1> }
339
If LineInfo.Thickness=NormWidth then
344
for i := 1 to numpixels do
346
DirectPutPixel(x, y);
359
CurrentColor := OldCurrentColor;
363
{ Thick width lines }
366
for i := 1 to numpixels do
368
{ all depending on the slope, we can determine }
369
{ in what direction the extra width pixels will be put }
372
DirectPutPixelClip(x-1,y);
373
DirectPutPixelClip(x,y);
374
DirectPutPixelClip(x+1,y);
378
DirectPutPixelClip(x, y-1);
379
DirectPutPixelClip(x, y);
380
DirectPutPixelClip(x, y+1);
394
CurrentColor := OldCurrentColor;
400
{******************************************}
401
{ begin patterned lines }
402
{******************************************}
404
{ Convert to global coordinates. }
405
x1 := x1 + StartXViewPort;
406
x2 := x2 + StartXViewPort;
407
y1 := y1 + StartYViewPort;
408
y2 := y2 + StartYViewPort;
409
{ if fully clipped then exit... }
412
if LineClipped(x1,y1,x2,y2,StartXViewPort, StartYViewPort,
413
StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
417
OldCurrentColor := CurrentColor;
421
{ Check if we must swap }
428
if LineInfo.Thickness = NormWidth then
430
for PixelCount:=x1 to x2 do
431
{ optimization: PixelCount mod 16 }
432
if LinePatterns[PixelCount and 15] = TRUE then
434
DirectPutPixel(PixelCount,y2);
441
for PixelCount:=x1 to x2 do
442
{ Optimization from Thomas - mod 16 = and 15 }
443
{this optimization has been performed by the compiler
444
for while as well (JM)}
445
if LinePatterns[PixelCount and 15] = TRUE then
447
DirectPutPixelClip(PixelCount,y2+i);
455
{ Check if we must swap }
462
if LineInfo.Thickness = NormWidth then
464
for PixelCount:=y1 to y2 do
465
{ compare if we should plot a pixel here , compare }
466
{ with predefined line patterns... }
467
if LinePatterns[PixelCount and 15] = TRUE then
469
DirectPutPixel(x1,PixelCount);
476
for PixelCount:=y1 to y2 do
477
{ compare if we should plot a pixel here , compare }
478
{ with predefined line patterns... }
479
if LinePatterns[PixelCount and 15] = TRUE then
481
DirectPutPixelClip(x1+i,PixelCount);
488
oldCurrentColor := CurrentColor;
489
{ Calculate deltax and deltay for initialisation }
490
deltax := abs(x2 - x1);
491
deltay := abs(y2 - y1);
493
{ Initialize all vars based on which is the independent variable }
494
if deltax >= deltay then
498
{ x is independent variable }
499
numpixels := deltax + 1;
500
d := (2 * deltay) - deltax;
501
dinc1 := deltay Shl 1;
502
dinc2 := (deltay - deltax) shl 1;
512
{ y is independent variable }
513
numpixels := deltay + 1;
514
d := (2 * deltax) - deltay;
515
dinc1 := deltax Shl 1;
516
dinc2 := (deltax - deltay) shl 1;
523
{ Make sure x and y move in the right directions }
535
{ Start drawing at <x1, y1> }
539
If LineInfo.Thickness=ThickWidth then
542
TmpNumPixels := NumPixels-1;
544
for i := 0 to TmpNumPixels do
546
{ all depending on the slope, we can determine }
547
{ in what direction the extra width pixels will be put }
550
{ compare if we should plot a pixel here , compare }
551
{ with predefined line patterns... }
552
if LinePatterns[i and 15] = TRUE then
554
DirectPutPixelClip(x-1,y);
555
DirectPutPixelClip(x,y);
556
DirectPutPixelClip(x+1,y);
561
{ compare if we should plot a pixel here , compare }
562
{ with predefined line patterns... }
563
if LinePatterns[i and 15] = TRUE then
565
DirectPutPixelClip(x,y-1);
566
DirectPutPixelClip(x,y);
567
DirectPutPixelClip(x,y+1);
586
{ instead of putting in loop , substract by one now }
587
TmpNumPixels := NumPixels-1;
589
for i := 0 to TmpNumPixels do
591
if LinePatterns[i and 15] = TRUE then
610
{******************************************}
611
{ end patterned lines }
612
{******************************************}
614
CurrentColor:=OldCurrentColor;
619
{********************************************************}
620
{ Procedure DummyPatternLine() }
621
{--------------------------------------------------------}
622
{ This is suimply an procedure that does nothing which }
623
{ can be passed as a patternlineproc for non-filled }
625
{********************************************************}
626
Procedure DummyPatternLine(x1, x2, y: smallint); {$ifdef tp} far; {$endif tp}
631
{********************************************************}
632
{ Procedure InternalEllipse() }
633
{--------------------------------------------------------}
634
{ This routine first calculates all points required to }
635
{ draw a circle to the screen, and stores the points }
636
{ to display in a buffer before plotting them. The }
637
{ aspect ratio of the screen is taken into account when }
638
{ calculating the values. }
639
{--------------------------------------------------------}
640
{ INPUTS: X,Y : Center coordinates of Ellipse. }
641
{ XRadius - X-Axis radius of ellipse. }
642
{ YRadius - Y-Axis radius of ellipse. }
643
{ stAngle, EndAngle: Start angle and end angles of the }
644
{ ellipse (used for partial ellipses and circles) }
645
{ pl: procedure which either draws a patternline (for }
646
{ FillEllipse) or does nothing (arc etc) }
647
{--------------------------------------------------------}
650
{********************************************************}
652
Procedure InternalEllipseDefault(X,Y: smallint;XRadius: word;
653
YRadius:word; stAngle,EndAngle: word; pl: PatternLineProc); {$ifndef fpc}far;{$endif fpc}
654
Const ConvFac = Pi/180.0;
657
j, Delta, DeltaEnd: graph_float;
658
NumOfPixels: longint;
659
TempTerm: graph_float;
660
xtemp, ytemp, xp, yp, xm, ym, xnext, ynext,
661
plxpyp, plxmyp, plxpym, plxmym: smallint;
662
BackupColor, TmpAngle, OldLineWidth: word;
664
If LineInfo.ThickNess = ThickWidth Then
665
{ first draw the two outer ellipses using normwidth and no filling (JM) }
667
OldLineWidth := LineInfo.Thickness;
668
LineInfo.Thickness := NormWidth;
669
InternalEllipseDefault(x,y,XRadius,YRadius,StAngle,EndAngle,
670
{$ifdef fpc}@{$endif fpc}DummyPatternLine);
671
InternalEllipseDefault(x,y,XRadius+1,YRadius+1,StAngle,EndAngle,
672
{$ifdef fpc}@{$endif fpc}DummyPatternLine);
673
If (XRadius > 0) and (YRadius > 0) Then
674
{ draw the smallest ellipse last, since that one will use the }
675
{ original pl, so it could possibly draw patternlines (JM) }
681
{ restore line thickness }
682
LineInfo.Thickness := OldLineWidth;
684
{ Adjust for screen aspect ratio }
685
XRadius:=(longint(XRadius)*10000) div XAspect;
686
YRadius:=(longint(YRadius)*10000) div YAspect;
687
If xradius = 0 then inc(xradius);
688
if yradius = 0 then inc(yradius);
689
{ check for an ellipse with negligable x and y radius }
690
If (xradius <= 1) and (yradius <= 1) then
692
putpixel(x,y,CurrentColor);
701
{ check if valid angles }
702
stangle := stAngle mod 361;
703
EndAngle := EndAngle mod 361;
704
{ if impossible angles then swap them! }
705
if Endangle < StAngle then
711
{ approximate the number of pixels required by using the circumference }
712
{ equation of an ellipse. }
713
{ Changed this formula a it (trial and error), but the net result is that }
714
{ less pixels have to be calculated now }
715
NumOfPixels:=Round(Sqrt(3)*sqrt(sqr(XRadius)+sqr(YRadius)));
716
{ Calculate the angle precision required }
717
Delta := 90.0 / NumOfPixels;
718
{ for restoring after PatternLine }
719
BackupColor := CurrentColor;
720
{ removed from inner loop to make faster }
721
{ store some arccall info }
724
TempTerm := (StAngle)*ConvFac;
725
ArcCall.XStart := round(XRadius*Cos(TempTerm)) + X;
726
ArcCall.YStart := round(YRadius*Sin(TempTerm+Pi)) + Y;
727
TempTerm := (EndAngle)*ConvFac;
728
ArcCall.XEnd := round(XRadius*Cos(TempTerm)) + X;
729
ArcCall.YEnd := round(YRadius*Sin(TempTerm+Pi)) + Y;
730
{ Always just go over the first 90 degrees. Could be optimized a }
731
{ bit if StAngle and EndAngle lie in the same quadrant, left as an }
732
{ exercise for the reader :) (JM) }
734
{ calculate stop position, go 1 further than 90 because otherwise }
735
{ 1 pixel is sometimes not drawn (JM) }
743
{ this is used by both sin and cos }
744
TempTerm := (j+Delta)*ConvFac;
746
xnext := round(XRadius*Cos(TempTerm));
747
ynext := round(YRadius*Sin(TempTerm+Pi));
753
plxpyp := maxsmallint;
754
plxmyp := -maxsmallint-1;
755
plxpym := maxsmallint;
756
plxmym := -maxsmallint-1;
757
If (j >= StAngle) and (j <= EndAngle) then
760
PutPixel(xp,yp,CurrentColor);
762
If ((180-j) >= StAngle) and ((180-j) <= EndAngle) then
765
PutPixel(xm,yp,CurrentColor);
767
If ((j+180) >= StAngle) and ((j+180) <= EndAngle) then
770
PutPixel(xm,ym,CurrentColor);
772
If ((360-j) >= StAngle) and ((360-j) <= EndAngle) then
775
PutPixel(xp,ym,CurrentColor);
777
If (ynext <> ytemp) and
780
CurrentColor := FillSettings.Color;
781
pl(plxmyp+1,plxpyp-1,yp);
782
pl(plxmym+1,plxpym-1,ym);
783
CurrentColor := BackupColor;
786
Until j > (DeltaEnd);
790
procedure PatternLineDefault(x1,x2,y: smallint); {$ifndef fpc}far;{$endif fpc}
791
{********************************************************}
792
{ Draws a horizontal patterned line according to the }
793
{ current Fill Settings. }
794
{********************************************************}
796
{ - CurrentColor must be set correctly before entering }
798
{********************************************************}
800
NrIterations: smallint;
803
TmpFillPattern : byte;
805
OldCurrentColor : word;
807
{ convert to global coordinates ... }
808
x1 := x1 + StartXViewPort;
809
x2 := x2 + StartXViewPort;
810
y := y + StartYViewPort;
811
{ if line was fully clipped then exit...}
812
if LineClipped(x1,y,x2,y,StartXViewPort,StartYViewPort,
813
StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
816
OldWriteMode := CurrentWriteMode;
817
CurrentWriteMode := NormalPut;
820
{ Get the current pattern }
821
TmpFillPattern := FillPatternTable
822
[FillSettings.Pattern][(y and $7)+1];
824
Case TmpFillPattern Of
827
OldCurrentColor := CurrentColor;
828
CurrentColor := CurrentBkColor;
829
{ hline converts the coordinates to global ones, but that has been done }
830
{ already here!!! Convert them back to local ones... (JM) }
831
HLine(x1-StartXViewPort,x2-StartXViewPort,y-StartYViewPort);
832
CurrentColor := OldCurrentColor;
836
HLine(x1-StartXViewPort,x2-StartXViewPort,y-StartYViewPort);
840
{ number of times to go throuh the 8x8 pattern }
841
NrIterations := abs(x2 - x1+8) div 8;
842
For i:= 0 to NrIterations do
847
if RevBitArray[x1 and 7] and TmpFillPattern <> 0 then
851
{ According to the TP graph manual, we overwrite everything }
852
{ which is filled up - checked against VGA and CGA drivers }
854
OldCurrentColor := CurrentColor;
855
CurrentColor := CurrentBkColor;
856
DirectPutPixel(x1,y);
857
CurrentColor := OldCurrentColor;
862
CurrentWriteMode := OldWriteMode;
869
CurrentWriteMode := OldWriteMode;
875
procedure LineRel(Dx, Dy: smallint);
878
Line(CurrentX, CurrentY, CurrentX + Dx, CurrentY + Dy);
879
CurrentX := CurrentX + Dx;
880
CurrentY := CurrentY + Dy;
884
procedure LineTo(x,y : smallint);
887
Line(CurrentX, CurrentY, X, Y);
895
procedure Rectangle(x1,y1,x2,y2:smallint);
898
{ Do not draw the end points }
906
procedure GetLineSettings(var ActiveLineInfo : LineSettingsType);
909
Activelineinfo:=Lineinfo;
913
procedure SetLineStyle(LineStyle: word; Pattern: word; Thickness: word);
920
if (LineStyle > UserBitLn) or ((Thickness <> Normwidth) and (Thickness <> ThickWidth)) then
921
_GraphResult := grError
924
LineInfo.Thickness := Thickness;
925
LineInfo.LineStyle := LineStyle;
927
UserBitLn: Lineinfo.Pattern := pattern;
928
SolidLn: Lineinfo.Pattern := $ffff; { ------- }
929
DashedLn : Lineinfo.Pattern := $F8F8; { -- -- --}
930
DottedLn: LineInfo.Pattern := $CCCC; { - - - - }
931
CenterLn: LineInfo.Pattern := $FC78; { -- - -- }
933
{ setup pattern styles }
938
{ bitwise mask for each bit in the word }
939
if (word($01 shl i) AND LineInfo.Pattern) <> 0 then
940
LinePatterns[j]:=TRUE
942
LinePatterns[j]:=FALSE;
950
{--------------------------------------------------------------------------}
952
{ VIEWPORT RELATED ROUTINES }
954
{--------------------------------------------------------------------------}
957
Procedure ClearViewPortDefault; {$ifndef fpc}far;{$endif fpc}
960
OldWriteMode, OldCurColor: word;
961
LineSets : LineSettingsType;
963
{ CP is always RELATIVE coordinates }
967
{ Save all old settings }
968
OldCurColor := CurrentColor;
969
CurrentColor:=CurrentBkColor;
970
OldWriteMode:=CurrentWriteMode;
971
CurrentWriteMode:=NormalPut;
972
GetLineSettings(LineSets);
973
{ reset to normal line style...}
974
SetLineStyle(SolidLn, 0, NormWidth);
975
{ routines are relative here...}
976
{ ViewHeight is Height-1 ! }
977
for J:=0 to ViewHeight do
978
HLine(0, ViewWidth , J);
980
{ restore old settings...}
981
SetLineStyle(LineSets.LineStyle, LineSets.Pattern, LineSets.Thickness);
982
CurrentColor := OldCurColor;
983
CurrentWriteMode := OldWriteMode;
987
Procedure SetViewPort(X1, Y1, X2, Y2: smallint; Clip: Boolean);
989
if (X1 > GetMaxX) or (X2 > GetMaxX) or (X1 > X2) or (X1 < 0) then
992
logln('invalid setviewport parameters: ('
993
+strf(x1)+','+strf(y1)+'), ('+strf(x2)+','+strf(y2)+')');
994
logln('maxx = '+strf(getmaxx)+', maxy = '+strf(getmaxy));
996
_GraphResult := grError;
999
if (Y1 > GetMaxY) or (Y2 > GetMaxY) or (Y1 > Y2) or (Y1 < 0) then
1002
logln('invalid setviewport parameters: ('
1003
+strf(x1)+','+strf(y1)+'), ('+strf(x2)+','+strf(y2)+')');
1004
logln('maxx = '+strf(getmaxx)+', maxy = '+strf(getmaxy));
1006
_GraphResult := grError;
1009
{ CP is always RELATIVE coordinates }
1012
StartXViewPort := X1;
1013
StartYViewPort := Y1;
1020
procedure GetViewSettings(var viewport : ViewPortType);
1022
ViewPort.X1 := StartXViewPort;
1023
ViewPort.Y1 := StartYViewPort;
1024
ViewPort.X2 := ViewWidth + StartXViewPort;
1025
ViewPort.Y2 := ViewHeight + StartYViewPort;
1026
ViewPort.Clip := ClipPixels;
1029
procedure ClearDevice;
1031
ViewPort: ViewPortType;
1037
ViewPort.X1 := StartXviewPort;
1038
ViewPort.X2 := ViewWidth - StartXViewPort;
1039
ViewPort.Y1 := StartYViewPort;
1040
ViewPort.Y2 := ViewHeight - StartYViewPort;
1041
ViewPort.Clip := ClipPixels;
1042
{ put viewport to full screen }
1043
StartXViewPort := 0;
1045
StartYViewPort := 0;
1049
{ restore old viewport }
1050
StartXViewPort := ViewPort.X1;
1051
ViewWidth := ViewPort.X2-ViewPort.X1;
1052
StartYViewPort := ViewPort.Y1;
1053
ViewHeight := ViewPort.Y2-ViewPort.Y1;
1054
ClipPixels := ViewPort.Clip;
1059
{--------------------------------------------------------------------------}
1061
{ BITMAP PUT/GET ROUTINES }
1063
{--------------------------------------------------------------------------}
1066
Procedure GetScanlineDefault (X1, X2, Y : smallint; Var Data); {$ifndef fpc}far;{$endif fpc}
1067
{**********************************************************}
1068
{ Procedure GetScanLine() }
1069
{----------------------------------------------------------}
1070
{ Returns the full scanline of the video line of the Y }
1071
{ coordinate. The values are returned in a WORD array }
1072
{ each WORD representing a pixel of the specified scanline }
1073
{ note: we only need the pixels inside the ViewPort! (JM) }
1074
{ note2: extended so you can specify start and end X coord }
1075
{ so it is usable for GetImage too (JM) }
1076
{**********************************************************}
1083
WordArray(Data)[x-x1]:=GetPixel(x, y);
1088
Function DefaultImageSize(X1,Y1,X2,Y2: smallint): longint; {$ifndef fpc}far;{$endif fpc}
1090
{ each pixel uses two bytes, to enable modes with colors up to 64K }
1092
DefaultImageSize := 12 + (((X2-X1+1)*(Y2-Y1+1))*2);
1095
Procedure DefaultPutImage(X,Y: smallint; var Bitmap; BitBlt: Word); {$ifndef fpc}far;{$endif fpc}
1097
pt = array[0..$fffffff] of word;
1098
ptw = array[0..2] of longint;
1101
oldCurrentColor: word;
1102
oldCurrentWriteMode, i, j, y1, x1, deltaX, deltaX1, deltaY: smallint;
1105
LogLn('putImage at ('+strf(x)+','+strf(y)+') with width '+strf(ptw(Bitmap)[0])+
1106
' and height '+strf(ptw(Bitmap)[1]));
1109
inc(x,startXViewPort);
1110
inc(y,startYViewPort);
1111
{ width/height are 1-based, coordinates are zero based }
1112
x1 := ptw(Bitmap)[0]+x-1; { get width and adjust end coordinate accordingly }
1113
y1 := ptw(Bitmap)[1]+y-1; { get height and adjust end coordinate accordingly }
1117
k := 3 * sizeOf(Longint) div sizeOf(Word); { Three reserved longs at start of bitmap }
1118
{ check which part of the image is in the viewport }
1121
if y < startYViewPort then
1123
deltaY := startYViewPort - y;
1124
inc(k,(x1-x+1)*deltaY);
1125
y := startYViewPort;
1127
if y1 > startYViewPort+viewHeight then
1128
y1 := startYViewPort+viewHeight;
1129
if x < startXViewPort then
1131
deltaX := startXViewPort-x;
1132
x := startXViewPort;
1134
if x1 > startXViewPort + viewWidth then
1136
deltaX1 := x1 - (startXViewPort + viewWidth);
1137
x1 := startXViewPort + viewWidth;
1141
LogLn('deltax: '+strf(deltax)+', deltax1: '+strf(deltax1)+',deltay: '+strf(deltay));
1143
oldCurrentColor := currentColor;
1144
oldCurrentWriteMode := currentWriteMode;
1145
currentWriteMode := bitBlt;
1151
currentColor := pt(bitmap)[k];
1152
directPutPixel(i,j);
1157
currentWriteMode := oldCurrentWriteMode;
1158
currentColor := oldCurrentColor;
1161
Procedure DefaultGetImage(X1,Y1,X2,Y2: smallint; Var Bitmap); {$ifndef fpc}far;{$endif fpc}
1163
pt = array[0..$fffffff] of word;
1164
ptw = array[0..2] of longint;
1169
k:= 3 * Sizeof(longint) div sizeof(word); { Three reserved longs at start of bitmap }
1173
GetScanLine(x1,x2,j,pt(Bitmap)[k]);
1176
ptw(Bitmap)[0] := X2-X1+1; { First longint is width }
1177
ptw(Bitmap)[1] := Y2-Y1+1; { Second longint is height }
1178
ptw(bitmap)[2] := 0; { Third longint is reserved}
1186
Procedure GetArcCoords(var ArcCoords: ArcCoordsType);
1188
ArcCoords.X := ArcCall.X;
1189
ArcCoords.Y := ArcCall.Y;
1190
ArcCoords.XStart := ArcCall.XStart;
1191
ArcCoords.YStart := ArcCall.YStart;
1192
ArcCoords.XEnd := ArcCall.XEnd;
1193
ArcCoords.YEnd := ArcCall.YEnd;
1197
procedure SetVisualPageDefault(page : word); {$ifndef fpc}far;{$endif fpc}
1202
procedure SetActivePageDefault(page : word); {$ifndef fpc}far;{$endif fpc}
1206
procedure DirectPutPixelDefault(X,Y: smallint);
1208
Writeln(stderr,'Error: Not in graphics mode (use InitGraph and test GraphResult afterwards)');
1212
function GetPixelDefault(X,Y: smallint): word;
1214
Writeln(stderr,'Error: Not in graphics mode (use InitGraph and test GraphResult afterwards)');
1216
exit(0); { avoid warning }
1219
procedure PutPixelDefault(X,Y: smallint; Color: Word);
1221
Writeln(stderr,'Error: Not in graphics mode (use InitGraph and test GraphResult afterwards)');
1225
procedure SetRGBPaletteDefault(ColorNum, RedValue, GreenValue, BlueValue: smallint);
1227
Writeln(stderr,'Error: Not in graphics mode (use InitGraph and test GraphResult afterwards)');
1231
procedure GetRGBPaletteDefault(ColorNum: smallint; var
1232
RedValue, GreenValue, BlueValue: smallint);
1234
Writeln(stderr,'Error: Not in graphics mode (use InitGraph and test GraphResult afterwards)');
1239
procedure OutTextXYDefault(x,y : smallint;const TextString : string);forward;
1240
procedure CircleDefault(X, Y: smallint; Radius:Word);forward;
1244
Procedure DefaultHooks;
1245
{********************************************************}
1246
{ Procedure DefaultHooks() }
1247
{--------------------------------------------------------}
1248
{ Resets all hookable routine either to nil for those }
1249
{ which need overrides, and others to defaults. }
1250
{ This is called each time SetGraphMode() is called. }
1251
{********************************************************}
1253
{ All default hooks procedures }
1256
DirectPutPixel := {$ifdef fpc}@{$endif}DirectPutPixelDefault;
1257
PutPixel := {$ifdef fpc}@{$endif}PutPixelDefault;
1258
GetPixel := {$ifdef fpc}@{$endif}GetPixelDefault;
1259
SetRGBPalette := {$ifdef fpc}@{$endif}SetRGBPaletteDefault;
1260
GetRGBPalette := {$ifdef fpc}@{$endif}GetRGBPaletteDefault;
1262
SetAllPalette := {$ifdef fpc}@{$endif}SetAllPaletteDefault;
1263
SetActivePage := {$ifdef fpc}@{$endif}SetActivePageDefault;
1264
SetVisualPage := {$ifdef fpc}@{$endif}SetVisualPageDefault;
1265
ClearViewPort := {$ifdef fpc}@{$endif}ClearViewportDefault;
1266
PutImage := {$ifdef fpc}@{$endif}DefaultPutImage;
1267
GetImage := {$ifdef fpc}@{$endif}DefaultGetImage;
1268
ImageSize := {$ifdef fpc}@{$endif}DefaultImageSize;
1269
GraphFreeMemPtr := nil;
1270
GraphGetMemPtr := nil;
1271
GetScanLine := {$ifdef fpc}@{$endif}GetScanLineDefault;
1272
Line := {$ifdef fpc}@{$endif}LineDefault;
1273
InternalEllipse := {$ifdef fpc}@{$endif}InternalEllipseDefault;
1274
PatternLine := {$ifdef fpc}@{$endif}PatternLineDefault;
1275
HLine := {$ifdef fpc}@{$endif}HLineDefault;
1276
VLine := {$ifdef fpc}@{$endif}VLineDefault;
1277
OuttextXY := {$ifdef fpc}@{$endif}OuttextXYDefault;
1278
Circle := {$ifdef fpc}@{$endif}CircleDefault;
1282
{********************************************************}
1283
{ Procedure InitVars() }
1284
{--------------------------------------------------------}
1285
{ Resets all internal variables, and resets all }
1286
{ overridable routines. }
1287
{********************************************************}
1289
DirectVideo := TRUE; { By default use fastest access possible }
1292
ArcCall.XStart := 0;
1293
ArcCall.YStart := 0;
1296
{ Reset to default values }
1297
IntCurrentMode := 0;
1298
IntCurrentDriver := 0;
1299
IntCurrentNewDriver := 0;
1306
DirectColor := FALSE;
1308
if hardwarepages=0 then; { remove note }
1314
function InstallUserDriver(Name: string; AutoDetectPtr: Pointer): smallint;
1316
_graphResult := grError;
1317
InstallUserDriver:=grError;
1320
function RegisterBGIDriver(driver: pointer): smallint;
1323
_graphResult := grError;
1324
RegisterBGIDriver:=grError;
1329
{ ----------------------------------------------------------------- }
1332
Procedure Arc(X,Y : smallint; StAngle,EndAngle,Radius: word);
1335
OldWriteMode: word;}
1338
{ Only if we are using thickwidths lines do we accept }
1339
{ XORput write modes. }
1340
{ OldWriteMode := CurrentWriteMode;
1341
if (LineInfo.Thickness = NormWidth) then
1342
CurrentWriteMode := NormalPut;}
1343
InternalEllipse(X,Y,Radius,Radius,StAngle,Endangle,{$ifdef fpc}@{$endif}DummyPatternLine);
1344
{ CurrentWriteMode := OldWriteMode;}
1348
procedure Ellipse(X,Y : smallint; stAngle, EndAngle: word; XRadius,YRadius: word);
1350
InternalEllipse(X,Y,XRadius,YRadius,StAngle,Endangle,{$ifdef fpc}@{$endif}DummyPatternLine);
1354
procedure FillEllipse(X, Y: smallint; XRadius, YRadius: Word);
1355
{********************************************************}
1356
{ Procedure FillEllipse() }
1357
{--------------------------------------------------------}
1358
{ Draws a filled ellipse using (X,Y) as a center point }
1359
{ and XRadius and YRadius as the horizontal and vertical }
1360
{ axes. The ellipse is filled with the current fill color}
1361
{ and fill style, and is bordered with the current color.}
1362
{********************************************************}
1364
InternalEllipse(X,Y,XRadius,YRadius,0,360,PatternLine)
1369
procedure CircleDefault(X, Y: smallint; Radius:Word);
1370
{********************************************************}
1371
{ Draws a circle centered at X,Y with the given Radius. }
1372
{********************************************************}
1373
{ Important notes: }
1374
{ - Thickwidth circles use the current write mode, while}
1375
{ normal width circles ALWAYS use CopyPut/NormalPut }
1376
{ mode. (Tested against VGA BGI driver -CEC 13/Aug/99 }
1377
{********************************************************}
1378
var OriginalArcInfo: ArcCoordsType;
1382
if (Radius = 0) then
1385
if (Radius = 1) then
1387
{ only normal put mode is supported by a call to PutPixel }
1388
PutPixel(X, Y, CurrentColor);
1392
{ save state of arc information }
1393
{ because it is not needed for }
1395
move(ArcCall,OriginalArcInfo, sizeof(ArcCall));
1396
if LineInfo.Thickness = Normwidth then
1398
OldWriteMode := CurrentWriteMode;
1399
CurrentWriteMode := CopyPut;
1401
InternalEllipse(X,Y,Radius,Radius,0,360,{$ifdef fpc}@{$endif}DummyPatternLine);
1402
if LineInfo.Thickness = Normwidth then
1403
CurrentWriteMode := OldWriteMode;
1404
{ restore arc information }
1405
move(OriginalArcInfo, ArcCall,sizeof(ArcCall));
1408
procedure SectorPL(x1,x2,y: smallint); {$ifndef fpc}far;{$endif fpc}
1409
var plx1, plx2: smallint;
1411
If (x1 = -maxsmallint) Then
1412
If (x2 = maxsmallint-1) Then
1413
{ no ellipse points drawn on this line }
1414
If (((Y < ArcCall.Y) and (Y > ArcCall.YStart)) or
1415
((Y > ArcCall.Y) and (Y < ArcCall.YStart))) Then
1416
{ there is a part of the sector at this y coordinate, but no }
1417
{ ellips points are plotted on this line, so draw a patternline }
1418
{ between the lines connecting (arccall.x,arccall.y) with }
1419
{ the start and the end of the arc (JM) }
1420
{ use: y-y1=(y2-y1)/(x2-x1)*(x-x1) => }
1421
{ x = (y-y1)/(y2-y1)*(x2-x1)+x1 }
1423
plx1 := (y-ArcCall.Y)*(ArcCall.XStart-ArcCall.X)
1424
div (ArcCall.YStart-ArcCall.Y)+ArcCall.X;
1425
plx2 := (y-ArcCall.Y)*(ArcCall.XEnd-ArcCall.X)
1426
div (ArcCall.YEnd-ArcCall.Y)+ArcCall.X;
1429
plx1 := plx1 xor plx2;
1430
plx2 := plx1 xor plx2;
1431
plx1 := plx1 xor plx2;
1434
{ otherwise two points which have nothing to do with the sector }
1437
{ the arc is plotted at the right side, but not at the left side, }
1438
{ fill till the line between (ArcCall.X,ArcCall.Y) and }
1439
{ (ArcCall.XStart,ArcCall.YStart) }
1441
If (y < ArcCall.Y) then
1443
plx1 := (y-ArcCall.Y)*(ArcCall.XEnd-ArcCall.X)
1444
div (ArcCall.YEnd-ArcCall.Y)+ArcCall.X
1446
else if (y > ArcCall.Y) then
1448
plx1 := (y-ArcCall.Y)*(ArcCall.XStart-ArcCall.X)
1449
div (ArcCall.YStart-ArcCall.Y)+ArcCall.X
1451
else plx1 := ArcCall.X;
1455
If (x2 = maxsmallint-1) Then
1456
{ the arc is plotted at the left side, but not at the rigth side. }
1457
{ the right limit can be either the first or second line. Just take }
1458
{ the closest one, but watch out for division by zero! }
1460
If (y < ArcCall.Y) then
1462
plx2 := (y-ArcCall.Y)*(ArcCall.XStart-ArcCall.X)
1463
div (ArcCall.YStart-ArcCall.Y)+ArcCall.X
1465
else if (y > ArcCall.Y) then
1467
plx2 := (y-ArcCall.Y)*(ArcCall.XEnd-ArcCall.X)
1468
div (ArcCall.YEnd-ArcCall.Y)+ArcCall.X
1470
else plx2 := ArcCall.X;
1474
{ the arc is plotted at both sides }
1481
PatternLine(plx1,plx2,y);
1485
procedure Sector(x, y: smallint; StAngle,EndAngle, XRadius, YRadius: Word);
1487
internalellipse(x,y,XRadius, YRadius, StAngle, EndAngle, {$ifdef fpc}@{$endif}SectorPL);
1488
Line(ArcCall.XStart, ArcCall.YStart, x,y);
1489
Line(x,y,ArcCall.Xend,ArcCall.YEnd);
1494
procedure SetFillStyle(Pattern : word; Color: word);
1497
{ on invalid input, the current fill setting will be }
1499
if (Pattern > UserFill) or (Color > GetMaxColor) then
1502
logln('invalid fillstyle parameters');
1504
_GraphResult := grError;
1507
FillSettings.Color := Color;
1508
FillSettings.Pattern := Pattern;
1512
procedure SetFillPattern(Pattern: FillPatternType; Color: word);
1513
{********************************************************}
1514
{ Changes the Current FillPattern to a user defined }
1515
{ pattern and changes also the current fill color. }
1516
{ The FillPattern is saved in the FillPattern array so }
1517
{ it can still be used with SetFillStyle(UserFill,Color) }
1518
{********************************************************}
1523
if Color > GetMaxColor then
1526
logln('invalid fillpattern parameters');
1528
_GraphResult := grError;
1532
FillSettings.Color := Color;
1533
FillSettings.Pattern := UserFill;
1535
{ Save the pattern in the buffer }
1537
FillPatternTable[UserFill][i] := Pattern[i];
1541
procedure Bar(x1,y1,x2,y2:smallint);
1542
{********************************************************}
1543
{ Important notes for compatibility with BP: }
1544
{ - WriteMode is always CopyPut }
1545
{ - No contour is drawn for the lines }
1546
{********************************************************}
1548
origcolor : longint;
1549
origlinesettings: Linesettingstype;
1550
origwritemode : smallint;
1552
origlinesettings:=lineinfo;
1553
origcolor:=CurrentColor;
1561
{ Always copy mode for Bars }
1562
origwritemode := CurrentWriteMode;
1563
CurrentWriteMode := CopyPut;
1565
{ All lines used are of this style }
1566
Lineinfo.linestyle:=solidln;
1567
Lineinfo.thickness:=normwidth;
1569
case Fillsettings.pattern of
1572
Currentcolor:=CurrentBkColor;
1578
CurrentColor:=FillSettings.color;
1584
CurrentColor:=FillSettings.color;
1586
patternline(x1,x2,y);
1589
CurrentColor:= Origcolor;
1590
LineInfo := OrigLineSettings;
1591
CurrentWriteMode := OrigWritemode;
1597
procedure bar3D(x1, y1, x2, y2 : smallint;depth : word;top : boolean);
1599
origwritemode : smallint;
1600
OldX, OldY : smallint;
1602
origwritemode := CurrentWriteMode;
1603
CurrentWriteMode := CopyPut;
1605
Rectangle(x1,y1,x2,y2);
1607
{ Current CP should not be updated in Bar3D }
1608
{ therefore save it and then restore it on }
1615
Lineto(x1+depth,y1-depth);
1616
Lineto(x2+depth,y1-depth);
1621
Moveto(x2+depth,y1-depth);
1622
Lineto(x2+depth,y2-depth);
1628
CurrentWriteMode := origwritemode;
1633
{--------------------------------------------------------------------------}
1635
{ COLOR AND PALETTE ROUTINES }
1637
{--------------------------------------------------------------------------}
1640
procedure SetColor(Color: Word);
1643
CurrentColor := Color;
1647
function GetColor: Word;
1650
GetColor := CurrentColor;
1653
function GetBkColor: Word;
1656
GetBkColor := CurrentBkColor;
1660
procedure SetBkColor(ColorNum: Word);
1661
{ Background color means background screen color in this case, and it is }
1662
{ INDEPENDANT of the viewport settings, so we must clear the whole screen }
1665
ViewPort: ViewportType;
1667
GetViewSettings(Viewport);
1669
logln('calling setviewport from setbkcolor');
1671
SetViewPort(0,0,MaxX,MaxY,FALSE);
1673
logln('calling setviewport from setbkcolor done');
1675
CurrentBkColor := ColorNum;
1677
if not DirectColor and (ColorNum<256) then
1679
DefaultColors[ColorNum].Red,
1680
DefaultColors[ColorNum].Green,
1681
DefaultColors[ColorNum].Blue);
1682
SetViewport(ViewPort.X1,Viewport.Y1,Viewport.X2,Viewport.Y2,Viewport.Clip);
1686
function GetMaxColor: word;
1687
{ Checked against TP VGA driver - CEC }
1690
GetMaxColor:=MaxColor-1; { based on an index of zero so subtract one }
1698
Procedure MoveRel(Dx, Dy: smallint);
1700
CurrentX := CurrentX + Dx;
1701
CurrentY := CurrentY + Dy;
1704
Procedure MoveTo(X,Y: smallint);
1705
{********************************************************}
1706
{ Procedure MoveTo() }
1707
{--------------------------------------------------------}
1708
{ Moves the current pointer in VIEWPORT relative }
1709
{ coordinates to the specified X,Y coordinate. }
1710
{********************************************************}
1717
function GraphErrorMsg(ErrorCode: smallint): string;
1721
grOk,grFileNotFound,grInvalidDriver: exit;
1722
grNoInitGraph: GraphErrorMsg:='Graphics driver not installed';
1723
grNotDetected: GraphErrorMsg:='Graphics hardware not detected';
1724
grNoLoadMem,grNoScanMem,grNoFloodMem: GraphErrorMsg := 'Not enough memory for graphics';
1725
grNoFontMem: GraphErrorMsg := 'Not enough memory to load font';
1726
grFontNotFound: GraphErrorMsg:= 'Font file not found';
1727
grInvalidMode: GraphErrorMsg := 'Invalid graphics mode';
1728
grError: GraphErrorMsg:='Graphics error';
1729
grIoError: GraphErrorMsg:='Graphics I/O error';
1730
grInvalidFont,grInvalidFontNum: GraphErrorMsg := 'Invalid font';
1731
grInvalidVersion: GraphErrorMsg:='Invalid driver version';
1738
Function GetMaxX: smallint;
1739
{ Routine checked against VGA driver - CEC }
1744
Function GetMaxY: smallint;
1745
{ Routine checked against VGA driver - CEC }
1753
Function GraphResult: smallint;
1755
GraphResult := _GraphResult;
1756
_GraphResult := grOk;
1760
Function GetX: smallint;
1766
Function GetY: smallint;
1771
Function GetDriverName: string;
1773
GetDriverName:=DriverName;
1777
procedure graphdefaults;
1778
{ PS: GraphDefaults does not ZERO the ArcCall structure }
1779
{ so a call to GetArcCoords will not change even the }
1780
{ returned values even if GraphDefaults is called in }
1785
lineinfo.linestyle:=solidln;
1786
lineinfo.thickness:=normwidth;
1787
{ reset line style pattern }
1789
LinePatterns[i] := TRUE;
1791
{ By default, according to the TP prog's reference }
1792
{ the default pattern is solid, and the default }
1793
{ color is the maximum color in the palette. }
1794
fillsettings.color:=GetMaxColor;
1795
fillsettings.pattern:=solidfill;
1796
{ GraphDefaults resets the User Fill pattern to $ff }
1797
{ checked with VGA BGI driver - CEC }
1799
FillPatternTable[UserFill][i] := $ff;
1802
CurrentColor:=white;
1806
{ Reset the viewport }
1807
StartXViewPort := 0;
1808
StartYViewPort := 0;
1818
{ normal write mode }
1819
CurrentWriteMode := CopyPut;
1821
{ Schriftart einstellen }
1822
CurrentTextInfo.font := DefaultFont;
1823
CurrentTextInfo.direction:=HorizDir;
1824
CurrentTextInfo.charsize:=1;
1825
CurrentTextInfo.horiz:=LeftText;
1826
CurrentTextInfo.vert:=TopText;
1828
XAspect:=10000; YAspect:=10000;
1832
procedure GetAspectRatio(var Xasp,Yasp : word);
1838
procedure SetAspectRatio(Xasp, Yasp : word);
1845
procedure SetWriteMode(WriteMode : smallint);
1846
{ TP sets the writemodes according to the following scheme (JM) }
1849
xorput, andput: CurrentWriteMode := XorPut;
1850
notput, orput, copyput: CurrentWriteMode := CopyPut;
1855
procedure GetFillSettings(var Fillinfo:Fillsettingstype);
1857
Fillinfo:=Fillsettings;
1860
procedure GetFillPattern(var FillPattern:FillPatternType);
1862
FillPattern:=FillpatternTable[UserFill];
1865
procedure DrawPoly(numpoints : word;var polypoints);
1867
ppointtype = ^pointtype;
1868
pt = array[0..16000] of pointtype;
1872
if numpoints < 2 then
1874
_GraphResult := grError;
1877
for i:=0 to numpoints-2 do
1878
line(pt(polypoints)[i].x,
1879
pt(polypoints)[i].y,
1880
pt(polypoints)[i+1].x,
1881
pt(polypoints)[i+1].y);
1885
procedure PieSlice(X,Y,stangle,endAngle:smallint;Radius: Word);
1887
Sector(x,y,stangle,endangle,radius,radius);
1893
procedure internDetectGraph(var GraphDriver, GraphMode:smallint;
1894
calledFromInitGraph: boolean);
1895
var LoMode, HiMode: smallint;
1897
CpyDriver: smallint;
1901
if not calledFromInitGraph or
1902
(graphDriver < lowNewDriver) or
1903
(graphDriver > highNewDriver) then
1905
{ Search lowest supported bitDepth }
1906
graphdriver := D1bit;
1907
while (graphDriver <= highNewDriver) and
1910
getModeRange(graphDriver,loMode,hiMode);
1916
_GraphResult := grNotDetected;
1921
GetModeRange(GraphDriver,LoMode,HiMode);
1922
{ save the highest mode possible...}
1924
logln('Found driver '+strf(graphdriver)+' with modes '+
1925
strf(lomode)+' - '+strf(himode));
1927
if HiMode <> -1 then
1930
CpyDriver:=GraphDriver;
1932
{ go to next driver if it exists...}
1934
until (graphDriver > highNewDriver);
1939
getModeRange(graphDriver,loMode,hiMode);
1940
if hiMode <> -1 then
1942
cpyDriver := graphDriver;
1948
_GraphResult := grNotDetected;
1951
_GraphResult := grOK;
1952
GraphDriver := CpyDriver;
1953
GraphMode := CpyMode;
1956
procedure detectGraph(var GraphDriver: smallint; var GraphMode:smallint);
1958
internDetectGraph(graphDriver,graphMode,false);
1961
procedure InitGraph(var GraphDriver:smallint;var GraphMode:smallint;
1962
const PathToDriver:String);
1964
dirchar = System.DirectorySeparator;
1967
{ path to the fonts (where they will be searched)...}
1968
bgipath:=PathToDriver;
1969
if (Length(bgipath) > 0) and (bgipath[length(bgipath)]<>dirchar) then
1970
bgipath:=bgipath+dirchar;
1972
if not assigned(SaveVideoState) then
1974
DriverName:=InternalDriverName; { DOS Graphics driver }
1976
if (Graphdriver=Detect)
1977
or (GraphMode = detectMode) then
1979
internDetectGraph(GraphDriver,GraphMode,true);
1980
If _GraphResult = grNotDetected then Exit;
1982
{ _GraphResult is now already set to grOK by DetectGraph }
1983
IntCurrentDriver := GraphDriver;
1985
if (graphDriver >= lowNewDriver) and
1986
(graphDriver <= highNewDriver) then
1987
IntCurrentNewDriver := GraphDriver
1988
else IntCurrentNewDriver := -1;
1990
{ Actually set the graph mode...}
1991
if firstCallOfInitgraph then
1994
firstCallOfInitgraph := false;
1996
SetGraphMode(GraphMode);
2000
{ Search if that graphics modec actually exists...}
2001
if SearchMode(GraphDriver,GraphMode) = nil then
2003
_GraphResult := grInvalidMode;
2008
_GraphResult := grOK;
2009
IntCurrentDriver := GraphDriver;
2011
if (graphDriver >= lowNewDriver) and
2012
(graphDriver <= highNewDriver) then
2013
IntCurrentNewDriver := GraphDriver
2014
else IntCurrentNewDriver := -1;
2016
if firstCallOfInitgraph then
2019
firstCallOfInitgraph := false;
2021
SetGraphMode(GraphMode);
2027
procedure SetDirectVideo(DirectAccess: boolean);
2029
DirectVideo := DirectAccess;
2032
function GetDirectVideo: boolean;
2034
GetDirectVideo := DirectVideo;
2037
procedure GraphExitProc; {$ifndef fpc} far; {$endif fpc}
2038
{ deallocates all memory allocated by the graph unit }
2044
{ restore old exitproc! }
2045
exitproc := exitsave;
2046
if IsGraphMode and ((errorcode<>0) or (erroraddr<>nil)) then
2048
{ release memory allocated for fonts }
2049
for c := 1 to installedfonts do
2051
If assigned(instr) Then
2052
System.Freemem(instr,instrlength);
2053
{ release memory allocated for modelist }
2055
while assigned(list) do
2061
for c := lowNewDriver to highNewDriver do
2063
list := newModeList.modeinfo[c];
2064
while assigned(list) do
2072
{ We had copied the buffer of mode information }
2073
{ and allocated it dynamically... now free it }
2074
{ Warning: if GetVESAInfo returned false, this buffer is not allocated! (JM)}
2076
Dispose(VESAInfo.ModeList);
2081
procedure InitializeGraph;
2084
assign(debuglog,'grlog.txt');
2088
isgraphmode := false;
2090
fillChar(newModeList.modeinfo,sizeof(newModeList.modeinfo),#0);
2091
{ lo and hi modenumber are -1 currently (no modes supported) }
2092
fillChar(newModeList.loHiModeNr,sizeof(newModeList.loHiModeNr),#255);
2093
SaveVideoState := nil;
2094
RestoreVideoState := nil;
2095
{ This must be called at startup... because GetGraphMode may }
2096
{ be called even when not in graph mode. }
2098
LogLn('Calling QueryAdapterInfo...');
2101
{ Install standard fonts }
2102
{ This is done BEFORE startup... }
2103
InstalledFonts := 0;
2104
InstallUserFont('TRIP');
2105
InstallUserFont('LITT');
2106
InstallUserFont('SANS');
2107
InstallUserFont('GOTH');
2108
InstallUserFont('SCRI');
2109
InstallUserFont('SIMP');
2110
InstallUserFont('TSCR');
2111
InstallUserFont('LCOM');
2112
InstallUserFont('EURO');
2113
InstallUserFont('BOLD');
2114
{ This installs an exit procedure which cleans up the mode list...}
2115
ExitSave := ExitProc;
2116
ExitProc := @GraphExitProc;
2118
charmessagehandler:=nil;