/****************************************************************************/ 
/*                                                                          */
/*                      ALLIANCE CAO & VLSI CAD                             */
/*                                                                          */
/*    Product : (S)ymbolic (2)to (R)eal translater                          */ 
/*    File    : postreat.c                                                  */ 
/*                                                                          */ 
/*    (c) copyright 1992 MASI laboratory CAO & VLSI team                    */ 
/*    All Right Reserved                                                    */ 
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */ 
/*                                                                          */ 
/****************************************************************************/
/*                                                                          */
/*                     Post treatement functions                            */
/*                                                                          */
/****************************************************************************/
/* fonction void couron_layer ()                                            */
/* ATTENTION! dx et dy ne sont pas les longueurs mais les positions hautes  */
/*            et droites des couronnes dans couronne[]                      */
/****************************************************************************/

#include "generic.h"
#include  MPH_H
#include  MUT_H
#include  RDS_H
#include  RPR_H
#include  RFM_H
#include "rdsacces+.h"
#include "postrat.h"

/*************************************************************************
 * resize_layer : extends the sides of all the rectangles in the specified
 *                layer in the specified model by the amount "qty" at each 
 *                extreme.
 *************************************************************************/
void resize_layer( model, layer_num)
rdsfig_list   *model;
char  layer_num;
{
rdsrec_list       * rectp;
long            qty;  /* given in rds_unit */

  qty = GET_S2R_OVERSIZE( layer_num);

  for ( rectp         = model ->LAYERTAB[layer_num];
        rectp;  
        rectp         = rectp ->NEXT) {
    (long) rectp ->X  -= qty ;
    (long) rectp ->Y  -= qty ;
    (long) rectp ->DX += 2 * qty ;
    (long) rectp ->DY += 2 * qty ;
  }
}

/*****************************************************************************
 * inv_resize_layer : minimizes the sides of all the rectangles in the specified
 *                    layer in the specified model by the amount "qty" at each 
 *                    extreme.
 *****************************************************************************/
void inv_resize_layer( model, layer_num)
rdsfig_list   *model;
char  layer_num;
{
rdsrec_list       * rectp;
long            qty;  /* given in rds_unit */

  qty = GET_S2R_OVERSIZE( layer_num);

  for ( rectp = model ->LAYERTAB[layer_num];  
        rectp ;  
        rectp = rectp ->NEXT) {
    (long) rectp ->X  += qty ;
    (long) rectp ->Y  += qty ;
    (long) rectp ->DX -= 2 * qty ;
    (long) rectp ->DY -= 2 * qty ;
  }
}

/******************************************************************************
 * adjust_rectangle: adjusts the data of the rectangle considering the symmetry
 *                   of the instance containning it.
 *                   The given symmetry might be different from the symmetry 
 *                   of the instance in its father ( the case of several 
 *                   hierarchical levels).
 *                   This function is used when copying the rectangle in higher 
 *                   hierarchical level.
 *****************************************************************************/
void adjust_rectangle( x, y, dx, dy, xins, yins, sym)
long  *x, *y, *dx, *dy;
long  xins, yins;
char  sym;
{
long  tx, ty, tdx, tdy;

tx = *x;
ty = *y;
tdx = *dx;
tdy = *dy;

  switch ( sym) {
  case NOSYM:
    *x += xins ;
    *y += yins;
    break;
  case SYM_X:
    *x  = xins - tx - tdx;
    *y += yins;
    break;
  case SYM_Y:
    *x += xins ;
    *y  = yins - ty - tdy;
    break;
  case SYMXY:
    *x  = xins - tx - tdx;
    *y  = yins - ty - tdy;
    break;
  case ROT_P:
    *x  = xins - ty - tdy;
    *y  = yins + tx;
    *dx = tdy;
    *dy = tdx;
    break;
  case ROT_M:
    *x  = xins + ty;
    *y  = yins - tx - tdx;
    *dx = tdy;
    *dy = tdx;
    break;
  case SY_RP:
    *x = xins + ty;
    *y = yins + tx;
    *dx = tdy;
    *dy = tdx;
    break;
  case SY_RM:
    *x = xins - ty - tdy;
    *y = yins - tx - tdx;
    *dx = tdy;
    *dy = tdx;
    break;
  default:
    (void) fprintf(stderr, 
           "**post_trat**adj_rect:unknown symetry number %d\n", 
           sym);
    exit(1);
  }
}

/******************************************************************************
 * readjust_rectangle: adjusts the data of the rectangle considering the 
 *                     symmetry of the instance that will contain it.
 *                     The given symmetry might be different from the symmetry 
 *                     of the instance in its father ( the case of several 
 *                     hierarchical levels).
 *                     This function is used when copying the rectangle in lower
 *                     hirerichal level.
 *****************************************************************************/
void readjust_rectangle( x, y, dx, dy, xins, yins, sym)
long  *x, *y, *dx, *dy;
long  xins, yins;
char  sym;
{
long  tx, ty, tdx, tdy;

  tx = *x;
  ty = *y;
  tdx = *dx;
  tdy = *dy;
  switch ( sym) {
  case NOSYM:
    *x -= xins ;
    *y -= yins;
    break;
  case SYM_X:
    *x  = xins - tx - tdx;
    *y -= yins;
    break;
  case SYM_Y:
    *x -= xins ;
    *y  = yins - ty - tdy;
    break;
  case SYMXY:
    *x  = xins - tx - tdx;
    *y  = yins - ty - tdy;
    break;
  case ROT_P:
    *x  = ty - yins;
    *y  = xins - tdx - tx;
    *dx = tdy;
    *dy = tdx;
    break;
  case ROT_M:
    *x = yins - tdy - ty;
    *y = tx - xins;
    *dx = tdy;
    *dy = tdx;
    break;
  case SY_RP:
    *x = ty - yins;
    *y = tx - xins;
    *dx = tdy;
    *dy = tdx;
    break;
  case SY_RM:
    *x = yins - tdy - ty;
    *y = xins - tdx - tx;
    *dx = tdy;
    *dy = tdx;
    break;
  default:
    (void) fprintf(stderr, 
           "**post_trat**readj_rect:unknown symetry number %d\n",
           sym);
    exit(1);
  }
}

/******************************************************************************
 * result_sym: gives the result of 2 successive symmetry.
 *****************************************************************************/
char  result_sym( first_sym, second_sym)
char  first_sym, second_sym;
{
  switch ( first_sym) {
  case NOSYM:
    switch ( second_sym) {
    case NOSYM: return( NOSYM);
    case SYM_X: return( SYM_X);
    case SYM_Y: return( SYM_Y);
    case SYMXY: return( SYMXY);
    case ROT_P: return( ROT_P);
    case ROT_M: return( ROT_M);
    case SY_RP: return( SY_RP);
    case SY_RM: return( SY_RM);
    default:
      (void) fprintf(stderr, 
             "**post_trat**result_sym:unknown symetry number %d\n", 
             second_sym);
      exit(1);
    }
  case SYM_X:
    switch ( second_sym) {
    case NOSYM: return( SYM_X);
    case SYM_X: return( NOSYM);
    case SYM_Y: return( SYMXY);
    case SYMXY: return( SYM_Y);
    case ROT_P: return( SY_RM);
    case ROT_M: return( SY_RP);
    case SY_RP: return( ROT_M);
    case SY_RM: return( ROT_P);
    default:
      (void) fprintf(stderr, 
             "**post_trat**result_sym:unknown symetry number %d\n", 
             second_sym);
      exit(1);
    }
  case SYM_Y:
    switch ( second_sym) {
    case NOSYM: return(SYM_Y);
    case SYM_X: return(SYMXY);
    case SYM_Y: return(NOSYM);
    case SYMXY: return(SYM_X);
    case ROT_P: return(SY_RP);
    case ROT_M: return(SY_RM);
    case SY_RP: return(ROT_P);
    case SY_RM: return(ROT_M);
    default:
      (void) fprintf(stderr, 
             "**post_trat**result_sym:unknown symetry number %d\n", 
             second_sym);
      exit(1);
    }
  case SYMXY:
    switch ( second_sym) {
    case NOSYM: return(SYMXY);
    case SYM_X: return(SYM_Y);
    case SYM_Y: return(SYM_X);
    case SYMXY: return(NOSYM);
    case ROT_P: return(ROT_M);
    case ROT_M: return(ROT_P);
    case SY_RP: return(SY_RM);
    case SY_RM: return(SY_RP);
    default:
      (void) fprintf(stderr, 
             "**post_trat**result_sym:unknown symetry number %d\n", 
             second_sym);
      exit(1);
    }
  case ROT_P:
    switch ( second_sym) {
    case NOSYM: return(ROT_P);
    case SYM_X: return(SY_RP);
    case SYM_Y: return(SY_RM);
    case SYMXY: return(ROT_M);
    case ROT_P: return(SYMXY);
    case ROT_M: return(NOSYM);
    case SY_RP: return(SYM_Y);
    case SY_RM: return(SYM_X);
    default:
      (void) fprintf(stderr, 
             "**post_trat**result_sym:unknown symetry number %d\n", 
             second_sym);
      exit(1);
    }
  case ROT_M:
    switch ( second_sym) {
    case NOSYM: return(ROT_M);
    case SYM_X: return(SY_RM);
    case SYM_Y: return(SY_RP);
    case SYMXY: return(ROT_P);
    case ROT_P: return(NOSYM);
    case ROT_M: return(SYMXY);
    case SY_RP: return(SYM_X);
    case SY_RM: return(SYM_Y);
    default:
      (void) fprintf(stderr, 
             "**post_trat**result_sym:unknown symetry number %d\n", 
             second_sym);
      exit(1);
    }
  case SY_RP:
    switch ( second_sym) {
    case NOSYM: return(SY_RP);
    case SYM_X: return(ROT_P);
    case SYM_Y: return(ROT_M);
    case SYMXY: return(SY_RM);
    case ROT_P: return(SYM_X);
    case ROT_M: return(SYM_Y);
    case SY_RP: return(NOSYM);
    case SY_RM: return(SYMXY);
    default:
      (void) fprintf(stderr, 
             "**post_trat**result_sym:unknown symetry number %d\n", 
             second_sym);
      exit(1);
    }
  case SY_RM:
    switch ( second_sym) {
    case NOSYM: return(SY_RM);
    case SYM_X: return(ROT_M);
    case SYM_Y: return(ROT_P);
    case SYMXY: return(SY_RP);
    case ROT_P: return(SYM_Y);
    case ROT_M: return(SYM_X);
    case SY_RP: return(SYMXY);
    case SY_RM: return(NOSYM);
    default:
      (void) fprintf(stderr, 
             "**post_trat**result_sym:unknown symetry number %d\n", 
             second_sym);
      exit(1);
    }
  default:
    (void) fprintf(stderr, 
           "**post_trat**result_sym:unknown symetry number %d\n", 
           first_sym);
    exit(1);
  }
  return(NOSYM);
}

/*****************************************************************************
 * flatten_instance_layer: copies to the given layer_tail, all the segments 
 *                         in the given instance that intersect the couron of
 *                         the given ancetre, using the given father_sym
 *                         to compose the resulting symmetry of the instance
 *                         in the ancetre.
 *                         The segments of the sons instances are copied also
 *                         as it is a recursive function.
 ******************************************************************************/
void flatten_instance_layer( instance, ancetre, comp_sym, origin_x, origin_y, layer_tail, layer_num)
rdsins_list *instance;        /* instance where there is rectangles to flatten */
rdsins_list *ancetre;         /* first instance where the ring is defined */
char  comp_sym;           /* symetry comp of instances without the first */
long  origin_x, origin_y; /* origin comp of instances without the first */
rds_rectanglep_typ *layer_tail;
char  layer_num;
{
rdsfig_list * modelp;
rdsins_list * instancef;
long      nx, ny, ndx, ndy;
long      dummy1, dummy2;
long      new_origin_x, new_origin_y;
rdsrec_list * rectp;

  modelp = rds_model_out( instance ->FIGNAME);

  dummy1 = 0l;
  dummy2 = 0l;
  new_origin_x = origin_x;
  new_origin_y = origin_y;
  origin_x = instance->X;
  origin_y = instance->Y;
  adjust_rectangle( &origin_x, &origin_y, &dummy1, &dummy2,  
                    new_origin_x, new_origin_y, comp_sym);
  comp_sym = result_sym( instance->TRANSF, comp_sym);

  for (  instancef = modelp->INSTANCE;  
         instancef;  
         instancef = instancef->NEXT )
    flatten_instance_layer( instancef,  ancetre,   comp_sym,  
                            origin_x, origin_y, layer_tail,  layer_num);

  for ( rectp = modelp ->LAYERTAB[layer_num];  rectp;  rectp = rectp ->NEXT ) {
    if ( IsRdsConExter( rectp ) )  continue;
    if (   IsRdsRefRef( rectp ) ) continue;
    if (   IsRdsRefCon( rectp ) ) continue;

    nx = rectp ->X;
    ny = rectp ->Y;
    ndx = rectp ->DX;
    ndy = rectp ->DY;

    adjust_rectangle( &nx,  &ny,  &ndx,  &ndy,  origin_x,  origin_y,  comp_sym);
    if(( nx         <= ancetre->COURONNE[layer_num]->X) 
    || (  ny        <= ancetre->COURONNE[layer_num]->Y)
    || (( nx + ndx) >= ancetre->COURONNE[layer_num]->DX) 
    || (( ny + ndy) >= ancetre->COURONNE[layer_num]->DY) ) {

      adjust_rectangle(&nx,  &ny,  &ndx,  &ndy,  
                       ancetre->X,  ancetre->Y,  ancetre->TRANSF);

      *layer_tail = rds_rectangle_in( *layer_tail,  nx,  ny,  ndx,  ndy,  
                                      layer_num, rectp->FLAGS, NULL );
      mark_flattenres( *layer_tail);
    }
  }
}

/******************************************************************************
 * flatten_layer: copies from: all the instances in the specified model in the
 *                             the specified layer any rectangle that intersects
 *                             the couron of the instance or even touches it.
 *                         to: the list of rectangles of the specified model in
 *                             th specified layer.
 *                A flattened rectangle is marked (flattened) so that if it is 
 *                not used in the merging stage, it will be removed in the 
 *                cleanning stage. 
 *                remark: if there is more than 2 hierarchical levels, there
 *                will be a call to the flatten_instance_layer() function.
 *****************************************************************************/
void flatten_layer( model, layer_num)
rdsfig_list *model;
char  layer_num;
{
rdsins_list * instance, *instancef;
rdsrec_list * rectp;
rds_rectanglep_typ * layer_tail;
rdsfig_list * modelp;
long  nx, ny, ndx, ndy;

  /* get the tail of the list of segments of the model */
  for ( rectp = model ->LAYERTAB[ layer_num];  
        (rectp && rectp ->NEXT);  
        rectp = rectp ->NEXT ) 
    ;
  if ( rectp)
    layer_tail = &(rectp ->NEXT);
  else
    layer_tail = &(model ->LAYERTAB[ layer_num]);

  for ( instance = model ->INSTANCE;  
        instance;  
        instance = instance->NEXT) {
    modelp = rds_model_out( instance ->FIGNAME);
    if (incataloggds(instance ->FIGNAME)) 
      continue;
    /* flatten lower levels of the hierarchy */
    for ( instancef = modelp->INSTANCE;  
          instancef;  
          instancef = instancef->NEXT)
      flatten_instance_layer( instancef,  instance,   
                              NOSYM, /* no symetry for the model */
                              0l, 0l,  layer_tail, layer_num);

    /* flatten the instances of the model */
    for ( rectp = modelp ->LAYERTAB[layer_num];  
          rectp;  
          rectp = rectp ->NEXT ) {
      nx = rectp ->X;
      ny = rectp ->Y;
      ndx = rectp ->DX;
      ndy = rectp ->DY;
      if (   ( nx <= instance->COURONNE[layer_num]->X) 
      || ( ny <= instance->COURONNE[layer_num]->Y) 
      || (( nx + ndx) >= instance->COURONNE[layer_num]->DX) 
      || (( ny + ndy) >= instance->COURONNE[layer_num]->DY)) {
        adjust_rectangle( &nx,  &ny,  &ndx,  &ndy,  
                          instance->X,  instance->Y,  instance->TRANSF);
        *layer_tail = rds_rectangle_in( *layer_tail,  nx,  ny,  ndx,  ndy,  
                                         layer_num, rectp->FLAGS, NULL );
        mark_flattenres( *layer_tail);
      }
    }
  }
}

/*****************************************************************************
 * envelop_layer: defines the envelop of the specified model in the specified 
 *                layer.
 *                i.e. the minimum rectangle that contains all the rectangles
 *                and all the envelops of all instances of the specified model
 *                in the specified layer.
 *                This function as it takes into consideration the envelops
 *                of the instances of the model it must be applied to the
 *                instances before the father model; what is done implicitly
 *                by the post_treat function.
 *                This function once applied on a model at a layer, marks that
 *                model enveloped at that layer.
 *                If the model at that layer does not contain any rectangles,
 *                it is marked empty at that layer.
 ****************************************************************************/
void envelop_layer( model, layer_num)
rdsfig_list *model;
char  layer_num;
{
rdsfig_list * modelp;
rdsins_list * instancep;
long  lx, ly, gx, gy;
rdsrec_list * rectp;
char  init = 0;
long  nx, ny, ndx, ndy;

  /* printf("envelop %d\n",layer_num); */

  /* segments of the model */
  if ( model->LAYERTAB[ layer_num]) {
    lx =    model->LAYERTAB[ layer_num]->X;
    ly =    model->LAYERTAB[ layer_num]->Y;
    gx =    model->LAYERTAB[ layer_num]->X  + model->LAYERTAB[ layer_num]->DX;
    gy =    model->LAYERTAB[ layer_num]->Y  + model->LAYERTAB[ layer_num]->DY;
    init = 1;
    for ( rectp = model->LAYERTAB[ layer_num];  rectp;  rectp = rectp->NEXT) {
      if ( rectp->X < lx)
        lx = rectp->X;
      if ( rectp->Y < ly)
        ly = rectp->Y;
      if ( ( rectp->X + rectp->DX) > gx)
        gx = rectp->X + rectp->DX;
      if ( ( rectp->Y + rectp->DY) > gy)
        gy = rectp->Y + rectp->DY;
    }
  }
  /* envelops of the instances of the model */
  for ( instancep = model ->INSTANCE;  instancep;  instancep = instancep ->NEXT) {
    modelp = rds_model_out( instancep ->FIGNAME);
    if (    !( is_empty(modelp, layer_num)) 
    &&      !( incataloggds(instancep ->FIGNAME))) {
      rectp = modelp->BBOXTAB[ layer_num];
      nx = rectp ->X;
      ny = rectp ->Y;
      ndx = rectp ->DX;
      ndy = rectp ->DY;
      adjust_rectangle( &nx,  &ny,  &ndx,  &ndy,  
                        instancep->X,  instancep->Y,  instancep->TRANSF);
      if ( init) {
        if ( nx < lx)
          lx = nx;
        if ( ny < ly)
          ly = ny;
        if ( ( nx + ndx) > gx)
          gx = nx + ndx;
        if ( ( ny + ndy) > gy)
          gy = ny + ndy;
      } else {
        lx = nx;
        ly = ny;
        gx = nx + ndx;
        gy = ny + ndy;
        init = 1;
      }
    }
  }
  if ( init)
    model->BBOXTAB[ layer_num] = 
        rds_rectangle_in( model->BBOXTAB[ layer_num], lx,  ly,  
                          gx - lx,  gy - ly, layer_num, NULL );
  else
    mark_empty( model, layer_num);
}

/*****************************************************************************
 * mod_ins_couron: given an instance, a layer and the rectangle of intersection
 *                 of this instance with another instance; it modifies the 
 *                 couron of this instance in that layer if the rectangle of
 *                 intersection makes the couron wider at any side.
 *****************************************************************************/
void mod_ins_couron( instance, layer_num, xi, yi, dxi, dyi)
rdsins_list       *instance;
char  layer_num;
long  xi,  yi,   dxi,  dyi;
{
rdsfig_list       * model;
long  corn_width,  xe,  ye,  dxe,  dye;

  model          = rds_model_out( instance ->FIGNAME);

  corn_width     = GET_S2R_RING_WIDTH( layer_num)
                 + GET_S2R_LAYER_WIDTH( layer_num) / 2;
  xe             = model->BBOXTAB[layer_num]->X;
  ye             = model->BBOXTAB[layer_num]->Y;
  dxe            = model->BBOXTAB[layer_num]->DX;
  dye            = model->BBOXTAB[layer_num]->DY;

  readjust_rectangle ( &xi,  &yi,  &dxi,  &dyi,  
                       instance->X,  instance->Y,  instance->TRANSF );

  if ( ( xi - xe) > ( ( xe + dxe) - ( xi + dxi))) {
    if ( (xi - corn_width) < instance->COURONNE[ layer_num]->DX)
      instance->COURONNE[ layer_num]->DX = xi - corn_width;
  } else if ( (xi + dxi + corn_width) > instance->COURONNE[ layer_num]->X)
    instance->COURONNE[ layer_num]->X = xi + dxi + corn_width;

  if ( ( yi - ye) > ( ( ye + dye) - ( yi + dyi))) {
    if ( (yi - corn_width) < instance->COURONNE[ layer_num]->DY)
      instance->COURONNE[ layer_num]->DY = yi - corn_width;
  } else if ( (yi + dyi + corn_width) > instance->COURONNE[ layer_num]->Y)
    instance->COURONNE[ layer_num]->Y = yi + dyi + corn_width;
}

/*****************************************************************************
 * couron_layer: defines the courons of every instance in the specified model 
 *               in the specified layer.
 *               The couron is determined by 4 limits: x, y, dx 
 *               and dy beyond which is the couron area.
 * ATTENTION! dx et dy ne sont pas les longueurs mais les positions hautes 
 *            et droites des couronnes dans couronne[]
 ****************************************************************************/
void couron_layer( model, layer_num, verbose)
rdsfig_list *model;
char  layer_num;
int verbose;
{
register rdsins_list *instance1, *instance2;
long  x1, x2, y1, y2, dx1, dx2, dy1, dy2, rx, rdx, ry, rdy;
register rdsfig_list *model1, *model2;
long  corn_width;
long  dot=0, nb_inst=0, prc=0, new_prc=0, iteration, first=1;

  corn_width     = GET_S2R_RING_WIDTH( layer_num)
                 + GET_S2R_LAYER_WIDTH( layer_num) / 2;

/*\
 * initial couron based on the abutment box and the envelop 
\*/
  for ( instance1 = model->INSTANCE, nb_inst=0;  
        instance1;  
        instance1 = instance1->NEXT, nb_inst++ ) {
    model1 = rds_model_out( instance1 ->FIGNAME);
    if (incataloggds(instance1 ->FIGNAME)) 
      continue;
/*\
 * allocation d'une structure rectancle pour la couronne[layer_num] 
\*/
    instance1->COURONNE[ layer_num] = (rdsrec_list * ) mbkalloc(sizeof(rdsrec_list));

    instance1->COURONNE[layer_num]->DY = model1->LAYERTAB[RDS_ABOX]->Y  
                                       + model1->LAYERTAB[RDS_ABOX]->DY  
                                       - corn_width;

    instance1->COURONNE[layer_num]->Y  = model1->LAYERTAB[RDS_ABOX]->Y 
                                       + corn_width;

    instance1->COURONNE[layer_num]->DX = model1->LAYERTAB[RDS_ABOX]->X  
                                       + model1->LAYERTAB[RDS_ABOX]->DX 
                                       - corn_width;

    instance1->COURONNE[layer_num]->X  = model1->LAYERTAB[RDS_ABOX]->X  
                                       + corn_width;

    if ( !is_empty( model1, layer_num)) {
      if ( instance1->COURONNE[layer_num]->DY >   
         (   model1->BBOXTAB[layer_num]->Y  
           + model1->BBOXTAB[layer_num]->DY 
           - corn_width                        ) ) {
        instance1->COURONNE[layer_num]->DY = model1->BBOXTAB[layer_num]->Y  
                                           + model1->BBOXTAB[layer_num]->DY 
                                           - corn_width;
      }
      if ( instance1->COURONNE[layer_num]->Y  <   
         (   model1->BBOXTAB[layer_num]->Y  
           + corn_width                       ) ) {
        instance1->COURONNE[layer_num]->Y = model1->BBOXTAB[layer_num]->Y  
                                          + corn_width;
      }
      if ( instance1->COURONNE[layer_num]->DX >   
         (   model1->BBOXTAB[layer_num]->X  
           + model1->BBOXTAB[layer_num]->DX 
           - corn_width                        ) ) {
        instance1->COURONNE[layer_num]->DX = model1->BBOXTAB[layer_num]->X  
                                           + model1->BBOXTAB[layer_num]->DX 
                                           - corn_width;
      }
      if ( instance1->COURONNE[layer_num]->X  <   
         (   model1->BBOXTAB[layer_num]->X  
           + corn_width                      ) ) {
        instance1->COURONNE[layer_num]->X = model1->BBOXTAB[layer_num]->X  
                                         	+ corn_width;
      }
    }
  }

/*\
 * final couron based on instance intersections 
\*/
  for ( instance1 = model ->INSTANCE, iteration=0;  
        instance1;  
        instance1 = instance1 ->NEXT, iteration++) {
    model1 = rds_model_out( instance1 ->FIGNAME);


    if (incataloggds(instance1 ->FIGNAME))
      continue;

    if (verbose) {
      if (first) {
        printf("\t    . %s ",RDS_LAYER_NAME[layer_num]); 
        first = 0;
      }
      new_prc  = (iteration*100/nb_inst) / 3; /* one dot each 3% */
      if (new_prc > prc) {
	dot++;
	printf("."); 
	fflush( stdout);
        prc=new_prc;
      }
    }

    if ( !( is_empty(model1, layer_num))) {
      x1    = model1->BBOXTAB[ layer_num]->X;
      y1    = model1->BBOXTAB[ layer_num]->Y;
      dx1   = model1->BBOXTAB[ layer_num]->DX;
      dy1   = model1->BBOXTAB[ layer_num]->DY;

      adjust_rectangle( &x1,  &y1,  &dx1,  &dy1,  
                        instance1->X,  instance1->Y,  instance1->TRANSF);

      for (instance2 = instance1->NEXT;  
           instance2;  
           instance2 = instance2->NEXT) {
        model2 = rds_model_out( instance2 ->FIGNAME);

        if (incataloggds(instance2 ->FIGNAME)) {
          continue;
        }

        if ( !( is_empty(model2, layer_num))) {
          x2    = model2->BBOXTAB[ layer_num]->X;
          y2    = model2->BBOXTAB[ layer_num]->Y;
          dx2   = model2->BBOXTAB[ layer_num]->DX;
          dy2   = model2->BBOXTAB[ layer_num]->DY;

          adjust_rectangle( &x2,  &y2,  &dx2,  &dy2,  
                            instance2->X,  instance2->Y,  instance2->TRANSF);

          if (rect_intersec( x1, x2,  dx1, dx2,   
                             y1, y2,  dy1, dy2,  &rx, &rdx,  &ry, &rdy   )) {
            mod_ins_couron( instance1,  layer_num,  rx,  ry,  rdx,  rdy);
            mod_ins_couron( instance2,  layer_num,  rx,  ry,  rdx,  rdy);
          }
        }
      }
    }
  }
  if (verbose && !first ) {
    for(;dot<33;dot++)printf(".");printf("\n");fflush( stdout);
  }

}

/******************************************************************************
 * envelop: envelops the post_treatable layers of the given model.
 *****************************************************************************/
void envelop( model)
rdsfig_list *model;
{
char  layer_num;

  for ( layer_num = 0;  layer_num < RDS_MAX_LAYER;  layer_num++) {

    if ( GET_S2R_POST_Y_OR_N ( layer_num ) == S2R_TREAT) { 
      envelop_layer( model, layer_num);
    }
  }
}

/******************************************************************************
 * couron: courons the post_treatable layers of the given model.
 *****************************************************************************/
void couron( model, verbose)
rdsfig_list *model;
int verbose;
{
char  layer_num;

  for ( layer_num = 0;  layer_num < RDS_MAX_LAYER;  layer_num++) {
    /* if ( GET_S2R_POST_Y_OR_N ( layer_num ) == S2R_TREAT) { */
    if ( GET_S2R_RING_WIDTH( layer_num) != 0 ) {
      couron_layer( model, layer_num, verbose);
    }
  }
}

/******************************************************************************
 * flatten: flattens the post_treatable layers of the model.
 *****************************************************************************/
void flatten( model)
rdsfig_list *model;
{
  char  layer_num;

  for ( layer_num = 0;  layer_num < RDS_MAX_LAYER;  layer_num++) {

    if ( GET_S2R_RING_WIDTH( layer_num) != 0 ) {
    /* if ( GET_S2R_POST_Y_OR_N ( layer_num ) == S2R_TREAT) { */
      flatten_layer( model, layer_num);
    }
  }
}

/******************************************************************************
 * resize: oversize all post_treatable layers of the model
 *****************************************************************************/
void resize( model)
rdsfig_list *model;
{
char  layer_num;

  for ( layer_num = 0;  layer_num < RDS_MAX_LAYER;  layer_num++) {

    if ( GET_S2R_POST_Y_OR_N (layer_num) == S2R_TREAT) {
      resize_layer( model, layer_num);
    }
  }
}

/******************************************************************************
 * merge: merges all post_treatable layers of the model.
 *        If the layer to be merged is of the type that needs scotchs 
 *        ( indicated by having a complementary layer in its postreat table), 
 *        merge_layer_2() will be called instead of merge_layer().
 *****************************************************************************/
void merge ( model, scotch_on_flag, verbose)
rdsfig_list *model;
int  scotch_on_flag, verbose;
{
char  layer_num;

  for ( layer_num = 0;  layer_num < RDS_MAX_LAYER;  layer_num++) {

    if ( GET_S2R_POST_Y_OR_N ( layer_num) == S2R_TREAT) {
      if ( (GET_S2R_POST_COMPLEMENTARY(layer_num) != RDS_S2R_POST_TREAT_EMPTY )
         && scotch_on_flag) {
        merge_layer_2( model, layer_num, verbose);
      } else {
        merge_layer( model, layer_num, verbose);
      }
    }
  }
}

/******************************************************************************
 * clean: cleans all post_treatable layers.
 *****************************************************************************/
void clean( model)
rdsfig_list *model;
{
char  layer_num;

  for ( layer_num = 0;  layer_num < RDS_MAX_LAYER;  layer_num++) {

    if ( GET_S2R_POST_Y_OR_N (layer_num) == S2R_TREAT) {
      rds_clean_layer( &( model->LAYERTAB[layer_num]));
    }
  }
}

/******************************************************************************
 * inv_resize: undersizes all post_treatable layers. 
 *****************************************************************************/
void inv_resize( model)
rdsfig_list *model;
{
char  layer_num;

  for ( layer_num = 0;  layer_num < RDS_MAX_LAYER;  layer_num++) {

    if ( GET_S2R_POST_Y_OR_N ( layer_num) == S2R_TREAT) {
      inv_resize_layer( model, layer_num);
    }
  }
}

/*****************************************************************************
 * post_treat: post_treats the specified model.
 *             After completion it marks this model at this layer post_treated. 
 *             This is a recursive function: if an instance of this model
 *             has its model not yet post treated at this layer, it is
 *             post treated first.
 ****************************************************************************/
void post_treat( model, scotch_on_flag, verbose)
rdsfig_list * model;
int       scotch_on_flag;
int       verbose;
{
  rdsins_list * instance;
  rdsfig_list * modelp;

  for ( instance = model->INSTANCE;  instance;  instance = instance->NEXT) {
    modelp = rds_model_out( instance->FIGNAME);

    if ( ! modelp->FLAGS && ! incataloggds(modelp->NAME) ) {
      post_treat( modelp, scotch_on_flag, verbose);
    }
  }
  if(verbose)
    printf("\t--> post-treating model %s\n", model->NAME);
  if(verbose && model->INSTANCE) { 
    printf("\t    ring flattenning  : \n"); fflush( stdout); 
  }
  envelop     ( model);
  couron      ( model, verbose);
  flatten     ( model);
  resize      ( model);
  if(verbose) { printf("\t    rectangle merging : \n"); fflush( stdout); }
  merge       ( model, scotch_on_flag, verbose);
  clean       ( model);
  inv_resize  ( model);
  mark_treat  ( model);

}

/*******************************************************************************
 * replace_cells: traverses the list of models and replaces the models that are 
 *                found in the gds catalog by the corresponding models parsed 
 *                from this catalog.
 *                remarks:
 ******************************************************************************/
void replace_cells(verbose)
int verbose;
{
  rdsfig_list * model, * model_next;
  int         error;
  static      not_print_yet=1; 

  for ( model = HEAD_RDSFIG;  model;) {
    model_next = model->NEXT;
    if ( incataloggds( model->NAME)) {
      if (not_print_yet) {
        printf("\to replacing black boxes\n");
	not_print_yet=0;
      }
      if(verbose)
        printf("\t--> replace cell %s \n", model->NAME);
      delrdsfig( model->NAME );
      (void)getrdsfig( model->NAME, 'A', 0 );
    }
    model = model_next;
  }
}
