// ChatDisCurve.bcpl -- P.Baudelaire // Copyright Xerox Corporation 1979 // January 31, 1978 9:52 AM get "Chat.d" get "ChatDis.d" // outgoing procedures: external [ CurveSetup DrawCurve ] // incoming procedures: external [ Gets // SYSTEM Zero DoubleAdd BitBlt // CHATDISOPS ] // incoming statics: external [ SS // CHAT ] // local statics: static [ DCbbc // current & next computed points DColdX DColdY DCx DCy DCnewX DCnewY // clipping limits DCminX DCmaxX DCminY DCmaxY // brush height (brush width DCbw is a constant) DCbh ] // local definitions: manifest [ DCbw=16 ] let CurveSetup(r, drawMode, brushShape, brushWidth) be [CurveSetup let brush=GetBrush(brushShape, brushWidth) // clipping information (statics) DCbh=brush!0 DCminX=r>>REG.Left - DCbw DCmaxX=r>>REG.Right DCminY=r>>REG.Top - DCbh DCmaxY=r>>REG.Bottom // setup BitBlt control block DCbbc=SS>>DISV.CurveBbc DCbbc>>BBC.SBCA=brush+1 DCbbc>>BBC.Function=drawMode & 3 ]CurveSetup and DrawCurve(x0, y0, x1, y1, d1X, d1Y, d2X, d2Y, d3X, d3Y, n) be [DrawCurve // d*X & d*Y are "double precision" finite differences in special format: // bit 0 is sign // bit 1 to 31 is 2's complement fractional part // starting point, with offset for brush size: DCx=x0-DCbw/2 DCy=y0-DCbh/2 DColdX, DColdY = DCx, DCy DCnewX, DCnewY = DCx, DCy DrawPoint() let x=vec 2; x!0=DCx; x!1=#100000 // for rounding let y=vec 2; y!0=DCy; y!1=#100000 let dX=vec 2; let dY=vec 2 for j=1 to n do [ dX!1=(d1X!0) lshift 1; dX!0=not((d1X!0) ge 0) dY!1=(d1Y!0) lshift 1; dY!0=not((d1Y!0) ge 0) DoubleAdd(x, dX); DoubleAdd(y, dY) DoubleAdd(d1X, d2X); DoubleAdd(d1Y, d2Y) DoubleAdd(d2X, d3X); DoubleAdd(d2Y, d3Y) DCnewX, DCnewY = x!0, y!0 // check consecutive points in L pattern unless ((DCnewX gr DColdX) ? DCnewX-DColdX, DColdX-DCnewX) le 1 & ((DCnewY gr DColdY) ? DCnewY-DColdY, DColdY-DCnewY) le 1 then [ DrawPoint() DColdX, DColdY = DCx, DCy ] DCx, DCy = DCnewX, DCnewY ] DrawPoint() DCx=x1-DCbw/2 DCy=y1-DCbh/2 DrawPoint() ]DrawCurve and DrawPoint() be [DrawPoint // draw point (DCx,DCy) iff inside clipping window if (DCx le DCminX) % (DCx gr DCmaxX) % (DCy le DCminY) % (DCy gr DCmaxY) return test DCx ls (DCminX+DCbw) ifso [ DCbbc>>BBC.DLX= DCminX+DCbw DCbbc>>BBC.DW= DCx-DCminX DCbbc>>BBC.SLX= DCminX+DCbw-DCx ] ifnot [ DCbbc>>BBC.DLX= DCx DCbbc>>BBC.DW= ((DCx gr (DCmaxX-DCbw+1)) ? (DCmaxX-DCx+1), DCbw) DCbbc>>BBC.SLX= 0 ] test DCy ls (DCminY+DCbh) ifso [ DCbbc>>BBC.DTY= DCminY+DCbh DCbbc>>BBC.DH= DCy-DCminY DCbbc>>BBC.STY= DCminY+DCbh-DCy ] ifnot [ DCbbc>>BBC.DTY= DCy DCbbc>>BBC.DH= (DCy gr (DCmaxY-DCbh+1)) ? (DCmaxY-DCy+1), DCbh DCbbc>>BBC.STY= 0 ] BitBlt(DCbbc) ]DrawPoint and GetBrush(brushShape, brushSize) = valof [ // returns a pointer to the brush pattern (16 wide, H height) // The brush pattern is stored as: // H word // bitPattern^1,H word // // Values for brushShape are: // 0= round brush // 1= rectangular brush // 2= horizontal bar brush // 3= vertical bar brush // 4= diagonal bar brush // // brushSize is any value between 1 and 16, which will be rounded // to the values 1, 2, 4, 8, 16. let brushTable= table [ // dot 1: 1; #200; // dot 2: 2; #600; #600; // dot 4: 4; #600; #1700; #1700; #600; // dot 8: 8; #1700; #3740; #7760; #7760; #7760; #7760; #3740; #1700; // dot 16: 16; #3740; #17770; #37774; #77776; #77776; #177777; #177777; #177777; #177777; #177777; #177777; #77776; #77776; #37774; #17770; #3740; // rect 4: 4; #1700; #1700; #1700; #1700; // rect 8: 8; #7760; #7760; #7760; #7760; #7760; #7760; #7760; #7760; // rect 16: 16; #177777; #177777; #177777; #177777; #177777; #177777; #177777; #177777; #177777; #177777; #177777; #177777; #177777; #177777; #177777; #177777; // hor 2: 1; #600; // hor 4: 1; #1700; // hor 8: 1; #7760; // hor 16: 1; #17777; // ver 2: 2; #400; #400; // ver 4: 4; #400; #400; #400; #400; // ver 8: 8; #400; #400; #400; #400; #400; #400; #400; #400; // ver 16: 16; #400; #400; #400; #400; #400; #400; #400; #400; #400; #400; #400; #400; #400; #400; #400; #400; // diag 2: 2; #200; #400; // diag 4; 4; #100; #200; #400; #1000; // diag 8: 8; #20; #40; #100; #200; #400; #1000; #2000; #4000; // diag 16: 16; 1; 2; 4; #10; #20; #40; #100; #200; #400; #1000; #2000; #4000; #10000; #20000; #40000; #100000 ] manifest [ dot1=0; dot2=dot1+2; dot4=dot2+3; dot8=dot4+5; dot16=dot8+9 rect1=dot1; rect2=dot2; rect4=dot16+17; rect8=rect4+5; rect16=rect8+9 hor1=dot1; hor2=rect16+17; hor4=hor2+2; hor8=hor4+2; hor16=hor8+2 ver1=dot1; ver2=hor16+2; ver4=ver2+3; ver8=ver4+5; ver16=ver8+9 diag1=dot1; diag2=ver16+17; diag4=diag2+3; diag8=diag4+5; diag16=diag8+9 ] let brushIndexTable = table [ dot1; dot2; dot4; dot8; dot16; rect1; rect2; rect4; rect8; rect16; hor1; hor2; hor4; hor8; hor16; ver1; ver2; ver4; ver8; ver16; diag1; diag2; diag4; diag8; diag16; ] let widthRoundingTable = table [ 0; 0; 1; 1; 2; 2; 2; 3; 3; 3; 3; 3; 4; 4; 4; 4; 4 ] if brushSize gr 16 then brushSize=16 if (brushShape ls 0) % (brushShape gr 4) then brushShape=0 resultis (brushTable + brushIndexTable!(5*brushShape + widthRoundingTable!brushSize)) ]