        SUBROUTINE GSFILL(X,Y,N,TX,TY)
        DIMENSION X(N),Y(N), TX(N),TY(N)
C
C       DIGLIB POLYGON FILL SUPPORT
C       DERIVED FROM "HATCH" ALGORITHM BY KELLY BOOTH
C
        INCLUDE GCDCHR.PRM
        INCLUDE GCDPRM.PRM
        INCLUDE GCLTYP.PRM
C
        DIMENSION XINS(40)
        INTEGER GSIVIS
        LOGICAL LEFT
        DATA FACT /16.0/
C
C       *****
C       DEFINE ARITHMETIC STATEMENT FUNCTION TO MAPPING VERTICES
        YMAP(YYY) = 2.0*AINT(YSCALE*YYY+0.5)+1.0
C       *****
C
        IF (N .LT. 3) RETURN
C
C
C       CONVERT TO ABSOLUTE COORD.
C
        DO 10 I=1,N
                CALL GSRST(X(I),Y(I),TX(I),TY(I))
10              CONTINUE
        CALL MINMAX(TY,N,YMIN,YMAX)
        CALL MINMAX(TX,N,XMIN,XMAX)
C
C       IF CLIPPING NEEDED OR IF NO HARDWARE POLYGON FILL, USE SOFTWARE
C
        IF ((GSIVIS(XMIN,YMIN) .NE. 0) .OR.
     1   (GSIVIS(XMAX,YMAX) .NE. 0) .OR.
     2   (IAND(IDVBTS,256) .EQ. 0)) GO TO 200
C
C       IF CAN HANDLE CONCAVE POLYGONS, JUST CALL DRIVER
C
        IF ((IAND(IDVBTS,512) .EQ. 0) .OR.
     1   (N .EQ. 3)) GO TO 150
C
C       IF HERE, DRIVER CAN HANDLE CONVEX NON-INTERSECTING POLYGONS ONLY,
C        SO MAKE SURE THIS POLYGON IS CONVEX AND NON-SELF-INTERSECTING.
C
        DX1 = X(1)-X(N)
        DY1 = Y(1)-Y(N)
C       !OLD NON-ZERO DELTA-Y
        DY = DY1
C       NUMBER OF TIMES DELTA-Y CHANGES SIGN
        NCHNGS = 0
        L = 1
        COSTH = 0.0
110     CONTINUE
C
C               CONVEXITY TEST
C
                DX2 = X(L+1)-X(L)
                DY2 = Y(L+1)-Y(L)
                A = DX1*DY2-DX2*DY1
                IF (A*COSTH .LT. 0.0) GO TO 200
                IF (COSTH .EQ. 0.0) COSTH = A
C
C               SELF INTERSECTION CHECK - RELYS ON "CONVEXITY" CHECK
C
                IF (DY .NE. 0.0) GO TO 120
                        DY = DY2
                        GO TO 130
120             CONTINUE
                IF (DY2*DY .GE. 0.0) GO TO 130
                        DY = DY2
                        NCHNGS = NCHNGS + 1
                        IF (NCHNGS .GE. 3) GO TO 200
130             CONTINUE
                DX1 = DX2
                DY1 = DY2
                L = L + 1
                IF (L .LT. N) GO TO 110
150     CONTINUE
        CALL GSDRVR(1024+N,TX,TY)
        RETURN
C
C       **********
C       SOFTWARE FILL
C       **********
C
200     CONTINUE
C
C       FILLING A POLYGON IS VERY SIMPLE IF AND ONLY IF THE VERTICES OF
C        THE POLYGON NEVER LIE ON A SCAN LINE.   WE CAN FORCE THIS TO HAPPEN
C        BY THE FOLLOWING TRICK: MAKE ALL VERTICES LIE JUST BARELY ABOVE
C        THE SCAN LINE THEY SHOULD LIE ON.   THIS IS DONE BY MAPPING THE
C        VERTICES TO A GRID THAT IS "FACT" TIMES THE DEVICE RESOLUTION,
C        AND THEN DOUBLING THE GRID DENSITY, AND OFFSETTING THE VERTICES
C        BY 1.   BECAUSE WE DO THIS, WE MUST OUTLINE THE POLYGON.
C
C       *******
C
C       FILL WITH SOLID LINES
C
        LINOLD = ILNTYP
        ILNTYP = 1
C
        LEFT = .TRUE.
        YSCALE = YS*YRES*FACT
        DLINES = 2.0*FACT
        CALL MINMAX(Y,N,YMIN,YMAX)
        YMIN = AINT(YMAP(YMIN)/DLINES)*DLINES+DLINES
        YMAX = AINT(YMAP(YMAX)/DLINES)*DLINES
        YSCAN = YMIN
210     CONTINUE
                INISEC = 0
                IFIRST = 0
C
C               DO EACH SIDE OF THE POLYGON. PUT ANY X INTERSECTIONS
C               WITH THE SCAN LINE Y=YSCAN IN XINS
C
                YBEGIN = YMAP(Y(N))
                XBEGIN = X(N)
                DO 400 L = 1, N
                        YEND = YMAP(Y(L))
                        DY = YSCAN-YBEGIN
                        IF (DY*(YSCAN-YEND) .GT. 0.0) GO TO 390
C
C                       INSERT AN INTERSECTION
C
                        INISEC = INISEC + 1
                        XINS(INISEC) = DY*(X(L)-XBEGIN)/(YEND-YBEGIN)+XBEGIN
C
390                     CONTINUE
                        YBEGIN = YEND
                        XBEGIN = X(L)
400                     CONTINUE
C
C               FILL IF THERE WERE ANY INTERSECTIONS
C
                IF (INISEC .EQ. 0) GOTO 500
C
C               FIRST WE MUST SORT ON X INTERSECTION.
C               USE BUBBLE SORT BECAUSE USUALLY ONLY 2.
C               WHEN "LEFT" IS TRUE, ASCENDING SORT, FALSE IS DESCENDING SORT
C
                DO 450 I =  1, INISEC-1
                        XKEY = XINS(I)
                        DO 430 J = I+1, INISEC
                                IF (.NOT. LEFT) GOTO 420
                                IF (XKEY .GE. XINS(J)) GO TO 430
410                             CONTINUE
                                TEMP = XKEY
                                XKEY = XINS(J)
                                XINS(J) = TEMP
                                GO TO 430
420                             IF (XKEY .GT. XINS(J)) GOTO 410
430                             CONTINUE
                        XINS(I) = XKEY
450                     CONTINUE
C
C               DRAW FILL LINES NOW
C
                YY = YSCAN/(2.0*YSCALE)
                DO 460 I = 1, INISEC, 2
                        CALL GSMOVE(XINS(I),YY)
                        CALL GSDRAW(XINS(I+1),YY)
460                     CONTINUE
500             CONTINUE
        YSCAN = YSCAN + DLINES
        LEFT = .NOT. LEFT
        IF (YSCAN .LE. YMAX) GO TO 210
C
C       FINALLY, OUTLINE THE POLYGON
C
        CALL GSMOVE(X(N),Y(N))
        DO 510 L=1,N
                CALL GSDRAW(X(L),Y(L))
510             CONTINUE
C
C       RESTORE LINE TYPE
C
        ILNTYP = LINOLD
        RETURN
        END
