Răsfoiți Sursa

* several changes to internalellipse to make it faster
and to make sure it updates the ArcCall correctly
(not yet done for width = 3)
* Arc mostly works now, only sometimes an endless loop, don't know
why

Jonas Maebe 26 ani în urmă
părinte
comite
062f4e5991
5 a modificat fișierele cu 240 adăugiri și 121 ștergeri
  1. 17 11
      rtl/inc/graph/clip.inc
  2. 10 17
      rtl/inc/graph/fills.inc
  3. 24 1
      rtl/inc/graph/graph.inc
  4. 177 87
      rtl/inc/graph/graph.pp
  5. 12 5
      rtl/inc/graph/text.inc

+ 17 - 11
rtl/inc/graph/clip.inc

@@ -42,7 +42,7 @@ const
    code1, code2: longint;
    done:boolean;
    code: longint;
-   newx,newy: integer;
+   newx,newy: word;
 
 
     function outcode(x,y:integer): longint;
@@ -59,13 +59,12 @@ const
     begin
       code := 0;
       if (x<xmin) then
-         code:=code or LEFT;
-      if (x>xmax) then
-         code:=code or RIGHT;
-
+        code:=code or LEFT
+      else if (x>xmax) then
+        code:=code or RIGHT;
       if (y>ymax) then
-        code:=code or BOTTOM;
-      if (y<ymin) then
+        code:=code or BOTTOM
+      else if (y<ymin) then
         code:=code or TOP;
 
       outcode:=code;
@@ -84,8 +83,8 @@ const
          begin
            done:=TRUE;
            LineClipped:=FALSE;
-  	       exit;
-   	     end
+               exit;
+             end
        else
        { Reject trivially }
        { Neither points are in window }
@@ -131,7 +130,7 @@ const
               x1 := newx;  y1:= newy;
               code1:=outcode(x1,y1)
             end
-	       else
+               else
             begin
               x2:= newx; y2:= newy;
               code2:=outcode(x2,y2);
@@ -143,7 +142,14 @@ end;
 
 {
 $Log$
-Revision 1.3  1999-07-12 13:27:09  jonas
+Revision 1.4  1999-09-12 17:28:59  jonas
+  * several changes to internalellipse to make it faster
+    and to make sure it updates the ArcCall correctly
+    (not yet done for width = 3)
+  * Arc mostly works now, only sometimes an endless loop, don't know
+    why
+
+Revision 1.3  1999/07/12 13:27:09  jonas
   + added Log and Id tags
   * added first FPC support, only VGA works to some extend for now
   * use -dasmgraph to use assembler routines, otherwise Pascal

+ 10 - 17
rtl/inc/graph/fills.inc

@@ -17,17 +17,6 @@
 {$R-}   { No range checking here, because we do some special typecasts }
 
 type
-{$IFDEF FPC}
-        graph_int = longint;      { platform specific integer used for indexes;
-                                                          should be 16 bits on TP/BP and 32 bits on every-
-                                                          thing else for speed reasons }
-        graph_float = double;   { the platform's preferred floating point size }
-{$ELSE}
-        graph_int = integer;    { platform specific integer used for indexes;
-                                                          should be 16 bits on TP/BP and 32 bits on every-
-                                                          thing else for speed reasons }
-        graph_float = real;     { the platform's preferred floating point size }
-{$ENDIF}
 
         pedge = ^edge;
         edge = packed record    { an edge structure }
@@ -172,7 +161,7 @@ begin
                 p := @ptable^[j];
                 q := @ptable^[index];
         end;
-        deltax := (q^.x-p^.x)/(q^.y-p^.y);
+        deltax := (q^.x-p^.x) div (q^.y-p^.y);
         with activetable^[activepoints] do begin
                 dx := deltax;
                 x := dx * (y { + 0.5} - p^.y) + p^.x;
@@ -274,7 +263,7 @@ begin
                 end;
         end;
 {$ifdef debug}
-{$R+}
+{$R+,Q+}
 {$endif debug}
         freemem(activetable, sizeof(edge) * numpoints);
         freemem(indextable, sizeof(graph_int) * numpoints);
@@ -418,14 +407,11 @@ var
    BackupColor : Word;
    x1, x2: integer;
    Index : Integer;
-{ !!! }
-   allocated: longint;
   Begin
     { Save current drawing color }
     BackupColor := CurrentColor;
     CurrentColor := FillSettings.Color;
     { MaxX is based on zero index }
-    allocated := (ViewWidth+1)*2;
     GetMem (s1,(ViewWidth+1)*2);  { A pixel color represents a word }
     GetMem (s2,(ViewWidth+1)*2);  { A pixel color represents a word }
     GetMem (s3,(ViewWidth+1)*2);  { A pixel color represents a word }
@@ -506,7 +492,14 @@ var
 
 {
 $Log$
-Revision 1.5  1999-09-11 19:43:00  jonas
+Revision 1.6  1999-09-12 17:28:59  jonas
+  * several changes to internalellipse to make it faster
+    and to make sure it updates the ArcCall correctly
+    (not yet done for width = 3)
+  * Arc mostly works now, only sometimes an endless loop, don't know
+    why
+
+Revision 1.5  1999/09/11 19:43:00  jonas
   * FloodFill: did not take into account current viewport settings
   * GetScanLine: only get line inside viewport, data outside of it
     is not used anyway

+ 24 - 1
rtl/inc/graph/graph.inc

@@ -618,7 +618,23 @@ CONST
     ScrOfs:=y*ScrWidth+x div 8;
     HLength:=x2 div 8-x div 8;
     LMask:=$ff shr (x and 7);
+{$ifopt r+}
+{$define rangeOn}
+{$r-}
+{$endif}
+{$ifopt q+}
+{$define overflowOn}
+{$q-}
+{$endif}
     RMask:=$ff shl (7-(x2 and 7));
+{$ifdef rangeOn}
+{$undef rangeOn}
+{$r+}
+{$endif}
+{$ifdef overflowOn}
+{$undef overflowOn}
+{$q+}
+{$endif}
     if HLength=0 then
       LMask:=LMask and RMask;
     port[$3ce]:=0;
@@ -2563,7 +2579,14 @@ const CrtAddress: word = 0;
 
 {
 $Log$
-Revision 1.10  1999-09-11 19:43:01  jonas
+Revision 1.11  1999-09-12 17:28:59  jonas
+  * several changes to internalellipse to make it faster
+    and to make sure it updates the ArcCall correctly
+    (not yet done for width = 3)
+  * Arc mostly works now, only sometimes an endless loop, don't know
+    why
+
+Revision 1.10  1999/09/11 19:43:01  jonas
   * FloodFill: did not take into account current viewport settings
   * GetScanLine: only get line inside viewport, data outside of it
     is not used anyway

+ 177 - 87
rtl/inc/graph/graph.pp

@@ -393,6 +393,17 @@ Interface
              xend,yend : integer;
        end;
 
+{$IFDEF FPC}
+        graph_int = longint;      { platform specific integer used for indexes;
+                                    should be 16 bits on TP/BP and 32 bits on every-
+                                    thing else for speed reasons }
+        graph_float = single;   { the platform's preferred floating point size }
+{$ELSE}
+        graph_int = integer;    { platform specific integer used for indexes;
+                                                          should be 16 bits on TP/BP and 32 bits on every-
+                                                          thing else for speed reasons }
+        graph_float = real;     { the platform's preferred floating point size }
+{$ENDIF}
 
   const
        fillpatternTable : array[0..12] of FillPatternType = (
@@ -661,7 +672,7 @@ Implementation
 {$ifdef fpc}
   {$ifdef go32v2}
     {$define dpmi}
-    uses go32;
+    uses go32,ports;
     Type TDPMIRegisters = go32.registers;
   {$endif go32v2}
 {$else fpc}
@@ -752,8 +763,7 @@ var
 
   { information for Text Output routines }
   CurrentTextInfo : TextSettingsType;
-  CurrentXRatio: Real;
-  CurrentYRatio: Real;
+  CurrentXRatio, CurrentYRatio: graph_float;
   installedfonts: longint;  { Number of installed fonts }
 
 
@@ -1282,19 +1292,37 @@ var
   Procedure InternalEllipseDefault(X,Y: Integer;XRadius: word;
     YRadius:word; stAngle,EndAngle: word); far;
    var
-    i:integer;
-    xpt: pinttable;
-    ypt: pinttable;
-    j,Delta:real;
+    j,Delta, DeltaEnd: graph_float;
     NumOfPixels: longint;
     NumOfPix: Array[0..2] of longint;
     count: longint;
-    ConvFac,TempTerm: real;
+    ConvFac,TempTerm: graph_float;
     aval,bval: integer;
-    OldcurrentColor: word;
     TmpAngle: word;
     DeltaAngle: word;
+    xtemp, ytemp, xp, yp, xm, ym: integer;
+    q1p, q2p, q3p, q4p: PointType;
   Begin
+   With q1p Do
+     Begin
+       x := $7fff;
+       y := $7fff;
+     End;
+   With q2p Do
+     Begin
+       x := $7fff;
+       y := $7fff;
+     End;
+   With q3p Do
+     Begin
+       x := $7fff;
+       y := $7fff;
+     End;
+   With q4p Do
+     Begin
+       x := $7fff;
+       y := $7fff;
+     End;
    If xradius = 0 then inc(x);
    if yradius = 0 then inc(y);
    inc(xradius);
@@ -1311,94 +1339,145 @@ var
      end;
    { calculate difference of angle now so we don't always have to calculate it }
    DeltaAngle:= EndAngle-StAngle;
-   i:=0;
    if LineInfo.Thickness=NormWidth then
      Begin
        { approximate the number of pixels required by using the circumference }
        { equation of an ellipse.                                              }
-       NumOfPixels:=8*Round(2.5*sqrt((sqr(XRadius)+sqr(YRadius)) div 2));
-       GetMem(xpt,NumOfpixels*sizeof(word));
-       GetMem(ypt,NumOfPixels*sizeof(word));
+       { In the worst case, we have to calculate everything from the }
+       { quadrant, so divide the circumference value by 4 (JM)       }
+       NumOfPixels:=(8 div 4)*Round(2.5*sqrt((sqr(XRadius)+sqr(YRadius)) div 2));
        { Calculate the angle precision required }
-       Delta := DeltaAngle / (NumOfPixels);
+       { Note: to get the same precision as before, we have to divide by an }
+       { extra 4 (JM)                                                       }
+       Delta := DeltaAngle / (NumOfPixels*4);
        { Adjust for screen aspect ratio }
        XRadius:=(longint(XRadius)*10000) div XAspect;
        YRadius:=(longint(YRadius)*10000) div YAspect;
-       { Initial counter value }
-       j:=Delta+StAngle;
        { removed from inner loop to make faster }
        ConvFac:=Pi/180.0;
+       { store some arccall info }
+       { Initial counter value }
+       TempTerm := (Delta+StAngle)*ConvFac;
+       ArcCall.XStart := round(XRadius*Cos(TempTerm)) + X;
+       ArcCall.XEnd := ArcCall.XStart;
+       ArcCall.YStart := round(YRadius*Sin(TempTerm+Pi)) + Y;
+       ArcCall.YEnd := ArcCall.YStart;
+
+       { convert the DeltaAngle to the new boundaries (JM) }
+       j := Delta;
+       DeltaAngle := 90;
+       { calculate stop position (JM)}
+       DeltaEnd := j + DeltaAngle;
        Repeat
-             { this used by both sin and cos }
+             { this is used by both sin and cos }
              TempTerm := j*ConvFac;
              { Calculate points }
-             xpt^[i]:=round(XRadius*Cos(TempTerm));
-         { calculate the value of y }
-             ypt^[i]:=round(YRadius*Sin(TempTerm+Pi));
+             xtemp := round(XRadius*Cos(TempTerm));
+             ytemp := round(YRadius*Sin(TempTerm+Pi));
+
+             xp := x + xtemp;
+             xm := x - xtemp;
+             yp := y + ytemp;
+             ym := y - ytemp;
+             If (j >= StAngle) and (j <= EndAngle) then
+               begin
+                 q1p.x := xp;
+                 q1p.y := yp;
+                 PutPixel(xp,yp,CurrentColor);
+               end;
+             If ((180-j) >= StAngle) and ((180-j) <= EndAngle) then
+               begin
+                 If (q2p.x = $7fff) then
+                   Begin
+                     q2p.x := xm;
+                     q2p.y := yp;
+                   End;
+                 PutPixel(xm,yp,CurrentColor);
+               end;
+             If ((j+180) >= StAngle) and ((j+180) <= EndAngle) then
+               begin
+                 q3p.x := xm;
+                 q3p.y := ym;
+                 PutPixel(xm,ym,CurrentColor);
+               end;
+             If ((360-j) >= StAngle) and ((360-j) <= EndAngle) then
+               begin
+                 If (q4p.x = $7fff) then
+                   Begin
+                     q4p.x := xp;
+                     q4p.y := ym;
+                   End;
+                 PutPixel(xp,ym,CurrentColor);
+               end;
              j:=j+Delta;
-             inc(i);
-       Until j > DeltaAngle;
+       Until j > (DeltaEnd);
      end
    else
    {******************************************}
    {  CIRCLE OR ELLIPSE WITH THICKNESS=3      }
    {******************************************}
     Begin
-      NumOfPix[1]:=8*Round(2.5*sqrt((sqr(XRadius)+sqr(YRadius)) div 2));
-      NumOfPix[0]:=8*Round(2.5*sqrt((sqr(XRadius-1)+sqr(YRadius-1)) div 2));
-      NumOfPix[2]:=8*Round(2.5*sqrt((sqr(XRadius+1)+sqr(YRadius+1)) div 2));
-      GetMem(xpt,(NumOfPix[1]+NumOfPix[2]+NumOfPix[0])*sizeof(word));
-      GetMem(ypt,(NumOfPix[1]+NumOfPix[2]+NumOfPix[0])*sizeof(word));
+      Writeln('thickness 3');
+      NumOfPix[1]:=2*Round(2.5*sqrt((sqr(XRadius)+sqr(YRadius)) div 2));
+      NumOfPix[0]:=2*Round(2.5*sqrt((sqr(XRadius-1)+sqr(YRadius-1)) div 2));
+      NumOfPix[2]:=2*Round(2.5*sqrt((sqr(XRadius+1)+sqr(YRadius+1)) div 2));
       { removed from inner loop to make faster }
       ConvFac:=Pi/180.0;
       for Count:=0 to 2 do
-            Begin
-             aval:=XRadius+Count-1;
-             bval:=YRadius+Count-1;
-             Delta := DeltaAngle / (NumOfPix[Count]);
-             aval:= (longint(aval)*10000) div XAspect;
-             bval:= (longint(bval)*10000) div YAspect;
-             j:=Delta+Stangle;
-             Repeat
-               { this used by both sin and cos }
-               TempTerm := j*ConvFac;
-               xpt^[i]:=round((aval)*Cos(TempTerm));
-               { calculate the value of y }
-               ypt^[i]:=round(bval*Sin(TempTerm+Pi));
-               j:=j+Delta;
-               inc(i);
-             Until j > DeltaAngle;
-            end;
+        Begin
+          aval:=XRadius+Count-1;
+          bval:=YRadius+Count-1;
+          Delta := DeltaAngle / (4*NumOfPix[Count]);
+          aval:= (longint(aval)*10000) div XAspect;
+          bval:= (longint(bval)*10000) div YAspect;
+          j:=Delta+Stangle;
+{ store some ArcCall info }
+          TempTerm := j*ConvFac;
+          ArcCall.XStart := round(aval*Cos(TempTerm)) + X;
+          ArcCall.YStart := round(bval*Sin(TempTerm)) + Y;
+{ plot ellipse }
+          Repeat
+            { this used by both sin and cos }
+            TempTerm := j*ConvFac;
+            xtemp:=round(aval*Cos(TempTerm));
+            ytemp:=round(bval*Sin(TempTerm));
+            PutPixel(x+xtemp,y+ytemp,CurrentColor);
+            PutPixel(x+xtemp,y-ytemp,CurrentColor);
+            PutPixel(x-xtemp,y+ytemp,CurrentColor);
+            PutPixel(x-xtemp,y-ytemp,CurrentColor);
+            j:=j+Delta;
+          Until j > (DeltaAngle/4);
+        end;
     end;
    {******************************************}
    {  NOW ALL PIXEL POINTS ARE IN BUFFER      }
    {  plot them all to the screen             }
    {******************************************}
    Count:=0;
-   OldcurrentColor:=currentColor;
-   Repeat
-     PutPixel(xpt^[Count]+X,ypt^[Count]+Y,CurrentColor);
-     inc(count);
-   until Count>=i;
-
+   If q4p.x <> $7fff Then
+     Begin
+       ArcCall.XEnd := q4p.x;
+       ArcCall.YEnd := q4p.y
+     End
+   Else If q3p.x <> $7fff Then
+     Begin
+       ArcCall.XEnd := q3p.x;
+       ArcCall.YEnd := q3p.y
+     End
+   Else If q2p.x <> $7fff Then
+     Begin
+       ArcCall.XEnd := q2p.x;
+       ArcCall.YEnd := q2p.y
+     End
+   Else If q1p.x <> $7fff Then
+     Begin
+       ArcCall.XEnd := q1p.x;
+       ArcCall.YEnd := q1p.y
+     End;
    { Get End and Start points into the ArcCall information record }
    ArcCall.X := X;
    ArcCall.Y := Y;
-   ArcCall.XStart := xpt^[0] + X;
-   ArcCall.YStart := ypt^[0] + Y;
-   ArcCall.XEnd := xpt^[Count-1] + X;
-   ArcCall.YEnd := ypt^[Count-1] + Y;
-   CurrentColor:=OldCurrentColor;
-   if LineInfo.Thickness=NormWidth then
-     Begin
-       Freemem(xpt,NumOfPixels*sizeof(word));
-       Freemem(ypt,NumOfPixels*sizeof(word));
-     end
-   else
-     Begin
-       FreeMem(xpt,(NumOfPix[1]+NumOfPix[2]+NumOfPix[0])*sizeof(word));
-       FreeMem(ypt,(NumOfPix[1]+NumOfPix[2]+NumOfPix[0])*sizeof(word));
-     end;
+
   end;
 
 
@@ -1426,7 +1505,7 @@ Procedure InternalEllipseDefault (x, y : integer;
 { Draw an ellipse arc. Crude but it works (anyone have a better one?) }
 Var
   aSqr, bSqr, twoaSqr, twobSqr, xa, ya, twoXbSqr, twoYaSqr, error : LongInt;
-  Alpha : Real;
+  Alpha : graph_float;
 const
   RadToDeg = 180/Pi;
 
@@ -1570,7 +1649,7 @@ End;
          OldCurrentColor := CurrentColor;
          CurrentColor := CurrentBkColor;
 { hline converts the coordinates to global ones, but that has been done }
-{ already here!!! Convert them bak to local ones... (JM)                }
+{ already here!!! Convert them back to local ones... (JM)                }
          HLine(x1-StartXViewPort,x2-StartXViewPort,y-StartYViewPort);
          CurrentColor := OldCurrentColor;
        end
@@ -2020,24 +2099,28 @@ end;
     OldWriteMode: word;
 
    Begin
-     if (Radius = 0) then
-           Exit;
-
-     if (Radius = 1) then
-       begin
-         { must use clipping ... }
-         { don't need to explicitly set NormalPut mode }
-         { because PutPixel only supports normal put   }
-             PutPixel(X, Y,CurrentColor);
-             Exit;
-       end;
+     if (Radius <= 1) then
+       Begin
+         With ArcCall Do
+           Begin
+             X := X;
+             Y := Y;
+             XStart := X;
+             YStart := Y;
+             XEnd := X;
+             YEnd := Y;
+           End;
+         If Radius = 1 then
+           PutPixel(X, Y,CurrentColor);
+         Exit;
+       End;
 
      { 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);
+     InternalEllipse(X,Y,Radius,Radius,StAngle,Endangle);
      CurrentWriteMode := OldWriteMode;
    end;
 
@@ -2070,7 +2153,7 @@ end;
     { only normal put supported }
     OldWriteMode := CurrentWriteMode;
     CurrentWriteMode := NormalPut;
-    InternalEllipse(X,Y,XRadius,YRadius,0,360);
+    InternalEllipse(X,Y,XRadius+1,YRadius+1,0,360);
     if (XRadius > 0) and (YRadius > 0) then
       FloodFill(X,Y,CurrentColor);
     { restore old write mode }
@@ -2121,7 +2204,7 @@ end;
 
 
  procedure Sector(x, y: Integer; StAngle,EndAngle, XRadius, YRadius: Word);
-  var angle : real;
+  var angle : graph_float;
       writemode : word;
   begin
      Ellipse(x,y,stAngle,endAngle,XRadius,YRadius);
@@ -2138,9 +2221,9 @@ end;
      PutPixel(ArcCall.xend,ArcCall.yend,CurrentColor);
      stangle:=Stangle mod 360; EndAngle:=Endangle mod 360;
      if stAngle<=Endangle then
-       Angle:=(stAngle+EndAngle)/2
+       Angle:=(stAngle+EndAngle) div 2
      else
-       angle:=(stAngle-360+EndAngle)/2;
+       angle:=(stAngle-360+EndAngle) div 2;
      { fill from the point in the middle of the slice }
      XRadius:=(longint(XRadius)*10000) div XAspect;
      YRadius:=(longint(YRadius)*10000) div YAspect;
@@ -2537,7 +2620,7 @@ end;
 
 
   procedure PieSlice(X,Y,stangle,endAngle:integer;Radius: Word);
-  var angle : real;
+  var angle : graph_float;
       XRadius, YRadius : word;
       writemode : word;
   begin
@@ -2551,9 +2634,9 @@ end;
      PutPixel(ArcCall.xend,ArcCall.yend,CurrentColor);
      Stangle:=stAngle mod 360; EndAngle:=Endangle mod 360;
      if Stangle<=Endangle then
-       angle:=(StAngle+EndAngle)/2
+       angle:=(StAngle+EndAngle) div 2
      else
-       angle:=(Stangle-360+Endangle)/2;
+       angle:=(Stangle-360+Endangle) div 2;
      { fill from the point in the middle of the slice }
      XRadius:=(longint(Radius)*10000) div XAspect;
      YRadius:=(longint(Radius)*10000) div YAspect;
@@ -2690,7 +2773,14 @@ DetectGraph
 
 {
   $Log$
-  Revision 1.19  1999-09-11 19:43:01  jonas
+  Revision 1.20  1999-09-12 17:29:00  jonas
+    * several changes to internalellipse to make it faster
+      and to make sure it updates the ArcCall correctly
+      (not yet done for width = 3)
+    * Arc mostly works now, only sometimes an endless loop, don't know
+      why
+
+  Revision 1.19  1999/09/11 19:43:01  jonas
     * FloodFill: did not take into account current viewport settings
     * GetScanLine: only get line inside viewport, data outside of it
       is not used anyway

+ 12 - 5
rtl/inc/graph/text.inc

@@ -616,8 +616,8 @@
          { This is only valid for stroked fonts }
          if (charsize <> usercharsize) then
          begin
-            CurrentXRatio := charsize / 4;
-            CurrentYRatio := charsize / 4;
+            CurrentXRatio := charsize div 4;
+            CurrentYRatio := charsize div 4;
          end;
          { if this is a stroked font then load it if not already loaded }
          { into memory...                                               }
@@ -684,13 +684,20 @@
 
     procedure SetUserCharSize(Multx,Divx,Multy,Divy : word);
       begin
-         CurrentXRatio := MultX / DivX;
-         CurrentYRatio := MultY / DivY;
+         CurrentXRatio := MultX div DivX;
+         CurrentYRatio := MultY div DivY;
       end;
 
 {
 $Log$
-Revision 1.6  1999-09-12 08:02:22  florian
+Revision 1.7  1999-09-12 17:29:00  jonas
+  * several changes to internalellipse to make it faster
+    and to make sure it updates the ArcCall correctly
+    (not yet done for width = 3)
+  * Arc mostly works now, only sometimes an endless loop, don't know
+    why
+
+Revision 1.6  1999/09/12 08:02:22  florian
   * fixed outtext(''), c was a byte, this leads to an underflow and
     garbage was written