<> <> <> <> DIRECTORY Basics USING [BITAND, BITSHIFT], Buttons USING [Button, ButtonProc, Create, SetDisplayStyle], CD USING [backGround, ContextFilter, FetchTechnology, highLightError, highLightShade, Layer, Technology], CDColors USING [Brick, DefineColor], CDIO USING [GetWorkingDirectory], CDMenus USING [CreateEntry], CDSequencer USING [Command, CommandProc, CommDescriptor, FetchCommand, ImplementCommand], CDSil USING [cdsil, xaqua, xblue, xbrown, xcyan, xgreen, xlime, xmagenta, xneutral, xorange, xpink, xred, xsmoke, xturquise, xultraviolet, xviolet, xwhite, xyellow], CDValue USING [Fetch], Commander USING [CommandProc, Handle, Register], Containers USING [ChildXBound, ChildYBound, Container, Create], Convert USING [RopeFromInt], Imager USING [Context], ImagerColor USING [ColorFromRGB], ImagerColorMap USING [LoadEntries, MapEntry], ImagerDitherContext USING [MapEntries, SetDitherMap], ImagerTerminal USING [BWContext, ColorContext], InterminalBackdoor USING [terminal], Icons USING [NewIconFromFile], Labels USING [Create, Label, Set], MessageWindow USING [Append], Process USING [Detach], Real USING [Fix, Float, RoundI], Rope USING [Cat, Concat, Equal, ROPE], Sliders USING [Create, NormalizedSliderValue, SetContents, Slider, SliderProc], Terminal USING [GetColorMode, LegalColorMode, SetColorCursorPresentation, Virtual], TerminalIO USING [RequestSelection, WriteRope], UserProfile USING [Boolean, Number, Token], ViewerClasses USING [Viewer], ViewerOps USING [FindViewer, OpenIcon, PaintViewer, SetOpenHeight], ViewerPrivate USING [ContextCreatorProc, SetCreator], WindowManager USING [ScreenPos, StartColorViewers]; CDSil8BitColors: CEDAR PROGRAM IMPORTS Basics, Buttons, CD, CDColors, CDIO, CDMenus, CDSequencer, CDSil, CDValue, Commander, Containers, Convert, Icons, ImagerColor, ImagerColorMap, ImagerDitherContext, ImagerTerminal, InterminalBackdoor, Labels, MessageWindow, Process, Real, Rope, Sliders, Terminal, TerminalIO, UserProfile, ViewerOps, ViewerPrivate, WindowManager = BEGIN <<>> terminal: Terminal.Virtual _ InterminalBackdoor.terminal; <<>> <<--**color device**************************************>> useMapEntries: ImagerDitherContext.MapEntries _ NIL; ContextCreator: ViewerPrivate.ContextCreatorProc = BEGIN context: Imager.Context; SELECT screen FROM bw => context _ ImagerTerminal.BWContext[vt: terminal, pixelUnits: TRUE]; color => { context _ ImagerTerminal.ColorContext[vt: terminal, pixelUnits: TRUE]; IF useMapEntries#NIL THEN ImagerDitherContext.SetDitherMap[context, useMapEntries]; <<--experimenting showed that the following line was necessary....>> [] _ Terminal.SetColorCursorPresentation[terminal, onesAreWhite]; } ENDCASE => ERROR; RETURN [context] END; ForceColors: PROC [mapEntries: ImagerDitherContext.MapEntries] = BEGIN useMapEntries _ mapEntries; ImagerColorMap.LoadEntries[vt: terminal, mapEntries: mapEntries, gamma: 1, shared: FALSE]; <> <> <> [] _ Terminal.SetColorCursorPresentation[terminal, onesAreWhite]; [] _ ViewerPrivate.SetCreator[ContextCreator]; END; CallMenu: Buttons.ButtonProc = BEGIN comm: REF READONLY CDSequencer.CommDescriptor _ CDSequencer.FetchCommand[$ColorDisplayMenuC, technology]; IF comm#NIL AND comm.p#NIL THEN comm.p[NIL]; END; <<--**end color device**************************************>> ColorRec: TYPE = RECORD [r, g, b, w: REAL _ 0, name: Rope.ROPE _ NIL]; <<--w is a weight; The color of an intersection (i.e. green1 over blue) is the >> <<--weighted sum of the rgb of each color.>> ColorDescRep: TYPE = ARRAY [0..numberOfColors) OF ColorRec; <<--index 0 is supposed to be background>> Exception: TYPE = RECORD [x: CARDINAL, c: ColorRec, replace: BOOL _ TRUE]; <<--XXXXXXXXXXXXXXXX TECHNOLOGY XXXXXXXXXXXXXXXX>> technology: CD.Technology _ CDSil.cdsil; technologyName: Rope.ROPE _ technology.name; numberOfColors: INT = 8; -- background and "primary" colors numberOfNormalColors: INT = 7; -- without background numberOfTotalColors: INT = 18; mapRange: TYPE = [0 .. numberOfTotalColors); myMap: ARRAY mapRange OF RECORD [l: CD.Layer, c: ColorRec] = [ [CD.backGround, [r: 0.49, g: 0.62, b: 0.62, w: 0.05, name: "Sub"]], [CDSil.xred, [r: 1, g: 0, b: 0, w: 0.75, name: "Red"]], [CDSil.xgreen, [r: 0, g: 1, b: 0, w: 0.75, name: "Green"]], [CDSil.xblue, [r: 0, g: 0, b: 1, w: 0.75, name: "Blue"]], [CDSil.xcyan, [r: 0, g: 1, b: 1, w: 0.75, name: "Cyan"]], [CDSil.xmagenta, [r: 1, g: 0, b: 1, w: 0.75, name: "Magenta"]], [CDSil.xyellow, [r: 1, g: 1, b: 0, w: 0.75, name: "Yellow"]], [CDSil.xwhite, [r: 1, g: 1, b: 1, w: 1, name: "White"]], [CDSil.xaqua, [r: 0.42, g: 0.92, b: 0.55, w: 0.75, name: "Aqua"]], [CDSil.xturquise, [r: 0.42, g: 0.70, b: 0.92, w: 0.75, name: "Turquoise"]], [CDSil.xbrown, [r: 0.25, g: 0.12, b: 0.08, w: 0.75, name: "DarkBrown"]], [CDSil.xviolet, [r: 0.45, g: 0.25, b: 0.75, w: 0.75, name: "Violet"]], [CDSil.xultraviolet, [r: 0.13, g: 0.0, b: 0.33, w: 0.75, name: "Ultraviolet"]], [CDSil.xorange, [r: 0.64, g: 0.2752, b: 0.16, w: 0.75, name: "Orange"]], -- we prefer our orange [CDSil.xsmoke, [r: 0.50, g: 0.50, b: 0.50, w: 0.75, name: "Smoke"]], -- grey [CDSil.xlime, [r: 0.39, g: 0.75, b: 0.25, w: 0.75, name: "Lime"]], [CDSil.xpink, [r: 0.90 , g: 0.45, b: 0.55, w: 0.75, name: "Pink"]], -- we need a bit more red and less green in it [CDSil.xneutral, [r: 0, g: 0, b: 0, w: 0.75, name: "Neutral"]]]; -- Black -- Order is important !!! <> cDefaults: REF ColorDescRep _ NEW [ColorDescRep _ [ myMap[0].c, myMap[1].c, myMap[2].c, myMap[3].c, myMap[4].c, myMap[5].c, myMap[6].c, myMap[7].c ]]; <<"Auxiliary" colours>> neutral: ColorRec = myMap[17].c; -- Black violet: ColorRec = myMap[11].c; darkBrown: ColorRec = myMap[10].c; <> lime: ColorRec = myMap[15].c; turquoise: ColorRec = myMap[9].c; aqua: ColorRec = myMap[8].c; ultraviolet: ColorRec = myMap[12].c; <> pink: ColorRec = myMap[16].c; smoke: ColorRec = myMap[14].c; -- Grey <> red: CARDINAL = 1; green: CARDINAL = 2; blue: CARDINAL = 4; cyan: CARDINAL = 8; magenta: CARDINAL = 16; yellow: CARDINAL = 32; white: CARDINAL = 64; fakeAqua: CARDINAL = green+cyan; -- 10 fakeTurquoise: CARDINAL = blue + cyan; -- 12 fakeBrown: CARDINAL = green+magenta; -- 18 fakeViolet: CARDINAL = cyan+magenta; -- 24 fakeUltraviolet: CARDINAL = blue + cyan + magenta; -- 28 orange: CARDINAL = red+yellow; -- 33 this orange is better than the one used by Sil fakeSmoke: CARDINAL = blue+yellow; -- 36 fakeLime: CARDINAL = cyan+yellow; -- 40 fakePink: CARDINAL = magenta + white; -- 80 fakeBlack: CARDINAL = white-1; Init8Patterns: Buttons.ButtonProc = <<--all parameter are discarded >> BEGIN <> <<1 2>> <<3 4>> <<5 6>> <<7 8>> <> pixel1: CARDINAL = 1; pixel3: CARDINAL = 256; <> Mixture: PROC [col: CARDINAL] RETURNS [REF CDColors.Brick] ~ BEGIN <> RETURN [Dither1to1 [col, col]] END; -- Dither1to0 Dither1to1: PROC [col1, col2: CARDINAL _ white] RETURNS [REF CDColors.Brick] ~ BEGIN <> RETURN [NEW [CDColors.Brick _ [col1*pixel1+col2*pixel3, col2*pixel1+col1*pixel3, col1*pixel1+col2*pixel3, col2*pixel1+col1*pixel3]]] END; -- Dither1to1 <> <> <> <> <> <> <> <> Lighten: PROC[l: CD.Layer, color: CARDINAL] = BEGIN CDColors.DefineColor [l, Dither1to1[color], bit8, pushedOut]; END; CDColors.DefineColor[CDSil.xneutral, Mixture[fakeBlack], bit8]; CDColors.DefineColor[CDSil.xred, Mixture[red], bit8]; CDColors.DefineColor[CDSil.xyellow, Mixture[yellow], bit8]; CDColors.DefineColor[CDSil.xgreen, Mixture[green], bit8]; CDColors.DefineColor[CDSil.xcyan, Mixture[cyan], bit8]; CDColors.DefineColor[CDSil.xviolet, Mixture[fakeViolet], bit8]; CDColors.DefineColor[CDSil.xmagenta, Mixture[magenta], bit8]; CDColors.DefineColor[CDSil.xwhite, Mixture[white], bit8]; CDColors.DefineColor[CDSil.xbrown, Mixture[fakeBrown], bit8]; CDColors.DefineColor[CDSil.xorange, Mixture[orange], bit8]; CDColors.DefineColor[CDSil.xlime, Mixture[fakeLime], bit8]; CDColors.DefineColor[CDSil.xturquise, Mixture[fakeTurquoise], bit8]; CDColors.DefineColor[CDSil.xaqua, Mixture[fakeAqua], bit8]; CDColors.DefineColor[CDSil.xultraviolet, Mixture[fakeUltraviolet], bit8]; CDColors.DefineColor[CDSil.xpink, Mixture[fakePink], bit8]; CDColors.DefineColor[CDSil.xsmoke, Mixture[fakeSmoke], bit8]; CDColors.DefineColor[CDSil.xblue, Mixture[blue], bit8]; CDColors.DefineColor[CD.backGround, NEW[CDColors.Brick _ [8, 0, 256*8, 0]], bit8]; CDColors.DefineColor[CD.highLightError, NEW[CDColors.Brick _ [255, 0, 0, 0]], bit8]; CDColors.DefineColor[CD.highLightShade, NEW[CDColors.Brick_[0, 255,0 , 255]], bit8]; Lighten[CDSil.xneutral, fakeBlack]; Lighten[CDSil.xred, red]; Lighten[CDSil.xyellow, yellow]; Lighten[CDSil.xgreen, green]; Lighten[CDSil.xcyan, cyan]; Lighten[CDSil.xviolet, fakeViolet]; Lighten[CDSil.xmagenta, magenta]; Lighten[CDSil.xwhite, white]; Lighten[CDSil.xbrown, fakeBrown]; Lighten[CDSil.xorange, orange]; Lighten[CDSil.xlime, fakeLime]; Lighten[CDSil.xturquise, fakeTurquoise]; Lighten[CDSil.xaqua, fakeAqua]; Lighten[CDSil.xultraviolet, fakeUltraviolet]; Lighten[CDSil.xpink, fakePink]; Lighten[CDSil.xsmoke, fakeBlack]; Lighten[CDSil.xblue, blue]; HackContextColors[]; END; SetupSpecials: PROC [] = BEGIN specials2 _ LIST [ [x: fakeAqua + 1, c: aqua], [x: fakeTurquoise + 1, c: turquoise], [x: fakeBrown + 1, c: darkBrown], [x: fakeViolet + 1, c: violet], [x: fakeUltraviolet + 1, c: ultraviolet], [x: fakeSmoke + 1, c: smoke], [x: fakeLime + 1, c: lime], [x: fakePink, c: pink], [x: fakeBlack, c: neutral]]; specials3 _ LIST[ [x: 245, c: [0, 0, 1, 1]], --get all nice colors back for other users [x: 247, c: [0, 1, 0, 1]], [x: 249, c: [0, 1, 1, 1]], [x: 250, c: [1, 0, 1, 1]], [x: 251, c: [1, 1, 0, 1]], [x: 252, c: [1, 1, 1, 1]], --white as opposite to 1+2 [x: 253, c: [0, 0, 0, 1]], [x: 254, c: [1, 0, 0, 1]], IF whiteOutLine THEN Exception[x: 255, c: [1, 1, 1, 1]] ELSE Exception[x: 255, c: [0, 0, 0, 1]] --all bits set ] END; <<>> HackContextColors: PROC [] = BEGIN WITH CDValue.Fetch[boundTo: NIL, key: $ContextFilter] SELECT FROM rcf: REF CD.ContextFilter => FOR i: mapRange IN mapRange DO rcf[myMap[i].l] _ ImagerColor.ColorFromRGB [ rgb: [R: myMap[i].c.r, G: myMap[i].c.g, B: myMap[i].c.b], calibration: NIL] ENDLOOP; ENDCASE => NULL END; <<>> <<--XXXXX end technology XXXXXXXXXXXXXXXXXXXXX>> whiteOutLine: BOOL; currentColor: REF ColorDescRep = NEW[ColorDescRep]; curLayer: INT _ 1; prevLayer: INT _ 1; -- to deselect the previous layer button <<>> CoefSlider: TYPE = RECORD [ value: Labels.Label _ NIL, select: Buttons.Button _ NIL, bar: Sliders.Slider _ NIL ]; ColorSlider: TYPE = RECORD [ value: Labels.Label _ NIL, bar: Sliders.Slider _ NIL ]; Handle: TYPE = REF AdjustColorRec; AdjustColorRec: TYPE = RECORD [ outer: Containers.Container _ NIL, coefLayer: ARRAY [0..numberOfColors) OF CoefSlider, potarColor: ARRAY [0..3) OF ColorSlider, height: CARDINAL _ 0 -- height measured from the top of the container ]; DataForSpecialProc: TYPE = REF DataForSpecialProcRec; DataForSpecialProcRec: TYPE = RECORD [ my: Handle, layer: CARDINAL ]; caption: Rope.ROPE = Rope.Concat[technologyName, " 8 bit color editor"]; ColorModeIs8: PROC [] RETURNS [BOOL] = INLINE BEGIN RETURN [terminal.hasColorDisplay AND ~terminal.GetColorMode[].full AND terminal.GetColorMode[].bitsPerPixelChannelA=8]; END; Check8BitMode: PROC [] RETURNS [ok: BOOL] = BEGIN ok _ ColorModeIs8[]; IF ~ok THEN TRUSTED{Process.Detach[FORK TerminalIO.WriteRope["Put the display in 8 bit per pixel mode first\n"]]}; END; UpdateWeightSlider: Sliders.SliderProc = BEGIN datac: DataForSpecialProc _ NARROW[clientData]; my: Handle _ datac.my; layer: CARDINAL _ datac.layer; IF ~ColorModeIs8[] THEN RETURN; currentColor[layer].w _ value; ComputeColors[]; Labels.Set[my.coefLayer[layer].value, Convert.RopeFromInt[Real.Fix[value*100]]]; END; UpdateColorSlider: Sliders.SliderProc = BEGIN data: DataForSpecialProc _ NARROW[clientData]; my: Handle _ data.my; layer: CARDINAL _ data.layer; IF ~ColorModeIs8[] THEN RETURN; Labels.Set[my.potarColor[layer].value, Convert.RopeFromInt[Real.Fix[value*100]]]; SELECT layer FROM 0 => currentColor[curLayer-1].r _ value; 1 => currentColor[curLayer-1].g _ value; 2 => currentColor[curLayer-1].b _ value; ENDCASE => ERROR; ComputeColors[]; END; ResetButton: Buttons.ButtonProc = BEGIN Init8Patterns[parent: parent, clientData: clientData]; ResetMapButton[parent: parent, clientData: clientData]; END; XSelection: Buttons.ButtonProc = BEGIN whiteOutLine _ ~whiteOutLine; ComputeColors[]; END; ResetAndCreateButton: Buttons.ButtonProc = BEGIN viewer: ViewerClasses.Viewer _ ViewerOps.FindViewer[caption]; IF viewer=NIL THEN { IF mouseButton=yellow THEN CallMenu[NIL] ELSE { IF Terminal.LegalColorMode[terminal, [FALSE, 8, 0]] AND ~ColorModeIs8[] THEN { pos: WindowManager.ScreenPos _ left; IF Rope.Equal["right", UserProfile.Token[key: "ColorDisplay.Side"], FALSE] THEN pos _ right; WindowManager.StartColorViewers[screenPos: pos, bitsPerPixel: 8]; }; ResetButton[parent: parent]; IF mouseButton=blue THEN CreateAnInstance[]; } } ELSE { <<--we do only open the viewer, >> <<--because resetting can not reset already painted sliders... >> IF viewer.iconic THEN ViewerOps.OpenIcon[viewer] ELSE MessageWindow.Append["use the color editor tool", TRUE]; }; END; ResetMapButton: Buttons.ButtonProc = <<--Resets color map;>> <<--does not touch patterns>> BEGIN UpdateAllSliders: PROC [my: Handle] = BEGIN w: Sliders.NormalizedSliderValue; IF my=NIL OR my.outer=NIL OR my.outer.destroyed THEN RETURN; FOR layer: INT IN [0..numberOfColors) DO w _ currentColor[layer].w; Sliders.SetContents[my.coefLayer[layer].bar, 0]; Sliders.SetContents[my.coefLayer[layer].bar, w]; Labels.Set[my.coefLayer[layer].value, Convert.RopeFromInt[Real.Fix[currentColor[layer].w*100]]]; ENDLOOP; ButtonProcLayerInternal[0, my]; END; <<>> <<--ResetMapButton>> IF Check8BitMode[] THEN { ReadProfileColors[]; ComputeColors[]; IF clientData#NIL THEN UpdateAllSliders[NARROW[clientData, Handle]]; }; END; ButtonProcLayer: Buttons.ButtonProc = BEGIN data: DataForSpecialProc _ NARROW[clientData]; IF Check8BitMode[] THEN { ButtonProcLayerInternal[data.layer, data.my]; } END; ButtonProcLayerInternal: PROC[layer: CARDINAL, my: Handle] = BEGIN SetPotar: PROC[layer: CARDINAL, my: Handle] = BEGIN Sliders.SetContents[my.potarColor[0].bar, currentColor[layer].r]; Sliders.SetContents[my.potarColor[1].bar, currentColor[layer].g]; Sliders.SetContents[my.potarColor[2].bar, currentColor[layer].b]; Labels.Set[my.potarColor[0].value, Convert.RopeFromInt[Real.Fix[currentColor[layer].r*100]]]; Labels.Set[my.potarColor[1].value, Convert.RopeFromInt[Real.Fix[currentColor[layer].g*100]]]; Labels.Set[my.potarColor[2].value, Convert.RopeFromInt[Real.Fix[currentColor[layer].b*100]]]; END; <<>> <<-- ButtonProcLayerInternal>> curLayer _ layer+1; SetPotar[layer, my]; Buttons.SetDisplayStyle[my.coefLayer[prevLayer-1].select, $BlackOnWhite]; Buttons.SetDisplayStyle[my.coefLayer[curLayer-1].select, $WhiteOnBlack]; prevLayer _ curLayer; END; CreateAnInstance: PROC[] = <<--create an icon of the tool;>> <<--does not change any color setup at initialization of the tool>> BEGIN nameColorSlider: ARRAY [0..3) OF Rope.ROPE _ ["R", "G", "B"]; coefX: CARDINAL = 10; coefDX: CARDINAL = 25; coefDeltaX: CARDINAL = coefDX+4; coefSelectY: CARDINAL = 3; coefSelectDY: CARDINAL = 15; coefValueY: CARDINAL = coefSelectY+coefSelectDY+3; coefValueDY: CARDINAL = 15; coefBarY: CARDINAL = coefValueY+coefValueDY; firstButtonY: CARDINAL = 3; buttonX: CARDINAL = coefX+numberOfColors*coefDeltaX+8; buttonDX: CARDINAL = 80; firstSliderY: CARDINAL = 6; sliderDY: CARDINAL = 22; interSliderY: CARDINAL = 6; labelX: CARDINAL = buttonX+buttonDX+10; -- R, G, B labelDX: CARDINAL = 14; label2X: CARDINAL = labelX+labelDX; -- number label2DX: CARDINAL = 30; sliderX: CARDINAL = label2X+label2DX; my: Handle = NEW[AdjustColorRec]; buttonWy: CARDINAL _ firstButtonY; NextButton: PROC [name: Rope.ROPE, proc: Buttons.ButtonProc] = BEGIN buttonDY: CARDINAL = 15; interButtonY: CARDINAL = 2; [] _ Buttons.Create[ info: [name: name, wx: buttonX, wy: buttonWy, wh: buttonDY, ww: buttonDX, parent: my.outer, border: TRUE], proc: proc, clientData: my, fork: TRUE ]; buttonWy _ buttonWy+buttonDY+interButtonY; END; IF ~ColorModeIs8[] THEN TerminalIO.WriteRope["The 8 bit color tool works only after setting the display in 8 bit mode\n"]; IF ViewerOps.FindViewer[caption]#NIL THEN { TerminalIO.WriteRope[caption]; TerminalIO.WriteRope[" viewer already exits\n"]; RETURN }; my.outer _ Containers.Create[[ name: caption, iconic: TRUE, icon: Icons.NewIconFromFile[CDIO.GetWorkingDirectory[NIL].Cat["Chipndale.icons"], 2], column: left, scrollable: FALSE ]]; my.height _ firstSliderY+3*(sliderDY+interSliderY); <<-- create sliders for weights>> FOR curLayer: INT IN [0..numberOfColors) DO wInit: REAL _ currentColor[curLayer].w; my.coefLayer[curLayer].select _ Buttons.Create[ info: [ name: cDefaults[curLayer].name, iconic: TRUE, wx: coefX+curLayer*coefDeltaX, wy: coefSelectY, wh: coefSelectDY, ww: coefDX, parent: my.outer, border: TRUE], proc: ButtonProcLayer, clientData: NEW[DataForSpecialProcRec _ [my: my, layer: curLayer]] ]; my.coefLayer[curLayer].value _ Labels.Create[ [ name: Convert.RopeFromInt[Real.Fix[wInit*100]], -- initial contents iconic: TRUE, wx: coefX+curLayer*coefDeltaX, wy: coefValueY, wh: coefValueDY, ww: coefDX, parent: my.outer, border: TRUE ]]; my.coefLayer[curLayer].bar _ Sliders.Create[ info: [ name: cDefaults[curLayer].name, iconic: TRUE, parent: my.outer, wx: coefX+curLayer*coefDeltaX, wy: coefBarY, wh: -5, --guardY ww: coefDX, border: TRUE], sliderProc: UpdateWeightSlider, orientation: vertical, value: wInit, clientData: NEW[DataForSpecialProcRec _ [my: my, layer: curLayer] ]]; Containers.ChildYBound[my.outer, my.coefLayer[curLayer].bar]; ENDLOOP; <<>> <<-- create command buttons>> NextButton["reset all", ResetButton]; NextButton["reset map", ResetMapButton]; NextButton["reset pattern", Init8Patterns]; NextButton["X Selection", XSelection]; NextButton["Menu", CallMenu]; <<>> <<-- create sliders for rgb colors>> FOR iColor: CARDINAL IN [0..3) DO cInit: REAL _ SELECT iColor FROM 0 => currentColor[curLayer-1].r, 1 => currentColor[curLayer-1].g, 2 => currentColor[curLayer-1].b, ENDCASE => ERROR; [] _ Labels.Create[ info: [name: nameColorSlider[iColor], parent: my.outer, wx: labelX, wy: firstSliderY+iColor*(sliderDY+interSliderY), ww: labelDX, wh: sliderDY, border: TRUE ]]; my.potarColor[iColor].bar _ Sliders.Create[ info: [parent: my.outer, wx: sliderX, wy: firstSliderY+iColor*(sliderDY+interSliderY), ww: 10, wh: sliderDY], sliderProc: UpdateColorSlider, orientation: horizontal, value: cInit, clientData: NEW[DataForSpecialProcRec _ [my: my, layer: iColor]] ]; Containers.ChildXBound[my.outer, my.potarColor[iColor].bar]; my.potarColor[iColor].value _ Labels.Create[[ name: Convert.RopeFromInt[Real.Fix[cInit*100]], -- initial contents wx: label2X, wy: firstSliderY+iColor*(sliderDY+interSliderY), ww: label2DX, wh: sliderDY, parent: my.outer, border: TRUE ]]; ENDLOOP; ViewerOps.SetOpenHeight[my.outer, my.height]; -- hint our desired height ViewerOps.PaintViewer[my.outer, all]; -- reflect above change Buttons.SetDisplayStyle[my.coefLayer[0].select, $WhiteOnBlack]; END; SaturationComm: CDSequencer.CommandProc = BEGIN sat: CARDINAL _ 1; IF Check8BitMode[] THEN { list: LIST OF Rope.ROPE _ LIST["from profile"]; FOR i: INT DECREASING IN [0..numberOfColors) DO list _ CONS[cDefaults[i].name, list] ENDLOOP; curLayer _ TerminalIO.RequestSelection[label: "Layers", choice: list]; IF curLayer=0 THEN RETURN[]; IF curLayer<=numberOfColors THEN { sat _ TerminalIO.RequestSelection[ label: "Values", choice: LIST["Invisible", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Saturated"] ]; IF sat = 0 THEN RETURN[]; currentColor[curLayer-1].w _ Real.Float[sat-1]/10; } ELSE ReadProfileColors[]; ComputeColors[]; }; END; specials1: LIST OF Exception _ NIL; --specials in the range of stipples [use for any comb] specials2: LIST OF Exception _ NIL; --specials in the range of stipples [use for exact comb] specials3: LIST OF Exception _ NIL; --specials to be considered later ComputeColors: PROC[] = <<--takes a color setting (weights and rgb values) and sets up the device>> BEGIN ComposeColor: PROC[c1, wc2: ColorRec] RETURNS [c: ColorRec] = <<--c1 not weighted; wc2 weighted>> INLINE BEGIN w: REAL _ wc2.w; c _ [c1.r+w*wc2.r, c1.g+w*wc2.g, c1.b+w*wc2.b, c1.w+w] END; SetMap: PROC[index: CARDINAL, color: ColorRec] = BEGIN RtoC: PROC [r: REAL] RETURNS [c: [0..256)] = INLINE { c _ MAX[0, MIN[255, Real.RoundI[r*255]]] }; mapEntrie: ImagerColorMap.MapEntry _ [index, RtoC[color.r], RtoC[color.g], RtoC[color.b]]; mapEntries _ CONS[mapEntrie, mapEntries]; END; mapEntries: LIST OF ImagerColorMap.MapEntry _ NIL; c: ColorRec; bits: CARDINAL _ numberOfNormalColors; power: CARDINAL _ Basics.BITSHIFT[1, bits]; IF ~ColorModeIs8[] THEN RETURN; SetupSpecials[]; <<--colors in the range of layers>> FOR i: CARDINAL IN [0..power) DO c _ [0, 0, 0, 0]; <<--bit loop>> FOR bit: CARDINAL IN [0..bits) DO IF Basics.BITAND[i, Basics.BITSHIFT[1, bit]]#0 THEN { c _ ComposeColor[c, currentColor[bit+1]]; }; ENDLOOP; <<--check exception loops>> FOR list: LIST OF Exception _ specials1, list.rest WHILE list#NIL DO IF Basics.BITAND[i, list.first.x]=list.first.x THEN { IF list.first.replace THEN c _ list.first.c ELSE c _ ComposeColor[c, list.first.c]; }; ENDLOOP; FOR list: LIST OF Exception _ specials2, list.rest WHILE list#NIL DO IF i=list.first.x THEN { IF list.first.replace THEN c _ list.first.c ELSE c _ ComposeColor[c, list.first.c]; }; ENDLOOP; <<--assign color>> IF c.w<0.2 THEN c _ ComposeColor[c, currentColor[0]]; IF c.w=0 THEN c _ currentColor[0] ELSE c _ [c.r/c.w, c.g/c.w, c.b/c.w, 0]; SetMap[i, c]; ENDLOOP; <<--include further colors from exception loop>> FOR list: LIST OF Exception _ specials3, list.rest WHILE list#NIL DO IF list.first.x>=power THEN SetMap[list.first.x, list.first.c]; ENDLOOP; ForceColors[mapEntries: mapEntries]; END; ReadProfileColors: PUBLIC PROC [] = BEGIN DefaultColor: PROC [def: ColorRec] RETURNS [c: ColorRec] = BEGIN r: Rope.ROPE _ Rope.Cat["ChipNDale.", technologyName, ".", def.name]; c.w _ Real.Float[UserProfile.Number[key: r.Concat[".w"], default: Real.RoundI[def.w*100]]]/100; c.r _ Real.Float[UserProfile.Number[key: r.Concat[".r"], default: Real.RoundI[def.r*100]]]/100; c.g _ Real.Float[UserProfile.Number[key: r.Concat[".g"], default: Real.RoundI[def.g*100]]]/100; c.b _ Real.Float[UserProfile.Number[key: r.Concat[".b"], default: Real.RoundI[def.b*100]]]/100; END; FOR i: INT IN [0..numberOfColors) DO currentColor[i] _ DefaultColor[cDefaults[i]]; ENDLOOP; whiteOutLine _ UserProfile.Boolean[ key: Rope.Cat["ChipNDale." , technologyName, ".WhiteOutline"], default: TRUE ]; END; ColorCommand: Commander.CommandProc = BEGIN CreateAnInstance[]; END; ColorComm: PROC [comm: CDSequencer.Command] = BEGIN CreateAnInstance[]; END; Init8Patterns[NIL]; ReadProfileColors[]; IF UserProfile.Boolean[ key: Rope.Cat["ChipNDale.", technologyName, ".StartColorMap8"], default: CD.FetchTechnology[$cmos]=NIL AND CD.FetchTechnology[$cmosB]=NIL AND CD.FetchTechnology[$nmos]=NIL ] THEN ComputeColors[]; CDSequencer.ImplementCommand[$SaturationComm, SaturationComm, technology, doQueue]; CDSequencer.ImplementCommand[$ColorTool, ColorComm, technology, dontQueue]; CDMenus.CreateEntry[$DisplayMenu, Rope.Concat[technologyName, " 8 bit tool"], $ColorTool]; [] _ Buttons.Create[ info: [name: Rope.Concat[technologyName, " colors"]], proc: ResetAndCreateButton ]; Commander.Register[ key: Rope.Cat["CD", technologyName, "ColorRec"], proc: ColorCommand, doc: Rope.Concat[technologyName, " 8 bit color tool"] ]; END.