// R O T A T E (PREPRESS) // BCPL/f Rotate.bcpl //ROTATE is used to rotate character descriptions (AC) by some multiple // of 90 degrees. //Last modified January 10, 1980 4:05 PM by Kerry A. LaPrade, (XEOS) // Fixed typo in RotateOne() case 0: //Modified December 19, 1979 5:38 PM by Lyle Ramshaw (PARC) to put in // rotations by other than +90, and to fix the off-by-one baseline bug. // The new version believes that the origin is located at the corner where // four pixels meet, and leaves the origin fixed under rotations. get "ix.dfs" // outgoing procedures external [ Rotate ] // outgoing statics //external // [ // ] //static // [ // ] // incoming procedures external [ //WINDOW WindowRead WindowReadBlock WindowWrite WindowWriteBlock WindowGetPosition WindowSetPosition WindowCopy WindowClose //MAPACTEMP MapACtemp //PREPRESSUTIL FSGetX FSPut MoveBlock DoubleAdd Scream //OS Usc ] // incoming statics external [ @angleToRotate ] // internal statics //static // [ // ] // File-wide structure and manifest declarations. // Procedures let Rotate(inputName,outputName;numargs na) be [ if na eq 0 then [ inputName="ACtemp";outputName="ACtemp"] MapACtemp(RotateIx, RotateOne, nil,inputName,outputName) ] and RotateIx(ix, nil) be [ unless ix>>IX.Type eq IXTypeChars then Scream("Rotate called with wrong input type") while angleToRotate ls 0 do angleToRotate = angleToRotate+360 while angleToRotate ge 360 do angleToRotate = angleToRotate-360 switchon angleToRotate into [ case 0: case 90: case 180: case 270: endcase default: Scream("Can't rotate rasters by other than multiples of 90 degrees") ] let r=ix>>IX.rotation+angleToRotate*60 //Rotated form if Usc(r, 360*60) ge 0 then r=r-360*60 ix>>IX.rotation=r ] and RotateOne(cp, si, so, nil) be [ let a=WindowRead(si) //FHEAD let ns=a<<FHEAD.ns let hw=a<<FHEAD.hw let bufSize=hw*ns let C=FSGetX(bufSize) //Space to hold the bits WindowReadBlock(si, C, bufSize) let w=cp>>CharWidth.W let h=cp>>CharWidth.H let xl=cp>>CharWidth.XL let yb=cp>>CharWidth.YB //nx,ny denote new x, new y let nw, nh, nxl, nyb = nil, nil, nil, nil switchon angleToRotate into [ case 0: nw=w; nh=h; nxl=xl; nyb=yb; endcase case 90: nw=h; nh=w; nxl=-(yb+h); nyb=xl; endcase case 180: nw=w; nh=h; nxl=-(xl+w); nyb=-(yb+h); endcase case 270: nw=h; nh=w; nxl=yb; nyb=-(xl+w); endcase ] //And fill into char descr cp>>CharWidth.W=nw cp>>CharWidth.H=nh cp>>CharWidth.XL=nxl cp>>CharWidth.YB=nyb //Now set the widths correctly let widthX, widthY = vec 1, vec 1 MoveBlock(widthX, lv cp>>CharWidth.WX, 2) MoveBlock(widthY, lv cp>>CharWidth.WY, 2) let minusWidthX, minusWidthY = vec 1, vec 1 DoubleNegate(minusWidthX, widthX) DoubleNegate(minusWidthY, widthY) switchon angleToRotate into [ case 0: MoveBlock(lv cp>>CharWidth.WX, widthX, 2) // MoveBlock(lv cp>>CharWidth.WY, widthY, w) MoveBlock(lv cp>>CharWidth.WY, widthY, 2) endcase case 90: MoveBlock(lv cp>>CharWidth.WX, minusWidthY, 2) MoveBlock(lv cp>>CharWidth.WY, widthX, 2) endcase case 180: MoveBlock(lv cp>>CharWidth.WX, minusWidthX, 2) MoveBlock(lv cp>>CharWidth.WY, minusWidthY, 2) endcase case 270: MoveBlock(lv cp>>CharWidth.WX, widthY, 2) MoveBlock(lv cp>>CharWidth.WY, minusWidthX, 2) endcase ] let nhw=(nh+15)/16 a<<FHEAD.ns=nw a<<FHEAD.hw=nhw WindowWrite(so, a) for nx=0 to nw-1 do for nwy=0 to nhw-1 do [ let nword=0 let nybase=nwy*16 for y=0 to 15 do [ let ny=y+nybase //We want to write the bit at (nx,ny) (0,0) at lower left of whole box. let ox, oy = nil, nil switchon angleToRotate into [ case 0: ox=nx; oy=ny; endcase case 90: ox=ny; oy=nw-nx-1; endcase case 180: ox=nw-nx-1; oy=nh-ny-1; endcase case 270: ox=nh-ny-1; oy=nx; endcase ] //Read bit at (ox,oy) let nbit=0 if ox ge 0 & ox ls w & oy ge 0 & oy ls h then [ let wd=C+(ox*hw)+(oy/16) nbit=@wd&(#100000 rshift (oy)) ] //Put it in word if nbit then nword=nword%(#100000 rshift y) ] WindowWrite(so, nword) ] FSPut(C) ] and DoubleNegate(dest, source) be [ dest!0 = not source!0 //take one's complement dest!1 = not source!1 DoubleAdd(dest, (table [ 0;1 ] ) ) //and add 1 ]