DIRECTORY Atom, Basics, Imager, ImagerBasic, ImagerDisplay, ImagerMasks, ImagerPixelMaps, ImagerPrivate, Terminal, ImagerStdColorDisplay, Real, RealFns, ConstantColors; ImagerSmoothGrayDisplayImpl: CEDAR PROGRAM IMPORTS Atom, Basics, Imager, ImagerDisplay, ImagerMasks, ImagerPixelMaps, ImagerPrivate, Terminal, ImagerStdColorDisplay, Real, RealFns, ConstantColors ~ BEGIN DisplayClass: TYPE ~ ImagerDisplay.DisplayClass; DisplayClassRep: TYPE ~ ImagerDisplay.DisplayClassRep; DisplayData: TYPE ~ ImagerDisplay.DisplayData; DisplayDataRep: TYPE ~ ImagerDisplay.DisplayDataRep; DeviceRectangle: TYPE ~ ImagerBasic.DeviceRectangle; Color: TYPE ~ ImagerBasic.Color; ColorRep: TYPE ~ ImagerBasic.ColorRep; SampledColor: TYPE = REF ColorRep.sampled; ConstantColor: TYPE = REF ColorRep.constant; SpecialColor: TYPE = REF ColorRep.special; Mask: TYPE ~ ImagerMasks.Mask; vt: Terminal.Virtual; mode: Terminal.ColorMode ~ [full: FALSE, bitsPerPixelChannelA: 8, bitsPerPixelChannelB: 2]; bitsPerPixel: NAT ~ 10; smthGrayDisplayClass: ImagerDisplay.DisplayClass ~ NEW[ImagerDisplay.DisplayClassRep _ [ displayType: $SmoothGray, viewUnitsPerPixel: 4, Create: Create, ApplyMask: ApplyMask, DoUnderLock: ImagerStdColorDisplay.DoUnderLock ]]; Create: PROC [displayClass: DisplayClass, creationData: REF] RETURNS [displayData: DisplayData] ~ { displayData _ ImagerStdColorDisplay.Create[ vt, mode, displayClass, creationData, bitsPerPixel, SetUpColorMap]; }; SetUpColorMap: ImagerStdColorDisplay.SetUpMapProc ~ { colorData: REF ImagerStdColorDisplay.ColorMapData _ NARROW[displayData.cachedColorData]; colorMap: REF ImagerStdColorDisplay.ColorSequence _ NEW[ImagerStdColorDisplay.ColorSequence[256]]; FOR i: NAT IN [0..256) DO value: REAL _ i/255.0; colorMap[i] _ ConstantColors.RGBToColor[value, value, value, colorData.colorCalibration]; ENDLOOP; colorData.nextEntry _ 256; colorData.map _ colorMap; -- plug the map into the colorData record IF Atom.GetPropFromList[displayData.props, $PixelMapStatus] = $Displayed THEN FOR i: NAT IN [0..256) DO LoadColor[colorData.map[i], colorData.colorCalibration, i]; ENDLOOP; }; ApplyMask: PROC [displayData: DisplayData, color: Color, mask: Mask, sTranslate, fTranslate: INTEGER] ~ { LockedApplyMask: PROC ~ { WITH color SELECT FROM constantColor: ConstantColor => { pixelValue: [0..255] _ currentPixelValue; lineBuff: ARRAY [0..1034] OF INTEGER _ ALL[0]; minPixel: NAT _ 1024; maxPixel: NAT _ 0; vupp: NAT _ displayData.displayClass.viewUnitsPerPixel; squpp: NAT _ vupp*vupp; line: NAT _ CARDINAL[MAX[bb.sMin, 0]]/vupp; s: NAT _ line*vupp; sModVupp: NAT _ 0; DoLine: PROC ~ { sum: NAT _ 0; pixel: NAT _ minPixel; FOR j: NAT IN [minPixel..maxPixel] DO lineBuff[j] _ sum _ sum + lineBuff[j]; ENDLOOP; lineBuff[maxPixel+1] _ LAST[NAT]; WHILE pixel <= maxPixel DO bltStart: NAT; WHILE lineBuff[pixel] = 0 DO pixel _ pixel + 1 ENDLOOP; bltStart _ pixel; WHILE lineBuff[pixel] = squpp DO pixel _ pixel + 1 ENDLOOP; IF pixel > bltStart THEN { displayData[0].Fill[[line, bltStart, 1, pixel-bltStart], pixelValue]; }; IF pixel <= maxPixel THEN { oldValue: CARDINAL _ displayData[0].Get8Bits[line, pixel]; mix: CARDINAL _ lineBuff[pixel]; mixedValue: CARDINAL _ Basics.LongDiv[ Basics.LongMult[oldValue, squpp-mix]+Basics.LongMult[pixelValue, mix], squpp ]; displayData[0].Fill[[line, pixel, 1, 1], mixedValue]; pixel _ pixel + 1; }; ENDLOOP; lineBuff[maxPixel+1] _ 0; FOR j: NAT IN [minPixel..maxPixel] DO lineBuff[j] _ 0; ENDLOOP; minPixel _ 1024; maxPixel _ 0; }; RunProc: PROC [sMin, fMin: INTEGER, fSize: NAT] ~ { q0, r0, q1, r1: CARDINAL; f0: CARDINAL _ MIN[MAX[fMin, 0], displayData.surfaceWidth]; f1: CARDINAL _ MIN[MAX[fMin+fSize, 0], displayData.surfaceWidth]; WHILE s < sMin DO s _ s + 1; sModVupp _ sModVupp + 1; IF sModVupp = vupp THEN { DoLine[]; sModVupp _ 0; line _ line + 1; }; ENDLOOP; IF fSize > 0 THEN { [q0, r0] _ Basics.LongDivMod[f0, vupp]; [q1, r1] _ Basics.LongDivMod[f1, vupp]; IF q0 < minPixel THEN minPixel _ q0; IF q1 > maxPixel THEN maxPixel _ q1; lineBuff[q0] _ lineBuff[q0] + vupp - r0; lineBuff[q0+1] _ lineBuff[q0+1] + r0; lineBuff[q1] _ lineBuff[q1] + r1 - vupp; lineBuff[q1+1] _ lineBuff[q1+1] - r1; }; }; ImagerMasks.GenerateRuns[ mask: mask, clipper: displayData.compositeClipper, runProc: RunProc, sTranslate: sTranslate, fTranslate: fTranslate ]; RunProc[s+vupp+1, 0, 0]; }; ENDCASE => Imager.Error[$UnsupportedColorType]; }; currentPixelValue: [0..256); colorData: REF ImagerStdColorDisplay.ColorMapData _ NARROW[displayData.cachedColorData]; bb: DeviceRectangle _ ImagerMasks.BoundingBox[mask]; bb.sMin _ bb.sMin + sTranslate; bb.fMin _ bb.fMin + fTranslate; IF color # displayData.cachedColor THEN { WITH color SELECT FROM constantColor: ConstantColor => { pixelValue: CARDINAL _ constantColor.Y/256; colorData.pixelValueList _ LIST[ pixelValue ]; }; ENDCASE => Imager.Error[$UnsupportedColorType]; displayData.cachedColor _ color; }; currentPixelValue _ colorData.pixelValueList.first; smthGrayDisplayClass.DoUnderLock[displayData, LockedApplyMask, bb]; }; SpecialOp: PROC[context: Imager.Context, op: ATOM, data: REF] RETURNS[REF] ~ { SELECT op FROM $LoadColorMap => ImagerStdColorDisplay.LoadColorMap[vt, data, NARROW[context.data, ImagerDisplay.DisplayData], LoadColor ]; ENDCASE => Imager.Error[$UnimplementedSpecialOp]; RETURN[ NIL ]; }; LoadColor: ImagerStdColorDisplay.LoadColorProc ~ { mapIndex, quadrant: [0..256); r, g, b: REAL; mr, mg, mb: [0..256); [r, g, b] _ ConstantColors.ColorToRGB[color, colorCalibration]; r _ MIN[1.0, MAX[0.0, r]]; g _ MIN[1.0, MAX[0.0, g]]; b _ MIN[1.0, MAX[0.0, b]]; mr _ Real.FixC[255.0 * RealFns.Power[r, .43]]; mg _ Real.FixC[255.0 * RealFns.Power[g, .43]]; mb _ Real.FixC[255.0 * RealFns.Power[b, .43]]; mapIndex _ mapEntry MOD 256; quadrant _ mapEntry / 256; vt.SetColor[ mapIndex, quadrant, mr, mg, mb]; }; Init: PROC[] ~ { smthGrayImagerClass: ImagerPrivate.Class ~ ImagerDisplay.CreateImagerClass[smthGrayDisplayClass]; -- pick up Imager class record smthGrayImagerClass.SpecialOp _ SpecialOp; -- modify procedure bindings ImagerPrivate.RegisterDevice[smthGrayImagerClass]; -- register device class vt _ Terminal.Current[]; }; Init[]; END. PImagerSmoothGrayDisplayImpl.mesa Michael Plass, March 26, 1984 10:15:15 am PST Frank Crow, August 10, 1984 3:40:38 pm PDT This is an example implementation of an Imager display device. It implements an 8-bit-per-pixel gray-level display with antialiasing. The creationData is inherited from the Create call. Here we ignore it, but a possible use for it is to point to an alternate buffer. PROC[displayData: DisplayData] PROC [ color: ConstantColor, colorCalibration: ColorModels.Calibration, mapEntry: [0..256) ] Map entries are assumed to be in four quadrants of 256 entries each ʘJ™ J™-™*J™—šÏk œŸ˜¨J˜—šœ ˜*Jšœ”˜ ™†J˜—Jšœœ˜0Jšœœ!˜6Jšœ œ˜.Jšœœ ˜4Jšœœ˜4šœœ˜ Jšœ œ˜&Jšœœœ˜*Jšœœœ˜,Jšœœœ˜*—Jšœœ˜J˜Jšœ˜Jšœ"œ4˜[šœœ˜J˜—šœ3œ"˜XJšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ.˜.J˜J˜——šÏnœœ,œ˜˜>Jšœ˜—Jšœ˜—J™—šž œœNœ˜išžœœ˜šœœ˜šœ!˜!Jšœ)˜)Jš œ œ œœœ˜.Jšœ œ˜Jšœ œ˜Jšœœ.˜7Jšœœ ˜Jšœœœœ˜+Jšœœ ˜Jšœ œ˜šžœœ˜Jšœœ˜ Jšœœ ˜šœœœ˜%Jšœ&˜&Jšœ˜—Jšœœœ˜!šœ˜Jšœ œ˜Jšœœ ˜7Jšœ˜Jšœœ ˜;šœœ˜JšœE˜EJšœ˜—šœœ˜Jšœ œ(˜:Jšœœ˜ šœ œ˜&JšœF˜FJšœ˜J˜—Jšœ5˜5Jšœ˜Jšœ˜—Jš˜—Jšœ˜šœœœ˜%Jšœ˜Jšœ˜—Jšœ˜Jšœ ˜ Jšœ˜—šžœœœ œ˜3Jšœœ˜Jšœœœœ%˜;Jšœœœœ+˜Ašœ ˜J˜ Jšœ˜šœœ˜J˜ Jšœ ˜ Jšœ˜Jšœ˜—Jš˜—šœ œ˜Jšœ'˜'Jšœ'˜'Jšœœ˜$Jšœœ˜$Jšœ(˜(Jšœ%˜%Jšœ(˜(Jšœ%˜%Jšœ˜—Jšœ˜—šœ˜Jšœ ˜ Jšœ&˜&Jšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšœ˜J˜—Jšœ(˜/—Jšœ˜—Jšœ˜Jšœ œ&œ˜XJšœ4˜4Jšœ˜Jšœ˜šœ!œ˜)šœœ˜šœ0œœ˜OJšœ&œ˜=—Jšœ(˜/—Jšœ ˜ Jšœ˜—Jšœ3˜3JšœC˜CJšœ˜J˜—š ž œœœœœœ˜Nšœ˜Jšœ=˜=Jšœ œ*˜