/*
 * plowInt.h --
 *
 * Internal definitions for the plow module.
 *
 *     *********************************************************************
 *     * Copyright (C) 1985, 1990 Regents of the University of California. *
 *     * Permission to use, copy, modify, and distribute this              *
 *     * software and its documentation for any purpose and without        *
 *     * fee is hereby granted, provided that the above copyright          *
 *     * notice appear in all copies.  The University of California        *
 *     * makes no representations about the suitability of this            *
 *     * software for any purpose.  It is provided "as is" without         *
 *     * express or implied warranty.  Export of this software outside     *
 *     * of the United States of America may require an export license.    *
 *     *********************************************************************
 *
 * Needs to include: magic.h, geometry.h, tile.h
 *
 * rcsid $Header: /usr/cvsroot/magic-8.0/plow/plowInt.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $
 */

#ifndef _MAGIC__PLOW__PLOWINT_H
#define	_MAGIC__PLOW__PLOWINT_H

#include "tiles/tile.h"

/*
 * The following is a TileType used by plowing to refer to an
 * edge on the subcell plane.
 */
#define	PLOWTYPE_CELL	(TT_MAXTYPES - 1)

/* --------------------------- Plowing rules -------------------------- */

/*
 * Plowing rules tables.  (These are not the plowing forms of
 * design rules, but rather the procedures that apply those
 * rules).
 *
 * These are initialized by PlowInit after the technology
 * file has been read.  Each entry in a rules table contains
 * two masks: rte_ltypes and rte_rtypes.  If the type on the
 * LHS of an edge is in rte_ltypes, and the type on the RHS
 * is in rte_rtypes, the procedure rte_proc is applied.
 */
typedef struct
{
    TileTypeBitMask	 rte_ltypes;	/* Apply if LHS type is in this set */
    TileTypeBitMask	 rte_rtypes;	/* Apply if RHS type is in this set */
    int			 rte_whichRules;/* See below */
    int		       (*rte_proc)();	/* Procedure implementing rule */
    const char		*rte_name;	/* Name of rule (for debugging) */
} RuleTableEntry;

#define	MAXRULES	100	/* Ridiculously high */

#define	RTE_NULL	0	/* Don't use any rules at all */
#define	RTE_MINWIDTH	1	/* Use minimum width */
#define	RTE_REALWIDTH	2	/* Use computed real widths */
#define	RTE_SPACING	3	/* Use spacing rules */
#define	RTE_NOSPACING	4	/* Only apply rule if there are no spacing
				 * rules across this edge.
				 */

extern RuleTableEntry *plowCurrentRule;	/* For debugging */

/* ----------------------------- Edges -------------------------------- */

/*
 * An Edge describes the boundary between tiles of two different types.
 * It is used by shadow search to describe an edge it found, and also
 * to store edges in the edge queue (these latter along with their final
 * positions).
 *
 * If e_use is non-NULL, the "edge" is really the right-hand side of
 * a cell use.
 */
typedef struct edge
{
    Rect	 e_rect;	/* Rectangle describing the edge (see below) */
    int		 e_pNum;	/* Plane # in plowYankDef */
    TileType	 e_ltype;	/* Type of LHS of edge */
    TileType	 e_rtype;	/* Type of RHS of edge */
    int		 e_flags;	/* Miscellaneous flags: see below */

    /* Non-NULL if this is a cell moving instead of a piece of geometry */
    CellUse	*e_use;		/* Cell use to be moved */

    /* Only used in the queue of edges to move */
    struct edge	*e_next;	/* Next edge in list */
} Edge;

    /* Flags from above */
#define	E_ISINITIAL	0x01	/* Edge was added from initial plow */

    /* When an edge moves, it has an initial and final X position */
#define	e_x	e_rect.r_xbot	/* Initial X coordinate */
#define	e_newx	e_rect.r_xtop	/* Final X coordinate */

    /* The top and bottom of an edge don't change during plowing */
#define	e_ytop	e_rect.r_ytop
#define	e_ybot	e_rect.r_ybot

extern CellDef *plowYankDef;	/* Cell def containing planes above */

/* ----------------------- Outline searching -------------------------- */

/*
 * The following describes the outline of a boundary followed by
 * plowSrOutline().
 *
 * The following structure also reflects the directions associated
 * with a particular edge in the outline of a collection of types.
 * It gives the direction from which we turned to follow the current
 * edge, the direction along which we are following the current edge,
 * and the direction we will turn for following the next edge along
 * the outline.
 *
 * All directions are one of: GEO_NORTH, GEO_WEST, GEO_SOUTH, GEO_EAST.
 * When facing the indicated direction, the material on the inside of
 * the region being followed is always to the left.
 */
typedef struct
{
    Rect		 o_rect;	/* Degenerate rectangle defining the
					 * outline segment being processed.
					 */
    Tile		*o_inside;	/* Tile on inside of outline */
    Tile		*o_outside;	/* Tile on outside of outline */
    int			 o_pNum;	/* Plane # on which outline was found */
    int			 o_prevDir;	/* Previous direction */
    int			 o_currentDir;	/* Direction following this segment */
    int			 o_nextDir;	/* Direction to be followed next */

    /* Used only by plowSrOutline() */
    TileTypeBitMask	 o_insideTypes;	/* Mask of types inside the outline */
    Tile		*o_nextIn;	/* Next inside tile */
    Tile		*o_nextOut;	/* Next outside tile */
    Rect		 o_nextRect;	/* Next segment of boundary */
} Outline;

/* Masks of directions */
#define	GMaskHasDir(m, d)	((m & DirToGMask(d)) != 0)
#define	DirToGMask(d)		(1 << (d))

#define	GMASK_NORTH		DirToGMask(GEO_NORTH)
#define	GMASK_SOUTH		DirToGMask(GEO_SOUTH)
#define	GMASK_EAST		DirToGMask(GEO_EAST)
#define	GMASK_WEST		DirToGMask(GEO_WEST)

/* ------------------- Leading and trailing edges --------------------- */

/*
 * The leading and trailing edge of a tile are the "new" positions
 * as determined by plowing, as opposed to the "initial" positions
 * still stored in LEFT and RIGHT.
 *
 * As with LEFT and RIGHT, only the trailing coordinate of a tile is
 * stored explicitly; the leading coordinate is the trailing coordinate
 * of the tile to its right.
 */
#define	TRAIL_UNINIT	CLIENTDEFAULT
#define	TRAILING(tp)	(((tp)->ti_client == INT2CD(TRAIL_UNINIT)) \
				? LEFT(tp) : ((int)CD2INT((tp)->ti_client)))
#define	LEADING(tp)	TRAILING(TR(tp))

#define	plowSetTrailing(tp, n)	((tp)->ti_client = INT2CD((n)))

/* ------------------ Design rules used by plowing -------------------- */

/*
 * The following structure is used both for spacing rules and
 * for width rules.
 */
typedef struct prule
{
    TileTypeBitMask	 pr_ltypes;	/* Material to the left of the
					 * outline of the LHS of the
					 * penumbra.
					 */
    TileTypeBitMask	 pr_oktypes;	/* Anything in the umbra or penumbra
					 * not of this type must be pr_dist
					 * away from the moving edge.
					 */
    int			 pr_dist;	/* Distance associated with this
					 * design rule.
					 */
    int			 pr_mod;	/* Modulus for pr_dist	*/
    short		 pr_pNum;	/* Plane on which to apply rule
					 * (for spacing rules only).
					 */
    short		 pr_flags;	/* See below */
    struct prule	*pr_next;	/* Next rule in bucket */
} PlowRule;

/* Flags */
#define	PR_WIDTH	0x01	/* Spacing has this bit clear */
#define	PR_PENUMBRAONLY	0x02	/* Apply rule only in penumbra */
#define	PR_EDGE		0x04	/* Debugging: came from "edge" rule */
#define	PR_EDGE4WAY	0x08	/* Debugging: came from "edge4way" rule */
#define	PR_EDGEBACK	0x10	/* Debugging: backward part of "edge4way" */

extern PlowRule *plowSpacingRulesTbl[TT_MAXTYPES][TT_MAXTYPES];
extern PlowRule *plowWidthRulesTbl[TT_MAXTYPES][TT_MAXTYPES];

/*
 * Entry [t] of the following table is the maximum distance associated
 * with any design rules in a bucket with type 't' on the LHS.
 */
extern int plowMaxDist[TT_MAXTYPES];

/* --------------- Structure when applying plowing rules -------------- */

/*
 * Structure used by rules procedures for passing information
 * down to their filter functions.  Not all rules fill in all
 * the information in this structure; see the comments in each
 * rule for details.
 */
struct applyRule
{
    Edge	*ar_moving;	/* Edge being moved */
    PlowRule	*ar_rule;	/* Plowing rule being applied */

    /* Only used in penumbra */
    Point	 ar_clip;	/* Boundary of clipping rectangle */

    /* Only used in slivers */
    TileType	 ar_slivtype;	/* Material in middle of sliver sandwich */
    int		 ar_lastx;	/* Rightmost X we've seen so far */
    int		 ar_mustmove;	/* Must move slivers this far right */

    /* Only used with cells */
    int		 ar_pNum;	/* Plane being searched (area search only) */
    Rect	 ar_search;	/* Area being searched */
};

/* ----------------------- Internal procedures ------------------------ */

/* Procedure called when we've found a new edge to add */
extern int (*plowPropagateProcPtr)();

/* Other exports */
extern int plowQueueAdd();
extern bool plowQueueLeftmost();
extern bool plowQueueRightmost();
extern Tile *plowSplitY();

/* C99 compat */
extern bool Plow();
extern void PlowClearBound();
extern bool PlowSelection();
extern void PlowSetBound();
extern void PlowStraighten();
extern int  plowApplySearchRules();
extern int  plowAtomize();
extern void plowCleanupJogs();
extern void plowDebugEdge();
extern int  plowFindWidth(Edge *edge, const TileTypeBitMask *typesp, Rect *bbox, Rect *prect);
extern int  plowFindWidthBack(Edge *edge, const TileTypeBitMask *typesp, Rect *bbox, Rect *prect);
extern int  plowGenRandom();
extern void plowQueueDone();
extern void plowQueueInit();
extern int  plowSrFinalArea();
extern void plowSrOutline(int pNum, Point *startPoint, const TileTypeBitMask *insideTypesp, int initialDir, int dirMask, int (*proc)(), ClientData cdata);
extern int  plowSrShadow(int pNum, Rect *area, const TileTypeBitMask *okTypesp, int (*proc)(), ClientData cdata);
extern int  plowSrShadowBack(int pNum, Rect *area, const TileTypeBitMask *okTypesp, int (*proc)(), ClientData cdata);
extern int  plowSrShadowInitial(int pNum, Rect *area, const TileTypeBitMask *okTypesp, int (*proc)(), ClientData cdata);
extern bool plowYankMore();
extern void PlowRandomTest();
extern void plowDebugInit();
extern void plowMergeBottom(Tile **delay1, Tile *tp, Plane *plane); /* for PlowTest.c */
extern void plowMergeTop(Tile **delay1, Tile *tp, Plane *plane); /* for PlowTest.c */
extern void plowMoveEdge();
extern int  plowShadowInitialRHS();
extern int  plowShadowLHS();
extern int  plowShadowRHS();
extern void plowTechShow();
extern void plowUpdateLabels();
extern void plowYankCreate();

#ifndef NO_RUSAGE
extern void plowShowTime();
#endif

/* ------------------------- Debugging flags -------------------------- */

/*
 * The following come from a separate file so we can add more
 * debugging flags without forcing the entire system to be
 * recompiled.
 */
#include "plowDebugInt.h"

#endif	/* _MAGIC__PLOW__PLOWINT_H */
