magic/tiles/tile.h

394 lines
12 KiB
C

/*
* tile.h --
*
* Definitions of the basic tile structures
* The definitions in this file are all that is visible to
* the Ti (tile) modules.
*
* *********************************************************************
* * 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. *
* *********************************************************************
*
* rcsid "$Header: /usr/cvsroot/magic-8.0/tiles/tile.h,v 1.3 2010/06/24 12:37:57 tim Exp $"
*/
#ifndef _MAGIC__TILES__TILE_H
#define _MAGIC__TILES__TILE_H
#ifndef _MAGIC__UTILS__MAGIC_H
#include "utils/magic.h"
#endif
#ifndef _MAGIC__UTILS__GEOMETRY_H
#include "utils/geometry.h"
#endif
/*
* A tile is the basic unit used for representing both space and
* solid area in a plane. It has the following structure:
*
* RT
* ^
* |
* -------------------------
* | | ---> TR
* | |
* | |
* | (lower left) |
* BL <--- -------------------------
* |
* v
* LB
*
* The (x, y) coordinates of the lower left corner of the tile are stored,
* along with four "corner stitches": RT, TR, BL, LB.
*
* Space tiles are distinguished at a higher level by having a distinguished
* tile body.
*/
typedef struct tile
{
ClientData ti_body; /* Body of tile */
struct tile *ti_lb; /* Left bottom corner stitch */
struct tile *ti_bl; /* Bottom left corner stitch */
struct tile *ti_tr; /* Top right corner stitch */
struct tile *ti_rt; /* Right top corner stitch */
Point ti_ll; /* Lower left coordinate */
ClientData ti_client; /* This space for hire. Warning: the default
* value for this field, to which all users
* should return it when done, is CLNTDEFAULT
* instead of NULL.
*/
} Tile;
/*
* The following macros make it appear as though both
* the lower left and upper right coordinates of a tile
* are stored inside it.
*/
#ifdef HAVE_SYS_MMAN_H
/* This is an on-demand Free List management */
typedef Tile *TileStore;
/* Page size is 4KB so we mmap a segment equal to 64 pages */
#define TILE_STORE_BLOCK_SIZE (4 * 1024 * 64)
#endif /* HAVE_SYS_MMAN_H */
#define BOTTOM(tp) ((tp)->ti_ll.p_y)
#define LEFT(tp) ((tp)->ti_ll.p_x)
#define TOP(tp) (BOTTOM(RT(tp)))
#define RIGHT(tp) (LEFT(TR(tp)))
#define LB(tp) ((tp)->ti_lb)
#define BL(tp) ((tp)->ti_bl)
#define TR(tp) ((tp)->ti_tr)
#define RT(tp) ((tp)->ti_rt)
/* ----------------------- Tile planes -------------------------------- */
/*
* A plane of tiles consists of the four special tiles needed to
* surround all internal tiles on all sides. Logically, these
* tiles appear as below, except for the fact that all are located
* off at infinity.
*
* --------------------------------------
* |\ /|
* | \ / |
* | \ TOP / |
* | \ / |
* | \ / |
* | -------------------------- |
* | | | |
* |LEFT | |RIGHT|
* | | | |
* | -------------------------- |
* | / \ |
* | / \ |
* | / BOTTOM \ |
* | / \ |
* |/ \|
* --------------------------------------
*/
typedef struct
{
Tile *pl_left; /* Left pseudo-tile */
Tile *pl_top; /* Top pseudo-tile */
Tile *pl_right; /* Right pseudo-tile */
Tile *pl_bottom; /* Bottom pseudo-tile */
Tile *pl_hint; /* Pointer to a "hint" at which to
* begin searching.
*/
} Plane;
#define PlaneGetHint(pl) ((pl)->pl_hint)
#define PlaneSetHint(pl, ti) ((pl)->pl_hint = (ti))
/*
* The following coordinate, INFINITY, is used to represent a
* tile location outside of the tile plane.
*
* It must be possible to represent INFINITY+1 as well as
* INFINITY.
*
* Also, because locations involving INFINITY may be transformed,
* it is desirable that additions and subtractions of small integers
* from either INFINITY or MINFINITY not cause overflow.
*
* Consequently, we define INFINITY to be the largest integer
* representable in wordsize - 2 bits.
*/
#undef INFINITY
#define INFINITY ((1 << (8*sizeof (int) - 2)) - 4)
#define MINFINITY (-INFINITY)
/* CLIENTDEFAULT differs from MINFINITY on 64-bit systems, where it */
/* prevents problems arising from MINFINITY being two different values */
/* depending on whether it is cast into a 32 or a 64 bit word. */
#define CLIENTMAX (((pointertype)1 << (8 * sizeof(pointertype) - 2)) - 4)
#define CLIENTDEFAULT INT2CD(-CLIENTMAX)
/* ------------------------ Flags, etc -------------------------------- */
#define BADTILE ((Tile *) -1) /* Invalid tile pointer */
/* ============== Function headers and external interface ============= */
/*
* The following macros and procedures should be all that are
* ever needed by modules other than the tile module.
*/
extern Plane *TiNewPlane(Tile *tile);
extern void TiFreePlane(Plane *plane);
extern void TiToRect(const Tile *tile, Rect *rect);
extern Tile *TiSplitX(Tile *tile, int x);
extern Tile *TiSplitY(Tile *tile, int y);
extern Tile *TiSplitX_Left(Tile *tile, int x);
extern Tile *TiSplitY_Bottom(Tile *tile, int y);
extern void TiJoinX(Tile *tile1, Tile *tile2, Plane *plane);
extern void TiJoinY(Tile *tile1, Tile *tile2, Plane *plane);
extern Tile *TiSrPoint(Tile *hint, Plane *plane, const Point *point);
#define TiBottom(tp) (BOTTOM(tp))
#define TiLeft(tp) (LEFT(tp))
#define TiTop(tp) (TOP(tp))
#define TiRight(tp) (RIGHT(tp))
/*
* For the following to work, the caller must include database.h
* (to get the definition of TileType).
*/
/*
* Non-Manhattan split tiles are defined as follows:
* d = SplitDirection, s = SplitSide
*
* d=1 d=0
* +---+ +---+
* |\XX| | /|
* | \X| | /X| s=1
* | \| |/XX|
* +---+ +---+
* 0x7 0x6
*
* +---+ +---+
* |\ | |XX/|
* |X\ | |X/ | s=0
* |XX\| |/ |
* +---+ +---+
* 0x5 0x4
*
*/
#define TiGetType(tp) ((TileType)(spointertype)((tp)->ti_body) & TT_LEFTMASK)
#define TiGetTypeExact(tp) ((TileType)(spointertype) (tp)->ti_body)
#define SplitDirection(tp) ((TileType)(spointertype)((tp)->ti_body) & TT_DIRECTION ? 1 : 0)
#define SplitSide(tp) ((TileType)(spointertype)((tp)->ti_body) & TT_SIDE ? 1 : 0)
#define IsSplit(tp) ((TileType)(spointertype)((tp)->ti_body) & TT_DIAGONAL ? TRUE : FALSE)
#define SplitLeftType(tp) ((TileType)(spointertype)((tp)->ti_body) & TT_LEFTMASK)
#define SplitRightType(tp) (((TileType)(spointertype)((tp)->ti_body) & TT_RIGHTMASK) >> 14)
#define SplitTopType(tp) (((TileType)(spointertype)((tp)->ti_body) & TT_DIRECTION) ? \
SplitRightType(tp) : SplitLeftType(tp))
#define SplitBottomType(tp) (((TileType)(spointertype)((tp)->ti_body) & TT_DIRECTION) ? \
SplitLeftType(tp) : SplitRightType(tp))
#define TiGetLeftType(tp) SplitLeftType(tp)
#define TiGetRightType(tp) ((IsSplit(tp)) ? SplitRightType(tp) : TiGetType(tp))
#define TiGetTopType(tp) ((IsSplit(tp)) ? SplitTopType(tp) : TiGetType(tp))
#define TiGetBottomType(tp) ((IsSplit(tp)) ? SplitBottomType(tp) : TiGetType(tp))
#define TiGetBody(tp) ((tp)->ti_body)
/* See diagnostic subroutine version in tile.c */
#define TiSetBody(tp, b) ((tp)->ti_body = INT2CD((b)))
#define TiGetClient(tp) ((tp)->ti_client)
#define TiGetClientINT(tp) (CD2INT((tp)->ti_client))
#define TiGetClientPTR(tp) (CD2PTR((tp)->ti_client))
#define TiSetClient(tp,cd) ((tp)->ti_client = (cd))
#define TiSetClientINT(tp,cd) ((tp)->ti_client = INT2CD((cd)))
#define TiSetClientPTR(tp,cd) ((tp)->ti_client = PTR2CD((cd)))
extern Tile *TiAlloc(void);
#ifdef __GNUC_STDC_INLINE__
/* Provide compiler visibility of STDC 'inline' semantics */
#ifdef HAVE_SYS_MMAN_H
extern Tile *TileStoreFreeList;
inline void
TiFree(Tile *tile)
{
tile->ti_client = PTR2CD(TileStoreFreeList);
TileStoreFreeList = tile;
}
#else
/*
* --------------------------------------------------------------------
*
* TiFree ---
*
* Release memory allocation for tiles
*
* Results:
* None.
*
* --------------------------------------------------------------------
*/
inline void
TiFree(Tile *tile)
{
freeMagic((char *)tile);
}
#endif
inline void
TiFreeIf(Tile *tile)
{
if (tile != NULL)
TiFree(tile);
}
inline void
TiFree1(Tile **delay1, Tile *tile)
{
TiFreeIf(*delay1);
*delay1 = tile;
}
inline void
TiJoinX1(Tile **delay1, Tile *tile1, Tile *tile2, Plane *plane)
{
TiFreeIf(*delay1);
TiJoinX(tile1, tile2, plane);
}
inline void
TiJoinY1(Tile **delay1, Tile *tile1, Tile *tile2, Plane *plane)
{
TiFreeIf(*delay1);
TiJoinY(tile1, tile2, plane);
}
#else
/* To support older compilers (that don't auto emit based on -O level) */
extern void TiFree(Tile *tile);
extern void TiFreeIf(Tile *tile);
extern void TiFree1(Tile **delay1, Tile *tile);
extern void TiJoinX1(Tile **delay1, Tile *tile1, Tile *tile2, Plane *plane);
extern void TiJoinY1(Tile **delay1, Tile *tile1, Tile *tile2, Plane *plane);
#endif
#define EnclosePoint(tile,point) ((LEFT(tile) <= (point)->p_x ) && \
((point)->p_x < RIGHT(tile)) && \
(BOTTOM(tile) <= (point)->p_y ) && \
((point)->p_y < TOP(tile) ))
#define EnclosePoint4Sides(tile,point) ((LEFT(tile) <= (point)->p_x ) && \
((point)->p_x <= RIGHT(tile)) && \
(BOTTOM(tile) <= (point)->p_y ) && \
((point)->p_y <= TOP(tile) ))
/* The four macros below are for finding next tile RIGHT, UP, LEFT or DOWN
* from current tile at a given coordinate value.
*
* For example, NEXT_TILE_RIGHT points tResult to tile to right of t
* at y-coordinate y.
*/
#define NEXT_TILE_RIGHT(tResult, t, y) \
for ((tResult) = TR(t); BOTTOM(tResult) > (y); (tResult) = LB(tResult)) \
/* Nothing */;
#define NEXT_TILE_UP(tResult, t, x) \
for ((tResult) = RT(t); LEFT(tResult) > (x); (tResult) = BL(tResult)) \
/* Nothing */;
#define NEXT_TILE_LEFT(tResult, t, y) \
for ((tResult) = BL(t); TOP(tResult) <= (y); (tResult) = RT(tResult)) \
/* Nothing */;
#define NEXT_TILE_DOWN(tResult, t, x) \
for ((tResult) = LB(t); RIGHT(tResult) <= (x); (tResult) = TR(tResult)) \
/* Nothing */;
#define TiSrPointNoHint(plane, point) (TiSrPoint((Tile *) NULL, plane, point))
/*
* GOTOPOINT is used whenever a macroized version of TiSrPoint is
* needed.
*/
#define GOTOPOINT(tp, p) \
{ \
if ((p)->p_y < BOTTOM(tp)) \
do tp = LB(tp); while ((p)->p_y < BOTTOM(tp)); \
else \
while ((p)->p_y >= TOP(tp)) tp = RT(tp); \
if ((p)->p_x < LEFT(tp)) \
do \
{ \
do tp = BL(tp); while ((p)->p_x < LEFT(tp)); \
if ((p)->p_y < TOP(tp)) break; \
do tp = RT(tp); while ((p)->p_y >= TOP(tp)); \
} \
while ((p)->p_x < LEFT(tp)); \
else \
while ((p)->p_x >= RIGHT(tp)) \
{ \
do tp = TR(tp); while ((p)->p_x >= RIGHT(tp)); \
if ((p)->p_y >= BOTTOM(tp)) break; \
do tp = LB(tp); while ((p)->p_y < BOTTOM(tp)); \
} \
}
/* Fill in the bounding rectangle for a tile */
#define TITORECT(tp, rp) \
((rp)->r_xbot = LEFT(tp), (rp)->r_ybot = BOTTOM(tp), \
(rp)->r_xtop = RIGHT(tp), (rp)->r_ytop = TOP(tp))
extern const Rect TiPlaneRect; /* Rectangle large enough to force area
* search to visit every tile in the
* plane. This is the largest rectangle
* that should ever be painted in a plane.
*/
#endif /* _MAGIC__TILES__TILE_H */