DIRECTORY FileIO, GraphicsBasic, CGArea USING [Empty, Ref, Remove], GraphicsToPress, GraphicsToPressPrivate, CGContext USING [Ref], CGDevice USING [Ref, Rep], CGMatrix USING [Inv, InvRel, Make, Ref], CGSource USING [Mode, Ref, Type], CGStorage USING [qZone], IO, SirPress, Inline, Graphics, GraphicsColor USING [Color, ColorToHSV], Rope, Real USING [Fix, FixC, RoundLI]; GraphicsToPressImpl: CEDAR MONITOR IMPORTS FileIO, CGArea, CGMatrix, CGStorage, Inline, Real, SirPress, GraphicsColor, Graphics EXPORTS GraphicsBasic, GraphicsToPress, GraphicsToPressPrivate = { ROPE: TYPE = Rope.ROPE; DeviceObject: PUBLIC TYPE = CGDevice.Rep; dataZone: ZONE = CGStorage.qZone; repZone: ZONE = CGStorage.qZone; Error: SIGNAL = CODE; Data: TYPE = REF DataRep; DataRep: TYPE = RECORD [ ph:SirPress.PressHandle, unit: INT, fatness: REAL, halftoneSubsamplingFactor: REAL, matrix: CGMatrix.Ref -- base transformation matrix ]; NewContext: PUBLIC PROCEDURE [fileName: ROPE, resolution: REAL] RETURNS [Graphics.Context] = {RETURN[NewContextFromStream[FileIO.Open[fileName, overwrite], fileName, resolution]]}; NewContextFromStream: PUBLIC PROC [ outputStream: IO.STREAM, fileNameForHeaderPage: ROPE _ NIL, resolution: REAL _ 384 -- in bits per inch ] RETURNS [Graphics.Context] = { RETURN[NewContextFromSirPressHandle[ SirPress.Create[outputStream, fileNameForHeaderPage], resolution ]]; }; NewContextFromSirPressHandle: PUBLIC PROC [ pressHandle: SirPress.PressHandle, resolution: REAL -- in bits per inch ] RETURNS [Graphics.Context] = { s: REAL _ resolution/72.0; data: Data _ dataZone.NEW[DataRep _ [ ph: pressHandle, unit: Real.RoundLI[SirPress.pt/s], fatness: 0.2, halftoneSubsamplingFactor: 5, matrix: CGMatrix.Make[[s,0,0,s,0,0]] ]]; context: Graphics.Context _ Graphics.NewContext[repZone.NEW[CGDevice.Rep _ [ GetMatrix: GetMatrix, GetBounds: GetBounds, Show: Show, GetRaster: GetRaster, data: data ]]]; SirPress.SetColor[pressHandle,0,0,0]; RETURN[context]; }; SirPressHandle: PUBLIC PROC [context: Graphics.Context] RETURNS [SirPress.PressHandle] = { contextRef: CGContext.Ref _ NARROW[context.data]; deviceRef: CGDevice.Ref _ contextRef.device; data: Data _ NARROW[deviceRef.data]; RETURN[data.ph]; }; Close: PUBLIC PROC [context: Graphics.Context] = { SirPressHandle[context].ClosePress[]; }; SetPageSize: PUBLIC PROC [context: Graphics.Context, width: REAL, height: REAL] = { SirPressHandle[context].SetPageSize[ height: Real.RoundLI[height*SirPress.pt], width: Real.RoundLI[width*SirPress.pt], unit: 1 ]; }; GetMatrix: SAFE PROC[self: CGDevice.Ref] RETURNS [CGMatrix.Ref] = CHECKED { data: Data _ NARROW[self.data]; RETURN[data.matrix]; }; GetBounds: SAFE PROC[self: CGDevice.Ref] RETURNS [GraphicsBasic.Box] = CHECKED { data: Data _ NARROW[self.data]; e: REAL = 0.1; -- small fudge factor RETURN[[xmin: e, ymin: e, xmax: 17*SirPress.in/(2*data.unit)-e, ymax: 11*SirPress.in/data.unit-e]]; }; GetRaster: SAFE PROC[self: CGDevice.Ref] RETURNS [LONG POINTER,CARDINAL] = CHECKED { RETURN[NIL,0]; }; Show: SAFE PROC[self: CGDevice.Ref, area: CGArea.Ref, src: CGSource.Ref, map: CGMatrix.Ref] = TRUSTED { data: Data _ NARROW[self.data]; SetColor[data.ph,src.color]; UNTIL CGArea.Empty[area] DO trap: GraphicsBasic.Trap _ CGArea.Remove[area]; ShowTrap[data,trap,src,map]; ENDLOOP; }; SetColor: PROC[pressHandle: SirPress.PressHandle, color: GraphicsColor.Color] = { h,s,v: REAL; [h,s,v] _ GraphicsColor.ColorToHSV[color]; SirPress.SetColor[pressHandle,Real.RoundLI[h*240],Real.RoundLI[s*255],Real.RoundLI[v*255]]; }; ScreenAngle: PROC[color: GraphicsColor.Color] RETURNS [INTEGER] = { h,s,v: REAL; [h,s,v] _ GraphicsColor.ColorToHSV[color]; RETURN[RndI[105 - 90*h] MOD 90]; }; Store: PROC [scanLine: REF SirPress.ScanLine, index: NAT, sample: CARDINAL] = { WITH scanLine: scanLine SELECT FROM bitMap => scanLine[index] _ sample; bitSampled => scanLine[index] _ sample; bitBitSampled => scanLine[index] _ sample; nybbleSampled => scanLine[index] _ sample; byteSampled => scanLine[index] _ sample; ENDCASE => ERROR; }; Bot: PROC[r: REAL] RETURNS [CARDINAL] = INLINE { RETURN[Real.FixC[r]] }; Top: PROC[r: REAL] RETURNS [CARDINAL] = INLINE { RETURN[Real.FixC[r]+1] }; Fix: PROC[r: REAL] RETURNS [CARDINAL] = INLINE { RETURN[Real.FixC[r]] }; Rnd: PROC[r: REAL] RETURNS [CARDINAL] = INLINE { RETURN[Real.FixC[r+.5]] }; RndI: PROC[r: REAL] RETURNS [INTEGER] = INLINE { RETURN[Real.FixC[r+(LAST [INTEGER]+.5)]-LAST[INTEGER]] }; RndUp: PROC[c, m: CARDINAL] RETURNS [CARDINAL] = INLINE {RETURN[(c+(m-1))/m*m]}; White: PROC[bitsPerSample: [0..16]] RETURNS [intensity: CARDINAL] = { intensity _ Inline.BITSHIFT[1, bitsPerSample]; intensity _ intensity-1; }; Line1: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..1B]]; Line2: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..3B]]; Line4: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..17B]]; Line8: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..377B]]; AGet: PROC[src: CGSource.Ref, x,y: CARDINAL] RETURNS[CARDINAL] = TRUSTED INLINE { xline: LONG POINTER _ src.xbase + Inline.LongMult[y,src.xrast]; SELECT src.bps FROM 0,1 => RETURN[LOOPHOLE[xline, LONG POINTER TO Line1][x]]; 2 => RETURN[LOOPHOLE[xline, LONG POINTER TO Line2][x]]; 4 => RETURN[LOOPHOLE[xline, LONG POINTER TO Line4][x]]; 8 => RETURN[LOOPHOLE[xline, LONG POINTER TO Line8][x]]; ENDCASE => ERROR; }; Frac: TYPE = Inline.LongNumber; fscl: Frac = [num[lowbits: 0, highbits: 1]]; FixF: PROC[r: REAL] RETURNS[Frac] = INLINE { RETURN[[li[Real.Fix[r*fscl.li]]]] }; FltF: PROC[f: Frac] RETURNS[REAL] = INLINE { r: REAL _ f.li; RETURN[r/fscl.li] }; AddF: PROC[a,b: Frac] RETURNS[Frac] = INLINE { RETURN[[li[a.li+b.li]]] }; IntF: PROC[f: Frac] RETURNS[INTEGER] = INLINE { RETURN[LOOPHOLE[f.highbits, INTEGER]] }; ShowTrap: ENTRY PROC[data: Data, trap: GraphicsBasic.Trap, src: CGSource.Ref, map: CGMatrix.Ref] = TRUSTED { type: CGSource.Type _ src.type; easy: BOOLEAN _ (SELECT type FROM const => TRUE, -- always easy array, tile => FALSE, -- Not easy proc => FALSE, -- never easy ENDCASE => ERROR); fat: BOOLEAN _ src.fat; yb, yt, yl, xl, xr: CARDINAL _ 0; rdxl, rdxr: REAL _ 0; -- left and right x increments rsdx, rsdy: REAL _ 0; -- increments for source position fsdx, fsdy: Frac; mode: CGSource.Mode _ src.mode; white: CARDINAL _ White[src.bps]; PutTrap: PROC[xbotL, xtopL, xtopR, xbotR, ybot, ytop: INT] = TRUSTED { IF xbotL=xtopL AND xbotR=xtopR THEN SirPress.PutRectangle[data.ph, xbotL, ybot, xbotR-xbotL, ytop-ybot, data.unit] ELSE { SirPress.StartOutline[data.ph]; SirPress.PutMoveTo[data.ph, xbotL, ybot, data.unit]; SirPress.PutDrawTo[data.ph, xtopL, ytop, data.unit]; SirPress.PutDrawTo[data.ph, xtopR, ytop, data.unit]; SirPress.PutDrawTo[data.ph, xbotR, ybot, data.unit]; SirPress.EndOutline[data.ph]; } }; IF fat THEN { yb_Bot[trap.ybot]; yt_Top[trap.ytop] } ELSE { yb_Rnd[trap.ybot]; yt_Rnd[trap.ytop] }; IF ybyt OR fat THEN SIGNAL Error; RETURN }; IF easy THEN { --constant color trapezoid IF fat THEN PutTrap[ xbotL: Bot[trap.xbotL], xtopL: Bot[trap.xtopL], xtopR: Top[trap.xtopR], xbotR: Top[trap.xbotR], ybot: yb, ytop: yt ] ELSE PutTrap[ xbotL: Rnd[trap.xbotL], xtopL: Rnd[trap.xtopL], xtopR: Rnd[trap.xtopR], xbotR: Rnd[trap.xbotR], ybot: yb, ytop: yt ] } ELSE { --going to put out a showbits command with carefully placed 0's scanLine: REF SirPress.ScanLine; scanLineOrigin: CARDINAL _ Bot[MIN[trap.xbotL, trap.xtopL]]; scanLineEnd: CARDINAL _ Top[MAX[trap.xbotR, trap.xtopR]]; scanLineLength: CARDINAL _ SELECT src.bps FROM 0 => RndUp[scanLineEnd - scanLineOrigin, 16], 1 => RndUp[scanLineEnd - scanLineOrigin, 16], 2 => RndUp[scanLineEnd - scanLineOrigin, 8], 4 => RndUp[scanLineEnd - scanLineOrigin, 4], 8 => RndUp[scanLineEnd - scanLineOrigin, 2], ENDCASE => ERROR; DoLine: PROC[xmin, xmax, y: CARDINAL] = TRUSTED { rsx, rsy: REAL; -- current source position fsx, fsy: Frac; sx, sy: CARDINAL; -- truncated source position s: CARDINAL; -- sample value from source FOR x: CARDINAL IN [scanLineOrigin..xmin) DO Store[scanLine, x-scanLineOrigin, white] ENDLOOP; FOR x: CARDINAL IN [xmin..xmax) DO --put in the rest of the samples IF x=xmin THEN { [[rsx,rsy]] _ CGMatrix.Inv[map,[x+0.5,y+0.5]]; fsx _ FixF[rsx]; fsy _ FixF[rsy]; } ELSE { fsx _ AddF[fsx,fsdx]; fsy _ AddF[fsy,fsdy]}; IF type=proc THEN s _ src.Get[FltF[fsx], FltF[fsy]] ELSE { sx _ IntF[fsx]; sy _ IntF[fsy]; s _ AGet[src, sx, sy] }; Store[scanLine, x-scanLineOrigin, s] ENDLOOP; FOR x: CARDINAL IN [xmax..scanLineEnd) DO Store[scanLine, x-scanLineOrigin, white] ENDLOOP; SirPress.ShowLine[data.ph, scanLine]; }; SELECT src.bps FROM 0 => scanLine _ NEW[SirPress.ScanLine[bitMap][scanLineLength]]; 1 => scanLine _ NEW[SirPress.ScanLine[bitSampled][scanLineLength]]; 2 => scanLine _ NEW[SirPress.ScanLine[bitBitSampled][scanLineLength]]; 4 => scanLine _ NEW[SirPress.ScanLine[nybbleSampled][scanLineLength]]; 8 => scanLine _ NEW[SirPress.ScanLine[byteSampled][scanLineLength]]; ENDCASE => ERROR; FOR i: NAT IN [scanLineEnd-scanLineOrigin..scanLineLength) DO Store[scanLine, i, white] ENDLOOP; IF src.mode=opaque THEN { SirPress.SetColor[data.ph, 0, 0, 255]; PutTrap[ xbotL: Rnd[trap.xbotL], xtopL: Rnd[trap.xtopL], xtopR: Rnd[trap.xtopR], xbotR: Rnd[trap.xbotR], ybot: yb, ytop: yt ]; SetColor[data.ph, src.color]; }; SirPress.BeginScannedRectangle[ p: data.ph, x: scanLineOrigin, y: yb, dotsPerLine: scanLineLength, numberOfLines: yt-yb, width: scanLineLength, height: yt-yb, unit: data.unit, nextLineDirection: up, nextDotDirection: right, coding: scanLine.coding, samplingProperties: [screenAngle: ScreenAngle[src.color]] ]; [[rsdx, rsdy]] _ CGMatrix.InvRel[map,[1,0]]; rsdx _ rsdx; rsdy _ rsdy; fsdx _ FixF[rsdx]; fsdy _ FixF[rsdy]; rdxl_(trap.xtopL-trap.xbotL); -- delta x, left rdxr_(trap.xtopR-trap.xbotR); -- delta x, right IF NOT(fat AND yb=yl) THEN { rdy: REAL_trap.ytop-trap.ybot; -- delta y rdxl_rdxl/rdy; rdxr_rdxr/rdy; -- dx/dy, left right }; IF fat THEN { rxlb, rxrb, rxlt, rxrt: REAL _ 0; -- x at bottom and top of current line ltop: BOOLEAN _ rdxl<0; -- TRUE means leftmost x is at top of line rtop: BOOLEAN _ rdxr>0; -- TRUE means rightmost x is at top of line FOR y: CARDINAL IN[yb..yl] DO -- for each scan line IF y=yb THEN { rxlb_trap.xbotL; rxrb_trap.xbotR } -- first line ELSE { rxlb_rxlt; rxrb_rxrt }; -- successive lines IF y=yl THEN { rxlt_trap.xtopL; rxrt_trap.xtopR } -- last line ELSE IF y=yb THEN { -- first line, if yl>yb d: REAL_(yb+1)-trap.ybot; -- distance to top of line rxlt_rxlb+d*rdxl; rxrt_rxrb+d*rdxr } ELSE { rxlt_rxlb+rdxl; rxrt_rxrb+rdxr }; -- middle lines xl_Bot[IF ltop THEN rxlt ELSE rxlb]; xr_Top[IF rtop THEN rxrt ELSE rxrb]; DoLine[xmin: xl, xmax: xr, y: y]; ENDLOOP; } ELSE { rxl, rxr: REAL _ 0; -- left and right x at middle of current line FOR y: CARDINAL IN[yb..yl] DO -- for each scan line IF y=yb THEN { -- first line d: REAL_(yb+0.5)-trap.ybot; -- distance to middle of line rxl_trap.xbotL+d*rdxl; rxr_trap.xbotR+d*rdxr } ELSE { rxl_rxl+rdxl; rxr_rxr+rdxr }; -- successive lines xl_Rnd[rxl]; xr_Rnd[rxr]; DoLine[xl,xr,y]; ENDLOOP; }; SirPress.EndScannedRectangle[data.ph]; }; }; }. GraphicsToPressImpl.mesa Last changed by Doug Wyatt, April 21, 1982 3:59 pm Last changed by Warnock June 4, 1982 1:38 pm Last changed by Michael Plass December 6, 1982 12:22 pm Last Edited by: Lamming, December 16, 1982 9:57 am main code for ShowTrap starts here compute yb (bottom of first scanline) and yt (top of last scanline) allocate storage for a scan line. Get a sample from the source if opaque, then blot out the trapezoidal region set up for getting samples out of a sampled source set up for the scan converter Κ 9– "Cedar" style˜Jšœ™JšΟc2™2Jš,™,Jšœ™7J™2unitšΟk ˜ J˜J˜Jšœžœ˜"Jšœ˜Jšœ˜Jšœ žœ˜Jšœ žœ ˜Jšœ žœ˜(Jšœ žœ˜!Jšœ žœ ˜J˜J˜ J˜J˜ Jšœžœ˜(Jšœ˜Jšœžœ˜ —šœžœž˜"šž˜J˜T—Jšžœ;˜B—Kšžœžœžœ˜Kšœ žœžœ˜)Kšœ žœ˜!Jšœ žœ˜ Kšœžœžœ˜Kšœžœžœ ˜šœ žœžœ˜J˜Jšœžœ˜ Jšœ žœ˜Jšœžœ˜ Jšœ˜2J˜—š Οn œžœž œ žœžœ˜?Jšžœ˜JšœžœP˜W—šŸœžœžœ˜#Jšœžœžœ˜Jšœžœžœ˜"Jšœ žœ˜*Jšœžœ˜ šžœ˜$Jšœ5˜5Jšœ ˜ Jšœ˜—J˜—šŸœžœžœ˜+J˜"Jšœ žœ˜$Jšœžœ˜ Jšœžœ˜šœžœ ˜%J˜J˜"J˜ J˜J˜$J˜—šœ8žœ˜LJ˜J˜J˜ J˜J˜ J˜—J˜%Jšžœ ˜J˜—šŸœžœžœžœ˜ZJšœžœ˜1Jšœ,˜,Jšœ žœ˜$Jšžœ ˜Jšœ˜—šŸœžœžœ ˜2Jšœ%˜%Jšœ˜—š Ÿ œžœžœ$žœ žœ˜Sšœ$˜$Jšœ)˜)Jšœ'˜'Jšœ˜Jšœ˜—Jšœ˜—š Ÿ œžœžœžœžœ˜KJšœ žœ ˜Jšžœ˜J˜—š Ÿ œžœžœžœžœ˜PJšœ žœ ˜Jšœžœ˜$Jšžœ]˜cJ˜—šŸ œžœžœžœžœžœžœžœ˜TJšžœžœ˜J˜—šŸœžœžœOžœ˜gJšœ žœ ˜J˜šžœž˜J˜/J˜Jšžœ˜—J˜—šŸœžœC˜QJšœžœ˜ J˜*J˜[J˜—šŸ œžœžœžœ˜CJšœžœ˜ J˜*Jšžœžœ˜ J˜—š Ÿœžœ žœžœ žœ˜Ošžœžœž˜#J˜#J˜'J˜*J˜*J˜(Jšžœžœ˜—J˜—KšŸœžœžœžœžœžœžœ˜HJšŸœžœžœžœžœžœžœ˜JJšŸœžœžœžœžœžœžœ˜HJšŸœžœžœžœžœžœžœ˜Kš Ÿœžœžœžœžœžœ˜0Jš žœžœžœžœžœ˜9—KšŸœžœžœžœžœžœžœ˜PšŸœžœžœ žœ˜EJšœžœ˜.J˜J˜—Kšœžœžœžœžœžœžœžœ ˜CJšœžœžœžœžœžœžœžœ ˜CJšœžœžœžœžœžœžœžœ ˜DJšœžœžœžœžœžœžœžœ ˜Eš Ÿœžœžœžœžœžœ˜QJšœžœžœ,˜?šžœ ž˜Jš œžœžœžœžœžœ ˜9Jš œžœžœžœžœžœ ˜7Jš œžœžœžœžœžœ ˜7Jš œžœžœžœžœžœ ˜7Jšžœžœ˜—J˜—Kšœžœ˜J˜,š Ÿœžœžœžœ žœ˜,Jšžœ˜$—š Ÿœžœ žœžœžœ˜,Jšœžœ žœ˜$—šŸœžœ žœ žœ˜.Jšžœ˜—š Ÿœžœ žœžœžœ˜/Jšžœžœ žœ˜(—šŸœžœžœOžœ˜lJ˜šœžœžœž˜!Jšœ žœ˜Jšœžœ ˜"Jšœžœ ˜Jšžœžœ˜—Jšœžœ ˜Jšœžœ˜!Jšœ žœ˜4Jšœ žœ!˜7J˜J˜Jšœžœ˜!šŸœžœ)žœžœ˜Gšžœ žœ ž˜#J˜N—šžœ˜J˜J˜4J˜4J˜4J˜4J˜J˜—J˜—Jšœ ™"JšC™CJšžœžœ)˜4Jšžœ*˜.Jšžœžœ ˜(Jš žœžœžœžœžœžœ˜3šžœžœ˜*šžœž˜ ˜J˜J˜J˜J˜J˜ J˜J˜——šžœ ˜ J˜J˜J˜J˜J˜ J˜J˜—J˜—šžœ?˜GJšœ žœ˜ Jš!™!Jšœžœžœ˜šžœžœžœ˜+Jšœžœ˜4J˜$—Jšžœ%˜8Jšœžœžœžœ˜$Jšœžœžœžœ˜$Jšœ!˜!Jšžœ˜—J˜—šžœ˜Jšœ žœ-˜Aš žœžœžœ žœ˜3šžœžœ ˜Jšœžœ˜9J˜.—Jšžœ!˜8J˜Jšœ˜Jšžœ˜—J˜—J˜&J˜—J˜—J˜J˜J˜—…—+`:«