/* * DBtechpaint2.c -- * * Default composition rules. * Pretty complicated, unfortunately, so it's in a separate file. * * ********************************************************************* * * 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/DBtpaint2.c,v 1.4 2009/12/30 13:42:33 tim Exp $"; #endif /* not lint */ #include #include #include "utils/magic.h" #include "utils/geometry.h" #include "utils/utils.h" #include "tiles/tile.h" #include "utils/hash.h" #include "database/database.h" #include "database/databaseInt.h" #include "utils/tech.h" #include "textio/textio.h" #define SETPAINT(have,paint,plane,get) \ if (IsDefaultPaint((have), (paint)) \ && TTMaskHasType(&DBPlaneTypes[(plane)], (have))) \ dbSetPaintEntry((have), (paint), (plane), (get)) #define SETERASE(have,erase,plane,get) \ if (IsDefaultErase((have), (erase)) \ && TTMaskHasType(&DBPlaneTypes[(plane)], (have))) \ dbSetEraseEntry((have), (erase), (plane), (get)) LayerInfo *dbTechLpPaint; /* Forward declarations */ extern void dbTechPaintErasePlanes(); extern void dbComposePaintAllImages(); extern void dbComposeResidues(); extern void dbComposeContacts(); extern void dbComposePaintContact(); extern void dbComposeEraseContact(); extern void dbComposeSavedRules(); extern void dbComposeCompose(); extern void dbComposeDecompose(); /* * ---------------------------------------------------------------------------- * * DBTechFinalCompose -- * * Process all the contact erase/compose rules saved by DBTechAddCompose * when it was reading in the "compose" section of a technology file. * Also sets up the default paint/erase rules for contacts. * * Since by the end of this section we've processed all the painting * rules, we initialize the tables that say which planes get affected * by painting/erasing a given type. * * There's a great deal of work done here, so it's broken up into a * number of separate procedures, each of which implements a single * operation or default rule. Most of the work deals with painting * and erasing contacts. * * Results: * None. * * Side effects: * Modifies the paint/erase tables. * Initializes DBTypePaintPlanesTbl[] and DBTypeErasePlanesTbl[]. * * ---------------------------------------------------------------------------- */ void DBTechFinalCompose() { TileType i; TileTypeBitMask testmask, *rMask; /* Default rules for painting/erasing contacts */ dbComposePaintAllImages(); dbComposeResidues(); dbComposeContacts(); /* Process rules saved from reading the "compose" section */ dbComposeSavedRules(); /* Build up exported tables */ dbTechPaintErasePlanes(); /* Adjust paint tables for any locked layers */ for (i = TT_TECHDEPBASE; i < DBNumUserLayers; i++) if (!TTMaskHasType(&DBActiveLayerBits, i)) if (DBIsContact(i)) DBLockContact(i); for (i = DBNumUserLayers; i < DBNumTypes; i++) { rMask = DBResidueMask(i); TTMaskAndMask3(&testmask, &DBActiveLayerBits, rMask); if (!TTMaskEqual(&testmask, rMask)) { TTMaskClearType(&DBActiveLayerBits, i); DBLockContact(i); } } /* Diagnostic */ /* dbTechPrintPaint("DBTechFinalCompose", TRUE, FALSE); */ /* dbTechPrintPaint("DBTechFinalCompose", FALSE, FALSE); */ } /* * ---------------------------------------------------------------------------- * * dbTechPaintErasePlanes -- * * Fill in the tables telling which planes get affected * by painting and erasing. One may take the naive view that only * the planes on which a type is defined can be affected, but then * one can't define arbitrary composite types. * * Results: * None. * * Side effects: * Fills in DBTypePaintPlanesTbl[] and DBTypeErasePlanesTbl[]. * * ---------------------------------------------------------------------------- */ void dbTechPaintErasePlanes() { TileType t, s; int pNum; /* Space tiles are special: they may appear on any plane except router */ DBTypePaintPlanesTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_ROUTER)); DBTypeErasePlanesTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_ROUTER)); /* Skip TT_SPACE */ for (t = 1; t < DBNumTypes; t++) { DBTypePaintPlanesTbl[t] = DBTypeErasePlanesTbl[t] = 0; for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) for (s = 0; s < DBNumTypes; s++) { if (DBStdPaintEntry(s, t, pNum) != s) DBTypePaintPlanesTbl[t] |= PlaneNumToMaskBit(pNum); if (DBStdEraseEntry(s, t, pNum) != s) DBTypeErasePlanesTbl[t] |= PlaneNumToMaskBit(pNum); } } } /* * ---------------------------------------------------------------------------- * * dbComposePaintAllImages -- * * Painting the primary type of a contact layer paints its image * over all types on each image's plane. (The only types that * should ever be painted are primary types.) * * This rule is called first because it may be overridden by later * rules, or by explicit composition rules. * * Only affects paint entries that haven't already been set to other * values by explicit paint rules. * * Results: * None. * * Side effects: * Modifies paint/erase tables. * * ---------------------------------------------------------------------------- */ void dbComposePaintAllImages() { TileType tPaint, s, res; LayerInfo *lp; int p, n; /* Iterate over primary types only */ for (n = 0; n < dbNumContacts; n++) { lp = dbContactInfo[n]; tPaint = lp->l_type; if (tPaint >= DBNumUserLayers) continue; for (res = TT_TECHDEPBASE; res < DBNumTypes; res++) { if (TTMaskHasType(&lp->l_residues, res)) { p = DBPlane(res); for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) if (DBPlane(s) == p) SETPAINT(s, tPaint, p, tPaint); if (IsDefaultPaint(TT_SPACE, tPaint)) dbSetPaintEntry(TT_SPACE, tPaint, p, tPaint); } } } } /* * ---------------------------------------------------------------------------- * * dbComposeResidues -- * * The behavior of a contact type when other, non-contact types are * painted over it or erased from it is derived from the behavior of * its residue types. * * 1. If painting doesn't affect a contact's residue on a plane, * it doesn't affect the contact's image on that plane either. * This allows, for example, painting metal1 over a contact * "containing" metal1 without breaking the contact. * * 2. If painting or erasing a type affects a residue of a * contact, the image's connectivity to adjacent planes * is broken and the image is replaced by the result of * painting or erasing over the residue. * * Results: * None. * * Side effects: * Modifies paint/erase tables. * * ---------------------------------------------------------------------------- */ void dbComposeResidues() { LayerInfo *lp; TileType s, res; int n; /* Painting that doesn't affect the residue doesn't affect the contact. */ for (n = 0; n < dbNumContacts; n++) { lp = dbContactInfo[n]; for (res = TT_TECHDEPBASE; res < DBNumUserLayers; res++) { if (TTMaskHasType(&lp->l_residues, res)) { for (s = TT_TECHDEPBASE; s < DBNumUserLayers; s++) if (!PAINTAFFECTS(res, s)) SETPAINT(lp->l_type, s, DBPlane(res), lp->l_type); } } } } /* * ---------------------------------------------------------------------------- * * dbComposeContacts -- * * This procedure handles the rules for composition of contact types. * We look at the results of painting each type of contact in * dbContactInfo[] over all other contact types. * * Results: * None. * * Side effects: * Modifies paint/erase tables. * * ---------------------------------------------------------------------------- */ void dbComposeContacts() { LayerInfo *lpImage, *lpPaint; int m, pNum; TileTypeBitMask *rmask; TileType n, ttype, itype, presult, eresult; for (m = 0; m < dbNumContacts; m++) { lpImage = dbContactInfo[m]; /* Existing contact image */ for (n = TT_TECHDEPBASE; n < DBNumUserLayers; n++) { lpPaint = &dbLayerInfo[n]; /* Layer being painted or erased */ if (lpImage->l_type != n) dbComposePaintContact(lpImage, lpPaint); dbComposeEraseContact(lpImage, lpPaint); } } /* For stacking types, determine the result of painting or erasing */ /* each stacking type by applying the paint and erase results of */ /* each of its residues in sequence. */ for (itype = 0; itype < DBNumTypes; itype++) { for (n = DBNumUserLayers; n < DBNumTypes; n++) { lpPaint = &dbLayerInfo[n]; /* Layer being painted or erased */ rmask = &lpPaint->l_residues; for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) { presult = eresult = itype; for (ttype = TT_TECHDEPBASE; ttype < DBNumUserLayers; ttype++) if (TTMaskHasType(rmask, ttype)) { presult = DBStdPaintEntry(presult, ttype, pNum); eresult = DBStdEraseEntry(eresult, ttype, pNum); } SETPAINT(itype, n, pNum, presult); SETERASE(itype, n, pNum, eresult); } } } } /* * ---------------------------------------------------------------------------- * dbComposePaintContact -- * * Construct the painting rules for painting type lpPaint over * the contact image lpImage. * ---------------------------------------------------------------------------- */ void dbComposePaintContact(lpImage, lpPaint) LayerInfo *lpImage, *lpPaint; { int pNum; PlaneMask pmask, pshared; LayerInfo *lp; TileTypeBitMask rmask, cmask; TileType newtype, ptype, itype; bool overlap; /* * If the residues of lpImage and lpPaint can be merged without * affecting any of the layers, then we merge them, and look for * any contact matching the merged residues. If none is found, * and the planes do not overlap, then just paint the new * contact. If they cannot be merged, then the original contact * is dissolved and replaced by its residues. */ pmask = lpImage->l_pmask & lpPaint->l_pmask; overlap = (pmask == 0) ? FALSE : TRUE; if (overlap) { for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) { if (PlaneMaskHasPlane(pmask, pNum)) { ptype = DBPlaneToResidue(lpPaint->l_type, pNum); itype = DBPlaneToResidue(lpImage->l_type, pNum); if (ptype != itype) break; } } if (pNum == DBNumPlanes) { /* Residues are compatible; check for a contact type with */ /* the merged residues (explicitly defined stacked contact */ /* type) */ TTMaskZero(&rmask); TTMaskSetMask3(&rmask, &lpImage->l_residues, &lpPaint->l_residues); dbTechMatchResidues(&rmask, &cmask, TRUE); /* Implicitly-defined stacking types override any */ /* explicitly-defined types, or havoc results. */ /* This allows one to create a type such as "pad" */ /* having the same residues as "m123c" without */ /* magic confusing them in the paint tables. */ newtype = DBTechFindStacking(lpImage->l_type, lpPaint->l_type); if (TTMaskIsZero(&cmask) || (newtype != -1)) { /* If there is a stacking contact type, use it */ if (newtype >= DBNumUserLayers) { pshared = lpImage->l_pmask & lpPaint->l_pmask; for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) if (PlaneMaskHasPlane(pshared, pNum)) SETPAINT(lpImage->l_type, lpPaint->l_type, pNum, newtype); } else if (lpPaint->l_isContact && (lpImage->l_type < DBNumUserLayers)) { /* Original contact is replaced by the new one where * the planes overlap, and is dissolved into its * residues where they don't. * In this condition, the residues of image must be * non-contact types. */ for (itype = TT_TECHDEPBASE; itype < DBNumUserLayers; itype++) { if (TTMaskHasType(&lpImage->l_residues, itype)) { if (TTMaskHasType(&lpPaint->l_residues, itype)) { SETPAINT(lpImage->l_type, lpPaint->l_type, DBPlane(itype), lpPaint->l_type); } else { SETPAINT(lpImage->l_type, lpPaint->l_type, DBPlane(itype), itype); } } } } else if (lpPaint->l_isContact && !TTMaskHasType(&lpImage->l_residues, lpPaint->l_type)) { /* Original contact is replaced by the new one where * the planes overlap, and is dissolved into its * residues where they don't. * In this condition, the residues of image are contact * types. */ for (itype = TT_TECHDEPBASE; itype < DBNumUserLayers; itype++) { if (TTMaskHasType(&lpImage->l_residues, itype)) { if (TTMaskHasType(&lpPaint->l_residues, itype)) { SETPAINT(lpImage->l_type, lpPaint->l_type, DBPlane(itype), lpPaint->l_type); } } } } else { /* Painting a residue type on top of a contact */ /* with a compatible residue does nothing, as does */ /* painting one of the types of a stacked contact */ /* on the stacking contact type. In the plane of */ /* the image type, this is non-default behavior. */ SETPAINT(lpImage->l_type, lpPaint->l_type, DBPlane(lpImage->l_type), lpImage->l_type); } } else { /* Presumably there is at most one contact type here */ for (newtype = TT_TECHDEPBASE; newtype < DBNumUserLayers; newtype++) { if (TTMaskHasType(&cmask, newtype)) { lp = &dbLayerInfo[newtype]; for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) if (PlaneMaskHasPlane(lp->l_pmask, pNum)) SETPAINT(lpImage->l_type, lpPaint->l_type, pNum, newtype); break; } } } } else { /* Image and paint types overlap in a plane, but */ /* residues are not compatible. Replace image with the */ /* residues of image, except on the overlapping plane. */ for (ptype = TT_TECHDEPBASE; ptype < DBNumUserLayers; ptype++) if (TTMaskHasType(&lpImage->l_residues, ptype)) if (ptype != itype) SETPAINT(lpImage->l_type, lpPaint->l_type, DBPlane(ptype), ptype); } } else if (lpPaint->l_isContact) { /* No overlapping planes, and both paint & image types are contacts */ TTMaskZero(&rmask); TTMaskSetMask3(&rmask, &lpImage->l_residues, &lpPaint->l_residues); dbTechMatchResidues(&rmask, &cmask, TRUE); if (!TTMaskIsZero(&cmask)) { /* Replace image with the new contact type */ for (newtype = TT_TECHDEPBASE; newtype < DBNumUserLayers; newtype++) { if (TTMaskHasType(&cmask, newtype)) { lp = &dbLayerInfo[newtype]; for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) if (PlaneMaskHasPlane(lp->l_pmask, pNum)) SETPAINT(lpImage->l_type, lpPaint->l_type, pNum, newtype); } } } /* else default paint/erase behavior */ } } /* * ---------------------------------------------------------------------------- * * dbComposeSubsetResidues -- * * Create a mask of all contact types whose residues are subsets * of the "have" type but are not supersets of the "erase" type. * * Results: * True if residues of types in outMask overlap, False if not. * * Side Effects: * outMask is filled with the mask of types. * * ---------------------------------------------------------------------------- */ bool dbComposeSubsetResidues(lpImage, lpErase, outMask) LayerInfo *lpImage, *lpErase; TileTypeBitMask *outMask; { TileTypeBitMask ires; TileTypeBitMask smask, overlapmask; LayerInfo *li; int n; bool rval = FALSE; /* The residues of lpImage must themselves be decomposed if lpImage */ /* is a stacking type. */ TTMaskZero(&ires); if (lpImage->l_type >= DBNumUserLayers) { for (n = 0; n < dbNumContacts; n++) { li = dbContactInfo[n]; if (TTMaskHasType(&lpImage->l_residues, li->l_type)) TTMaskSetMask(&ires, &li->l_residues); } } else TTMaskSetMask(&ires, &lpImage->l_residues); /* * Generate a mask of all contact types whose residue masks are * subsets of the residues of lpImage. These are all types * which contain no residues that are not part of lpImage. */ TTMaskZero(outMask); TTMaskZero(&overlapmask); for (n = 0; n < dbNumContacts; n++) { li = dbContactInfo[n]; TTMaskAndMask3(&smask, &li->l_residues, &ires); if (TTMaskEqual(&smask, &li->l_residues)) { /* The residues of type cannot be a superset of the */ /* residues of the erase type */ TTMaskAndMask3(&smask, &li->l_residues, &lpErase->l_residues); if (!TTMaskEqual(&smask, &lpErase->l_residues)) { TTMaskSetType(outMask, li->l_type); /* Check if the residues of type overlap one of */ /* the types already generated. */ TTMaskAndMask3(&smask, &overlapmask, &li->l_residues); if (TTMaskIsZero(&smask)) TTMaskSetMask(&overlapmask, &li->l_residues); else rval = TRUE; } } } return rval; } /* * ---------------------------------------------------------------------------- * dbComposeEraseContact -- * * Construct the erasing rules for erasing type lpErase from * the contact image lpImage. * ---------------------------------------------------------------------------- */ void dbComposeEraseContact(lpImage, lpErase) LayerInfo *lpImage, *lpErase; { int pNum; PlaneMask pmask; LayerInfo *lp; TileTypeBitMask cmask; TileType itype; bool overlap; /* The erased planes generally end up with space, so we generate */ /* space as default behavior. This may be altered in specific */ /* cases, below. */ /* The specific check for lpImage as a stacking contact is not */ /* necessary, but prevents generation of non-default rules in */ /* cases which cannot occur. */ for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) if (PlaneMaskHasPlane(lpErase->l_pmask, pNum)) if ((lpImage->l_type < DBNumUserLayers) || (pNum == DBPlane(lpImage->l_type))) SETERASE(lpImage->l_type, lpErase->l_type, pNum, TT_SPACE); /* Erasing self should always leave space; otherwise */ /* the "undo" records aren't symmetric, which screws */ /* everything up. */ if (lpImage->l_type == lpErase->l_type) return; /* If planes of HAVE and ERASE types don't overlap, we can erase */ /* the ERASE type without affecting the image, so we're done. */ pmask = lpImage->l_pmask & lpErase->l_pmask; overlap = (pmask == 0) ? FALSE : TRUE; if (!overlap) return; /* Find what contacts are subsets of this one and generate a mask */ /* of the types that might be left over after erasing this one. */ /* If those types overlap, leave the existing type alone. If they */ /* don't, then paint them. */ overlap = dbComposeSubsetResidues(lpImage, lpErase, &cmask); if (overlap) { for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) if (PlaneMaskHasPlane(lpImage->l_pmask, pNum)) // SETERASE(lpImage->l_type, lpErase->l_type, pNum, TT_SPACE); SETERASE(lpImage->l_type, lpErase->l_type, pNum, lpImage->l_type); } else { pmask = lpImage->l_pmask & (~(lpErase->l_pmask)); for (itype = TT_TECHDEPBASE; itype < DBNumTypes; itype++) if (TTMaskHasType(&cmask, itype)) { lp = &dbLayerInfo[itype]; pmask &= ~(lp->l_pmask); for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) if (PlaneMaskHasPlane(lp->l_pmask, pNum)) if ((lpImage->l_type < DBNumUserLayers) || (pNum == DBPlane(lpImage->l_type))) SETERASE(lpImage->l_type, lpErase->l_type, pNum, itype); } /* If there are any planes in the image which have not been */ /* accounted for, then we decompose these into the residues */ /* of the image. */ for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) if (PlaneMaskHasPlane(pmask, pNum)) { itype = DBPlaneToResidue(lpImage->l_type, pNum); SETERASE(lpImage->l_type, lpErase->l_type, pNum, itype); } } /* Diagnostic (to be removed or commented out) */ /* if (!TTMaskIsZero(&cmask)) { TxPrintf("Have %s, Erase %s: ", DBTypeLongNameTbl[lpImage->l_type], DBTypeLongNameTbl[lpErase->l_type]); for (itype = TT_TECHDEPBASE; itype < DBNumTypes; itype++) if (TTMaskHasType(&cmask, itype)) TxPrintf("%s ", DBTypeLongNameTbl[itype]); if (overlap) TxPrintf("overlapping"); TxPrintf("\n"); } */ } /* * ---------------------------------------------------------------------------- * DBLockContact -- * * This procedure modifies the erase tables so that the specified contact * type cannot be erased by erasing one of its residues, which is the default * behavior. * ---------------------------------------------------------------------------- */ void DBLockContact(ctype) TileType ctype; { LayerInfo *lpImage, *lpPaint; TileType c, n, itype, eresult; TileTypeBitMask *rmask; int m, pNum; /* Have type, Erase * --> Result is type */ lpPaint = &dbLayerInfo[ctype]; for (n = TT_TECHDEPBASE; n < DBNumTypes; n++) { if (n == ctype) continue; /* Avoid the case, e.g., if ctype is pc+v, then pc+v - pc = v */ /* is still valid if pc is an active layer. */ if (ctype >= DBNumUserLayers) { rmask = DBResidueMask(ctype); if (TTMaskHasType(rmask, n)) if (TTMaskHasType(&DBActiveLayerBits, n)) continue; } for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) if (PlaneMaskHasPlane(lpPaint->l_pmask, pNum)) SETERASE(ctype, n, pNum, ctype); } } /* * ---------------------------------------------------------------------------- * DBUnlockContact -- * * This procedure reverses the operation of DBLockContact, allowing a contact * to be erased by erasing one of its residues. This is the same code as * dbComposeContacts(), for a single contact type. * ---------------------------------------------------------------------------- */ void DBUnlockContact(ctype) TileType ctype; { LayerInfo *lpImage, *lpPaint; TileType n, itype, eresult; TileTypeBitMask *rmask; int m, pNum; lpImage = &dbLayerInfo[ctype]; for (n = TT_TECHDEPBASE; n < DBNumUserLayers; n++) { lpPaint = &dbLayerInfo[n]; dbComposeEraseContact(lpImage, lpPaint); } /* To be done (maybe): revert rules for stacked contact types */ } /* * ---------------------------------------------------------------------------- * * dbComposeSavedRules -- * * Process all the contact compose/decompose rules saved * when the compose section of the tech file was read. * Each pair on the RHS of one of these rules must contain * exactly one contact type that spans the same set of planes * as the image type. * * Results: * None. * * Side effects: * Modifies entries in the paint and erase tables. * * ---------------------------------------------------------------------------- */ void dbComposeSavedRules() { LayerInfo *lpContact; TileType imageType; TypePair *pair; Rule *rule; int n; for (n = 0; n < dbNumSavedRules; n++) { rule = &dbSavedRules[n]; lpContact = &dbLayerInfo[rule->r_result]; imageType = lpContact->l_type; for (pair = rule->r_pairs; pair < &rule->r_pairs[rule->r_npairs]; pair++) { dbComposeDecompose(imageType, pair->rp_a, pair->rp_b); dbComposeDecompose(imageType, pair->rp_b, pair->rp_a); if (rule->r_ruleType == RULE_COMPOSE) { dbComposeCompose(imageType, pair->rp_a, pair->rp_b); dbComposeCompose(imageType, pair->rp_b, pair->rp_a); } } } } /* * ---------------------------------------------------------------------------- * dbComposeDecompose -- * * Painting componentType over imageType is a no-op. * Erasing componentType from imageType gives either the image of * remainingType, if one exists on DBPlane(imageType), or else * gives the residue of imageType. * * Results: * None. * * Side effects: * Modifies the paint/erase tables as described above. * Indicates that these modifications are not default * rules by setting the corresponding bits in the tables * dbNotDefaultPaintTbl[] and dbNotDefaultEraseTbl[]. * ---------------------------------------------------------------------------- */ void dbComposeDecompose(imageType, componentType, remainingType) TileType imageType; TileType componentType; TileType remainingType; { int pNum = DBPlane(imageType); TileType resultType; /* Painting componentType is a no-op */ dbSetPaintEntry(imageType, componentType, pNum, imageType); TTMaskSetType(&dbNotDefaultPaintTbl[imageType], componentType); /* Which residue belongs to the plane pNum? */ resultType = DBPlaneToResidue(imageType, pNum); /* * Erasing componentType gives remainingType or breaks * imageType's contact. */ dbSetEraseEntry(imageType, componentType, pNum, resultType); TTMaskSetType(&dbNotDefaultEraseTbl[imageType], componentType); } /* * ---------------------------------------------------------------------------- * dbComposeCompose -- * * Painting paintType over existingType gives imageType. * * Results: * None. * * Side effects: * Modifies the paint/erase tables as described above. * Indicates that these modifications are not default * rules by setting the corresponding bits in the tables * dbNotDefaultPaintTbl[] and dbNotDefaultEraseTbl[]. * ---------------------------------------------------------------------------- */ void dbComposeCompose(imageType, existingType, paintType) TileType imageType; TileType existingType; TileType paintType; { int pNum = DBPlane(imageType); if (PlaneMaskHasPlane(LayerPlaneMask(existingType), pNum)) { dbSetPaintEntry(existingType, paintType, pNum, imageType); TTMaskSetType(&dbNotDefaultPaintTbl[existingType], paintType); } }