Exemple #1
0
/* ---------------------------------------------------------------------------
 * moves an element
 */
static void *
MoveElement (ElementTypePtr Element)
{
  bool didDraw = false;

  if (PCB->ElementOn && (FRONT (Element) || PCB->InvisibleObjectsOn))
    {
      EraseElement (Element);
      MoveElementLowLevel (PCB->Data, Element, DeltaX, DeltaY);
      DrawElementName (Element);
      DrawElementPackage (Element);
      didDraw = true;
    }
  else
    {
      if (PCB->PinOn)
	EraseElementPinsAndPads (Element);
      MoveElementLowLevel (PCB->Data, Element, DeltaX, DeltaY);
    }
  if (PCB->PinOn)
    {
      DrawElementPinsAndPads (Element);
      didDraw = true;
    }
  if (didDraw)
    Draw ();
  return (Element);
}
static void
replace_one_footprint_aux(ElementTypePtr old_element,
                          PadOrPinType* old1_pp, PadOrPinType* old2_pp,
                          ElementTypePtr copy_element,
                          PadOrPinType* copy1_pp, PadOrPinType* copy2_pp)
{
  Boolean two_points = (old2_pp && copy2_pp);
  Boolean reflect = IS_REFLECTED(copy_element, old_element);

  debug_log("Reflect?: %s\n", (reflect ? "yes" : "no"));
  if (reflect) {
    /* Change side of board */
    ChangeElementSide(copy_element, 0);
  }

  CheapPointType copy1_pt = pad_or_pin_center(copy1_pp);
  CheapPointType old1_pt = pad_or_pin_center(old1_pp);

  BYTE rot_steps = 0;
  if (two_points) {
    /* Calculate nearest rotation steps */
    CheapPointType copy2_pt = pad_or_pin_center(copy2_pp);
    CheapPointType old2_pt = pad_or_pin_center(old2_pp);
    rot_steps =
      calculate_rotation_steps(copy1_pt, copy2_pt, old1_pt, old2_pt);
  }
  if (rot_steps) {
    /* Rotate copy */
    RotateElementLowLevel(PCB->Data, copy_element, 0, 0, rot_steps);
    /* Recalculate since copy_element has changed. */
    copy1_pt = pad_or_pin_center(copy1_pp);
  }

  /* Calculate translation */
  LocationType dx = old1_pt.X - copy1_pt.X;
  LocationType dy = old1_pt.Y - copy1_pt.Y;
  /* Move element */
  MoveElementLowLevel(PCB->Data, copy_element, dx, dy);

  /* Transfer pad/pin text and names. */
  transfer_text(old_element, copy_element);
  transfer_names(old_element, copy_element);
  transfer_flags(old_element, copy_element);
  SetElementBoundingBox(PCB->Data, copy_element, &PCB->Font);

  AddObjectToCreateUndoList(ELEMENT_TYPE,
                            copy_element, copy_element, copy_element);
  /* Remove old element. */
  MoveObjectToRemoveUndoList(ELEMENT_TYPE,
                             old_element, old_element, old_element);
}
Exemple #3
0
/*!
 * \brief Move everything.
 *
 * Call our own 'MyMove*LowLevel' where they don't exist in move.c.
 * This gets very slow if there are large polygons present, since every
 * element move re-clears the poly, followed by the polys moving and
 * re-clearing everything again.
 */
static void
MoveAll(Coord dx, Coord dy)
{
  ELEMENT_LOOP (PCB->Data);
  {
    MoveElementLowLevel (PCB->Data, element, dx, dy);
    AddObjectToMoveUndoList (ELEMENT_TYPE, NULL, NULL, element, dx, dy);
  }
  END_LOOP;
  VIA_LOOP (PCB->Data);
  {
    MyMoveViaLowLevel (PCB->Data, via, dx, dy);
    AddObjectToMoveUndoList (VIA_TYPE, NULL, NULL, via, dx, dy);
  }
  END_LOOP;
  ALLLINE_LOOP (PCB->Data);
  {
    MyMoveLineLowLevel (PCB->Data, layer, line, dx, dy);
    AddObjectToMoveUndoList (LINE_TYPE, NULL, NULL, line, dx, dy);
  }
  ENDALL_LOOP;
  ALLARC_LOOP (PCB->Data);
  {
    MyMoveArcLowLevel (PCB->Data, layer, arc, dx, dy);
    AddObjectToMoveUndoList (ARC_TYPE, NULL, NULL, arc, dx, dy);
  }
  ENDALL_LOOP;
  ALLTEXT_LOOP (PCB->Data);
  {
    MyMoveTextLowLevel (layer, text, dx, dy);
    AddObjectToMoveUndoList (TEXT_TYPE, NULL, NULL, text, dx, dy);
  }
  ENDALL_LOOP;
  ALLPOLYGON_LOOP (PCB->Data);
  {
    /*
     * XXX MovePolygonLowLevel does not mean "no gui" like
     * XXX MoveElementLowLevel, it doesn't even handle layer
     * XXX tree activity.
     */
    MyMovePolygonLowLevel (PCB->Data, layer, polygon, dx, dy);
    AddObjectToMoveUndoList (POLYGON_TYPE, NULL, NULL, polygon, dx, dy);
  }
  ENDALL_LOOP;
}
Exemple #4
0
/*!
 * \brief Place one element.
 *
 * Must initialize statics above before calling for the first time.
 *
 * This is taken almost entirely from ActionDisperseElements, with cleanup
 */
static void
place (ElementType *element)
{
  Coord dx, dy;

  /* figure out how much to move the element */
  dx = minx - element->BoundingBox.X1;
  dy = miny - element->BoundingBox.Y1;

  /* snap to the grid */
  dx -= (element->MarkX + dx) % (long) (PCB->Grid);
  dx += (long) (PCB->Grid);
  dy -= (element->MarkY + dy) % (long) (PCB->Grid);
  dy += (long) (PCB->Grid);

  /*
   * and add one grid size so we make sure we always space by GAP or
   * more
   */
  dx += (long) (PCB->Grid);

  /* Figure out if this row has room.  If not, start a new row */
  if (minx != GAP && GAP + element->BoundingBox.X2 + dx > PCB->MaxWidth)
  {
    miny = maxy + GAP;
    minx = GAP;
    place(element); /* recurse can't loop, now minx==GAP */
    return;
  }

  /* move the element */
  MoveElementLowLevel (PCB->Data, element, dx, dy);

  /* and add to the undo list so we can undo this operation */
  AddObjectToMoveUndoList (ELEMENT_TYPE, NULL, NULL, element, dx, dy);

  /* keep track of how tall this row is */
  minx += element->BoundingBox.X2 - element->BoundingBox.X1 + GAP;
  if (maxy < element->BoundingBox.Y2)
  {
    maxy = element->BoundingBox.Y2;
  }
}
Exemple #5
0
void
PostLoadElementPCB ()
{
  PCBTypePtr pcb_save = PCB;
  ElementTypePtr e;

  if (!yyPCB)
    return;

  CreateNewPCBPost (yyPCB, 0);
  ParseGroupString("1,c:2,s", &yyPCB->LayerGroups, yyData->LayerN);
  e = yyPCB->Data->Element; /* we know there's only one */
  PCB = yyPCB;
  MoveElementLowLevel (yyPCB->Data,
		       e, -e->BoundingBox.X1, -e->BoundingBox.Y1);
  PCB = pcb_save;
  yyPCB->MaxWidth = e->BoundingBox.X2;
  yyPCB->MaxHeight = e->BoundingBox.Y2;
}
Exemple #6
0
void
doPerturb (PerturbationType * pt, bool undo)
{
  LocationType bbcx, bbcy;
  /* compute center of element bounding box */
  bbcx = (pt->element->VBox.X1 + pt->element->VBox.X2) / 2;
  bbcy = (pt->element->VBox.Y1 + pt->element->VBox.Y2) / 2;
  /* do exchange, shift or flip/rotate */
  switch (pt->which)
    {
    case SHIFT:
      {
	LocationType DX = pt->DX, DY = pt->DY;
	if (undo)
	  {
	    DX = -DX;
	    DY = -DY;
	  }
	MoveElementLowLevel (PCB->Data, pt->element, DX, DY);
	return;
      }
    case ROTATE:
      {
	BYTE b = pt->rotate;
	if (undo)
	  b = (4 - b) & 3;
	/* 0 - flip; 1-3, rotate. */
	if (b)
	  RotateElementLowLevel (PCB->Data, pt->element, bbcx, bbcy, b);
	else
	  {
	    LocationType y = pt->element->VBox.Y1;
	    MirrorElementCoordinates (PCB->Data, pt->element, 0);
	    /* mirroring moves the element.  move it back. */
	    MoveElementLowLevel (PCB->Data, pt->element, 0,
				 y - pt->element->VBox.Y1);
	  }
	return;
      }
    case EXCHANGE:
      {
	/* first exchange positions */
	LocationType x1 = pt->element->VBox.X1;
	LocationType y1 = pt->element->VBox.Y1;
	LocationType x2 = pt->other->BoundingBox.X1;
	LocationType y2 = pt->other->BoundingBox.Y1;
	MoveElementLowLevel (PCB->Data, pt->element, x2 - x1, y2 - y1);
	MoveElementLowLevel (PCB->Data, pt->other, x1 - x2, y1 - y2);
	/* then flip both elements if they are on opposite sides */
	if (TEST_FLAG (ONSOLDERFLAG, pt->element) !=
	    TEST_FLAG (ONSOLDERFLAG, pt->other))
	  {
	    PerturbationType mypt;
	    mypt.element = pt->element;
	    mypt.which = ROTATE;
	    mypt.rotate = 0;	/* flip */
	    doPerturb (&mypt, undo);
	    mypt.element = pt->other;
	    doPerturb (&mypt, undo);
	  }
	/* done */
	return;
      }
    default:
      assert (0);
    }
}
Exemple #7
0
static void
pinout_set_data (GhidPinoutPreview * pinout, ElementType * element)
{
  gint tx, ty, x_min = 0, y_min = 0;

  if (element == NULL)
    {
      FreeElementMemory (&pinout->element);
      pinout->w_pixels = 0;
      pinout->h_pixels = 0;
      return;
    }

  /* 
   * copy element data 
   * enable output of pin and padnames
   * move element to a 5% offset from zero position
   * set all package lines/arcs to zero width
   */
  CopyElementLowLevel (NULL, &pinout->element, element, FALSE, 0, 0);
  PIN_LOOP (&pinout->element);
  {
    tx = abs (pinout->element.Pin[0].X - pin->X);
    ty = abs (pinout->element.Pin[0].Y - pin->Y);
    if (x_min == 0 || (tx != 0 && tx < x_min))
      x_min = tx;
    if (y_min == 0 || (ty != 0 && ty < y_min))
      y_min = ty;
    SET_FLAG (DISPLAYNAMEFLAG, pin);
  }
  END_LOOP;

  PAD_LOOP (&pinout->element);
  {
    tx = abs (pinout->element.Pad[0].Point1.X - pad->Point1.X);
    ty = abs (pinout->element.Pad[0].Point1.Y - pad->Point1.Y);
    if (x_min == 0 || (tx != 0 && tx < x_min))
      x_min = tx;
    if (y_min == 0 || (ty != 0 && ty < y_min))
      y_min = ty;
    SET_FLAG (DISPLAYNAMEFLAG, pad);
  }
  END_LOOP;


  MoveElementLowLevel (NULL, &pinout->element,
		       Settings.PinoutOffsetX -
		       pinout->element.BoundingBox.X1,
		       Settings.PinoutOffsetY -
		       pinout->element.BoundingBox.Y1);

  if (!pinout_zoom_fit (pinout, 2))
    pinout_zoom_fit (pinout, 3);

  ELEMENTLINE_LOOP (&pinout->element);
  {
    line->Thickness = 0;
  }
  END_LOOP;

  ARC_LOOP (&pinout->element);
  {
    /* 
     * for whatever reason setting a thickness of 0 causes the arcs to
     * not display so pick 1 which does display but is still quite
     * thin.
     */
    arc->Thickness = 1;
  }
  END_LOOP;
}
Exemple #8
0
/*
 * Distribute(X, [Lefts/Rights/Centers/Marks/Gaps, [First/Last/Crosshair, First/Last/Crosshair[, Gridless]]])
 * Distribute(Y, [Tops/Bottoms/Centers/Marks/Gaps, [First/Last/Crosshair, First/Last/Crosshair[, Gridless]]])
 *
 * As with align, plus:
 *
 *	Gaps		- Make gaps even rather than spreading points evenly
 *	First, Last,
 *	Crosshair	- Two arguments specifying both ends of the
 *			  distribution, they can't both be the same.
 *
 * Defaults are Marks, First, Last
 *
 * Distributed elements always retain the same relative order they had
 * before they were distributed.
 */
static int
distribute(int argc, char **argv, Coord x, Coord y)
{
	int dir;
	int point;
	int refa, refb;
	int gridless;
	Coord s, e, slack;
	int divisor;
	int changed = 0;
	int i;

	if (argc < 1 || argc == 3 || argc > 4) {
		AFAIL(distribute);
	}

	/* parse direction arg */
	switch ((dir = keyword(ARG(0)))) {
	case K_X:
	case K_Y:
		break;
	default:
		AFAIL(distribute);
	}

	/* parse point (within each element) which will be distributed */
	switch ((point = keyword(ARG(1)))) {
	case K_Centers:
	case K_Marks:
	case K_Gaps:
		break;
	case K_Lefts:
	case K_Rights:
		if (dir == K_Y) {
			AFAIL(distribute);
		}
		break;
	case K_Tops:
	case K_Bottoms:
		if (dir == K_X) {
			AFAIL(distribute);
		}
		break;
	case K_none:
		point = K_Marks;	/* default value */
		break;
	default:
		AFAIL(distribute);
	}

	/* parse reference which will determine first distribution coordinate */
	switch ((refa = keyword(ARG(2)))) {
	case K_First:
	case K_Last:
	case K_Average:
	case K_Crosshair:
		break;
	case K_none:
		refa = K_First;	/* default value */
		break;
	default:
		AFAIL(distribute);
	}

	/* parse reference which will determine final distribution coordinate */
	switch ((refb = keyword(ARG(3)))) {
	case K_First:
	case K_Last:
	case K_Average:
	case K_Crosshair:
		break;
	case K_none:
		refb = K_Last;	/* default value */
		break;
	default:
		AFAIL(distribute);
	}
	if (refa == refb) {
		AFAIL(distribute);
	}

	/* optionally work off the grid (solar cells!) */
	switch (keyword(ARG(4))) {
	case K_Gridless:
		gridless = 1;
		break;
	case K_none:
		gridless = 0;
		break;
	default:
		AFAIL(distribute);
	}

	/* build list of elements in orthogonal axis order */
	sort_elements_by_pos(K_distribute, dir, point);

	/* find the endpoints given the above options */
	s = reference_coord(K_distribute, x, y, dir, point, refa);
	e = reference_coord(K_distribute, x, y, dir, point, refb);
	slack = e - s;

	/* use this divisor to calculate spacing (for 1 elt, avoid 1/0) */
	divisor = (nelements_by_pos > 1) ? (nelements_by_pos - 1) : 1;

	/* even the gaps instead of the edges or whatnot */
	/* find the "slack" in the row */
	if (point == K_Gaps) {
		Coord w;

		/* subtract all the "widths" from the slack */
		for (i = 0; i < nelements_by_pos; ++i) {
			ElementType *element = elements_by_pos[i].element;

			/* coord doesn't care if I mix Lefts/Tops */
			w = elements_by_pos[i].width =
				coord(element, dir, K_Rights) -
				coord(element, dir, K_Lefts);
			/* Gaps distribution is on centers, so half of
			 * first and last element don't count */
			if (i == 0 || i == nelements_by_pos - 1) {
				w /= 2;
			}
			slack -= w;
		}
		/* slack could be negative */
	}

	/* move all selected elements to the new coordinate */
	for (i = 0; i < nelements_by_pos; ++i) {
		ElementType *element = elements_by_pos[i].element;
		Coord p, q, dp, dx, dy;

		/* find reference point for this element */
		q = s + slack * i / divisor;
		/* find delta from reference point to reference point */
		p = coord(element, dir, point);
		dp = q - p;
		/* ...but if we're gridful, keep the mark on the grid */
		if (! gridless) {
			dp -= (coord(element, dir, K_Marks) + dp)
					% (long) (PCB->Grid);
		}
		if (dp) {
			/* move from generic to X or Y */
			dx = dy = dp;
			if (dir == K_X)
				dy = 0;
			else
				dx = 0;
			MoveElementLowLevel(PCB->Data, element, dx, dy);
			AddObjectToMoveUndoList(ELEMENT_TYPE, NULL, NULL,
						element, dx, dy);
			changed = 1;
		}
		/* in gaps mode, accumulate part widths */
		if (point == K_Gaps) {
			/* move remaining half of our element */
			s += elements_by_pos[i].width / 2;
			/* move half of next element */
			if (i < nelements_by_pos - 1)
				s += elements_by_pos[i + 1].width / 2;
		}
	}

	if (changed) {
		IncrementUndoSerialNumber();
		Redraw();
		SetChangedFlag(1);
	}

	free_elements_by_pos();

	return 0;
}
Exemple #9
0
/*
 * Align(X, [Lefts/Rights/Centers/Marks, [First/Last/Crosshair/Average[, Gridless]]])
 * Align(Y, [Tops/Bottoms/Centers/Marks, [First/Last/Crosshair/Average[, Gridless]]])
 *
 *	X or Y		- Select which axis will move, other is untouched
 *	Lefts, Rights,
 *	Tops, Bottoms,
 *	Centers, Marks	- Pick alignment point within each element
 *	First, Last, 
 *	Crosshair, 
 *	Average		- Alignment reference, First=Topmost/Leftmost,
 *			  Last=Bottommost/Rightmost, Average or Crosshair point
 *	Gridless	- Do not force results to align to prevailing grid
 *
 * Defaults are Marks, First
 */
static int
align(int argc, char **argv, Coord x, Coord y)
{
	int dir;
	int point;
	int reference;
	int gridless;
	Coord q;
	int changed = 0;

	if (argc < 1 || argc > 4) {
		AFAIL(align);
	}

	/* parse direction arg */
	switch ((dir = keyword(ARG(0)))) {
	case K_X:
	case K_Y:
		break;
	default:
		AFAIL(align);
	}

	/* parse point (within each element) which will be aligned */
	switch ((point = keyword(ARG(1)))) {
	case K_Centers:
	case K_Marks:
		break;
	case K_Lefts:
	case K_Rights:
		if (dir == K_Y) {
			AFAIL(align);
		}
		break;
	case K_Tops:
	case K_Bottoms:
		if (dir == K_X) {
			AFAIL(align);
		}
		break;
	case K_none:
		point = K_Marks;	/* default value */
		break;
	default:
		AFAIL(align);
	}

	/* parse reference which will determine alignment coordinates */
	switch ((reference = keyword(ARG(2)))) {
	case K_First:
	case K_Last:
	case K_Average:
	case K_Crosshair:
		break;
	case K_none:
		reference = K_First;	/* default value */
		break;
	default:
		AFAIL(align);
	}

	/* optionally work off the grid (solar cells!) */
	switch (keyword(ARG(3))) {
	case K_Gridless:
		gridless = 1;
		break;
	case K_none:
		gridless = 0;
		break;
	default:
		AFAIL(align);
	}

	/* find the final alignment coordinate using the above options */
	q = reference_coord(K_align, Crosshair.X, Crosshair.Y,
				dir, point, reference);

	/* move all selected elements to the new coordinate */
	ELEMENT_LOOP(PCB->Data);
	{
		Coord p, dp, dx, dy;

		if (! TEST_FLAG (SELECTEDFLAG, element))
			continue;
		/* find delta from reference point to reference point */
		p = coord(element, dir, point);
		dp = q - p;
		/* ...but if we're gridful, keep the mark on the grid */
		if (! gridless) {
			dp -= (coord(element, dir, K_Marks) + dp)
					% (long) (PCB->Grid);
		}
		if (dp) {
			/* move from generic to X or Y */
			dx = dy = dp;
			if (dir == K_X)
				dy = 0;
			else
				dx = 0;
			MoveElementLowLevel(PCB->Data, element, dx, dy);
			AddObjectToMoveUndoList(ELEMENT_TYPE, NULL, NULL,
						element, dx, dy);
			changed = 1;
		}
	}
	END_LOOP;

	if (changed) {
		IncrementUndoSerialNumber();
		Redraw();
		SetChangedFlag(1);
	}

	free_elements_by_pos();

	return 0;
}