    	SUBROUTINE IFFILL( IPT )
C
C  PROGRAMMER:  RONG-SHENG ZHOU
C		BOSTON COLLEGE, 8/1988
C
C	THIS ROUTINE IMPLEMENTS AREA/POLYGON FILL.
C
C	IPT >0< : START AREA/POLYGON FILL.
C	IPT = 0 : TERMINATE AREA FILL.
C	IPT > 0 : EDGE/OUTLINE THE FILLED AREA.
C	IPT < 0 : DO NOT EDGE/OUTLINE THE FILLED AREA.
C
    	INCLUDE 'HP7550.CBS'
     	PARAMETER MNP= 1025		!POLYGON BUFFER
     	BYTE      PEN
     	COMMON/IFFILL/	NPT, XFP(MNP), YFP(MNP), PEN(MNP), YMAX

     	IF( IPT.EQ.IFP ) GOTO 999

     	IF( IPT.NE.0 ) THEN
     	    IFP = IPT
     	    NPT = 0		!INITIALIZE POLYGON BUFFER POINTER
     	ELSE
     	    IPF = IFP
     	    IFP = 0
     	    JSK = 1
     	    CALL IFFILL_FILL( IPF )
     	    JSK = 0
     	ENDIF

999	RETURN
    	END

     	SUBROUTINE IFFILL_VERTEX( XPS, YPS, IPN )
C
C  PROGRAMMER:  RONG-SHENG ZHOU
C		BOSTON COLLEGE, 8/1988
C
C	THIS ROUTINE STORES POLYGON VERTICES FOR AREA FILL
C	(IT IS CALLED IN SUBROUTINE "IFPLOT").
C
     	INCLUDE		'HP7550.CBS'
     	PARAMETER	MNP= 1025
     	BYTE		PEN
     	COMMON/IFFILL/	NPT, XFP(MNP), YFP(MNP), PEN(MNP), YMAX
     	SAVE		XPSL,YPSL

     	IF( NPT.EQ.MNP-1 ) GOTO 555
C
C  SAVE THE VERTEX...
C
     	IF( NPT.EQ.0 ) THEN
     	    IF( IPN.NE.2 ) GOTO 999	!WAIT FOR THE 1ST PEN DOWN
     	    NPT = 1
     	    IF( XANG.NE.0.0 .OR. YANG.NE.0.0 ) THEN
     		XOP = XPSL*XCTH-YPSL*YSTH
     		YPSL= XPSL*XSTH+YPSL*YCTH
     		XPSL= XOP
     	    ENDIF
     	    XFP(NPT) = XSCL*XPSL + XORS
     	    YFP(NPT) = YSCL*YPSL + YORS
     	    PEN(NPT) = 3
     	ENDIF
     	NPT = NPT + 1
     	PEN(NPT) = IPN
     	IF( XANG.NE.0.0 .OR. YANG.NE.0.0 ) THEN
     	    XOP = XPS*XCTH-YPS*YSTH
     	    YPS = XPS*XSTH+YPS*YCTH
     	    XPS = XOP
     	ENDIF
     	XFP(NPT) = XSCL*XPS + XORS
     	YFP(NPT) = YSCL*YPS + YORS
     	GOTO 999
C
C  BUFFER OVERFLOW...
C
555	IFP = 0
     	DO I=1, NPT
     	    IPF = PEN(I)
     	    CALL IFPLOT( XFP(I), YFP(I), IPF )
     	ENDDO
     	NPT = 0
     	WRITE(6,1000) MNP-1
1000	FORMAT('__ERROR: POLYGON BUFFER(',I4,' VERTICES) OVERFLOW.',
     1' AREA FILL BYPASSED!')

999	XPSL = XPS
     	YPSL = YPS
     	RETURN
     	END

     	SUBROUTINE IFFILL_FILL( IFP )
C
C  PROGRAMMER:  RONG-SHENG ZHOU
C		BOSTON COLLEGE, 8/1988
C
C	THIS ROUTINE FILLS A POLYGON USING "IFDRAW" COMMANDS.
C
C	IFP --- HATCHING PATTERN NUMBER:
C
C	IFP= 0: NO FILL BUT THE POLYGON IS EDGED/OUTLINED.
C	IFP= 1: SOLID FILL (AUTO-BIDIRECTIONAL. 1-LINEWIDTH SPACING).
C	IFP= 2: HORIZONTAL BIDIRECTIONAL LINES (2-LINEWIDTH SPACING).
C	IFP= 3: HORIZONTAL BIDIRECTIONAL LINES (4-LINEWIDTH SPACING).
C	IFP= 4: HORIZONTAL BIDIRECTIONAL LINES (8-LINEWIDTH SPACING).
C	IFP= 5:   VERTICAL BIDIRECTIONAL LINES (2-LINEWIDTH SPACING).
C	IFP= 6:   VERTICAL BIDIRECTIONAL LINES (4-LINEWIDTH SPACING).
C	IFP= 7:   VERTICAL BIDIRECTIONAL LINES (8-LINEWIDTH SPACING).
C	IFP= 8:  45 DEGREE BIDIRECTIONAL LINES (2-LINEWIDTH SPACING).
C	IFP= 9:  45 DEGREE BIDIRECTIONAL LINES (4-LINEWIDTH SPACING).
C	IFP=10:  45 DEGREE BIDIRECTIONAL LINES (8-LINEWIDTH SPACING).
C	IFP=11: -45 DEGREE BIDIRECTIONAL LINES (2-LINEWIDTH SPACING).
C	IFP=12: -45 DEGREE BIDIRECTIONAL LINES (4-LINEWIDTH SPACING).
C	IFP=13: -45 DEGREE BIDIRECTIONAL LINES (8-LINEWIDTH SPACING).
C	IFP=14:  45 DEGREE BIDIRECTIONAL  DOTS (2-LINEWIDTH SPACING).
C	IFP=15:  45 DEGREE BIDIRECTIONAL  DOTS (4-LINEWIDTH SPACING).
C	IFP=16:  45 DEGREE BIDIRECTIONAL  DOTS (8-LINEWIDTH SPACING).
C
C	IFP>0: FILL AND EDGE THE POLYGON.
C	IFP<0: FILL BUT NOT EDGE THE POLYGON.
C
C	ACTIVE PLOTTING STYLUS DOES NOT AFFECT THE HATCHING PATTERN
C	BUT POLYGON EDGING IS USING THE ACTIVE PLOTTING STYLUS.
C
     	PARAMETER	MNP= 1025
     	BYTE		IDI, IPI, PEN
     	LOGICAL		DOT
     	INTEGER*2	EDGE, CEDGE
     	COMMON/IFFILL/	NPT, XFP(MNP), YFP(MNP), PEN(MNP), YMAX
     	COMMON/IFFILL_EDGE/ NSD,NED,IED,YLINE,EDGE(2,MNP),CEDGE(2,MNP)
C
C  INITIALIZE HATCHING PARAMETERS...
C
     	ANGLE = 0.0
     	IPF = IABS(IFP)
     	IF( NPT.LT.3 .OR. IPF.EQ.0 ) GOTO 888
     	CALL IFSTYL_NOW( LTYP, LWID )
     	YSPAC = 0.012*LWID		!LINEWIDHT IN INCHES
     	IPI = MOD( IPF-2, 3 )
     	IF( IPI.EQ.0 ) YSPAC = 2.0*YSPAC
     	IF( IPI.EQ.1 ) YSPAC = 4.0*YSPAC
     	IF( IPI.EQ.2 ) YSPAC = 8.0*YSPAC
     	IF( IPF.GT.4 ) ANGLE = 90.0
     	IF( IPF.GT.7 ) ANGLE = 45.0
     	IF( IPF.GT.10 .AND. IPF.LT.14 ) ANGLE = -45.0
     	DOT = .FALSE.
     	IF( IPF.GT.13 ) THEN
     	    DOT = .TRUE.
     	    DOTC = 0.012*LWID		!DOT DIAMETER
     	ENDIF
C
C  IF SOLID FILL FOR A SIMPLE POLYGON, GET THE OPTIMUM DRAW DIRECTION...
C
     	IF( IPF.EQ.1 .AND. NPT.LT.6 ) CALL IFFILL_ANGLE( ANGLE )
C
C  TRANSFORM VERTEX COORDINATES IF ANGLE.NE.0.0 ...
C
     	IF( ANGLE.NE.0.0 ) CALL IFFILL_ROTA( -ANGLE )
C
C  SORT POLYGON VERTICES ON ASCENDING Y COORDINATES
C  (EDGE ARRAY STORES THE POINTERS TO VERTICES) ...
C
     	CALL IFFILL_SORT
C
C  SET PLOT ROTATION IF ANGLE.NE.0.0 ...
C
     	IF( ANGLE.NE.0.0 ) THEN
     	    CALL IFROTA_NOW( XANG, YANG )
     	    CALL IFROTA( XANG+ANGLE, YANG+ANGLE )
     	ENDIF
C
C  START HATCHING FROM BOTTOM UP...
C
     	YTOP  = YMAX - YSPAC			!TOP Y COORDINATE - YSPAC
     	YLINE = YFP( EDGE(1,  1) )		!GET THE SMALLEST Y-COORDINATE
     	IED = 0					!NUMBER OF FILLED EDGES
     	IDI = 1					!HATCHING DIRECTIONAL FLAG

111	IF( YLINE.GE.YTOP ) GOTO 777		!END OF FILLING!
     	YLINE = YLINE + YSPAC			!GET THE NEXT HATCHING LINE
C
C  GET THE ACTIVE LIST OF EDGES INTERSECTING THE "YLINE"...
C
     	CALL IFFILL_EDGE
C
C  LOOP THROUGH THE EDGES FOR INTERSECTING X-COORDINATES...
C
     	IPI = 1					!JUMP FLAG
     	IF( IDI.GT.0 ) THEN
     	    II1 = 1
     	    II2 = NED
     	    II3 = 1
     	ELSE
     	    II1 = NED
     	    II2 = 1
     	    II3 = -1
     	ENDIF
     	DO I= II1, II2, II3	!BIDIRECTIONAL HATCHING LOOP
     	   J = CEDGE(1,I)
     	   K = CEDGE(2,I)
     	   XING = XFP(K)+(YLINE-YFP(K))*(XFP(J)-XFP(K))/(YFP(J)-YFP(K))
     	   IF( IPI.GT.0 ) THEN
     	       CALL IFDRAW( XING, YLINE, 3 )	!DUMP
     	       XLAST = XING
     	   ELSE IF( .NOT. DOT ) THEN
     	       CALL IFDRAW( XING, YLINE, 2 )	!DRAW
     	   ELSE
222	       XLAST = XLAST + IDI*YSPAC	!DOT
     	       IF( IDI.GT.0 .AND. XLAST.GE.XING ) GOTO 333
     	       IF( IDI.LT.0 .AND. XLAST.LE.XING ) GOTO 333
     	       CALL IFDRAW( XLAST, YLINE, 3 )
     	       CALL IFDRAW( XLAST+DOTC, YLINE, 2 )
     	       GOTO 222
     	   ENDIF
333	   IPI = -IPI
     	ENDDO
     	IDI = -IDI
     	GOTO 111
C
C  IF "IFP" IS NEGATIVE, SKIP EDGING THE POLYGON...
C
777	IF( IFP.LT.0 ) GOTO 999
C
C  EDGE THE POLYGON USING ACTIVE PLOTTING STYLUS...
C
888	DO I=1, NPT
     	   IPF = PEN(I)
     	   CALL IFPLOT( XFP(I), YFP(I), IPF )
     	ENDDO
C
C  SET PLOT ROTATION BACK IF ANGLE.NE.0.0 ...
C
999	IF( ANGLE.NE.0.0 ) CALL IFROTA( XANG, YANG )
     	NPT = 0

     	RETURN
     	END

     	SUBROUTINE IFFILL_ANGLE( ANGLE )
C
C  PROGRAMMER:  RONG-SHENG ZHOU
C		BOSTON COLLEGE, 8/1988
C
C	THIS ROUTINE FINDS THE LONGER PATH FOR SOLID FILL.
C
     	PARAMETER	MNP= 1025, D2R= 0.174532E-1
     	BYTE		PEN
     	COMMON/IFFILL/	NPT, XFP(MNP), YFP(MNP), PEN(MNP), YMAX

     	XMAX = XFP(1)
     	YMAX = YFP(1)
     	XMIN = XFP(1)
     	YMIN = YFP(1)
     	DO I=2, NPT
     	   IF( XFP(I).LT.XMIN ) XMIN = XFP(I)
     	   IF( XFP(I).GT.XMAX ) XMAX = XFP(I)
     	   IF( YFP(I).LT.YMIN ) YMIN = YFP(I)
     	   IF( YFP(I).GT.YMAX ) YMAX = YFP(I)
     	ENDDO
     	IF( (XMAX-XMIN) .LT. 0.9*(YMAX-YMIN) ) ANGLE = 90.0

999	RETURN
     	END

     	SUBROUTINE IFFILL_ROTA( ANGLE )
C
C  PROGRAMMER:  RONG-SHENG ZHOU
C		BOSTON COLLEGE, 8/1988
C
C	THIS ROUTINE TRANFORMS THE POLYGON VERTICES.
C
     	PARAMETER	MNP= 1025, D2R= 0.174532E-1
     	BYTE		PEN
     	COMMON/IFFILL/	NPT, XFP(MNP), YFP(MNP), PEN(MNP), YMAX

     	ANG = ANGLE
     	CTH = COS(D2R*ANG)
     	STH = SIN(D2R*ANG)
     	DO I=1, NPT
     	   XPS    = XFP(I)*CTH - YFP(I)*STH
     	   YFP(I) = XFP(I)*STH + YFP(I)*CTH
     	   XFP(I) = XPS
     	ENDDO

     	RETURN
     	END

     	SUBROUTINE IFFILL_SORT
C
C  PROGRAMMER:  RONG-SHENG ZHOU
C		BOSTON COLLEGE, 8/1988
C
C	THIS ROUTINE SORTS THE POLYGON VERTICES ON ASCENDING
C	Y-COORDINATES AND STORES SEQUENCE IN POINTER ARRAY "EDGE".
C
     	PARAMETER	MNP= 1025, ERR= 0.001
     	BYTE		PEN
     	LOGICAL		DONE
     	INTEGER*2	EDGE, CEDGE
     	COMMON/IFFILL/	NPT, XFP(MNP), YFP(MNP), PEN(MNP), YMAX
     	COMMON/IFFILL_EDGE/ NSD,NED,IED,YLINE,EDGE(2,MNP),CEDGE(2,MNP)
C
C  IF THE POLYGON IS NOT CLOSE, FORCE IT...
C
     	IF(  ABS(XFP(1)-XFP(NPT)) .GT. ERR
     1  .OR. ABS(YFP(1)-YFP(NPT)) .GT. ERR ) THEN
     	     NPT = NPT + 1
     	     XFP(NPT) = XFP(1)
     	     YFP(NPT) = YFP(1)
     	     PEN(NPT) = 3
     	ENDIF
C
C  PAIR VERTICES TO FORM EDGES (AN EDGE IMMEDIATELY FOLLOWING
C  A LOOP IS ALSO IGNORED FOR MULTI-LOOP POLYGON)...
C
     	NSD = 0
     	XLP = XFP(1)
     	YLP = YFP(1)
     	YMAX= YLP
     	DO 111 I=1, NPT-1
     	    IF( PEN(I+1).EQ.3 ) THEN	!PEN-UP SIGNIFIES A POSSIBLE LOOP
     		IF( ABS(XLP-XFP(I)) .LT. ERR
     1        .AND. ABS(YLP-YFP(I)) .LT. ERR ) THEN
     		    XLP = XFP(I+1)	!SAVE THE TERMINAL OF LOOP
     		    YLP = YFP(I+1)	!SAVE THE TERMINAL OF LOOP
     		    GOTO 111		!SKIP THIS EDGE
     		ENDIF
     	    ENDIF
     	    NSD = NSD + 1
     	    IF( YFP(I).LT.YFP(I+1) ) THEN
     		EDGE(1,NSD) = I
     		EDGE(2,NSD) = I+1
     	        IF( YFP(I+1).GT.YMAX ) YMAX = YFP(I+1)
     	    ELSE
     		EDGE(1,NSD) = I+1
     		EDGE(2,NSD) = I
     	        IF( YFP(I).GT.YMAX ) YMAX = YFP(I)
     	    ENDIF
111	CONTINUE
C
C  SORT "EDGE" ARRAY ON ASCENDING Y-COORDINATES...
C
222	DONE = .TRUE.
     	DO I=1, NSD-1
     	    IF( YFP(EDGE(1,I)).GT.YFP(EDGE(1,I+1)) ) THEN
     		IED = EDGE(1,I)
     		NED = EDGE(2,I)
     		EDGE(1,I) = EDGE(1,I+1)
      		EDGE(1,I+1) = IED
     		EDGE(2,I) = EDGE(2,I+1)
     		EDGE(2,I+1) = NED
     		DONE = .FALSE.
     	    ENDIF
     	ENDDO
     	IF( .NOT. DONE ) GOTO 222

999	RETURN
     	END

     	SUBROUTINE IFFILL_EDGE
C
C  PROGRAMMER:  RONG-SHENG ZHOU
C		BOSTON COLLEGE, 8/1988
C
C	THIS ROUTINE GETS THE ACTIVE LIST OF EDGES INTERSECTING
C	THE CURRENT HATCHING LINE "YLINE".
C
     	PARAMETER	MNP= 1025
     	BYTE		PEN
     	LOGICAL		DONE
     	INTEGER*2	EDGE, CEDGE
     	COMMON/IFFILL/	NPT, XFP(MNP), YFP(MNP), PEN(MNP), YMAX
     	COMMON/IFFILL_EDGE/ NSD,NED,IED,YLINE,EDGE(2,MNP),CEDGE(2,MNP)

     	NED = 0
     	IEDGE = IED
     	DONE  = .TRUE.
     	DO 222 I=IED+1, NSD
     	   YSTR = YFP(EDGE(1,I))
     	   YEND = YFP(EDGE(2,I))
     	   IF( ABS(YSTR-YEND).LT.0.001 ) GOTO 111		!HORIZONTAL LINE
     	   IF( YSTR.GE.YLINE .OR. YEND.LT.YLINE ) GOTO 111	!OUT OF REACH
     	   IF( YEND.EQ.YLINE ) THEN
     		IF( I.EQ.1 ) THEN
     		    I1 = EDGE(2,NSD)
     		    I2 = EDGE(2,I+1)
     		ELSE
     		    I1 = EDGE(2,I-1)
     		    IF( I.EQ.NSD ) THEN
     			I2 = EDGE(2,1)
     		    ELSE
     			I2 = EDGE(2,I+1)
     		    ENDIF
     		ENDIF
     		IF(YFP(I1).LT.YEND.AND.YFP(I2).LT.YEND) GOTO 111
     		IF(YFP(I1).GT.YEND.AND.YFP(I2).GT.YEND) GOTO 111
     	   ENDIF
     	   NED = NED + 1
     	   CEDGE(1,NED) = EDGE(1,I)
     	   CEDGE(2,NED) = EDGE(2,I)
     	   DONE = .FALSE.
     	   GOTO 222
 111	   IF( YEND.LT.YLINE ) THEN
     		IF( DONE ) IEDGE = I
     	   ENDIF
222	CONTINUE
     	IED = IEDGE
     	IF( NED.LT.2 ) GOTO 999
C
C  SORT "CEDGE" ARRAY ON ASCENDING X-COORDINATES...
C
333	DONE = .TRUE.
     	DO I=1, NED-1
     	    J = CEDGE(1,I)
     	    K = CEDGE(2,I)
     	    YSTR=XFP(K)+(YLINE-YFP(K))*(XFP(J)-XFP(K))/(YFP(J)-YFP(K))
     	    J = CEDGE(1,I+1)
     	    K = CEDGE(2,I+1)
     	    YEND=XFP(K)+(YLINE-YFP(K))*(XFP(J)-XFP(K))/(YFP(J)-YFP(K))
     	    IF( YSTR.GT.YEND ) THEN
     		IEDGE = CEDGE(1,I)
     		JEDGE = CEDGE(2,I)
     		CEDGE(1,I) = CEDGE(1,I+1)
      		CEDGE(1,I+1) = IEDGE
     		CEDGE(2,I) = CEDGE(2,I+1)
      		CEDGE(2,I+1) = JEDGE
     		DONE = .FALSE.
     	    ENDIF
     	ENDDO
     	IF( .NOT. DONE ) GOTO 333

999	RETURN
     	END

