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, ColorToHSV, 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

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;
colorAccuracy: REAL _ .1;

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: REAL] RETURNS [REAL] ~ 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 ];
$SetColorAccuracy => colorAccuracy _ 
								NARROW[ NARROW[ data, LIST OF REF ANY].first , REF REAL]^;
ENDCASE => Imager.Error[$UnimplementedSpecialOp];
RETURN[ NIL ];
};

SetUpColorMap: ImagerStdColorDisplay.SetUpMapProc ~ {
colorData: REF ImagerStdColorDisplay.ColorMapData _ NARROW[displayData.cachedColorData];
colorMap: REF ImagerStdColorDisplay.ColorSequence _
													 NEW[ImagerStdColorDisplay.ColorSequence[4]];	
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 ~ {
mapIndex, quadrant: [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]];
mapIndex _ mapEntry MOD 4;
quadrant _ MIN[mapEntry / 4, 3];  
vt.SetColor[ mapIndex, quadrant, nr, ng, nb];
};

CacheColor: ImagerStdColorDisplay.CachedColorProc ~ {
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;
IF displayData.cachedColor = NIL THEN {
minIndex: NAT;
minDist: REAL _ 2.0; 		-- max value for min. summed-squares distance in CIE space
h, s, v: REAL _ 0;
[h, s, v] _ ConstantColors.ColorToHSV[constantColor, colorData.colorCalibration];
FOR i: NAT IN [0..colorData.map.length) DO
mapHue, mapSat, mapVal: REAL;    dist: REAL;
[mapHue, mapSat, mapVal] _ ConstantColors.ColorToHSV[colorData.map[i],
																   colorData.colorCalibration];
dist _  Sqr[h -  mapHue] * 2 + Sqr[s -  mapSat] + Sqr[v -  mapVal];
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[];
};

Init[];

END.

���ImagerStd2BitDisplayImpl.mesa
Copyright c 1984 by Xerox Corporation.  All rights reserved.
Frank Crow, April 19, 1984 3:39:45 pm PST

This implements a 2-bit-per-pixel color-mapped display with no antialiasing.
Maximum summed-squares distance allowed in color matching.  Determined by trial to allow hits with 2-level color names (eg. "vivid dark bluish green")
PROC[displayData: DisplayData]
Set up 4 standard colors so that complements contrast
PROC [ color: ConstantColor, colorCalibration: ColorModels.Calibration, mapEntry: [0..1024) ]
Map entries are assumed to be in four quadrants of 4 entries each
PROC [displayData: DisplayData, color: Color]
Check for presence of color in this context's cache.
Failed completely, find closest color
Ê©��˜�Ihead1™šœ
Ïmœ1™<J™)J™�—šÏk	œ˜
Jšœ
žœ˜"Jšœžœ%˜8JšœžœB˜VJšœžœ3˜NJšœ?˜?JšœF˜FJšœžœ˜!Jšœžœ	˜Jšœžœ˜.Jšœžœ˜"Jšœžœ3˜HJšœžœ*˜;Jšœ	žœ˜!Jšœ	žœ˜Jšœžœ	˜J˜�—šœžœž˜'JšžœU˜\Jšœ˜Jšœž˜™LJ˜�—Jšœžœ˜0Jšœžœ!˜6Jšœ
žœ˜.šœžœ˜ Jšœ
žœ˜&Jšœžœžœ˜,—šœžœ˜J˜�—Jšœžœžœ˜Jšœžœžœ˜šœžœ˜JšÏc–™–—Jšœžœ˜J˜�Jšœ˜Jšœ"žœ5˜\J˜�šœ2žœ"˜WJšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ.˜.J˜J˜�—Iunitš	œžœžœ
žœžœ˜6J˜�—ašÏnœž	œ
žœžœžœžœžœ˜SM˜�—š œžœ,žœ˜<Jšžœ˜&šœ+˜+JšœJ˜J—Jšœ˜J˜�—Jš 	œžœ6˜Ešœžœ˜*Jšœ^˜^J˜J˜�—š 	œžœžœžœžœžœ˜Nšžœž˜šœŸI˜_Jšœ&žœ+˜WJšœ˜J˜—šœ?˜?Jšœžœ+˜=—Jšœ>Ÿ˜SJšœ=˜=Jšœžœ*˜<Jšœ˜Jšœ%˜%Jšœžœžœžœžœžœžœ
žœ˜BJšžœ*˜1—Jšžœžœ˜Jšœ˜J˜�—š 
œ(˜5Jšžœ™Jšœžœ&žœ˜XJšœ
žœ&˜3šœžœ*˜;Jšœ5™5—JšœJ˜JJšœG˜GJšœ!Ÿ)˜JšžœGžœ˜Nšžœžœžœžœ˜Jšœ>˜>Jšžœ˜——Jšœ˜J˜�—š 	œ)˜2JšžœY™]J™AJšœ˜Jšœ	žœ˜Jšœ˜Jšœ?˜?Jš
œžœžœžœžœžœžœ˜WJšœ1˜1Jšœ/˜/Jšœ.˜.Jšœžœ˜Jšœžœ˜"Jšœ-˜-Jšœ˜J˜�—šÏb
œ+˜5Jšžœ)™-J™4Jšœžœ&žœ˜XJšœžœ˜šžœžœž˜šœ!˜!šžœžœžœžœžœžœ˜NJšœžœ˜%Jšœ"Ÿ˜?J˜Jšžœ˜—š
žœžœžœžœžœžœž˜Pšž
œ
žœžœŸ)˜ZJšžœ
žœž˜)Jšžœžœžœ˜+—šžŸ%˜,Jšœžœ˜%Jšœ ˜ J˜—Jšžœ˜JšŸ%™%—šžœžœžœ˜'Jšœ
žœ˜Jšœ	žœŸ<˜QJšœ	žœ˜JšœQ˜Qšžœžœžœž˜*Jšœžœžœ˜,Jšœv˜vJšœC˜CJšžœžœ(˜>Jšžœ˜—šžœžœ˜!Jšœžœ
˜,Jšœ ˜ J˜—Jšœ˜—Jšœ˜—Jšžœ(˜/Jšžœžœžœ Ÿ
˜O—Jšœ˜J˜�—š œžœ˜Jšœ`Ÿ˜Jšœ-Ÿ˜JJšœ3Ÿ˜LMšœ˜J˜J˜�—˜J˜�—Jšžœ˜—�…—����j��"��