CNSColorImpl.mesa
Written by Darlene Plebon on June 23, 1983 11:48 am
Last Edited by: Beach, June 22, 1983 2:52 pm
Last Edited by: Stone, June 20, 1985 4:38:58 pm PDT
DIRECTORY
Atom USING [GetPName, MakeAtom],
CNSColor,
Rope USING [ROPE];
CNSColorImpl: CEDAR PROGRAM
IMPORTS Atom
EXPORTS CNSColor =
BEGIN OPEN CNSColor;
hueRecord: TYPE = RECORD [
name: ATOM,
value: REAL
];
hueMapping: ARRAY CSLChroma OF hueRecord ← [
[$Achromatic,    0.0],
[$Red,      0.0],
[$OrangishRed,    0.01],
[$RedOrange,    0.02],
[$ReddishOrange,   0.03],
[$Orange,     0.04],
[$YellowishOrange,  0.07],
[$OrangeYellow,   0.10],
[$OrangishYellow,   0.13],
[$Yellow,     0.1673],
[$GreenishYellow,   0.2073],
[$YellowGreen,    0.2473],
[$YellowishGreen,   0.2873],
[$Green,      0.3333],
[$BluishGreen,    0.4133],
[$GreenBlue,    0.4933],
[$GreenishBlue,   0.5733],
[$Blue,      0.6666],
[$PurplishBlue,    0.6816],
[$BluePurple,    0.6966],
[$BluishPurple,    0.7116],
[$Purple,     0.73],
[$ReddishPurple,   0.80],
[$PurpleRed,    0.87],
[$PurplishRed,    0.94],
[$BrownishRed,   0.01],
[$RedBrown,    0.02],
[$ReddishBrown,   0.03],
[$Brown,     0.04],
[$YellowishBrown,   0.07],
[$BrownYellow,   0.10],
[$BrownishYellow,   0.13]
];
saturationRecord: TYPE = RECORD [
name: ATOM,
value: REAL
];
saturationMapping: ARRAY CSLSaturation OF saturationRecord ← [
[$NoSaturation,  0.0],
[$Grayish,   0.25],
[$Moderate,   0.50],
[$Strong,   0.75],
[$Vivid,    1.0]
];
lightnessRecord: TYPE = RECORD [
name: ATOM,
value: REAL
];
lightnessMapping: ARRAY CSLLightness OF lightnessRecord ← [
[$Black,    0.0],
[$VeryDark,  0.1666],
[$Dark,    0.3333],
[$Medium,   0.5],
[$Light,    0.6666],
[$VeryLight,  0.8333],
[$White,    1.0]
];
CSLFromCNS: PUBLIC PROCEDURE [hue, saturation, lightness: Rope.ROPE] RETURNS [c: CSLChroma, s: CSLSaturation, l: CSLLightness] = {
hueAtom, saturationAtom, lightnessAtom: ATOM;
hueAtom ← Atom.MakeAtom[hue];
FOR c IN [red..brownishYellow] DO
IF hueAtom = hueMapping[c].name THEN EXIT;
REPEAT
FINISHED => c ← achromatic;
ENDLOOP;
IF c = achromatic THEN s ← noSaturation
ELSE {
saturationAtom ← Atom.MakeAtom[saturation];
FOR s IN [grayish..vivid] DO
IF saturationAtom = saturationMapping[s].name THEN EXIT;
REPEAT
FINISHED => s ← vivid;
ENDLOOP;
};
SELECT hueAtom FROM
$Black => l ← black;
$White => l ← white;
ENDCASE => {
lightnessAtom ← Atom.MakeAtom[lightness];
FOR l IN [veryDark..veryLight] DO
IF lightnessAtom = lightnessMapping[l].name THEN EXIT;
REPEAT
FINISHED => l ← medium;
ENDLOOP;
};
RETURN[c, s, l];
};
CNSFromCSL: PUBLIC PROCEDURE [c: CSLChroma, s: CSLSaturation, l: CSLLightness] RETURNS [hue, saturation, lightness: Rope.ROPE] = {
IF c = achromatic THEN {
saturation ← "";
SELECT l FROM
black => {
hue ← "Black";
lightness ← "";
};
white => {
hue ← "White";
lightness ← "";
};
ENDCASE => {
hue ← "Gray";
lightness ← Atom.GetPName[lightnessMapping[l].name];
};
}
ELSE {
hue ← Atom.GetPName[hueMapping[c].name];
saturation ← Atom.GetPName[saturationMapping[s].name];
lightness ← Atom.GetPName[lightnessMapping[l].name];
};
RETURN[hue, saturation, lightness];
};
HSLFromCSL: PUBLIC PROCEDURE [c: CSLChroma, s: CSLSaturation, l: CSLLightness] RETURNS [hue, saturation, lightness: REAL] = {
IF c = achromatic THEN {
hue ← 0.0;
saturation ← 0.0;
lightness ← lightnessMapping[l].value;
}
ELSE {
hue ← hueMapping[c].value;
saturation ← saturationMapping[s].value;
lightness ← lightnessMapping[l].value;
};
RETURN[hue, saturation, lightness];
};
CSLFromHSL: PUBLIC PROCEDURE [hue, saturation, lightness: REAL] RETURNS [c: CSLChroma, s: CSLSaturation, l: CSLLightness] = {
FOR s IN [noSaturation..vivid] DO
IF s = vivid THEN EXIT;
IF saturation <= saturationMapping[s].value + (saturationMapping[s+1].value - saturationMapping[s].value)/2 THEN EXIT;
ENDLOOP;
IF s = noSaturation THEN {
c ← achromatic;
FOR l IN [black..white] DO
IF l = white THEN EXIT;
IF lightness <= lightnessMapping[l].value + (lightnessMapping[l+1].value - lightnessMapping[l].value)/2 THEN EXIT;
ENDLOOP;
}
ELSE {
FOR c IN [red..purplishRed] DO
IF c = purplishRed THEN {
IF hue > hueMapping[c].value + (1.0 - hueMapping[c].value)/2 THEN c ← red;
EXIT;
};
IF hue <= hueMapping[c].value + (hueMapping[c+1].value - hueMapping[c].value)/2 THEN EXIT;
ENDLOOP;
FOR l IN [veryDark..veryLight] DO
IF l = veryLight THEN EXIT;
IF lightness <= lightnessMapping[l].value + (lightnessMapping[l+1].value - lightnessMapping[l].value)/2 THEN EXIT;
ENDLOOP;
};
RETURN[c, s, l];
};
END.