unit GrHacks; { Low-level screen graphics, used by Plt. } { Last edited by J. Stolfi on 93-04-20. } {$N+} interface procedure gr_begin_drawing(x_min, x_max, y_min, y_max: real); { Initializes the graphics state, using whatever device and mode are available. (Currently recognizes only CGA, EGA, VGA, or a few others.). The visible plotting window will cover most of the screen; points in the window will have coordinates in the ranges [x_min .. x_max] and [y_min .. y_max], with the X-axis pointing to the left, and the Y axis pointing up. } procedure gr_end_drawing; { Closes the graphics screen. } function gr_x(x: real): integer; function gr_y(y: real): integer; procedure gr_set_pen(width: real); { Sets the pen width for line drawing. } procedure gr_set_color(color: real); { Sets the color for both line drawing and area fill. } procedure gr_draw_point(x, y: real); { Paints a round dot at (x,y), in the current color, and using the current pen width as the diameter. } procedure gr_draw_segment(x1, y1, x2, y2: real); { Draws a segment from (x1,y1) to (x2,y2), using the current pen width and color. } procedure gr_paint_triangle(x1, y1, x2, y2, x3, y3: real); { Paints the interior of the triangle with vertices (x1,y1), (x2,y2), (x3,y3), in the current color. } procedure gr_paint_plane; { Paints the whole screen using the current color. } implementation uses Crt, Graph; const gr_drivers_directory = '\TP\BGI'; { Change to suit your system. } var blackcolor, whitecolor, maxcolor, curcolor: word; gr_x_mag, gr_y_mag: real; gr_x_off, gr_y_off: real; gr_x_min, gr_x_max, gr_y_min, gr_y_max: integer; procedure gr_test_error(err: integer); begin if err <> Graph.grOk then begin Writeln('GrHachs: Graphics error - ', Graph.GraphErrorMsg(err)); Halt(1); end; end; procedure gr_init_graphics; var driver, mode: integer; begin { driver := Graph.CGA; mode := Graph.CGAC1; } { driver := Graph.VGA; mode := Graph.VGAHi; } driver := Detect; Graph.DetectGraph(driver, mode); gr_test_error(Graph.GraphResult); case driver of Graph.VGA: { mode := Graph.VGAMed }; Graph.CGA: begin driver := Graph.CGA; mode := Graph.CGAC1; end; Graph.MCGA: begin case mode of Graph.MCGAMed, Graph.MCGAHi: mode := Graph.MCGAC1; end; end; Graph.EGA: mode := Graph.EGAHi; Graph.EGAMono: { OK }; Graph.EGA64: mode := Graph.EGA64Hi; Graph.PC3270: begin driver := Graph.CGA; mode := Graph.CGAC1; end; Graph.ATT400: case mode of Graph.ATT400C1, Graph.ATT400C2, Graph.ATT400Med, Graph.ATT400Hi: mode := Graph.ATT400C1; end; Graph.HercMono: { OK } end; Graph.InitGraph(driver, mode, gr_drivers_directory); gr_test_error(Graph.GraphResult); end; procedure gr_center_window(var g_min, g_max: integer; newwd: real); var ow, nw: integer; begin ow := g_max - g_min; nw := round(newwd); g_min := g_min + (ow - nw) div 2; g_max := g_min + nw; end; procedure gr_set_scale(x_min, x_max, y_min, y_max: real); var t: real; begin { Get Graph window size: } gr_x_min := 0; gr_x_max := Graph.GetMaxX; gr_y_min := 0; gr_y_max := Graph.GetMaxY; { Compute scale transformations: } gr_x_off := x_min; gr_y_off := y_min; gr_x_mag := gr_x_max/(x_max - x_min); gr_y_mag := gr_y_max/(y_max - y_min); { Equalize scales: } if gr_x_mag > gr_y_mag then begin gr_x_mag := gr_y_mag; gr_center_window(gr_x_min, gr_x_max, gr_x_mag * (x_max - x_min)); end else begin gr_y_mag := gr_x_mag; gr_center_window(gr_y_min, gr_y_max, gr_y_mag * (y_max - y_min)); end; end; function gr_x(x: real): integer; begin gr_x := gr_x_min + round((x - gr_x_off) * gr_x_mag) end; function gr_y(y: real): integer; begin gr_y := gr_y_max - round((y - gr_y_off) * gr_y_mag) end; procedure gr_begin_drawing(x_min, x_max, y_min, y_max: real); begin gr_init_graphics; gr_set_scale(x_min, x_max, y_min, y_max); blackcolor := Graph.GetBkColor; maxcolor := Graph.GetMaxColor; whitecolor := maxcolor; Graph.SetColor(whitecolor); curcolor := whitecolor; Graph.ClearViewPort; end; procedure gr_end_drawing; begin repeat until Crt.KeyPressed; Graph.CloseGraph; end; procedure gr_set_color(color: real); begin if color = 0.0 then curcolor := blackcolor else if color = 1.0 then curcolor := whitecolor else curcolor := round(color * maxcolor); Graph.SetColor(curcolor); Graph.SetFillStyle(Graph.SolidFill, curcolor); end; procedure gr_set_pen(width: real); begin end; procedure gr_draw_point(x, y: real); begin Graph.PutPixel(gr_x(x), gr_y(y), curcolor); end; procedure gr_draw_segment(x1, y1, x2, y2: real); begin Graph.Moveto(gr_x(x1), gr_y(y1)); Graph.LineTo(gr_x(x2), gr_y(y2)); end; procedure gr_paint_plane; begin Graph.Bar(gr_x_min, gr_y_min, gr_x_max, gr_y_max); end; procedure gr_paint_triangle(x1, y1, x2, y2, x3, y3: real); var pt: array [1..4] of Graph.PointType; begin pt[1].X := gr_x(x1); pt[1].Y := gr_y(y1); pt[2].X := gr_x(x2); pt[2].Y := gr_y(y2); pt[3].X := gr_x(x3); pt[3].Y := gr_y(y3); pt[4] := pt[1]; Graph.FillPoly(4, pt) end; end.