home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
vpbgib1.zip
/
DGRAPH.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-08-08
|
54KB
|
1,967 lines
{█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█}
{█ █}
{█ Virtual Pascal Run-time Library v1.1 █}
{█ BGI Graphics unit for PM applications █}
{█ ─────────────────────────────────────────────────█}
{█ Copyright (C) 1996 fPrint UK Ltd █}
{█ Written May-July 1996 by Allan Mertner █}
{█ Inspired by DIVERace by Michael Mrosowski █}
{█ █}
{▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀}
Unit dGraph;
Interface
{$Delphi+}
Uses
Use32, Os2Def, Os2Base, Os2PmApi, Strings, SysUtils, VPUtils;
type
EGraph = class(Exception);
Str12 = String[12];
Const
x_Size : Longint = 640;
y_Size : Longint = 480;
WindowTitle : string = 'BGI Window';
grOk = 0; // error status values reported by graphresult }
grNoInitGraph = -1; // BGI graphics not installed
grNotDetected = -2; // Graphics hardware not detected
grFileNotFound = -3; // Device driver file not found
grInvalidDriver = -4; // Invalid device driver file
grNoLoadMem = -5; // Not enough memory to load driver
grNoScanMem = -6; // Out of memory in scan fill
grNoFloodMem = -7; // Out of memory in flood fill
grFontNotFound = -8; // Font file not found
grNoFontMem = -9; // Not enough memory to load font
grInvalidMode = -10; // Invalid graphics mode for selected driver
grError = -11; // Graphics error (generic error)
grIOerror = -12; // Graphics I/O error
grInvalidFont = -13; // Invalid font file
grInvalidFontNum = -14; // Invalid font number
Detect = 0;
Black = 0; { Colour values }
Blue = 1;
Green = 2;
Cyan = 3;
Red = 4;
Magenta = 5;
Brown = 6;
LightGray = 7;
DarkGray = 8;
LightBlue = 9;
LightGreen = 10;
LightCyan = 11;
LightRed = 12;
LightMagenta = 13;
Yellow = 14;
White = 15;
EGA_Black = 0; { different than DOS BGI values }
EGA_Blue = 1;
EGA_Green = 2;
EGA_Cyan = 3;
EGA_Red = 4;
EGA_Magenta = 5;
EGA_Brown = 6;
EGA_LightGray = 7;
EGA_DarkGray = 8;
EGA_LightBlue = 9;
EGA_LightGreen = 10;
EGA_LightCyan = 11;
EGA_LightRed = 12;
EGA_LightMagenta = 13;
EGA_Yello = 14;
EGA_White = 15;
NormWidth = 1; { constants for line thickness }
ThickWidth = 3;
SolidLn = 0; { constants for line patterns }
DottedLn = 1;
CenterLn = 2;
DashedLn = 3;
UserBitLn = 4;
DefaultFont = 0; { font constants for settextstyle }
TriplexFont = 1;
SmallFont = 2;
SansSerifFont = 3;
GothicFont = 4;
ScriptFont = 5;
SimplexFont = 6;
TriplexScrFont = 7;
ComplexFont = 8;
EuropeanFont = 9;
BoldFont = 10;
FontNames : Array[1..10] of Str12
= ( 'TRIP.CHR', 'LITT.CHR', 'SANS.CHR', 'GOTH.CHR', 'SCRI.CHR',
'SIMP.CHR', 'TSCR.CHR', 'LCOM.CHR', 'EURO.CHR', 'BOLD.CHR' );
HorizDir = 0;
VertDir = 90;
UserCharSize = 0;
ClipOn = TRUE;
ClipOff = FALSE;
TopOn = TRUE;
TopOff = FALSE;
EmptyFill = 0; { fill patterns }
SolidFill = 1;
LineFill = 2;
LtSlashFill = 3;
SlashFill = 4;
BkSlashFill = 5;
LtBkSlashFill = 6;
HatchFill = 7;
XHatchFill = 8;
InterleaveFill = 9;
WideDotFill = 10;
CloseDotFill = 11;
UserFill = 12;
NormalPut = 0; { operators for image blits and setwritemode }
CopyPut = 0;
XORPut = 1;
OrPut = 2;
AndPut = 3;
NotPut = 4;
LeftText = 0; { text justification constants }
CenterText = 1;
RightText = 2;
BottomText = 0;
TopText = 2;
MaxColors = 255; // Different from DOS
LinePatterns : Array[0..3] of Word
= ( $FFFFFFFF, $33333333, $3CCF3CCF, $0F0F0F0F );
type
str4 = String[4];
FillPatternType = array [1..8] of Byte;
NewPatternType = array [0..15] of SmallWord;
IntArray = array [0..65000] of Integer;
PaletteType = record
Size : word;
Colors : array[0..MaxColors] of Byte;
end;
LineSettingsType = record
LineStyle : Word;
Pattern : Word;
Thickness : Word;
end;
TextSettingsType = record
Font : Word;
Direction : Word;
CharSize : Integer; { different than DOS BGI }
Horiz : Word;
Vert : Word;
userxscale: double;
useryscale: double;
end;
FillSettingsType = record
Pattern : Word;
Color : Word;
end;
PointType = record
X : Integer;
Y : Integer;
end;
PointArray = Array[0..65000] of PointType;
ViewPortType = record
X1 : Integer;
Y1 : Integer;
X2 : Integer;
Y2 : Integer;
Clip : Boolean;
end;
ArcCoordsType = record
X : Integer;
Y : Integer;
Xstart : Integer;
Ystart : Integer;
Xend : Integer;
Yend : Integer;
end;
MouseStatusType = record
X : Integer;
Y : Integer;
LButt : Integer;
MButt : Integer;
RButt : Integer;
NewInfo : Integer;
end;
procedure Delay(MS: Longint);
function KeyPressed: Boolean;
function ReadKey: Char;
function AltPressed: Boolean;
function ShiftPressed: Boolean;
function CtrlPressed: Boolean;
procedure WaitDraw;
{ BGI Function Prototypes }
Procedure Arc(X, Y: Integer; StAngle, EndAngle, Radius: Word);
Procedure Bar(X1, Y1, X2, Y2: Integer);
Procedure Bar3D(X1, Y1, X2, Y2: Integer; Depth: Word; Top: Boolean);
Procedure Circle(X, Y: Integer; Radius: Word);
Procedure ClearDevice;
Procedure ClearViewport;
Procedure CloseGraph;
procedure DetectGraph(var GraphDriver, GraphMode: Integer);
Procedure DrawPoly(NumPoints: Word; var PolyPoints);
Procedure Ellipse(X, Y: Integer; StAngle, EndAngle: Word; XRadius, YRadius: Word);
Procedure FillEllipse(X, Y: Integer; XRadius, YRadius: Word);
Procedure FillPoly(NumPoints: Word; var PolyPoints);
Procedure FloodFill(X, Y: Integer; Border: Word);
Procedure GetArcCoords(var ArcCoords: ArcCoordsType);
Procedure GetAspectRatio(var Xasp, Yasp: Word);
Function GetBkColor: Word;
Function GetColor: Word;
Procedure GetDefaultPalette(var Palette: PaletteType);
Function GetDriverName: string;
Procedure GetFillPattern(var FillPattern: FillPatternType);
Procedure GetFillSettings(var FillInfo: FillSettingsType);
function GetGraphMode: Integer;
function GetFrameRate: Double; // Frames Per Second
function GetFrameTime: Double; // Time (mSec) Per Frame
procedure GetImage(x1, y1, x2, y2: Integer; var BitMap);
Procedure GetLineSettings(var LineInfo: LineSettingsType);
Function GetMaxColor: Word;
Function GetMaxX: Word;
Function GetMaxY: Word;
Function GetModeName(ModeNumber: Integer): string;
Procedure GetPalette(var Palette: PaletteType);
Function GetPaletteSize: Integer;
Function GetPixel(X,Y: Integer): Word;
Procedure GetTextSettings(var TextInfo: TextSettingsType);
Procedure GetViewSettings(var ThisViewPort: ViewPortType);
Function GetX: Integer;
Function GetY: Integer;
Procedure GraphDefaults;
Function GraphErrorMsg(ErrorCode: Integer): String;
Function GraphResult: Integer;
function ImageSize(x1, y1, x2, y2: Integer): Word;
procedure InitGraph(var GraphDriver:Integer; var GraphMode: Integer;
PathToDriver: string);
Function InstallUserFont(FontFileName: string) : Integer;
Procedure Line(X1, Y1, X2, Y2: Integer);
Procedure LineRel(Dx, Dy: Integer);
Procedure LineTo(X, Y: Integer);
Procedure MoveRel(Dx, Dy: Integer);
Procedure MoveTo(X, Y: Integer);
Procedure OutText(TextString: string);
Procedure OutTextXY(X, Y: Integer; TextString: string);
Procedure PieSlice(X, Y: Integer; StAngle, EndAngle, Radius: Word);
procedure PutImage(X, Y: Integer; var BitMap; BitBlt: Word);
Procedure PutPixel(X, Y: Integer; Color: Word);
Procedure Rectangle(X1, Y1, X2, Y2: Integer);
Procedure RegisterBGIFont(FontID: Integer; Font: Pointer);
Procedure Sector(X, Y: Integer; StAngle, EndAngle, XRadius, YRadius: Word);
Procedure SetAllPalette(var Palette: PaletteType);
Procedure SetAspectRatio(Xasp, Yasp: Word);
Procedure SetBkColor(ColorNum: Word);
Procedure SetColor(Color: Word);
Procedure SetFillPattern(Pattern: FillPatternType; Color: Word);
Procedure SetFillStyle(Pattern: Word; Color: Word);
Procedure SetLineStyle(LineStyle: Word; Pattern: Word; Thickness: Word);
Procedure SetPalette(ColorNum: Word; Color: Byte);
Procedure SetRGBPalette(ColorNum: Word; Red, Green, Blue: Byte);
Procedure SetTextJustify(Horiz, Vert: Word);
Procedure SetTextStyle(Font, Direction, CharSize: Integer);
Procedure SetUserCharSize(MultX, DivX, MultY, DivY: Word);
Procedure SetViewPort(X1, Y1, X2, Y2: Integer; Clip: Boolean);
Procedure SetWriteMode(WriteMode: Integer);
Function TextHeight(TextString: string): Word;
Function TextWidth(TextString: string): Word;
// VP additional BGI functions
procedure SetWideFillPattern(Pattern: NewPatternType; Color: Word);
// Blitter control functions
procedure SuspendRefresh; // Suspend refreshing of screen
procedure EnableRefresh; // Enable refreshing of screen
procedure AcceleratedBlit; // Enable faster blitting routine (Only updated DIVE.DLL)
procedure SlowBlit; // Enable slow blitting routine
// procedure SetBlitterPriority(Priority: Integer);
// Constants modifying behavious of Graph
const
WaitKeypressed : Boolean = True; // Delay() when calling keypressed
{$IFDEF DEBUG}
procedure log( s: String );
{$ENDIF}
Implementation
uses
Os2Dive;
{$IFDEF DEBUG}
procedure log( s: String );
begin
os2dive.log(s);
end;
{$ENDIF}
const
MaxFonts = 20;
FontScale: Array[ 1..10 ] of Double
= ( 0.60, 0.66, 0.75, 1.0, 1.33, 1.66, 2.0, 2.5, 3.0, 4.0);
type
tFont = record
FirstChar: Char;
Chars: Byte;
LastChar: Char;
Org_To_Top : smallint;
Org_To_Base : smallint;
Org_To_Dec : smallint;
CharIndex: Array[0..255] of SmallWord;
CharWidth: Array[0..255] of Byte;
ChDataMem: Integer;
CharData: Pointer;
FontName: String;
Linked: Boolean;
end;
tGraphWindow = class( tDiveWindow )
private
Position : PointType; // Current position
FgColor : Longint; // Background color
BkColor : Longint; // Background color
TxtHoriz : Byte; // Horizontal text alignment
TxtVert : Byte; // Vertical text alignment
TxtDir : Integer; // Txt angle
FntSel : Integer; // Currently selected font
xScale : Double; // Txt Scaling factor
yScale : Double; // Txt Scaling factor
UserxScale: Double; // User Txt Scaling factor (CharSz = 0)
UseryScale: Double; // User Txt Scaling factor (CharSz = 0)
CharSz : Integer;
PalInfo : PaletteType;
LineInfo : LineSettingsType;
FillInfo : FillSettingsType;
WriteMode : Integer; // Write mode (or, xor, etc)
public
constructor Create( SizeX, SizeY: Longint; ColorBits: Byte; WindowTitle:string );
end;
tBGI = record
Fonts: 0..MaxFonts;
Font: Array[1..MaxFonts] of tFont;
PathToFont: String[80];
LastError : Longint; // Last error
DW : tGraphWindow;
end;
// State variables
var
BGI : tBGI;
GrStatus: Integer;
SaveExit: Pointer; // After InitGraph, contains ExitProc
tidMessage : Integer; // Thread ID of message handling loop
constructor tGraphWindow.Create( SizeX, SizeY: Longint; ColorBits: Byte ;WindowTitle:String);
begin
Inherited Create( SizeX, SizeY, ColorBits{, WindowTitle});
VPClip := False;
inherited SetViewPort( 0, 0, SizeX-1, SizeY-1 );
FgColor := White;
BkColor := Black;
xScale := 1;
yScale := 1;
UserxScale := 1;
UseryScale := 1;
CharSz := 1;
TxtDir := 0;
TxtHoriz := LeftText;
TxtVert := TopText;
FntSel := DefaultFont;
PalInfo.Size := Colours; // Ask DIVE for color count
GetDefaultPalette( PalInfo );
LineInfo.LineStyle := SolidLn;
LineInfo.Thickness := NormWidth;
LineInfo.Pattern := $FFFF;
FillInfo.Color:=White;
FillInfo.Pattern:= SolidFill;
SetLineThickness( LineInfo.Thickness );
xAspect := 10000;
yAspect := xAspect; // Default 1:1 aspect ratio
WriteMode := NormalPut;
// Statistics := True;
end;
Procedure Arc(X, Y: Integer; StAngle, EndAngle, Radius: Word);
Var
Center: Pixel;
begin
If Assigned( BGI.DW ) then
With BGI.DW do
begin
Center.x := x;
Center.y := y;
LineMode := True;
BeginUpdate;
DrawArc( Center, Radius, StAngle, EndAngle, FgColor );
EndUpdate;
end;
end;
Procedure Bar(X1, Y1, X2, Y2: Integer);
begin
If Assigned( BGI.DW ) then
with BGI.DW do
begin
BeginUpdate;
DrawFillRect( x1,y1, x2,y2, FgColor );
EndUpdate;
end;
end;
Procedure Bar3D(X1, Y1, X2, Y2: Integer; Depth: Word; Top: Boolean );
var
dy: Integer;
Poly: Array[1..5] of PointType;
begin
If Assigned( BGI.DW ) then
with BGI.DW do
begin
BeginUpdate;
LineMode := True;
If Depth = 0 then
DrawBox( x1,y1, x2,y2, FgColor )
else
DrawFillRect( x1,y1, x2,y2, FgColor );
if Depth <> 0 then
begin
dy := (Depth*3) div 4;
DrawLine( x2,y2, x2+depth,y2-dy, FgColor );
DrawLine( x2+depth,y2-dy, x2+depth, y1-dy, FgColor );
if top then
begin
DrawLine( x1,y1, x1+depth,y1-dy, FgColor );
DrawLine( x1+depth,y1-dy, x2+Depth,y1-dy, FgColor );
DrawLine( x2+Depth,y1-dy, x2,y1, FgColor );
end;
end;
EndUpdate;
end;
end;
Procedure Circle(X, Y: Integer; Radius: Word);
Var
Center: Pixel;
begin
If Assigned( BGI.DW ) then
with BGI.DW, LineInfo do
begin
Center.x := x;
Center.y := y;
LineMode := True;
BeginUpdate;
if LineStyle = UserBitLn then
SetLinePattern( Pattern )
else
SetLinePattern( LinePatterns[LineStyle] );
SetLineThickness( LineInfo.Thickness );
LinePutMode := WriteMode;
DrawArc( Center, Radius, 0, 360, FgColor );
EndUpdate;
end;
end;
Procedure ClearDevice;
begin
if Assigned( BGI.DW ) then
with BGI.DW do
begin
BeginUpdate;
Clear( BkColor );
EndUpdate;
Position.X := 0;
Position.X := 0;
FillColor := White;
FillBkColor := Black;
end;
end;
Procedure ClearViewport;
begin
if Assigned( BGI.DW ) then
with BGI.DW do
begin
BeginUpdate;
LineMode := False;
DrawBox( 0, 0, VPWidth, VPHeight, BkColor );
EndUpdate;
Position.X := 0;
Position.X := 0;
FillColor := White;
FillBkColor := Black;
end;
end;
Procedure CloseGraph;
var
timeout: Integer;
begin
If Assigned( BGI.DW ) then
begin
if SaveExit <> nil then
begin
ExitProc := SaveExit;
SaveExit := nil;
end;
WinPostMsg( BGI.DW.hwndFrame, WM_CLOSE, 0, 0 );
WinPostMsg( BGI.DW.hwndFrame, ID_EXIT, 0, 0 );
timeout := 0;
if GetThreadID <> tidMessage then // Msg handling thread should not wait!
While ( BGI.DW <> nil ) and (timeOut < 50) do
begin
DosSleep( 50 );
Inc(TimeOut );
end;
end;
end;
procedure DetectGraph(var GraphDriver, GraphMode: Integer);
begin
GraphDriver := 9; // 640x480 VGA
GraphMode := 2;
end;
Procedure DrawPoly(NumPoints: Word; var PolyPoints);
var
i : Integer;
p,q : ^PointType;
begin
if Assigned( BGI.DW ) then
with BGI.DW do
begin
LinePutMode := WriteMode;
p := @PolyPoints;
q := p;
inc(q);
BeginUpdate;
for i := 0 to NumPoints-2 do
begin
DrawLine( p^.x, p^.y, q^.x, q^.y, FgColor );
inc( p );
inc( q );
end;
Position.x := p^.x;
Position.y := p^.y;
LinePutMode := NormalPut;
EndUpdate;
end;
end;
Procedure Ellipse(X, Y: Integer; StAngle, EndAngle: Word; XRadius, YRadius: Word);
Var
Center: Pixel;
begin
If Assigned( BGI.DW ) then
with BGI.DW do
begin
Center.x := x;
Center.y := y;
LineMode := True;
BeginUpdate;
DrawEllipse( Center, XRadius, YRadius, StAngle, EndAngle, FgColor );
EndUpdate;
end;
end;
Procedure FillEllipse(X, Y: Integer; XRadius, YRadius: Word);
Var
Center: Pixel;
v: Integer;
y1 : Integer;
x2,y2 : Integer;
row: Integer;
begin
If Assigned( BGI.DW ) then
with BGI.DW do
begin
Center.x := x;
Center.y := y;
LineMode := False;
BeginUpdate;
y2 := YRadius;
for v := 90 downto 0 do // Quarter circle
begin
y1 := y2;
x2 := (XRadius*tCos[v*4]) div 1024;
y2 := (YRadius*tSin[v*4]) div 1024;
for row := y2 to y1-1 do
If FillInfo.Pattern = SolidFill then
begin
DrawLine( x-x2, y+Row, x+x2, y+Row, FillInfo.Color );
DrawLine( x-x2, y-Row, x+x2, y-Row, FillInfo.Color );
end
else
begin
DrawFillLine( x-x2, x+x2, y+Row );
DrawFillLine( x-x2, x+x2, y-Row );
end;
end;
EndUpdate;
Ellipse( x,y, 0,360, XRadius, YRadius );
end;
end;
Procedure FillPoly(NumPoints: Word; var PolyPoints);
VAR
i,j,k : Integer;
xi : ^IntArray;
PointMem : Integer;
InP : ^PointArray;
ymin, ymax : Integer;
Row : Integer;
Col : Integer;
BEGIN
PointMem := NumPoints*Sizeof(Integer);
GetMem( xi, PointMem );
fillchar( xi^, PointMem, 0 );
InP := @PolyPoints; // Make it easier to address points
with InP^[0] do
begin
ymin := y;
ymax := y;
moveto(x, y);
end;
for i := 1 to NumPoints-1 do
with Inp^[i] do
begin
ymin := min( y, ymin );
ymax := max( y, ymax );
end;
with BGI.DW do
begin
BeginUpdate;
yMax := Max( 0, Min( GetMaxY-1, yMax ) );
for Row := ymin to ymax do
begin
j := 0;
for i := 1 to NumPoints-1 do
with Inp^[ pred(i) ] do
if ( (y < Row) xor ( InP^[i].y < Row ) ) then
begin
Col := x+(Row-y)*(x-InP^[i].x) div (y-InP^[i].y);
k:=0;
while ( k<>j ) and ( Col >= xi^[k] ) do
Inc( k );
IF k < j then
move( xi^[k], xi^[succ(k)], (j-k)*sizeof(integer) );
xi^[k] := Col;
Inc( j );
end;
for i := 0 to j-2 do
begin
DrawFillLine( xi^[i], xi^[succ(i)], Row );
if i < j then
Inc( i );
END;
end; // For Row
EndUpdate;
FreeMem( xi, PointMem );
DrawPoly( Numpoints, PolyPoints );
end;
end;
Procedure FloodFill(X, Y: Integer; Border: Word);
begin
end;
Procedure GetArcCoords(var ArcCoords: ArcCoordsType);
begin
If Assigned( BGI.DW ) then
With BGI.DW do
begin
ArcCoords.x := LastArc.x;
ArcCoords.y := LastArc.y;
ArcCoords.xStart := LastArc.xStart;
ArcCoords.yStart := LastArc.yStart;
ArcCoords.xEnd := LastArc.xEnd;
ArcCoords.yEnd := LastArc.yEnd;
end;
end;
Procedure GetAspectRatio(var Xasp, Yasp: Word);
begin
If Assigned( BGI.DW ) then
begin
XAsp := BGI.DW.XAspect;
yAsp := BGI.DW.YAspect;
end
else
begin
XAsp := 0;
yAsp := 0;
end
end;
Function GetBkColor: Word;
begin
if Assigned( BGI.DW ) then
Result := BGI.DW.BkColor
else
Result := 0;
end;
Function GetColor: Word;
begin
if Assigned( BGI.DW ) then
Result := BGI.DW.FgColor
else
Result := 0;
end;
Procedure GetDefaultPalette(var Palette: PaletteType);
var
i: Integer;
begin
If Assigned( BGI.DW ) then
with BGI.DW.PalInfo do
Case Size of
2 : Palette.Size := 2;
256 : Palette.Size := 256;
else Palette.Size := 16;
end
else
Palette.Size := 256;
With Palette do
begin
For i := 0 to Size-1 do
Colors[i] := i{+16;};
For i := Size to High(Colors) do
Colors[i] := 1;
end;
end;
Function GetDriverName: string;
begin
Result := 'VP/2 DIVE VGA emulator';
end;
Procedure GetFillPattern(var FillPattern: FillPatternType);
begin
end;
function GetGraphMode: Integer;
begin
Result := 3;
end;
Procedure GetFillSettings(var FillInfo: FillSettingsType);
begin
if Assigned( BGI.DW ) then
FillInfo := BGI.DW.FillInfo
end;
function GetFrameRate: Double; // Frames Per Second
begin
if Assigned( BGI.DW ) then
GetFrameRate := BGI.DW.FrameRate
else
GetFrameRate := 0;
end;
function GetFrameTime: Double; // Time (mSec) Per Frame
begin
if Assigned( BGI.DW ) then
GetFrameTime := BGI.DW.FrameTime
else
GetFrameTime := 0;
end;
procedure GetImage(x1, y1, x2, y2: Integer; var BitMap);
var
p: Pchar;
y: Integer;
x: Integer;
begin
x := x2-x1+1;
p := @BitMap;
pSmallWord(p)^ := x;
inc(p,sizeof(smallword));
pSmallWord(p)^ := y2-y1+1;
inc(p,sizeof(smallword));
pSmallWord(p)^ := 0; // Reserved
inc(p,sizeof(smallword));
If assigned( BGI.DW ) then
with BGI.DW do
begin
VPTransformXYXY( x1, y1, x2, y2 );
BeginUpdate;
for y := y1 to y2 do
begin
move( DisplayBuffer^[ x1+y*xSize ], p^, x );
inc( p, x );
end;
EndUpdate;
end;
end;
Procedure GetLineSettings(var LineInfo: LineSettingsType);
begin
If assigned( BGI.DW ) then
begin
LineInfo := BGI.DW.LineInfo;
end;
end;
Function GetMaxColor: Word;
begin
if Assigned( BGI.DW ) then
Result := BGI.DW.Colours-1;
end;
Function GetMaxX: Word;
begin
if Assigned( BGI.DW ) then
Result := BGI.DW.xSize-1;
end;
Function GetMaxY: Word;
begin
if Assigned( BGI.DW ) then
Result := BGI.DW.ySize-1;
end;
Function GetModeName(ModeNumber: Integer): string;
begin
Result := 'VP/2 DIVE VGA';
end;
Procedure GetPalette(var Palette: PaletteType);
var
i : Integer;
begin
If assigned( BGI.DW ) then
with BGI.DW, Palette do
begin
Size := PalInfo.Size;
move( PalInfo.Colors, Colors, Sizeof( Colors ) );
end;
end;
Function GetPaletteSize: Integer;
begin
If Assigned( BGI.DW ) then
Result := BGI.DW.PalInfo.Size
else
Result := 0;
end;
Function GetPixel(X,Y: Integer): Word;
const
LastCol : Integer = 0;
var
i: Integer;
begin
if Assigned( BGI.DW ) then
with BGI.DW, PalInfo do
begin
Result := Pixels[ x, y ];
// First check if it is identical to the last one
if Colors[LastCol] = Result then
begin
Result := LastCol;
Exit;
end;
for i := 0 to Size-1 do
If Colors[i] = Result then
begin
Result := i;
LastCol := i;
Exit;
end;
end;
Result := 0;
end;
Procedure GetTextSettings(var TextInfo: TextSettingsType);
begin
if assigned( BGI.DW ) then
with BGI.DW do
begin
TextInfo.Font := FntSel;
TextInfo.Direction := TxtDir;
TextInfo.CharSize := CharSz;
TextInfo.Horiz := TxtHoriz;
TextInfo.Vert := TxtVert;
TextInfo.userxscale := uSerxScale;
TextInfo.userYscale := uSerYScale;
end;
end;
Procedure GetViewSettings(var ThisViewPort: ViewPortType);
begin
If Assigned( BGI.DW ) then
with BGI.DW, ThisViewPort do
begin
x1 := ViewPort.x1;
x2 := ViewPort.x2;
y1 := ViewPort.y1;
y2 := ViewPort.y2;
Clip := VPClip;
end;
end;
Function GetX: Integer;
begin
If Assigned( BGI.DW ) then
Result := BGI.DW.Position.x;
end;
Function GetY: Integer;
begin
If Assigned( BGI.DW ) then
Result := BGI.DW.Position.y;
end;
Procedure GraphDefaults;
begin
if assigned( BGI.DW ) then
with BGI.DW do
begin
SetViewPort( 0, 0, xSize-1, ySize-1 );
FgColor := White;
BkColor := Black;
xScale := 1;
yScale := 1;
UserxScale := 1;
UseryScale := 1;
CharSz := 1;
TxtDir := 0;
TxtHoriz := LeftText;
TxtVert := TopText;
FntSel := DefaultFont;
PalInfo.Size := Colours; // Ask DIVE for color count
GetDefaultPalette( PalInfo );
LineInfo.LineStyle := SolidLn;
LineInfo.Thickness := NormWidth;
LineInfo.Pattern := $FFFF;
FillInfo.Color:=White;
FillInfo.Pattern:= SolidFill;
SetLineThickness( LineInfo.Thickness );
xAspect := 10000;
yAspect := xAspect; // Default 1:1 aspect ratio
WriteMode := NormalPut;
end;
end;
Function GraphErrorMsg(ErrorCode: Integer): String;
begin
end;
Function GraphResult: Integer;
begin
If Assigned(BGI.DW) then
Result := BGI.LastError
else
Result := grNoInitGraph;
end;
function ImageSize(x1, y1, x2, y2: Integer): Word;
begin
Result := (x2-x1+1)*(y2-y1+1)+6;
end;
var
_KeyPressed: Longint;
DelayCount: Longint;
const
KeyCount: Integer = 0; { Count of keys in KeyBuffer }
CheckBreak: Boolean = True; { Allow Ctrl-C for break? }
_Shift: Integer = 0;
_Ctrl: Integer = 0;
_Alt: Integer = 0;
var
KeyBuffer: array[0..63] of Char; { Keyboard type-ahead buffer }
{ Waits for next timer tick or delays 1ms }
function DelayLoop(Count: Longint; var StartValue: ULong): Longint;
var
Value: ULong;
begin
repeat
DosQuerySysInfo(qsv_Ms_Count,qsv_Ms_Count,Value,SizeOf(Value));
Dec(Count);
until (Value <> StartValue) or (Count = -1);
StartValue := Value;
DelayLoop := Count;
end;
{ Delays a specified number of milliseconds. DosSleep is too inexact on }
{ small time intervals. More over, the least time interval for DosSleep }
{ is 1 timer tick (usually 31ms). That is why for small time intervals }
{ special delay routine is used. Unfortunately, even this routine cannot}
{ be exact in the multitasking environment. }
procedure Delay(MS: Longint);
var
StartValue,Value: ULong;
Count: Longint;
begin
if (MS >= 31) or (Random>0.9) then DosSleep(MS)
else
begin
DosQuerySysInfo(qsv_Ms_Count,qsv_Ms_Count,StartValue,SizeOf(StartValue));
Value := StartValue;
Count := MS;
repeat
DelayLoop(DelayCount,Value);
Dec(Count)
until (Value-StartValue >= MS) or (Count <= 0);
end;
end;
{ Calculates 1ms delay count for DelayLoop routine. }
{ CalcDelayCount is called once at startup. }
procedure CalcDelayCount;
var
Interval,StartValue,Value: ULong;
begin
DosQuerySysInfo(qsv_Timer_Interval,qsv_Timer_Interval,Interval,SizeOf(Interval));
DosQuerySysInfo(qsv_Ms_Count,qsv_Ms_Count,StartValue,SizeOf(StartValue));
repeat
DosQuerySysInfo(qsv_Ms_Count,qsv_Ms_Count,Value,SizeOf(Value));
until Value <> StartValue;
DelayCount := -DelayLoop(-1,Value) div Interval * 10;
if DelayCount = 0 then Inc(DelayCount);
end;
function AltPressed: Boolean;
begin
Result := _Alt > 0;
end;
function ShiftPressed: Boolean;
begin
Result := _Shift > 0;
end;
function CtrlPressed: Boolean;
begin
Result := _Ctrl > 0;
end;
function KeyPressed: Boolean;
var
m: qMsg;
begin
KeyPressed := KeyCount > 0;
If WaitKeypressed and ( KeyCount = 0 ) then
DosSleep( 1 );
end;
function ReadKey: Char;
begin
while not KeyPressed do
;
ReadKey := KeyBuffer[0];
Dec(KeyCount);
Move(KeyBuffer[1], KeyBuffer[0], KeyCount);
end;
procedure WindowChar(Ch: Char);
begin
if KeyCount < SizeOf(KeyBuffer) then
begin
KeyBuffer[KeyCount] := Ch;
Inc(KeyCount);
end;
end;
function MyMsgs( Wnd: HWnd; Msg: ULong; mp1, mp2: MParam ): MResult; cdecl;
var
KeyUp: Boolean;
begin
case msg of
wm_char :
begin
KeyUp := (CharMsgMp1(Mp1).fs and kc_KeyUp) <> 0;
if (CharMsgMp1(Mp1).fs and kc_VirtualKey) <> 0 then
begin
case CharMsgMp2(Mp2).VKey of
vk_Shift : If KeyUp then
Dec( _Shift )
else
if CharMsgMp1(Mp1).fs and kc_PrevDown = 0 then
Inc( _Shift );
vk_Ctrl : If KeyUp then
Dec( _Ctrl )
else
if CharMsgMp1(Mp1).fs and kc_PrevDown = 0 then
Inc( _Ctrl );
vk_Alt : If KeyUp then
Dec( _Alt )
else
if CharMsgMp1(Mp1).fs and kc_PrevDown = 0 then
Inc( _Alt );
vk_ESC : If KeyUp then
WindowChar( #27 );
end;
end;
if not KeyUp then
begin { Key is down }
if CheckBreak then { Break enabled }
if (CharMsgMp2(Mp2).VKey = vk_Break) or { Ctrl-Break }
(((CharMsgMp1(Mp1).fs and kc_Ctrl) <> 0) and
((CharMsgMp2(Mp2).Chr = Ord('C')) or { Ctrl-C }
(CharMsgMp2(Mp2).Chr = Ord('c')))) then
Halt(255);{ Ctrl-c }
if (CharMsgMp2(Mp2).Chr > 0) and (CharMsgMp2(Mp2).Chr <= 255) and
((CharMsgMp1(Mp1).fs and (kc_Ctrl + kc_Alt)) = 0)
then
begin
WindowChar(Chr(CharMsgMp2(Mp2).Chr));
Result := 1;
end;
// else WindowKeyDown(CharMsgMp2(Mp2).VKey, (CharMsgMp1(Mp1).fs and kc_Ctrl) <> 0);
end;
end;
end;
Result := 0;
end;
Function _InitGraph( p: Pointer ): Longint;
begin
GrStatus := 0;
_KeyPressed := 0;
BGI.DW := tGraphWindow.Create( x_size, y_size, 8 , WindowTitle);
if assigned( BGI.DW ) then
with BGI, DW do
try
LastError := grOK;
GrStatus := 1;
MessageHandler := MyMsgs;
Run;
finally
Destroy;
end;
BGI.DW := nil;
GrStatus := 2;
tidMessage := -1;
end;
procedure MyExitProc;
begin
ExitProc := SaveExit;
SaveExit := nil;
CloseGraph;
end;
procedure InitGraph(var GraphDriver:Integer; var GraphMode: Integer;
PathToDriver: string);
begin
If GrStatus = 1 then
Exit; // Already running;
tidMessage := VPBeginThread( _InitGraph, 4*16384, nil);
if tidMessage <> 0 then
begin
While GrStatus = 0 do
DosSleep( 50 );
SaveExit := ExitProc;
ExitProc := @MyExitProc;
If GrStatus = 1 then
begin
GraphDriver := 9; // VGA
GraphMode := 2; // VGAHi
BGI.PathToFont := PathToDriver;
If BGI.PathToFont[Length(BGI.PathToFont)] <> '\' then
BGI.PathToFont := BGI.PathToFont + '\';
ClearViewPort;
WaitDraw;
end;
end;
end;
Function InstallUserFont(FontFileName: string) : Integer;
var
i: Integer;
begin
with BGI do
if Fonts = MaxFonts then
Result := -1
else
begin
Inc( Fonts );
with Font[ Fonts ] do
begin
FontName := FontFileName;
Linked := False;
CharData := nil;
end;
Result := Fonts;
end;
end;
Procedure Line(X1, Y1, X2, Y2: Integer);
begin
if Assigned( BGI.DW ) then
With BGI.DW, LineInfo do
begin
BeginUpdate;
if LineStyle = UserBitLn then
SetLinePattern( Pattern )
else
SetLinePattern( LinePatterns[LineStyle] );
SetLineThickness( LineInfo.Thickness );
LinePutMode := WriteMode;
DrawLine( x1, y1, x2, y2, FgColor );
LinePutMode := NormalPut;
SetLinePattern( $FFFFFFFF );
EndUpdate;
end;
end;
Procedure LineRel(Dx, Dy: Integer);
begin
if Assigned( BGI.DW ) then
With BGI.DW do
begin
BeginUpdate;
LinePutMode := WriteMode;
DrawLine( Position.x, Position.y,
Position.x+Dx, Position.y+Dy, FgColor );
LinePutMode := NormalPut;
EndUpdate;
Inc( Position.x, Dx );
Inc( Position.y, Dy );
end;
end;
Procedure LineTo(X, Y: Integer);
begin
if Assigned( BGI.DW ) then
With BGI.DW do
begin
BeginUpdate;
LinePutMode := WriteMode;
DrawLine( Position.x, Position.y, X, Y, FgColor );
LinePutMode := NormalPut;
EndUpdate;
Position.x := x;
Position.y := y;
end;
end;
Procedure MoveRel(Dx, Dy: Integer);
begin
if Assigned( BGI.DW ) then
With BGI.DW do
begin
Inc( Position.x, Dx );
Inc( Position.y, Dy );
end;
end;
Procedure MoveTo(X, Y: Integer);
begin
if Assigned( BGI.DW ) then
With BGI.DW do
begin
Position.x := x;
Position.y := y;
end;
end;
procedure RotateXY( var x,y: Integer; Angle: Integer );
var
x1, y1: Double;
begin
While Angle < 0 do
Inc( Angle, 360 );
Angle := Angle mod 360;
x1 := x;
y1 := y;
x := Round( x1*tcos[Angle*4] + y1*tsin[Angle*4] ) div 1024;
y := Round( -x1*tsin[Angle*4] + y1*tcos[Angle*4] ) div 1024;
end;
procedure DrawBGIChar( var x,y: Integer; Ch: Char );
procedure DecodeBGI( w: SmallWord; var x,y,Op: Integer );
begin
x := w and $7F;
if x and $40 <> 0 then
x := x or $FFFFFF80;
y := (w shr 8) and $7F;
if y and $40 <> 0 then
y := y or $FFFFFF80;
Op := byte(w) shr 7 or ((w shr 14) and 2); // I think :)
end;
const
bgi_PenDone = 0;
bgi_PenMove = 1;
bgi_PenDraw = 3;
type
psWord = ^SmallWord;
var
ChOffs: Integer;
ChPtr: Pchar;
x1,y1,op: Integer;
newx,newy: Integer;
lastx,lasty: Integer;
begin
With BGI.DW, BGI.Font[FntSel] do
begin
If ( Ch < FirstChar ) or ( Ch > LastChar ) then
Exit;
ChOffs := ord(ch)-ord(FirstChar);
ChPtr := Ptr( Longint(CharData)+CharIndex[ChOffs] );
DecodeBGI( psWord(ChPtr)^, x1, y1, Op );
while Op <> bgi_PenDone do
begin
x1 := Round(x1 * xScale);
y1 := Round(-y1 * yScale);
RotateXY( x1, y1, TxtDir );
if Op = bgi_PenMove then
begin
Lastx := x + x1;
Lasty := y + y1;
end
else
begin
Newx := x + x1;
Newy := y + y1;
DrawLine( Lastx, Lasty, Newx, Newy, FgColor );
Lastx := Newx;
Lasty := Newy;
end;
Inc( ChPtr, Sizeof(SmallWord) );
DecodeBGI( pWord(ChPtr)^, x1, y1, Op );
end;
x1 := Round(CharWidth[ChOffs] * xScale);
y1 := 0;
RotateXY( x1, y1, TxtDir );
Inc( x, x1 );
Inc( y, y1 );
end;
end;
Procedure OutText(TextString: string);
var
x,y: Integer;
offx, offy: Integer;
i: Integer;
begin
If assigned( BGI.DW ) then
with BGI, BGI.DW do
begin
x := Position.x;
y := Position.y;
Offx := 0;
Offy := 0;
If TxtHoriz = CenterText then
Offx := -TextWidth( textString ) div 2
else If TxtHoriz = RightText then
Offx := -TextWidth( textString );
If TxtVert = TopText then
Offy := TextHeight(TextString)
else if TxtVert = CenterText then
Offy := TextHeight(TextString) div 2;
RotateXY( Offx, Offy, TxtDir );
Inc( x, Offx );
SetLineThickness( 1 );
If FntSel = DefaultFont then
begin
BeginUpdate;
DrawStr( x,y, FgColor, BkColor, TextString );
EndUpdate;
// Inc( Position.x, Length(TextString)*8 );
end
else
begin
Inc( y, Offy );
For i := 1 to Length( TextString ) do
DrawBGIChar( x, y, TextString[i] );
end;
SetLineThickness( LineInfo.Thickness );
// Finally adjust drawing position
case TxtHoriz of
LeftText: Offx := TextWidth( TextString );
CenterText: Offx := TextWidth( TextString ) div 2;
RightText: Offx := 0;
end;
Offy := 0;
RotateXY( Offx, Offy, TxtDir );
inc( Position.x, Offx );
inc( Position.y, Offy );
end;
end;
Procedure OutTextXY(X, Y: Integer; TextString: string);
Var
OldPos : PointType;
begin
With BGI, DW do
If Assigned( DW ) and ( FntSel <> -1 ) then
begin
OldPos := Position;
Position.x := x;
Position.y := y;
OutText( TextString );
// Ignore position change
Position := OldPos;
end;
end;
Procedure PieSlice(X, Y: Integer; StAngle, EndAngle, Radius: Word);
begin
If Assigned( BGI.DW ) then
with BGI.DW do
begin
LineMode := False;
Sector( x, y, StAngle, EndAngle, Radius, Radius );
end;
end;
procedure PutImage(X, Y: Integer; var BitMap; BitBlt: Word);
var
p: Pchar;
width: Integer;
height: Integer;
i,j: Integer;
inx, iny: Integer;
Disp : ^Byte;
begin
p := @BitMap;
width := pSmallWord(p)^; inc(p,sizeof(smallword));
height := pSmallWord(p)^; inc(p,2*sizeof(smallword));
If assigned( BGI.DW ) then
with BGI.DW do
begin
inx := x;
iny := y;
VPTransformXY( x, y );
BeginUpdate;
for i := 0 to height-1 do
begin
if BitBlt < 0 then
begin
move( p^, DisplayBuffer^[ x+(i+y)*xSize ], width );
inc( p, width );
end
else
with PalInfo do
begin
Disp := @DisplayBuffer^[ x+(i+y)*xSize ];
for j := 1 to width do
begin
Case BitBlt of
CopyPut:Disp^ := ord(p^);
XORPut: Disp^ := ord(p^) xor Disp^;
ORPut: Disp^ := ord(p^) or Disp^;
ANDPut: Disp^ := ord(p^) and Disp^;
NOTPut: Disp^ := not ord(p^);
end;
inc(Disp);
Inc(p);
end;
end;
end;
EndUpdate;
RectChanged( x, y, x+width-1, y+height-1 );
end;
end;
Procedure PutPixel(X, Y: Integer; Color: Word);
begin
if Assigned( BGI.DW ) then
with BGI.DW, PalInfo do
begin
BeginUpdate;
Pixels[ x, y ] := Colors[ Color ];
EndUpdate;
end;
end;
Procedure Rectangle(X1, Y1, X2, Y2: Integer);
begin
if Assigned( BGI.DW ) then
with BGI.DW do
begin
BeginUpdate;
LineMode := True;
LinePutMode := WriteMode;
DrawBox( x1, y1, x2, y2, FgColor );
LinePutMode := NormalPut;
EndUpdate;
end;
end;
Procedure RegisterBGIFont(FontID: Integer; Font: Pointer);
begin
end;
Procedure Sector(X, Y: Integer; StAngle, EndAngle, XRadius, YRadius: Word);
var
Center: Pixel;
begin
If Assigned( BGI.DW ) then
with BGI.DW do
begin
BeginUpdate;
StAngle := StAngle mod 360;
If EndAngle <> 360 then
EndAngle := EndAngle mod 360;
Center.x := x;
Center.y := y;
DrawEllipse( Center, xRadius, YRadius, StAngle, EndAngle, FgColor );
DrawLine( x,y, LastArc.xStart, LastArc.yStart, FgColor );
DrawLine( x,y, LastArc.xEnd, LastArc.yEnd, FgColor );
EndUpdate;
end
end;
Procedure SetAllPalette(var Palette: PaletteType);
begin
end;
Procedure SetAspectRatio(Xasp, Yasp: Word);
begin
If Assigned( BGI.DW ) then
with BGI.DW do
begin
XAspect := XAsp;
yAspect := YAsp;
end
end;
Procedure SetBkColor(ColorNum: Word);
begin
if Assigned( BGI.DW ) then
BGI.DW.BkColor := ColorNum;
end;
Procedure SetColor(Color: Word);
begin
if Assigned( BGI.DW ) then
BGI.DW.FgColor := Color;
end;
Procedure SetFillPattern(Pattern: FillPatternType; Color: Word);
var
i: Integer;
begin
if Assigned( BGI.DW ) then
with BGI.DW do
begin
FillInfo.Pattern := UserFill;
FillInfo.Color := Color;
for i := 1 to 8 do
begin
// Expand 8x8 to 16x16 matrix
FillPattern[ (i-1) ] := Pattern[i] or Pattern[i] shl 8;
FillPattern[ (i-1)+8 ] := FillPattern[ i-1 ];
end;
FillColor := Color;
end;
end;
Procedure SetWideFillPattern(Pattern: NewPatternType; Color: Word);
var
i: Integer;
begin
if Assigned( BGI.DW ) then
with BGI.DW do
begin
FillInfo.Pattern := UserFill;
FillInfo.Color := Color;
move( Pattern, FillPattern, Sizeof( FillPattern ) );
FillColor := Color;
end;
end;
Procedure SetFillStyle(Pattern: Word; Color: Word);
const
AllPatterns : ARRAY [0..11] OF NewPatternType =
(($0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,
$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000),
($FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,
$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF),
($0000,$0000,$0000,$FFFF,$0000,$0000,$0000,$0000,
$0000,$0000,$0000,$FFFF,$0000,$0000,$0000,$0000),
($0001,$0002,$0004,$0008,$0010,$0020,$0040,$0080,
$0100,$0200,$0400,$0800,$1000,$2000,$4000,$8000),
($0303,$0606,$0C0C,$1818,$3030,$6060,$C0C0,$8181,
$0303,$0606,$0C0C,$1818,$3030,$6060,$C0C0,$8181),
($8181,$C0C0,$6060,$3030,$1818,$0C0C,$0606,$0303,
$8181,$C0C0,$6060,$3030,$1818,$0C0C,$0606,$0303),
($8000,$4000,$2000,$1000,$0800,$0400,$0200,$0100,
$0080,$0040,$0020,$0010,$0008,$0004,$0002,$0001),
($0808,$0808,$0808,$FFFF,$0808,$0808,$0808,$0808,
$0808,$0808,$0808,$FFFF,$0808,$0808,$0808,$0808),
($8002,$4004,$2008,$1010,$0820,$0440,$0280,$0100,
$0280,$0440,$0820,$1010,$2008,$4004,$8002,$0001),
($8282,$4444,$2828,$1010,$2828,$4444,$8282,$0101,
$8282,$4444,$2828,$1010,$2828,$4444,$8282,$0101),
($0000,$0800,$0000,$0000,$0000,$0000,$0000,$0000,
$0000,$0010,$0000,$0000,$0000,$0000,$0000,$0000),
($0000,$4444,$0000,$0000,$0000,$2222,$0000,$0000,
$0000,$4444,$0000,$0000,$0000,$2222,$0000,$0000));
begin
if Assigned( BGI.DW ) then
with BGI.DW do
begin
If Pattern > High( AllPatterns ) then
Pattern := SolidFill;
FillInfo.Pattern := Pattern;
FillInfo.Color := Color;
move( AllPatterns[Pattern], FillPattern, Sizeof( FillPattern ) );
FillColor := Color;
end;
end;
Procedure SetLineStyle(LineStyle: Word; Pattern: Word; Thickness: Word);
begin
If Assigned( BGI.DW ) then
with BGI.DW do
begin
LineInfo.Thickness := ThickNess;
LineInfo.Pattern := Pattern or (Pattern shl 16);
LineInfo.LineStyle := LineStyle;
SetLineThickness( LineInfo.Thickness );
if LineStyle = UserBitLn then
SetLinePattern( Pattern )
else
SetLinePattern( LinePatterns[LineStyle] );
end;
end;
Procedure SetPalette(ColorNum: Word; Color: Byte);
begin
end;
Procedure SetRGBPalette(ColorNum: Word; Red, Green, Blue: Byte);
begin
If Assigned( BGI.DW ) then
begin
with BGI.DW do
SetRGBColor( ColorNum, Red, Green, Blue );
// DosSleep(1);
end;
end;
Procedure SetTextJustify(Horiz, Vert: Word);
begin
with BGI, DW do
begin
if not assigned( DW ) or ( FntSel = -1 ) then
Exit;
If ( Horiz < LeftText ) or ( Horiz > RightText ) or
( Vert < BottomText ) or ( Vert > TopText ) then
Exit;
TxtHoriz := Horiz;
TxtVert := Vert;
end;
end;
procedure UnloadFont( Font: Integer );
begin
if Font > DefaultFont then
With BGI.Font[Font] do
If ( ChDataMem > 0 ) and ( CharData <> nil ) then
begin
FreeMem( CharData, ChDataMem );
CharData := nil;
end;
end;
function LoadFont( Font: Integer ): Boolean;
const
Ext: Array[1..3] of str4 = ('','.CHR','.BGI');
var
f: File;
Buf: Array[1..16] of char;
Err: Integer;
i: Integer;
Path: Integer;
fName : String;
begin
LoadFont := False;
Path := 1;
Repeat
i := Low(Ext);
Repeat
fName := BGI.Font[Font].FontName+Ext[i];
If Path = 1 then
fName := BGI.PathToFont + fName;
if fName <> '' then
begin
Assign( f, fName );
{$I-}
reset(f, 1);
{$I+}
end;
inc(i);
Until ((IOResult = 0) and (fName <> '')) or (i>High(Ext));
Inc( Path );
Until ( Path > 2 ) or ( i <= High(Ext) );
BGI.LastError := GrInvalidFont;
If i <= High(Ext) then
try
BlockRead( f, Buf, 2, Err );
If ( Buf[1] <> 'P' ) or ( Buf[2] <> 'K' ) then
Exit;
Seek( f, $80 );
BlockRead( f, Buf, 16, Err );
If (Buf[1] <> '+') or (err <> 16) then
Exit;
BGI.LastError := grOK;
with BGI.Font[Font] do
begin
FirstChar := Buf[5];
Chars := ord(Buf[2]);
LastChar := Chr( ord(FirstChar)+Chars-1 );
Org_To_Top := ord(buf[9]);
Org_To_Base:= ord(buf[10]);
Org_To_Dec := ord(buf[11]);
if Org_To_Dec and $80 > 0 then
Org_To_Dec := Org_To_Dec or $FF00;
BlockRead( f, CharIndex, Chars*2, Err );
BlockRead( f, CharWidth, Chars, Err );
ChDataMem := FileSize(f)-filePos(f);
GetMem( CharData, ChDataMem );
BlockRead( f, CharData^, ChDataMem, Err );
Linked := True;
end;
Result := True;
finally
close(f);
end;
end;
Procedure SetTextStyle(Font, Direction, CharSize: Integer);
begin
If assigned( BGI.DW ) then
with BGI.DW do
begin
If Font <> FntSel then
begin
UnloadFont( FntSel );
If (Font = DefaultFont) or LoadFont( Font ) then
begin
FntSel := Font;
end
else
begin
Raise EGraph.CreateFmt(
'Font %d (%s) could not be found!', [FntSel, BGI.Font[FntSel].FontName] );
FntSel := -1;
Exit;
end;
end;
If CharSize > 10 then CharSize := 10;
If CharSize = 0 then
begin
xScale := UserxScale;
yScale := UseryScale;
end
else
if CharSize > 0 then
begin
xScale := FontScale[ CharSize ];
yScale := FontScale[ CharSize ];
end
else
begin // CharSize < 0
xScale := Abs(CharSize) / FontScale[ CharSize ];
yScale := xScale;
end;
CharSz := CharSize;
TxtDir := Direction;
end;
end;
Procedure SetUserCharSize(MultX, DivX, MultY, DivY: Word);
begin
with BGI, DW do
begin
if not assigned( DW ) or ( FntSel = -1 ) then
Exit;
If ( DivX = 0 ) or ( DivY = 0 ) then
Exit;
UserxScale := MultX / DivX;
UseryScale := MultY / DivY;
If CharSz = 0 then
begin
xScale := UserxScale;
yScale := UseryScale;
end;
end;
end;
Procedure SetViewPort(X1, Y1, X2, Y2: Integer; Clip: Boolean);
begin
If Assigned( BGI.DW ) then
if ( x1 < 0 ) or ( x2 < x1 ) or
( y1 < 0 ) or ( y2 < y1 ) then
BGI.LastError := grError
else
With BGI.DW do
begin
SetViewPort( x1,y1, x2,y2 );
VPClip := Clip;
Position.x := 0;
Position.y := 0;
end;
end;
Procedure SetWriteMode(WriteMode: Integer);
begin
If Assigned( BGI.DW ) then
if WriteMode in [0..4] then
BGI.DW.WriteMode := WriteMode;
end;
Function TextHeight(TextString: string): Word;
begin
With BGI, DW do
If FntSel = DefaultFont then
Result := 8
else
with Font[ FntSel ] do
Result := round(( Org_to_Top - Org_To_Dec ) * Yscale);
end;
Function TextWidth(TextString: string): Word;
var
ChOffs : Integer;
i: Integer;
begin
Result := 0;
If not assigned( BGI.DW ) or ( BGI.DW.FntSel = -1 ) then
Exit;
with BGI.DW do
begin
If FntSel = DefaultFont then
begin
Result := 8*Length(TextString);
Exit;
end;
with BGI.Font[ FntSel ] do
for i := 1 to Length( TextString ) do
begin
ChOffs := ord(TextString[i]) - ord(FirstChar);
If ( ChOffs >= 0 ) and ( ChOffs < Chars ) then
Inc( Result, CharWidth[ChOffs] );
end;
end;
Result := Round( Result * BGI.DW.xScale );
end;
procedure WaitDraw;
begin
If Assigned( BGI.DW ) then
BGI.DW.WaitDraw;
end;
procedure SuspendRefresh; // Suspend refreshing of screen
begin
If Assigned( BGI.DW ) then
BGI.DW.PauseDisplay := True;
end;
procedure EnableRefresh; // Enable refreshing of screen
begin
If Assigned( BGI.DW ) then
BGI.DW.PauseDisplay := False;
end;
procedure AcceleratedBlit; // Enable faster blitting routine (Only updated DIVE.DLL)
begin
If Assigned( BGI.DW ) then
BGI.DW.FastBlit := True;
end;
procedure SlowBlit; // Enable slow blitting routine
begin
If Assigned( BGI.DW ) then
BGI.DW.FastBlit := False;
end;
var
i: Integer;
initialization
BGI.DW := nil;
BGI.Fonts := High(FontNames);
for i := Low(FontNames) to High(FontNames) do
with BGI.Font[i] do
begin
FontName := FontNames[i];
Linked := false;
end;
BGI.LastError := grOK;
GrStatus := 0;
CalcDelayCount;
SaveExit := nil;
tidMessage := -1;
end.