ImagerStd2BitDisplayImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Frank Crow, April 19, 1984 3:39:45 pm PST
DIRECTORY
Imager USING [Error, Context],
ImagerBasic USING [DeviceRectangle, Color, ColorRep],
ImagerDisplay USING [DisplayClass, DisplayClassRep, DisplayData, CreateImagerClass],
ImagerStdColorDisplay USING [SetUpMapProc, CachedColorProc, Create, ApplyMask,
LoadColorMap, DoUnderLock, ColorMapData, MoveOverlay,
ColorSequence, PinPixelMap, ReleasePixelMap, LoadColorProc],
ImagerManhattan USING [Polygon],
ImagerMasks USING [Mask],
ImagerPrivate USING [Class, RegisterDevice],
ColorModels USING [Calibration],
ConstantColors USING [ColorToRGB, black, white, red, cyan],
Terminal USING [ColorMode, Current, SetColor, Virtual],
Atom USING [GetPropFromList],
Real USING [FixC],
RealFns USING [Power];
ImagerStd2BitDisplayImpl:
CEDAR
MONITOR
IMPORTS Imager, ImagerDisplay, ImagerPrivate, ConstantColors, Terminal, Real, RealFns, Atom,
ImagerStdColorDisplay
~ BEGIN
This implements a 2-bit-per-pixel color-mapped display with no 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;
bitsPerPixel:
NAT ~ 4;
Maximum summed-squares distance allowed in color matching. Determined by trial to allow hits with 2-level color names (eg. "vivid dark bluish green")
colorAccuracy: NAT ~ 8192;
vt: Terminal.Virtual;
mode: Terminal.ColorMode ~ [full: FALSE, bitsPerPixelChannelA: 2, bitsPerPixelChannelB: 2];
std2BitDisplayClass: ImagerDisplay.DisplayClass ~
NEW[ImagerDisplay.DisplayClassRep ← [
displayType: $Std2bpp,
viewUnitsPerPixel: 1,
Create: Create,
ApplyMask: ApplyMask,
DoUnderLock: ImagerStdColorDisplay.DoUnderLock
]];
ColorDisplayError: PUBLIC ERROR [reason: ATOM] ~ CODE;
Sqr:
PROCEDURE [number:
INT]
RETURNS [
INT] ~
INLINE {
RETURN[number * number]; };
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] ~ {
ImagerStdColorDisplay.ApplyMask[displayData, color, mask, sTranslate, fTranslate, CacheColor];
};
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]];
$MoveOverlay => ImagerStdColorDisplay.MoveOverlay[vt, data]; -- change DCB offsets
$LoadColorMap => ImagerStdColorDisplay.LoadColorMap[vt, data,
NARROW[context.data, ImagerDisplay.DisplayData],
LoadColor ];
ENDCASE => Imager.Error[$UnimplementedSpecialOp];
RETURN[ NIL ];
};
SetUpColorMap: ImagerStdColorDisplay.SetUpMapProc ~ {
PROC[displayData: DisplayData]
colorData: REF ImagerStdColorDisplay.ColorMapData ← NARROW[displayData.cachedColorData];
colorMap: REF ImagerStdColorDisplay.ColorSequence ←
NEW[ImagerStdColorDisplay.ColorSequence[4]];
Set up 4 standard colors so that complements contrast
colorMap[0] ← ConstantColors.black; colorMap[3] ← ConstantColors.white;
colorMap[1] ← ConstantColors.red; colorMap[2] ← ConstantColors.cyan;
colorData.map ← colorMap; -- plug the map into the colorData record
IF Atom.GetPropFromList[displayData.props, $PixelMapStatus] = $Displayed
THEN
FOR i:
NAT
IN [0..4)
DO
LoadColor[colorData.map[i], colorData.colorCalibration, i];
ENDLOOP;
};
LoadColor: ImagerStdColorDisplay.LoadColorProc ~ {
PROC [ color: ConstantColor, colorCalibration: ColorModels.Calibration, mapEntry: [0..256) ]
r, g, b: REAL;
nr, ng, nb: [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]];
nr ← Real.FixC[255.0 * RealFns.Power[r, .43]];
ng ← Real.FixC[255.0 * RealFns.Power[g, .43]];
nb ← Real.FixC[255.0 * RealFns.Power[b, .43]];
vt.SetColor[ mapEntry, 0, nr, ng, nb];
};
CacheColor: ImagerStdColorDisplay.CachedColorProc ~ {
PROC [displayData: DisplayData, color: Color]
Check for presence of color in this context's cache.
colorData: REF ImagerStdColorDisplay.ColorMapData ← NARROW[displayData.cachedColorData];
displayData.cachedColor ← NIL;
WITH color
SELECT
FROM
constantColor: ConstantColor => {
FOR i:
NAT
IN [0..colorData.map.length)
DO
IF color = colorData.map[i]
THEN {
colorData.pixelValueList ← LIST[ i ];
displayData.cachedColor ← color; -- already in colormap
};
ENDLOOP;
IF displayData.cachedColor =
NIL
THEN
FOR i:
NAT
IN [0..colorData.map.length)
DO
IF constantColor
.x = colorData.map[i]
.x
-- check if identical to a previous color
AND constantColor.y = colorData.map[i].y
AND constantColor.Y = colorData.map[i].Y
THEN {
-- already in colormap
colorData.pixelValueList ← LIST[ i ];
displayData.cachedColor ← color;
};
ENDLOOP;
Failed completely, find closest color
IF displayData.cachedColor =
NIL
THEN {
minDist, minIndex: INT ← LAST[INT]; -- min. summed-squares distance in r, g, b space
FOR i:
NAT
IN [0..colorData.map.length)
DO
dist: INT ← Sqr[constantColor.x - INT[colorData.map[i].x]]
+ Sqr[constantColor.y - INT[colorData.map[i].y]]
+ Sqr[constantColor.Y - INT[colorData.map[i].Y]];
IF dist < minDist THEN { minIndex ← i; minDist ← dist; };
ENDLOOP;
IF minDist < colorAccuracy
THEN {
colorData.pixelValueList ← LIST[ minIndex ];
displayData.cachedColor ← color;
};
};
};
ENDCASE => Imager.Error[$UnsupportedColorType];
IF displayData.cachedColor = NIL THEN Imager.Error[$CantMatchColor]; -- sorry!
};
Init:
PROC[] ~ {
std2BitImagerClass: ImagerPrivate.Class ~ ImagerDisplay.CreateImagerClass[std2BitDisplayClass]; -- pick up Imager class record
std2BitImagerClass.SpecialOp ← SpecialOp; -- modify procedure bindings
ImagerPrivate.RegisterDevice[std2BitImagerClass]; -- register device class
vt ← Terminal.Current[];
};
END.