[Oberon] System-V - Frame Clipping

Andreas Pirklbauer andreas_pirklbauer at yahoo.com
Mon Mar 4 11:28:31 CET 2019


   > I will experiment with `Clip(F)', `Clip(NIL)' inside `Display1.Mod’. It actually
   > consolidates graph primitives, some based on input from the list here,
   > simplified for PO2013, currently does not support brush idea, vectors, etc. 

Not 100% sure what problem you are trying to solve. But at least for *patterns*
that are copied "as is” into the frame buffer using SYSTEM.PUT, one can do
the clipping by applying appropriate masks, as shown in the example below.

-ap


Display.CopyPattern with left, right, top, and bottom margins:

  PROCEDURE CopyPattern*(col, patadr, x, y, left, right, top, bot, mode: INTEGER);  (*only for modes = paint, invert*)
    VAR a, a0, pwd: INTEGER;
      w, h, pbt: BYTE; pix, mask, ml, mr: SET;
  BEGIN (*0 <= top < h, 0 <= bot < h, top + bot < h, 0 <= right < w, 0 <= left < w, left + right < w*)
    SYSTEM.GET(patadr, w); SYSTEM.GET(patadr+1, h); INC(patadr, 2 + bot*((w + 7) DIV 8)); h := h - top - bot;
    a := base + (x DIV 32)*4 + (y+bot)*128; x := x MOD 32; mask := SYSTEM.VAL(SET, ASR(7FFFFFFFH, 31-x));
    FOR a0 := a TO a + (h-1)*128 BY 128 DO
      (*build pattern line; w < 32*)
      SYSTEM.GET(patadr, pbt); INC(patadr); pwd := pbt;
      IF w > 8 THEN SYSTEM.GET(patadr, pbt); INC(patadr); pwd := pbt*100H + pwd;
        IF w > 16 THEN SYSTEM.GET(patadr, pbt); INC(patadr); pwd := pbt*10000H + pwd;
          IF w > 24 THEN SYSTEM.GET(patadr, pbt); INC(patadr); pwd := pbt*1000000H + pwd END
        END
      END ;
      IF left + right > 0 THEN (*clip*)
        ml := {0 .. w-right-1}; mr := {left .. w-1}; pwd := SYSTEM.VAL(INTEGER, SYSTEM.VAL(SET, pwd) * ml * mr)
      END ;
      SYSTEM.GET(a0, pix);
      IF mode = invert THEN SYSTEM.PUT(a0, SYSTEM.VAL(SET, LSL(pwd, x)) / pix)
      ELSE SYSTEM.PUT(a0, SYSTEM.VAL(SET, LSL(pwd, x)) + pix)
      END ;
      IF x + w > 32 THEN (*spill over*)
        SYSTEM.GET(a0+4, pix);
        IF mode = invert THEN SYSTEM.PUT(a0+4, SYSTEM.VAL(SET, ASR(pwd, -x)) * mask/ pix)
        ELSE SYSTEM.PUT(a0+4, SYSTEM.VAL(SET, ASR(pwd, -x)) * mask+ pix)
        END
      END
    END
  END CopyPattern;

TextFrames.DisplayLine which uses the above procedure to implement fractional text rendering:

  PROCEDURE DisplayLine (F: Frame; L: Line;
    VAR R: Texts.Reader; X, Y, topY, botY: INTEGER; len: LONGINT);
    VAR patadr, NX, dx, x, y, w, h, left, right, top, bot: INTEGER;
  BEGIN NX := F.X + F.W - F.right; left := 0;
    WHILE (nextCh # CR) & (R.fnt # NIL) DO
      Fonts.GetPat(R.fnt, nextCh, dx, x, y, w, h, patadr);
      IF (X + x < NX) & (h # 0) THEN y := Y + y;
        IF y + h <= topY THEN top := 0 ELSIF y >= topY THEN top := h ELSE (*clip*) top := y + h - topY END;
        IF y >= botY THEN bot := 0 ELSIF y + h <= botY THEN bot := h ELSE (*clip*) bot := botY - y END;
        IF x + X + w <= NX THEN right := 0 ELSE (*clip*) right := x + X + w - NX END;
        IF top + bot < h THEN Display.CopyPattern(R.col, patadr, X + x, y, left, right, top, bot, Display.invert) END
      END;
      X := X + dx; INC(len); Texts.Read(R, nextCh)
    END;
    L.len := len + 1; L.wid := X + eolW - (F.X + F.left);
    L.eot := R.fnt = NIL; Texts.Read(R, nextCh)
  END DisplayLine;








More information about the Oberon mailing list