-- BoardPaint.mesa
-- last modified by E. McCreight, October 15, 1982 4:21 pm

DIRECTORY
 DoradoBoard,
 Graphics USING [black, Color, Context, DrawBox, DrawRope, RopeBox,
  Restore, Rotate, Save, Scale, SetColor, SetCP, SetPaintMode,
  Translate, white, NewContext,
  CopyContext, Map, Box, GetBounds, GetDefaultFont, FontRef, FontBox],
 GraphicsColor USING [red, green, blue, magenta, cyan, yellow, black],
IO USING [SetIndex, PutFR, int, char],
 Real USING [RoundI],
 RealFns USING [ArcTanDeg, SqRt, TanDeg],
 Rope USING [ROPE],
 ViewerClasses USING [PaintProc];

BoardPaint: CEDAR MONITOR

IMPORTS DoradoBoard, Graphics, IO, Real, RealFns
EXPORTS DoradoBoard =

BEGIN OPEN DoradoBoard, Graphics;

------ global module values ------

bottom: Mils = 1410; -- bottom border
left: Mils = 1110; -- left border
chipW: Mils = 800; -- dimensions of a chip
chipH: Mils = 400;
maxRows: INTEGER = 24;
maxCols: INTEGER = 12;
sipH: Mils = 100; -- dimensions of sip
sipW: Mils = 800;
tenth: Mils = 100; -- one hundred Mils = five pixels at scale=1.0
middleWidth: Mils = 750;

MilsBox: TYPE = RECORD[xmin, ymin, xmax, ymax: Mils];



PaintBoard: PUBLIC ENTRY ViewerClasses.PaintProc =
TRUSTED BEGIN
JOIN (FORK DoPaintBoard[self: self, context: context, whatChanged: whatChanged,
  clear: clear]);
END;


DoPaintBoard: ViewerClasses.PaintProc =
TRUSTED BEGIN
 state: Board = NARROW[self.data];
 nextRow: Mils;
 [] ← BoardContext[state, context];
 [] ← SetPaintMode[context, opaque];
 SetColor[context, black];
IF state.showPads AND state.milsPerPixel<20 THEN PaintPads[state, context];
 PaintFingers[state, context];
 nextRow ← PaintRows[state, context];
 PaintFingers[state, context, nextRow+400];
FOR s: SigPadList ← state.signalPads, s.rest WHILE s#NIL DO
  PaintSignalInner[state, context, s.first];
  ENDLOOP;
END; -- of DoPaintBoard --

PaintSignalInner: PROC [state: Board, context: Context, index: PadIndex] =
TRUSTED BEGIN
IF state.padCount <= index THEN RETURN;
 index ← GetCanonicalPad[state, index];
FOR layer: WiringLayer IN WiringLayer DO
  IF state.plotLayer[layer] THEN DrawLayer[state, context, layer, index];
  ENDLOOP;
END; -- of PaintSignalInner --

DrawLayer: PROC [state: Board, context: Context, layer, count: CARDINAL] =
-- Draw the wires on the corresponding layer.
TRUSTED BEGIN
 index: INT ← state.pads[count].segs.l[layer];
IF index # 0 THEN --do nothing if there are no segments to paint
  BEGIN
  box: MilsBox;
  segCount: CARDINAL;
  [] ← Save[context];
  Translate[context, asiOffset.x, asiOffset.y];
  box ← GetMilsBox[context];
  SetColor[context, colorTable[layer]];
  state.asiFile.SetIndex[index];
  segCount ← GetCardinal[state];
  FOR i: CARDINAL IN [0 ..segCount) DO
   start: Point = GetPoint[state];
   end: Point = GetPoint[state];
   IF MIN[start.x, end.x]<=box.xmax AND box.xmin<=MAX[start.x, end.x] AND
    MIN[start.y, end.y]<=box.ymax AND box.ymin<=MAX[start.y, end.y] THEN
    DrawWire[state, context, start.x, start.y, end.x, end.y];
   ENDLOOP;
  Restore[context];
  END;
END; -- of DrawLayer --

DrawWire: PROC [state: Board, context: Context, x, y, xx, yy: Mils] =
TRUSTED BEGIN OPEN RealFns;
 dx: REAL = xx-x;
 dy: REAL = yy-y;
 halfLineWidth: REAL = MAX[2*state.milsPerPixel, 10]/2; -- in mils
 [] ← Save[context];
 Translate[context, x, y];
 Rotate[context, ArcTanDeg[x: dx, y: dy]];
 DrawBox[context, [-tanHalf45*halfLineWidth, -halfLineWidth,
  SqRt[dx*dx+dy*dy]+tanHalf45*halfLineWidth, halfLineWidth]];
 Restore[context];
END; -- of DrawWire --




BoardContext: PUBLIC PROC [state: Board, context: Context ← NIL] RETURNS [Context] =
TRUSTED BEGIN
 cx, cy, dx, dy: REAL;
 start: Context;
IF context = NIL THEN
  context ← NewContext[];
 start ← CopyContext[context];
 Rotate[context, state.rotAngle];
 Scale[context, state.mirFact*state.scale*.05, state.scale*.05];
 [dx: cx, dy: cy] ← Map[dc: context, sc: start,
  sx: state.boardPicture.ww/2, sy: state.boardPicture.wh/2];
 Translate[context, cx-state.center.x, cy-state.center.y];
 [dx: cx, dy: cy] ← Map[dc: context, sc: start,
  sx: 0, sy: 0];
 [dx: dx, dy: dy] ← Map[dc: context, sc: start,
  sx: 1, sy: 1];
 state.milsPerPixel ← MAX[ABS[dx-cx], ABS[dy-cy]]+.001 -- epsilon --;
RETURN[context];
END;


PaintText: PROC [state: Board, context: Context, height: Mils, center: Point, text: Rope.ROPE,
 color: Graphics.Color ← Graphics.black, font: Graphics.FontRef ← NIL] =
TRUSTED BEGIN
 xmin, xmax, ymin, ymax, scanLinesPerFontPixel, scaleAdjust: REAL;
IF font = NIL THEN font ← context.GetDefaultFont[];
 [ymin: ymin, ymax: ymax] ← FontBox[font];
 scanLinesPerFontPixel ← height/(state.milsPerPixel*(ymax-ymin));
 scaleAdjust ← state.milsPerPixel*MAX[1.0, Real.RoundI[scanLinesPerFontPixel]]
  + .001 -- epsilon --;
 [] ← Save[context];
 [xmin: xmin, xmax: xmax] ← RopeBox[font, text];
 Translate[context, center.x-scaleAdjust*(xmax+xmin)/2,
  center.y-scaleAdjust*(ymax+ymin)/2];
 Scale[context, scaleAdjust, scaleAdjust];
 SetCP[context, 0, 0];
 SetColor[context, color];
 DrawRope[context, text];
 Restore[context];
END; -- of PaintText --


PaintChip: PROC [state: Board, context: Context, x, y: Mils, chipName: Rope.ROPE] =
TRUSTED BEGIN
 SetColor[context, black];
 DrawBox[context, [x, y, x+chipW, y+state.milsPerPixel]];
 DrawBox[context, [x, y+chipH-state.milsPerPixel, x+chipW, y+chipH]];
 DrawBox[context, [x, y, x+state.milsPerPixel, y+chipH]];
 DrawBox[context, [x+chipW-state.milsPerPixel, y, x+chipW, y+120]];
 DrawBox[context, [x+chipW-state.milsPerPixel, y+chipH-120, x+chipW, y+chipH]];
IF state.showLabels THEN
  PaintText[state: state, context: context, height: 200,
  center: [x: x+chipW/2, y: y+chipH/2], text: chipName];
END; -- of PaintChip --


PaintFingers: PROC [state: Board, context: Context, fngRow: Mils ← 0] =
TRUSTED BEGIN
 box: MilsBox = GetMilsBox[context];
 fngW: Mils = 120;
 fngH: Mils = 1000;
 x: Mils ← 0;
IF box.ymin<=fngRow+fngH+20 AND fngRow<=box.ymax THEN
  BEGIN
  SetColor[context, black];
  DrawBox[context, [x, fngRow, x+boardWidth-20, fngRow+fngH+20]];
  SetColor[context, white];
  x ← left;
  FOR j: INTEGER IN [0 .. 100)
   WHILE x < boardWidth DO
   DrawBox[context, [x+20, fngRow+20, x+fngW, fngRow+fngH]];
   x ← x + fngW;
   ENDLOOP;
  END;
END; -- of PaintFingers --


PaintPads: PROC [state: Board, context: Context] =
TRUSTED BEGIN
 box: MilsBox;
 qtrTenth: Mils ← tenth/4;
 [] ← Save[context];
 Translate[context, asiOffset.x, asiOffset.y];
 box ← GetMilsBox[context];
FOR i: CARDINAL IN
  [MinPadGE[state, box.xmin] .. MinPadGE[state, box.xmax+1])
  DO
  p: Point = state.pads[i].p;
  IF p.y IN [box.ymin..box.ymax] THEN
   BEGIN
   SetColor[context, SELECT state.pads[i].type.t FROM
    noProbe => GraphicsColor.magenta,
    signal => GraphicsColor.yellow,
    gnd => GraphicsColor.black,
    vee => GraphicsColor.green,
    vdd => GraphicsColor.cyan,
    vtt => GraphicsColor.blue,
    vcc => GraphicsColor.red
    ENDCASE => GraphicsColor.black];
    
    DrawBox[context, [p.x-qtrTenth, p.y-qtrTenth, p.x+qtrTenth, p.y+qtrTenth]];
   END;
  ENDLOOP;
 Restore[context];
END; -- of PaintPads --


PaintRows: PROC [state: Board, context: Context] RETURNS [nextRow: Mils] =
TRUSTED BEGIN
 box: MilsBox = GetMilsBox[context];
 y: Mils;
 y ← bottom;
FOR i: INTEGER IN [0 .. maxRows) DO-- paint rows
  x: Mils ← left;
  IF box.ymin<=y+chipH+tenth/2 AND y<=box.ymax THEN
   FOR col: INTEGER IN [0 .. maxCols) DO
    IF i=maxRows-1 THEN
     PaintText[state, context, 300, [x: x+chipW/2, y: y+chipH+2*tenth],
      IO.PutFR[v1: IO.char['A+col]]];
    PaintChip[state, context, x, y,
     IO.PutFR["%g%02d", IO.char['A + col], IO.int[maxRows-i]]];
    SELECT TRUE FROM
     col = 5 => {  -- paint row numbers
      PaintText[state, context, 300,
       [x: x+chipW+middleWidth/2, y: y+chipH/2],
       IO.PutFR[v1: IO.int[maxRows-i]]];
      x ← x + chipW + middleWidth;
      };
     ((col+1) MOD 3) = 0 => x ← x + chipW + 2*tenth; -- every third chip
     ENDCASE => x ← x + chipW + tenth;
    ENDLOOP;
  y ← y + chipH + tenth/2;
  IF (i MOD 2) = 0 THEN
   BEGIN
   IF box.ymin<=y+sipH+tenth/2 AND y<=box.ymax THEN PaintSips[state, context, y];
   y ← y + sipH + tenth/2;
   END;
  ENDLOOP;
 nextRow ← y;
END; -- of PaintRows --



PaintSips: PROC [state: Board, context: Context, y: Mils] =
TRUSTED BEGIN
 x: Mils ← left;
 qtrTenth: Mils ← tenth/4;
FOR col: INTEGER IN [0 .. maxCols) DO
  SetColor[context, black];
  OutlineBox[context, [x+sipW/2, y+sipH/2], [sipW/2, sipH/2], state.milsPerPixel];
  SELECT TRUE FROM
   col = 5 => x ← x + sipW + middleWidth;
   ((col+1) MOD 3) = 0 => x ← x + sipW + 2*tenth;
   ENDCASE => x ← x + sipW + tenth;
  ENDLOOP;
END; -- of PaintSips --

OutlineBox: PROC [context: Context, center, radius: Point, width: REAL] =
BEGIN
 DrawBox[context, [center.x-radius.x, center.y-radius.y,
  center.x-radius.x+width, center.y+radius.y]];
 DrawBox[context, [center.x-radius.x, center.y-radius.y,
  center.x+radius.x, center.y-radius.y+width]];
 DrawBox[context, [center.x-radius.x, center.y+radius.y-width,
  center.x+radius.x, center.y+radius.y]];
 DrawBox[context, [center.x+radius.x-width, center.y-radius.y,
  center.x+radius.x, center.y+radius.y]];
END;




colorTable: ARRAY WiringLayer OF Color =
 [GraphicsColor.red, GraphicsColor.green, GraphicsColor.blue, GraphicsColor.magenta];


tanHalf45: REAL -- = RealFns.TanDeg[22.5] --;


GetMilsBox: PROC [context: Context] RETURNS [MilsBox] =
TRUSTED BEGIN
 box: Graphics.Box = GetBounds[context];
RETURN[[
  xmin: Real.RoundI[box.xmin],
  ymin: Real.RoundI[box.ymin],
  xmax: Real.RoundI[box.xmax],
  ymax: Real.RoundI[box.ymax]]];
END;

TRUSTED BEGIN
tanHalf45 ← RealFns.TanDeg[22.5];
END;

END. -- of BoardPaint --


CHANGE LOG

Created by L. Hilton, September 9, 1982 7:05 pm