INTERFACE ScrnPaintOp; IMPORT TrestleComm, PaintOp;
A ScrnPaintOp.T is a painting operation that is valid for some particular screentype.
If op is a ScrnPaintOp.T valid for screentype st, then op maps a source pixel s and destination pixel d to a result pixel op(d, s). It will be used in a painting operation that sets d := op(d, s). Both d and op(d, s) have type st, and s either has type st or st.bits. (The type st.bits is the screentype for one-bit deep sources that can be used with st.) For example, in a copy operation, s has type st, while in painting a bitmap, s has type st.bits.
A ScrnPaintOp.Oracle is meaningful only as the op field of some screentype st. It provides methods to generate ScreenPaintOp.Ts that are valid for st.
A tint is a paintop that is independent of s. If op is a tint, we write op(d) instead of op(d, s). (Even in the case of a tint, the type of s must be st.bits; otherwise the result of applying the tint is undefined.)
TYPE Pixel = INTEGER; Oracle = Private OBJECT METHODS <* LL.sup <= VBT.mu *> opaque(pix: Pixel): T RAISES {Failure, TrestleComm.Failure}; bgfg(bg, fg: T): T RAISES {Failure, TrestleComm.Failure}; swap(p,q: Pixel): T RAISES {Failure, TrestleComm.Failure}; transparent(): T RAISES {Failure, TrestleComm.Failure}; copy(): T RAISES {Failure, TrestleComm.Failure}; builtIn(op: PaintOp.Predefined): T; END; Private <: ROOT; EXCEPTION Failure;
For a screentype st, the field st.op is an Oracle whose methods satisfy the following specifications:
The method call
op := st.op.opaque(pix)
sets op to a tint such that op(p) = pix for any p. The method call
op := st.op.bgfg(bg, fg)
sets op to a tint such that op(p, 0) = bg(p) and op(p, 1) = fg(p), for any p, if bg and fg are tints. The method call
op := st.op.swap(p, q)
sets op to a tint such that op(p)=q, op(q)=p, and for any x, op(op(x))=x. The method call
op := st.op.transparent()
sets op to a tint such that op(p) = p for any p. The method call
op := st.op.copy()
sets op to a painting operation such that op(p, q) = q for any p and q. The method call
st.op.builtIn(op)
returns the operation valid for st that corresponds to the predefined screen-independent operation PaintOp.T{op}.
The exception Failure is raised if the screentype cannot provide the requested painting operation. For all the methods, LL.sup <= VBT.mu.
TYPE PlaneWiseOracle = Oracle OBJECT METHODS <* LL.sup <= VBT.mu *> planewise( READONLY mask: ARRAY OF BOOLEAN; op1, op2: T): T RAISES {Failure, TrestleComm.Failure}; END;
If a screentype's op oracle is a PlaneWiseOracle (which you can test with TYPECASE), then you can use its planewise method to define painting operations by their effects on each bit position of the destination pixel. Let p[i] denote bit i of pixel p. Assuming NUMBER(mask) = st.depth, the method call
op := st.op.planewise(mask, bitOps)
sets op so that for d and s of screentype st and i in [0..st.depth-1],
IF mask[i] THEN op(d, s)[i] = op1(d[i], s[i]) ELSE op(d, s)[i] = op2(d[i], s[i]) END
The method may raise Failure if it does not support a particular combination of op1, op2, and mask.
The convenience procedure ConstructPlanewiseOp can be used to construct a painting operation from an array of boolean functions represented by the enumeration by BitOp:
TYPE BitOp = { Zero, (* 0 *) And, (* dest AND src *) NotAnd, (* (NOT dest) AND src *) Src, (* src *) AndNot, (* dest and (NOT src) *) Dest, (* dest *) Xor, (* dest XOR src *) Or, (* dest OR src *) Nor, (* (NOT dest) AND (NOT src) *) Equal, (* dest XOR (NOT src) *) Invert, (* NOT dest *) NotOr, (* (NOT dest) OR src *) NotSrc, (* NOT src *) OrNot, (* dest OR (NOT src) *) Nand, (* (NOT dest) OR (NOT src) *) One}; (* 1 *) PROCEDURE ConstructPlanewiseOp( pwo: PlaneWiseOracle; READONLY bitOps: ARRAY OF BitOp): T RAISES {Failure, TrestleComm.Failure}; <* LL.sup <= VBT.mu *>
If NUMBER(bitOps) = st.depth then ConstructPlanewiseOp uses pwo to construct and return an operation op such that for s and d of screentype st and i in [0 .. st.depth-1],
op(d, s)[i] = bitOps[i](d[i], s[i])
The procedure may raise Failure if the screentype does not support a particular array bitOps.
TYPE T <: Public; Public = OBJECT id: INTEGER; pix: Pixel := -1 END;
If p is a T, then p.id is an identifier whose interpretation depends on the screentype. If p was created by a call st.op.opaque(pix), then p.pix = pix; otherwise p.pix = -1.
END ScrnPaintOp.
Return the painting operation that applies bitOp[i] to plane i of the source and destination.