ImagerSmoothColorDisplayImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Frank Crow, July 30, 1984 5:50:05 pm PDT
DIRECTORY
Imager USING [Error, Context],
ImagerBasic USING [DeviceRectangle, Color, ColorRep],
ImagerDisplay USING [DisplayClass, DisplayClassRep, DisplayData, CreateImagerClass],
ImagerStdColorDisplay USING [SetUpMapProc, CachedColorProc, Create, ColorSequence,
PinPixelMap, ReleasePixelMap, LoadColorMap, DoUnderLock,
ColorMapData, LoadColorProc],
ImagerManhattan USING [Polygon],
ImagerMasks USING [Mask, BoundingBox, GenerateRuns],
ImagerPixelMaps USING [Fill, GetPixel],
ImagerPixelMapsExtras USING [MergeMaps],
ImagerPrivate USING [Class, RegisterDevice],
ColorModels USING [Calibration],
ConstantColors USING [ColorToRGB, RGBToColor],
Terminal USING [ColorMode, Current, SetRedMap, SetGreenMap, SetBlueMap, Virtual],
Atom USING [GetPropFromList],
Basics USING [LongDiv, LongDivMod, LongMult],
Real USING [FixC],
RealFns USING [Power];
ImagerSmoothColorDisplayImpl:
CEDAR
MONITOR
IMPORTS Imager, ImagerDisplay, ImagerPrivate, ConstantColors, Terminal, Real, RealFns, Atom,
ImagerMasks, ImagerPixelMaps, ImagerPixelMapsExtras, ImagerStdColorDisplay, Basics
~ BEGIN
This implements a 32-bit-per-pixel color display with antialiasing.
DisplayClass: TYPE ~ ImagerDisplay.DisplayClass;
DisplayClassRep: TYPE ~ ImagerDisplay.DisplayClassRep;
DisplayData: TYPE ~ ImagerDisplay.DisplayData;
Color:
TYPE ~ ImagerBasic.Color;
ColorRep: TYPE ~ ImagerBasic.ColorRep;
ConstantColor: TYPE = REF ColorRep.constant;
Mask:
TYPE ~ ImagerMasks.Mask;
on: BOOLEAN ~ TRUE;
off: BOOLEAN ~ FALSE;
autoMergingOn: BOOLEAN ← FALSE;
vt: Terminal.Virtual;
mode: Terminal.ColorMode ~ [full: TRUE, bitsPerPixelChannelA: 8, bitsPerPixelChannelB: 8];
bitsPerPixel: NAT ~ 32;
smthColorDisplayClass: ImagerDisplay.DisplayClass ~
NEW[ImagerDisplay.DisplayClassRep ← [
displayType: $SmoothColor,
viewUnitsPerPixel: 4,
Create: Create,
ApplyMask: ApplyMask,
DoUnderLock: ImagerStdColorDisplay.DoUnderLock
]];
ColorDisplayError: PUBLIC ERROR [reason: ATOM] ~ CODE;
Create:
PROC [displayClass: DisplayClass, creationData:
REF]
RETURNS [displayData: DisplayData] ~ {
displayData ← ImagerStdColorDisplay.Create[
vt, mode, displayClass, creationData, bitsPerPixel, SetUpColorMap];
};
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[separationNumber].Fill[[line, bltStart, 1, pixel-bltStart], pixelValue];
};
IF pixel <= maxPixel
THEN {
oldValue: CARDINAL ← displayData[separationNumber].GetPixel[line, pixel];
mix: CARDINAL ← lineBuff[pixel];
mixedValue:
CARDINAL ← Basics.LongDiv[
Basics.LongMult[oldValue, squpp-mix]+Basics.LongMult[pixelValue, mix],
squpp
];
displayData[separationNumber].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-1];
f1: CARDINAL ← MIN[MAX[fMin+fSize, 0], displayData.surfaceWidth-1];
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];
};
separationNumber: NAT;
pixelValues: LIST OF CARDINAL;
currentPixelValue: [0..256);
colorData: REF ImagerStdColorDisplay.ColorMapData ← NARROW[displayData.cachedColorData];
bb: ImagerBasic.DeviceRectangle ← ImagerMasks.BoundingBox[mask];
bb.sMin ← bb.sMin + sTranslate;
bb.fMin ← bb.fMin + fTranslate;
IF color # displayData.cachedColor THEN CacheColor[displayData, color];
pixelValues ← colorData.pixelValueList;
FOR separationNumber
IN [0..displayData.numberOfSeparations)
DO
IF pixelValues #
NIL
THEN {
currentPixelValue ← pixelValues.first; pixelValues ← pixelValues.rest;
IF Atom.GetPropFromList[displayData.props, $PixelMapStatus] = $Displayed
THEN
smthColorDisplayClass.DoUnderLock[displayData, LockedApplyMask, bb]
ELSE LockedApplyMask[];
};
ENDLOOP;
};
SpecialOp:
PROC[context: Imager.Context, op:
ATOM, data:
REF]
RETURNS[
REF] ~ {
SELECT op
FROM
$DisplayContext => {
-- Pin a pixel map to the color display, replace what was there before.
ImagerStdColorDisplay.PinPixelMap[vt, NARROW[context.data, ImagerDisplay.DisplayData],
mode ];
};
$UnDisplayContext => ImagerStdColorDisplay.ReleasePixelMap[vt,
NARROW[context.data, ImagerDisplay.DisplayData]];
$LoadColorMap => ImagerStdColorDisplay.LoadColorMap[vt, data,
NARROW[context.data, ImagerDisplay.DisplayData],
LoadColor ];
$TurnOffRGMerging => autoMergingOn ← FALSE; -- client merging of Red & Grn pixelmaps
$TurnOnRGMerging => autoMergingOn ← TRUE; -- auto merging of Red & Grn pixelmaps
$MergeRGMaps => MergeRGMaps[NARROW[context.data, ImagerDisplay.DisplayData]];
ENDCASE => Imager.Error[$UnimplementedSpecialOp];
RETURN[ NIL ];
};
MergeRGMaps:
PROC[displayData: ImagerDisplay.DisplayData] ~ {
ImagerPixelMapsExtras.MergeMaps[displayData[1], displayData[0], 8, 0];
};
LoadColor: ImagerStdColorDisplay.LoadColorProc ~ {
PROC [ color: ConstantColor, colorCalibration: ColorModels.Calibration, mapEntry: [0..1024) ]
r, g, b: REAL;
mr, mg, mb: [0..256);
IF mapEntry < 256
THEN {
[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]];
vt.SetRedMap[mapEntry, mr];
vt.SetGreenMap[mapEntry, mg];
vt.SetBlueMap[mapEntry, mb];
};
};
SetUpColorMap: ImagerStdColorDisplay.SetUpMapProc ~ {
PROC[displayData: DisplayData]
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;
};
CacheColor: ImagerStdColorDisplay.CachedColorProc ~ {
PROC [displayData: DisplayData, color: Color]
Convert color to RGB and cache merged RG value plus blue for subsequent writes
colorData: REF ImagerStdColorDisplay.ColorMapData ← NARROW[displayData.cachedColorData];
WITH color
SELECT
FROM
constantColor: ConstantColor => {
r, g, b: REAL;
nr, ng, nb: CARDINAL;
[r, g, b] ← ConstantColors.ColorToRGB[constantColor, colorData.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]];
nr ← Real.FixC[255.0 * r]; ng ← Real.FixC[255.0 * g]; nb ← Real.FixC[255.0 * b];
displayData.cachedColor ← color;
colorData.pixelValueList ← LIST[ nr, ng, nb];
};
ENDCASE => Imager.Error[$UnsupportedColorType];
};
Init:
PROC[] ~ {
smthColorImagerClass: ImagerPrivate.Class ~ ImagerDisplay.CreateImagerClass[smthColorDisplayClass]; -- pick up Imager class record
smthColorImagerClass.SpecialOp ← SpecialOp; -- modify procedure bindings
ImagerPrivate.RegisterDevice[smthColorImagerClass]; -- register device class
vt ← Terminal.Current[];
};
END.