magic/database/DBcount.c

169 lines
4.8 KiB
C
Raw Normal View History

/*
* DBcount.c --
*
* Functions to compute statistics on the paint of
* a tree of cells.
*
* *********************************************************************
* * 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. *
* *********************************************************************
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/database/DBcount.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include "utils/magic.h"
#include "utils/hash.h"
#include "utils/geometry.h"
#include "tiles/tile.h"
#include "database/database.h"
#include "database/databaseInt.h"
/*
* ----------------------------------------------------------------------------
*
* DBTreeCountPaint --
*
* Allow the client to compute statistics on the paint in a subtree.
* The client provides three functions: 'count', 'hiercount', and
* 'cleanup', which should be of the following form:
*
* int
* count(def, cdata)
* CellDef *def;
* ClientData cdata;
* {
* }
*
* The 'count' function is applied in a pre-order traversal of the
* cell graph; if it returns 0 then the subcells of 'def' are visited;
* if it returns 1 then the subcells are not visited.
*
* int
* hiercount(parent, uses, child, cdata)
* CellDef *parent, *child;
* int uses; /# Scale factor: number of times child
* # is used by parent
* #/
* ClientData cdata;
* {
* }
*
* The 'hiercount' function is applied in a post-order traversal of
* the cell graph, ie, it is applied only after all children of a
* cell have been visited.
*
* int
* cleanup(def, cdata)
* CellDef *def;
* ClientData cdata;
* {
* }
*
* The 'cleanup' function is applied in a pre-order traversal of the
* cell graph; if it returns 0 then the subcells of 'def' are visited;
* if it returns 1 then the subcells are not visited.
*
* Results:
* None.
*
* Side effects:
* Applies the client procedures as described above.
* The client is free to use each CellDef's cd_client
* field, but should reset this field to zero when the
* cleanup procedure is supplied.
*
* Algorithm:
* We first visit all CellDefs in the tree, applying the
* client's 'count' procedure to each CellDef.
*
* Next, we make a second pass over the cells, applying
* the client's 'hiercount' procedure to each CellDef
* in post-order (ie, the 'hiercount' procedure is first
* applied recursively to all the subtrees of a given
* def before being applied to the def itself).
*
* Finally, we make a pass over all CellDefs and apply
* the client's 'cleanup' procedure.
*
* ----------------------------------------------------------------------------
*/
struct countArg
{
int (*ca_count)();
int (*ca_hiercount)();
ClientData ca_cdata;
};
void
DBTreeCountPaint(def, count, hiercount, cleanup, cdata)
CellDef *def;
int (*count)();
int (*hiercount)();
int (*cleanup)();
ClientData cdata;
{
struct countArg ca;
int dbCountFunc(), dbCountHierFunc();
ca.ca_cdata = cdata;
/* Apply the count procedure to each cell */
ca.ca_count = count;
if ((*count)(def, cdata) == 0)
(void) DBCellEnum(def, dbCountFunc, (ClientData) &ca);
/* Now the hiercount */
ca.ca_hiercount = hiercount;
(void) DBCellEnum(def, dbCountHierFunc, (ClientData) &ca);
/* Now the cleanup */
ca.ca_count = cleanup;
if ((*cleanup)(def, cdata) == 0)
(void) DBCellEnum(def, dbCountFunc, (ClientData) &ca);
}
int
dbCountFunc(use, ca)
CellUse *use;
struct countArg *ca;
{
if ((*ca->ca_count)(use->cu_def, ca->ca_cdata) == 0)
(void) DBCellEnum(use->cu_def, dbCountFunc, (ClientData) ca);
return (0);
}
int
dbCountHierFunc(use, ca)
CellUse *use;
struct countArg *ca;
{
int nx, ny;
(void) DBCellEnum(use->cu_def, dbCountHierFunc, (ClientData) ca);
if (use->cu_xlo > use->cu_xhi)
nx = use->cu_xlo - use->cu_xhi + 1;
else
nx = use->cu_xhi - use->cu_xlo + 1;
if (use->cu_ylo > use->cu_yhi)
ny = use->cu_ylo - use->cu_yhi + 1;
else
ny = use->cu_yhi - use->cu_ylo + 1;
(*ca->ca_hiercount)(use->cu_parent, nx * ny, use->cu_def, ca->ca_cdata);
return (0);
}