From 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 Mon Sep 17 00:00:00 2001 From: Joe Hunkeler Date: Tue, 11 Aug 2015 16:51:37 -0400 Subject: Repatch (from linux) of OSX IRAF --- sys/plio/pllrop.x | 271 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 sys/plio/pllrop.x (limited to 'sys/plio/pllrop.x') diff --git a/sys/plio/pllrop.x b/sys/plio/pllrop.x new file mode 100644 index 00000000..2f5f1358 --- /dev/null +++ b/sys/plio/pllrop.x @@ -0,0 +1,271 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include +include "pllseg.h" +include + +# PL_LINEROP -- Rasterop operation between source and destination line lists. +# The indicated rasterop operation is performed upon the source and destination +# line lists, writing the result to LL_OUT, which is a copy of LL_DST except +# for the region affected by the rasterop operation (note that the destination +# line list cannot be edited in place since it may change size). + +procedure pl_linerop (ll_src, xs, src_maxval, + ll_dst, ds, dst_maxval, ll_out, npix, rop) + +short ll_src[ARB] #I source line list +int xs #I starting pixel index in src line list +int src_maxval #I maximum pixel value, source mask +short ll_dst[ARB] #I destination line list +int ds #I starting pixel index in dst line list +int dst_maxval #I maximum pixel value, dst mask +short ll_out[ARB] #O output list (edited version of ll_dst) +int npix #I number of pixels to convert +int rop #I rasterop + +int segsize, v_src, v_dst, pv +bool need_src, need_dst, rop_enable +int o_op, o_iz, o_pv, o_np, o_hi, src_value +int opcode, data, nz, iz, x1, hi, dv, v, np, op, n, i +int d_src[LEN_PLLDES], d_dst[LEN_PLLDES] +define done_ 91 + +begin + need_src = R_NEED_SRC(rop) + need_dst = R_NEED_DST(rop) + opcode = R_OPCODE(rop) + data = R_DATA(rop) + + # Pixel value to be used if input mask is boolean. + if (src_maxval == 1) { + src_value = data + if (src_value <= 0) + src_value = dst_maxval + } + + # Advance to the desired position in the source list, discarding + # the instructions once read. The point XS may lie within the range + # of an instruction. + + if (need_src) { + x1 = 1 + pll_init (ll_src, d_src) + do i = 1, ARB { + np = min (pll_nleft(d_src), xs - x1) + pll_getseg (ll_src, d_src, np, v_src) + x1 = x1 + np + if (x1 >= xs || np == 0) + break + } + } + + # Copy DST to OUT, applying the rasterop in the region of NPIX pixels + # beginning at DS. To simplify things (avoid pathological complexity + # in this case) we suffer some unnecessary unpacking and repacking + # of encoded line list instructions in the regions of the DST list + # which are simply copied. This avoids the need for special treatment + # at the edges of the region to which the ROP applies. ROP_ENABLE is + # false initially, true in the ROP region, and false again to the + # right. The number of pixels in each region is given by SEGSIZE. + + o_pv = -1 + op = LL_CURHDRLEN + 1 + segsize = ds - 1 + rop_enable = false + x1 = 1; iz = 1; hi = 1 + pll_init (ll_dst, d_dst) + + do i = 1, ARB { + # Set up for the next segment (before, in, and after the region to + # which the ROP applies), when the current segment is exhausted. + + if (segsize <= 0) + if (!rop_enable) { + # Begin processing central region. + segsize = npix + rop_enable = true + if (segsize <= 0) + next + } else { + # Begin processing final region. + segsize = ARB + rop_enable = false + } + + # Determine the length of the next output segment. This is the + # largest segment of constant value formed by the intersection of + # the two lists. If bounds checking has been properly performed + # then it should not be possible to see nleft=zero on either input + # list. Note that zeroed regions are valid data here. + + np = min (segsize, pll_nleft(d_dst)) + if (need_src && rop_enable && pll_nleft(d_src) > 0) + np = min (np, pll_nleft(d_src)) + if (np <= 0) + break + + # Get the segment value and advance the line pointers. We always + # have to read the DST list in order to copy the unmodified regions + # to the output. We read the SRC list and apply the rasterop only + # in the region to which the ROP applies. + + pll_getseg (ll_dst, d_dst, np, v_dst) + if (rop_enable) { + # Get v_src. + if (need_src) { + v_src = 0 + if (pll_nleft (d_src) > 0) + pll_getseg (ll_src, d_src, np, v_src) + + if (R_NOTSRC(rop)) { + v_src = not (v_src) + if (src_maxval != 0) + v_src = and (v_src, src_maxval) + } + + if (v_src != 0 && src_maxval == 1) + v_src = src_value + } + + # Get v_dst. + if (need_dst) { + if (R_NOTDST(rop)) { + v_dst = not (v_dst) + if (dst_maxval != 0) + v_dst = and (v_dst, dst_maxval) + } + } + + # Apply the rasterop. + switch (opcode) { + case PIX_CLR: + pv = 0 + case PIX_SET: + pv = data + case PIX_SRC, PIX_NOTSRC: + pv = v_src + case PIX_DST, PIX_NOTDST: + pv = v_dst + case PIX_SRC_AND_DST, PIX_SRC_AND_NOTDST, PIX_NOTSRC_AND_DST: + pv = and (v_src, v_dst) + case PIX_SRC_OR_DST, PIX_SRC_OR_NOTDST, PIX_NOTSRC_OR_DST: + pv = or (v_src, v_dst) + case PIX_SRC_XOR_DST: + pv = xor (v_src, v_dst) + case PIX_NOT_SRC_AND_DST: + pv = not (and (v_src, v_dst)) + case PIX_NOT_SRC_OR_DST: + pv = not (or (v_src, v_dst)) + case PIX_NOT_SRC_XOR_DST: + pv = not (xor (v_src, v_dst)) + } + + # Mask the high bits to prevent negative values, or map int + # to bool for the case of a boolean output mask. + + if (dst_maxval == 1 && pv != 0) + pv = 1 + else if (dst_maxval > 1) + pv = and (dst_maxval, pv) + + } else + pv = v_dst + + + if (pv == 0) { + if (pll_nleft (d_dst) <= 0) { + # Output zeros at end of list. + x1 = x1 + np + } else { + # Keep going until we get a nonzero range. + o_pv = 0 + x1 = x1 + np + segsize = segsize - np + next + } + } else if (pv == o_pv) { + # Combine with previous range. + iz = o_iz + hi = o_hi + op = o_op + x1 = x1 - o_np + segsize = segsize + o_np + np = np + o_np + o_np = np + } else { + # Save current range parameters. + o_op = op + o_np = np + o_iz = iz + o_hi = hi + o_pv = pv + } + + # Encode an instruction to regenerate the current range of NP data + # values of nonzero level PV, starting at X1. In the most complex + # case we must update the high value and output a range of zeros, + # followed by a range of NP high values. If NP is 1, we can + # probably use a PN or [ID]S instruction to save space. + + nz = x1 - iz + + # Change the high value? + if (pv > 0) { + dv = pv - hi + if (dv != 0) { + # Output IH or DH instruction? + hi = pv + if (abs(dv) > I_DATAMAX) { + ll_out[op] = M_SH + and (pv, I_DATAMAX) + op = op + 1 + ll_out[op] = pv / I_SHIFT + op = op + 1 + } else { + if (dv < 0) + ll_out[op] = M_DH + (-dv) + else + ll_out[op] = M_IH + dv + op = op + 1 + + # Convert to IS or DS if range is a single pixel. + if (np == 1 && nz == 0) { + v = ll_out[op-1] + ll_out[op-1] = or (v, M_MOVE) + goto done_ + } + } + } + } + + # Output range of zeros to catch up to current range? + if (nz > 0) { + # Output the ZN instruction. + for (n=nz; n > 0; n = n - I_DATAMAX) { + ll_out[op] = M_ZN + min(I_DATAMAX,n) + op = op + 1 + } + # Convert to PN if range is a single pixel. + if (np == 1 && pv > 0) { + ll_out[op-1] = ll_out[op-1] + M_PN + 1 + goto done_ + } + # At end of list. + if (pv == 0) + goto done_ + } + + # The only thing left is the HN instruction if we get here. + for (n=np; n > 0; n = n - I_DATAMAX) { + ll_out[op] = M_HN + min(I_DATAMAX,n) + op = op + 1 + } +done_ + segsize = segsize - np + x1 = x1 + np + iz = x1 + } + + # Update the line list header. + call amovs (ll_dst, ll_out, LL_CURHDRLEN) + LL_SETLEN(ll_out, op - 1) +end -- cgit