ui/src/nt/NTScrnPntOp.m3


Copyright (C) 1994, Digital Equipment Corp.
 by Steve Glassman, Mark Manasse and Greg Nelson 
<*PRAGMA LL*>

UNSAFE MODULE NTScrnPntOp;

IMPORT NT, NTScreenType, NTScrnTpRep, PaintOp, ScreenType, ScrnPaintOp,
       TrestleClass, VBTClass, WinGDI, Word;

REVEAL
  T = T_Pub BRANDED OBJECT
        opcount: CARDINAL := 0;
        (* numbers of entries in optable. *)
      END;

TYPE
  NTPaintOp = ScrnPaintOp.T;
  OpOracle = ScrnPaintOp.Oracle OBJECT
               st: NTScreenType.T
             OVERRIDES
               opaque      := Opaque;
               bgfg        := Bgfg;
               swap        := Swap;
               transparent := Transparent;
               copy        := Copy;
               builtIn     := OpBuiltIn;
             END;

PROCEDURE NewOracle (st: NTScreenType.T): ScrnPaintOp.Oracle =
  BEGIN
    RETURN NEW(OpOracle, st := st)
  END NewOracle;

PROCEDURE Opaque (orc: OpOracle; pix: ScrnPaintOp.Pixel): ScrnPaintOp.T
  RAISES {} =
  VAR rec: NTScrnTpRep.OpRecord;
  BEGIN
    rec.rop := WinGDI.R2_COPYPEN;
    rec.fg := pix;
    rec.bg := pix;
    RETURN NewPaintOp(orc.st, rec, pix)
  END Opaque;

PROCEDURE Swap (orc: OpOracle; p, q: ScrnPaintOp.Pixel): ScrnPaintOp.T
  RAISES {} =
  VAR rec: NTScrnTpRep.OpRecord;
  BEGIN
    IF p = q THEN RETURN Transparent(orc) END;
    rec.rop := WinGDI.R2_XORPEN;
    rec.fg := Word.Xor(p, q);
    rec.bg := Word.Xor(p, q);
    RETURN NewPaintOp(orc.st, rec)
  END Swap;

PROCEDURE Transparent (orc: OpOracle): ScrnPaintOp.T RAISES {} =
  VAR rec: NTScrnTpRep.OpRecord;
  BEGIN
    rec.rop := WinGDI.R2_NOP;
    rec.fg := 0;
    rec.bg := 0;
    RETURN NewPaintOp(orc.st, rec)
  END Transparent;

PROCEDURE Copy (orc: OpOracle): ScrnPaintOp.T RAISES {} =
  VAR rec: NTScrnTpRep.OpRecord;
  BEGIN
    rec.rop := WinGDI.R2_COPYPEN;
    rec.fg := 0;
    rec.bg := 0;
    RETURN NewPaintOp(orc.st, rec)
  END Copy;

PROCEDURE Bgfg (orc: OpOracle; bg, fg: ScrnPaintOp.T): ScrnPaintOp.T
  RAISES {ScrnPaintOp.Failure} =
  VAR rec: NTScrnTpRep.OpRecord;
  BEGIN
    LOCK orc.st.trsl DO
      IF (bg.id < 0) OR (bg.id >= orc.st.opcount) OR (fg.id < 0)
           OR (fg.id >= orc.st.opcount) THEN
        RAISE ScrnPaintOp.Failure
      END;
      WITH bgrec = orc.st.optable[bg.id],
           fgrec = orc.st.optable[fg.id]  DO
        IF (bgrec.rop = WinGDI.R2_NOP) THEN
          rec := fgrec;
          rec.bgMode := WinGDI.TRANSPARENT;
        ELSIF (bgrec.rop = fgrec.rop) THEN
          rec := fgrec;
          rec.bg := bgrec.bg;
        ELSE
          RAISE ScrnPaintOp.Failure
        END
      END
    END;
    RETURN NewPaintOp(orc.st, rec)
  END Bgfg;

PROCEDURE OpBuiltIn (orc: OpOracle; op: PaintOp.Predefined):
  ScrnPaintOp.T =
  VAR rec: NTScrnTpRep.OpRecord;
  BEGIN
    CASE op OF
      PaintOp.Bg.op => RETURN Opaque(orc, orc.st.bg)
    | PaintOp.Fg.op => RETURN Opaque(orc, orc.st.fg)
    | PaintOp.Transparent.op => RETURN Transparent(orc)
    | PaintOp.Swap.op => RETURN Swap(orc, orc.st.bg, orc.st.fg)
    | PaintOp.Copy.op => RETURN Copy(orc)
    | PaintOp.BgFg.op =>
        rec.rop := WinGDI.R2_COPYPEN;
        rec.fg := orc.st.fg;
        rec.bg := orc.st.bg ;
    | PaintOp.FgBg.op =>
        rec.rop := WinGDI.R2_COPYPEN;
        rec.fg := orc.st.fg;
        rec.bg := orc.st.bg ;
    | PaintOp.TransparentBg.op =>
        rec.rop := WinGDI.R2_COPYPEN;
        rec.fg := orc.st.bg;
        rec.bg := 0;
        rec.bgMode := WinGDI.TRANSPARENT;
    | PaintOp.TransparentFg.op =>
        rec.rop := WinGDI.R2_COPYPEN;
        rec.fg := orc.st.fg;
        rec.bg := 0;
        rec.bgMode := WinGDI.TRANSPARENT;
    | PaintOp.TransparentSwap.op =>
        rec.rop := WinGDI.R2_XORPEN;
        rec.fg := Word.Xor(orc.st.bg, orc.st.fg);
        rec.bg := 0;
        rec.bgMode := WinGDI.TRANSPARENT;
    | PaintOp.SwapTransparent.op =>
        NT.Assert(1); (* NYI *)
    ELSE
      NT.Assert(1); (* NYI *)
    END;
    RETURN NewPaintOp(orc.st, rec)
  END OpBuiltIn;

PROCEDURE NewPaintOp (VAR      st : NTScreenType.T;
                      READONLY rec: NTScrnTpRep.OpRecord;
                               pix                         := -1):
  NTPaintOp =
  VAR res := NEW(NTPaintOp, pix := pix);
  BEGIN
    LOCK st.trsl DO
      WITH n = NUMBER(st.optable^) DO
        IF n = st.opcount THEN
          WITH new = NEW(REF ARRAY OF NTScrnTpRep.OpRecord, 2 * n) DO
            FOR i := 0 TO n - 1 DO new[i] := st.optable[i] END;
            st.optable := new
          END
        END
      END;
      res.id := st.opcount;
      st.optable[res.id] := rec;
      INC(st.opcount)
    END;
    RETURN res
  END NewPaintOp;

BEGIN
END NTScrnPntOp.