ColorPatchImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Written by: Maureen Stone August 15, 1985 10:17:43 pm PDT
Avi Naiman, September 8, 1985 7:53:15 pm PDT
DIRECTORY
ColorPatch,
CGColorWithCIE,
Imager USING [Box, Context, MaskBox, SetColor, white],
ImagerColor USING [ConstantColor, RGB, ColorFromRGB],
ImagerColorMap USING [LoadEntries, MapEntry],
ImagerDitheredDevice USING [ColorFromSpecialRGB],
Real USING [RoundC],
ViewerClasses USING [Column, PaintProc, Viewer, ViewerClass, ViewerClassRec, DestroyProc],
ViewerOps USING [CreateViewer, RegisterViewerClass],
Terminal USING [Current, ChannelValue, ColorValue]
;
ColorPatchImpl: CEDAR PROGRAM
IMPORTS Imager, ImagerColorMap, ImagerDitheredDevice, ViewerOps, ImagerColor, CGColorWithCIE, Real, Terminal
EXPORTS ColorPatch
~ BEGIN OPEN ColorPatch;
Viewer: TYPE = ViewerClasses.Viewer;
ColorPatchViewer: TYPE = ViewerClasses.Viewer;
MakeColorPatch: PUBLIC PROCEDURE[parent: Viewer, wx, wy, width, height: CARDINAL] RETURNS[ColorPatchViewer] = {
viewer: ColorPatchViewer;
instanceData: ColorPatchData ← NEW[ColorPatchDataRec];
instanceData.box ← [xmin: 0, ymin: 0, xmax: width, ymax: height];
viewer ← ViewerOps.CreateViewer[
flavor: $ColorPatch,
info: [
parent: parent,
wx: wx,
wy: wy,
ww: width,
wh: height,
data: instanceData,
scrollable: FALSE],
paint: FALSE
];
RETURN[viewer];
};
PaintColorPatch: ViewerClasses.PaintProc = {
patchData: ColorPatchData ← NARROW[self.data];
patchColor: ImagerColor.ConstantColor ← ImagerColor.ColorFromRGB[patchData.rgb];
rgbContrastColor: ImagerColor.RGB ← CGColorWithCIE.ContrastInRGB[patchData.rgb];
hsvContrastColor: ImagerColor.RGB ← CGColorWithCIE.ContrastInHSV[patchData.rgb];
hslContrastColor: ImagerColor.RGB ← CGColorWithCIE.ContrastInHSL[patchData.rgb];
yiqContrastColor: ImagerColor.RGB ← CGColorWithCIE.ContrastInYIQ[patchData.rgb];
argybContrastColor: ImagerColor.RGB ← CGColorWithCIE.ContrastInARgYb[patchData.rgb];
contrastWidth: CARDINALIF patchData.interpolationRequest = off THEN 50 ELSE 40;
contrastHeight: CARDINALIF patchData.interpolationRequest = off THEN 50 ELSE 40;
stripW: REAL ← 16;
boxW: REAL ← patchData.box.xmax-patchData.box.xmin;
interpolationBarHeight: REAL = IF patchData.interpolationRequest = off THEN 0 ELSE 50;
numberInterpolationElements: INT = 16;
widthInterpolationElement: REAL = 10;
border: REAL = IF patchData.interpolationRequest = off THEN 10 ELSE 6;
hsvContrastBox: Imager.Box ← [xmin: border, ymin: patchData.box.ymax - border - contrastHeight, xmax: border + contrastWidth, ymax: patchData.box.ymax - border];
hslContrastBox: Imager.Box ← [xmin: border, ymin: interpolationBarHeight + border, xmax: border + contrastWidth, ymax: interpolationBarHeight + contrastHeight + border];
rgbContrastBox: Imager.Box ← [xmin: boxW/2.0 - contrastWidth/2.0, ymin: patchData.box.ymax - border - contrastHeight, xmax: boxW/2.0 - contrastWidth/2.0 + contrastWidth, ymax: patchData.box.ymax - border];
yiqContrastBox: Imager.Box ← [xmin: patchData.box.xmax - contrastWidth - border, ymin: patchData.box.ymax - border - contrastHeight, xmax: patchData.box.xmax - border, ymax: patchData.box.ymax - border];
argybContrastBox: Imager.Box ← [xmin: patchData.box.xmax - contrastWidth - border, ymin: interpolationBarHeight + border, xmax: patchData.box.xmax - border, ymax: interpolationBarHeight + contrastHeight + border];
w: REALIF patchData.separate THEN (boxW-stripW)/2.0 ELSE boxW/2.0;
IF patchData.dither THEN {
box: Imager.Box ← [xmin: 0, ymin: interpolationBarHeight, xmax: w, ymax: patchData.box.ymax];
rx: REAL; --position of the next (rightmost) x value
Do the dithered box
Imager.SetColor[context, patchColor];
Imager.MaskBox[context, box];
rx ← w;
IF patchData.separate THEN {
strip: Imager.Box ← [xmin: rx, ymin: interpolationBarHeight, xmax: rx+stripW, ymax: patchData.box.ymax];
Do the background strip
Imager.SetColor[context, Imager.white];
Imager.MaskBox[context, strip];
rx ← rx+stripW;
};
Do the full color (assume colormap animation)
box ← [xmin: rx, ymin: interpolationBarHeight, xmax: rx+w, ymax: patchData.box.ymax];
patchData.patchMapEntry.red ← ToByte[patchData.rgb.R];
patchData.patchMapEntry.green ← ToByte[patchData.rgb.G];
patchData.patchMapEntry.blue ← ToByte[patchData.rgb.B];
ImagerColorMap.LoadEntries[vt: Terminal.Current[],
mapEntries: LIST[patchData.patchMapEntry], shared: FALSE];
Imager.SetColor[context, ImagerDitheredDevice.ColorFromSpecialRGB[
specialPixel: [patchData.patchMapEntry.mapIndex,null], rgb: patchData.rgb]];
Imager.MaskBox[context, box];
}
ELSE {
box: Imager.Box ← [xmin: 0, ymin: interpolationBarHeight, xmax: w * 2, ymax: patchData.box.ymax];
patchData.patchMapEntry.red ← ToByte[patchData.rgb.R];
patchData.patchMapEntry.green ← ToByte[patchData.rgb.G];
patchData.patchMapEntry.blue ← ToByte[patchData.rgb.B];
ImagerColorMap.LoadEntries[vt: Terminal.Current[],
mapEntries: LIST[patchData.patchMapEntry], shared: FALSE];
Imager.SetColor[context, ImagerDitheredDevice.ColorFromSpecialRGB[
specialPixel: [patchData.patchMapEntry.mapIndex,null], rgb: patchData.rgb]];
Imager.MaskBox[context, box];
};
IF patchData.interpolationRequest # off THEN {
step, new: ImagerColor.RGB;
newMapEntry: ImagerColorMap.MapEntry ← [mapIndex: patchData.leftInterpolateMapEntry.mapIndex - 1, red: 0, green: 0, blue: 0];
box: Imager.Box;
IF patchData.interpolationRequest = left THEN {
patchData.leftInterpolateMapEntry.red ← ToByte[patchData.rgb.R];
patchData.leftInterpolateMapEntry.green ← ToByte[patchData.rgb.G];
patchData.leftInterpolateMapEntry.blue ← ToByte[patchData.rgb.B];
patchData.leftInterpolateColor ← patchData.rgb;
}
ELSE IF patchData.interpolationRequest = right THEN {
patchData.rightInterpolateMapEntry.red ← ToByte[patchData.rgb.R];
patchData.rightInterpolateMapEntry.green ← ToByte[patchData.rgb.G];
patchData.rightInterpolateMapEntry.blue ← ToByte[patchData.rgb.B];
patchData.rightInterpolateColor ← patchData.rgb;
};
box ← [xmin: 0, ymin: 0, xmax: (w * 2 - numberInterpolationElements * widthInterpolationElement) / 2.0, ymax: interpolationBarHeight];
ImagerColorMap.LoadEntries[vt: Terminal.Current[],
mapEntries: LIST[patchData.leftInterpolateMapEntry], shared: FALSE];
Imager.SetColor[context, ImagerDitheredDevice.ColorFromSpecialRGB[
specialPixel: [patchData.leftInterpolateMapEntry.mapIndex, null], rgb: patchData.leftInterpolateColor]];
Imager.MaskBox[context, box];
step.R ← (patchData.rightInterpolateColor.R - patchData.leftInterpolateColor.R) / (numberInterpolationElements - 1);
step.G ← (patchData.rightInterpolateColor.G - patchData.leftInterpolateColor.G) / (numberInterpolationElements - 1);
step.B ← (patchData.rightInterpolateColor.B - patchData.leftInterpolateColor.B) / (numberInterpolationElements - 1);
FOR i: INT IN [0..numberInterpolationElements) DO
box ← [xmin: (w * 2 - numberInterpolationElements * widthInterpolationElement) / 2.0 + i * widthInterpolationElement, ymin: 0, xmax: (w * 2 - numberInterpolationElements * widthInterpolationElement) / 2.0 + (i+1) * widthInterpolationElement, ymax: interpolationBarHeight];
new.R ← patchData.leftInterpolateColor.R + i * step.R;
new.G ← patchData.leftInterpolateColor.G + i * step.G;
new.B ← patchData.leftInterpolateColor.B + i * step.B;
newMapEntry.red ← ToByte[new.R];
newMapEntry.green ← ToByte[new.G];
newMapEntry.blue ← ToByte[new.B];
ImagerColorMap.LoadEntries[vt: Terminal.Current[],
mapEntries: LIST[newMapEntry], shared: FALSE];
Imager.SetColor[context, ImagerDitheredDevice.ColorFromSpecialRGB[
specialPixel: [newMapEntry.mapIndex,null], rgb: new]];
Imager.MaskBox[context, box];
newMapEntry.mapIndex ← newMapEntry.mapIndex - 1;
ENDLOOP;
box ← [xmin: w * 2 - (w * 2 - numberInterpolationElements * widthInterpolationElement) / 2.0, ymin: 0, xmax: w * 2, ymax: interpolationBarHeight];
ImagerColorMap.LoadEntries[vt: Terminal.Current[],
mapEntries: LIST[patchData.rightInterpolateMapEntry], shared: FALSE];
Imager.SetColor[context, ImagerDitheredDevice.ColorFromSpecialRGB[
specialPixel: [patchData.rightInterpolateMapEntry.mapIndex, null], rgb: patchData.rightInterpolateColor]];
Imager.MaskBox[context, box];
};
IF patchData.hsvContrast THEN {
patchData.hsvContrastMapEntry.red ← ToByte[hsvContrastColor.R];
patchData.hsvContrastMapEntry.green ← ToByte[hsvContrastColor.G];
patchData.hsvContrastMapEntry.blue ← ToByte[hsvContrastColor.B];
ImagerColorMap.LoadEntries[vt: Terminal.Current[],
mapEntries: LIST[patchData.hsvContrastMapEntry], shared: FALSE];
Imager.SetColor[context, ImagerDitheredDevice.ColorFromSpecialRGB[
specialPixel: [patchData.hsvContrastMapEntry.mapIndex,null], rgb: hsvContrastColor]];
Imager.MaskBox[context, hsvContrastBox];
};
IF patchData.hslContrast THEN {
patchData.hslContrastMapEntry.red ← ToByte[hslContrastColor.R];
patchData.hslContrastMapEntry.green ← ToByte[hslContrastColor.G];
patchData.hslContrastMapEntry.blue ← ToByte[hslContrastColor.B];
ImagerColorMap.LoadEntries[vt: Terminal.Current[],
mapEntries: LIST[patchData.hslContrastMapEntry], shared: FALSE];
Imager.SetColor[context, ImagerDitheredDevice.ColorFromSpecialRGB[
specialPixel: [patchData.hslContrastMapEntry.mapIndex,null], rgb: hslContrastColor]];
Imager.MaskBox[context, hslContrastBox];
};
IF patchData.rgbContrast THEN {
patchData.rgbContrastMapEntry.red ← ToByte[rgbContrastColor.R];
patchData.rgbContrastMapEntry.green ← ToByte[rgbContrastColor.G];
patchData.rgbContrastMapEntry.blue ← ToByte[rgbContrastColor.B];
ImagerColorMap.LoadEntries[vt: Terminal.Current[],
mapEntries: LIST[patchData.rgbContrastMapEntry], shared: FALSE];
Imager.SetColor[context, ImagerDitheredDevice.ColorFromSpecialRGB[
specialPixel: [patchData.rgbContrastMapEntry.mapIndex,null], rgb: rgbContrastColor]];
Imager.MaskBox[context, rgbContrastBox];
};
IF patchData.yiqContrast THEN {
patchData.yiqContrastMapEntry.red ← ToByte[yiqContrastColor.R];
patchData.yiqContrastMapEntry.green ← ToByte[yiqContrastColor.G];
patchData.yiqContrastMapEntry.blue ← ToByte[yiqContrastColor.B];
ImagerColorMap.LoadEntries[vt: Terminal.Current[],
mapEntries: LIST[patchData.yiqContrastMapEntry], shared: FALSE];
Imager.SetColor[context, ImagerDitheredDevice.ColorFromSpecialRGB[
specialPixel: [patchData.yiqContrastMapEntry.mapIndex,null], rgb: yiqContrastColor]];
Imager.MaskBox[context, yiqContrastBox];
};
IF patchData.argybContrast THEN {
patchData.argybContrastMapEntry.red ← ToByte[argybContrastColor.R];
patchData.argybContrastMapEntry.green ← ToByte[argybContrastColor.G];
patchData.argybContrastMapEntry.blue ← ToByte[argybContrastColor.B];
ImagerColorMap.LoadEntries[vt: Terminal.Current[],
mapEntries: LIST[patchData.argybContrastMapEntry], shared: FALSE];
Imager.SetColor[context, ImagerDitheredDevice.ColorFromSpecialRGB[
specialPixel: [patchData.argybContrastMapEntry.mapIndex,null], rgb: argybContrastColor]];
Imager.MaskBox[context, argybContrastBox];
};
};
ToByte: PROC[v: REAL] RETURNS[Terminal.ColorValue] = INLINE { RETURN[Real.RoundC[v*255]] };
DestroyColorPatch: ViewerClasses.DestroyProc = {};
colorPatchClass is a record containing the procedures and data common to all ColorPatch viewer instances (class record).
colorPatchClass: ViewerClasses.ViewerClass ←
NEW[ViewerClasses.ViewerClassRec ← [paint: PaintColorPatch, destroy: DestroyColorPatch]];
Register the ColorPatch class of viewer with the Window Manager
ViewerOps.RegisterViewerClass[$ColorPatch, colorPatchClass];
END.