<> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> DIRECTORY Args USING [Arg, ArgsGet, Error, NArgs], Atom USING [GetPName], CD USING [Layer, LayerKey], CDColorsExtras USING [ColorNotRegistered, InitialColor, RegisteredColor], Checksum USING [ComputeChecksum], Commander USING [CommandProc, Register], CommandTool USING [NextArgument], FS USING [ComponentPositions, Error, ExpandName, StreamOpen, tText], FSExtras USING [GetWDir], Imager USING [black, Error], ImagerColor USING [ColorFromRGB, ColorOperator, ColorRep, ConstantColor, Find, NarrowToOpConstantColor, OpConstantColor, RGB, SpecialColor], ImagerColorFns USING [CMY, CMYK, CMYFromRGB, HSLFromRGB, NewColorOperatorCMYK], ImagerColorPrivate USING [RGBFromColor], ImagerInterpress USING [DeclareColor, Ref], IO USING [atom, card, Close, EndOf, EndOfStream, Error, GetAtom, GetCard, GetCedarTokenRope, GetIndex, GetInt, GetLength, GetLineRope, int, PutF, PutFR, PutRope, RIS, real, rope, SetIndex, STREAM, TokenKind], MessageWindow USING [Append, Blink, Clear], NamedColors USING [HSLToRope], NectarineColors, Real USING [Float, InlineRoundC, Round], RealFns USING [AlmostZero], RefTab USING [Create, EachPairAction, EqualProc, Erase, Fetch, GetSize, HashProc, Insert, Pairs, Ref], Rope USING [Cat, Equal, Fetch, IsEmpty, ROPE, Substr], RuntimeError USING [UNCAUGHT], SymTab USING [Ref, Create, GetSize, Fetch, Store, Val], TerminalIO USING [PutF, PutRope], UserProfile USING [Boolean, Token], ViewerOps USING [BlinkDisplay]; NectarineColorsImpl: CEDAR PROGRAM IMPORTS Args, Atom, CD, CDColorsExtras, Checksum, Commander, CommandTool, FS, FSExtras, Imager, ImagerColor, ImagerColorFns, ImagerColorPrivate, ImagerInterpress, IO, MessageWindow, NamedColors, Real, RealFns, RefTab, Rope, RuntimeError, SymTab, TerminalIO, UserProfile, ViewerOps EXPORTS NectarineColors ~ BEGIN OPEN NectarineColors, Real, RealFns; ROPE: TYPE ~ Rope.ROPE; RGB: TYPE ~ ImagerColor.RGB; CMYK: TYPE ~ ImagerColorFns.CMYK; cmyk255: ImagerColor.ColorOperator ~ ImagerColorFns.NewColorOperatorCMYK [255]; colSubDef: PUBLIC BOOL _ TRUE; -- default for colour substitution traceColourInferences: PUBLIC BOOL _ FALSE; obeyToChipNDale: BOOL _ FALSE; magicNumber: CARDINAL ~ 557; -- or 997 debug: BOOL _ TRUE; break: SIGNAL ~ CODE; -- for debugging argError, lastWDir: ROPE; currentlyUsedLayers: Bitset; currentlyUsedLayerNames: SymTab.Ref _ SymTab.Create [magicNumber]; <> aqua, black, blue, brown, colourBlack, cyan, doubleYellow, green, grey, lightMagenta, lightYellow, lime, magenta, orange, pink, red, turquise, ultraviolet, undefColour, violet, white, yellow: Color; blackRGB, blueRGB, cyanRGB, doubleYellowRGB, greenRGB, magentaRGB, redRGB, yellowRGB: RGB; blackBlack, orableBackground: PUBLIC Color; unColour: PUBLIC RGB; <> cyanCMYK: Color ~ ColorFromCMYK [[1.0, 0.0, 0.0, 0.0]]; magentaCMYK: Color ~ ColorFromCMYK [[0.0, 1.0, 0.0, 0.0]]; yellowCMYK: Color ~ ColorFromCMYK [[0.0, 0.0, 1.0, 0.0]]; blackCMYK: Color ~ ColorFromCMYK [[0.0, 0.0, 0.0, 1.0]]; blueCMYK: Color ~ ColorFromCMYK [[1.0, 1.0, 0.0, 0.0]]; redCMYK: Color ~ ColorFromCMYK [[0.0, 1.0, 1.0, 0.0]]; greenCMYK: Color ~ ColorFromCMYK [[1.0, 0.0, 1.0, 0.0]]; greenishBlackCMYK: Color ~ ColorFromCMYK [[1.0, 0.0, 1.0, 1.0]]; greyCMYK: Color ~ ColorFromCMYK [[0.0, 0.0, 0.0, 0.5]]; UseSimpleColours: PUBLIC PROC [] ~ BEGIN <> undefColour _ NIL; unColour _ [0.0, 0.0, 0.0]; blackRGB _ [0.0, 0.0, 0.0]; blackBlack _ blackCMYK; colourBlack _ Imager.black; grey _ greyCMYK; white _ ImagerColor.ColorFromRGB [rgb: [R: 1, G: 1, B: 1]]; red _ redCMYK; green _ greenCMYK; blueRGB _ [0.0, 0.0, 1.0]; cyan _ cyanCMYK; magentaRGB _ [1.0, 0.0, 1.0]; magenta _ magentaCMYK; lightMagenta _ ImagerColor.ColorFromRGB [[5.0/7.0, 0.0, 5.0/7.0]]; doubleYellowRGB _ [2.0, 2.0, 0.0]; doubleYellow _ ImagerColor.ColorFromRGB [doubleYellowRGB]; lightYellow _ ImagerColor.ColorFromRGB [[13.0/14.0, 13.0/14.0, 10.0/21.0]]; yellow _ yellowCMYK; violet _ ImagerColor.ColorFromRGB [rgb: [R: 0.45, G: 0.25, B: 0.75]]; brown _ ImagerColor.ColorFromRGB [rgb: [R: 0.64, G: 0.2752, B: 0.16]]; orange _ ImagerColor.ColorFromRGB [rgb: [R: 0.64, G: 0.2752, B: 0.16]]; -- we prefer our orange lime _ ImagerColor.ColorFromRGB [rgb: [R: 0.39, G: 0.75, B: 0.75]]; turquise _ ImagerColor.ColorFromRGB [rgb: [R: 0.42, G: 0.7, B: 0.92]]; aqua _ ImagerColor.ColorFromRGB [rgb: [R: 0.42, G: 0.92, B: 0.55]]; ultraviolet _ ImagerColor.ColorFromRGB [rgb: [R: 0.13, G: 0, B: 0.33]]; pink _ ImagerColor.ColorFromRGB [rgb: [R: 0.9, G: 0.45, B: 0.55]]; -- we need a bit more red and less green in it orableBackground _ CDColorsExtras.InitialColor []; black _ blackCMYK; blue _ blueCMYK END; -- UseSimpleColours UseSqueezedColours: PUBLIC PROC [] ~ BEGIN <> <<"-- [x, y], Y" means that we computed CalibratedColorFns.XYZFromChromaticity [[x, y], Y]>> undefColour _ NIL; unColour _ [0.0, 0.0, 0.0]; blackRGB _ [0.0, 0.0, 0.0]; blackBlack _ blackCMYK; colourBlack _ Imager.black; grey _ greyCMYK; white _ ImagerColor.ColorFromRGB [rgb: [R: 1, G: 1, B: 1]]; redRGB _ [R: 0.916726, G: 2.183968e-2, B: 2.917295e-2]; -- [0.59, 0.335], 5.31 red _ ImagerColor.ColorFromRGB [redRGB]; greenRGB _ [R: -0.2129092, G: 1.04013, B: 0.1963416]; -- [0.25, 0.525], 17.53 green _ ImagerColor.ColorFromRGB [greenRGB]; blueRGB _ [R: 1.158857e-2, G: 8.760574e-2, B: 0.2601715]; -- [0.2, 0.2], 2.16 cyanRGB _ [R: -0.2437036, G: 1.042247, B: 1.25352]; -- [0.2, 0.3], 19.69 <> cyan _ ImagerColor.ColorFromRGB [cyanRGB]; magentaRGB _ [R: 0.5401293, G: 0.1748126, B: 0.7118298]; -- [0.29, 0.21], 7.47 magenta _ ImagerColor.ColorFromRGB [rgb: magentaRGB]; lightMagenta _ ImagerColor.ColorFromRGB [[5.0/7.0*magentaRGB.R, 0.0, 5.0/7.0*magentaRGB.B]]; yellowRGB _ [R: 1.495448, G: 0.8532933, B: -0.0296737]; -- [0.47, 0.48], 22.83 yellow _ ImagerColor.ColorFromRGB [rgb: yellowRGB]; doubleYellowRGB _ [2*yellowRGB.R, 2*yellowRGB.G, 2*yellowRGB.B]; lightYellow _ ImagerColor.ColorFromRGB [[13.0/14.0*yellowRGB.R, 13.0/14.0*yellowRGB.G, 10.0/21.0*yellowRGB.B]]; violet _ ImagerColor.ColorFromRGB [rgb: [R: 0.45, G: 0.25, B: 0.75]]; brown _ ImagerColor.ColorFromRGB [rgb: [R: 0.64, G: 0.2752, B: 0.16]]; orange _ ImagerColor.ColorFromRGB [rgb: [R: 0.64, G: 0.2752, B: 0.16]]; -- we prefer our orange lime _ ImagerColor.ColorFromRGB [rgb: [R: 0.39, G: 0.75, B: 0.75]]; turquise _ ImagerColor.ColorFromRGB [rgb: [R: 0.42, G: 0.7, B: 0.92]]; aqua _ ImagerColor.ColorFromRGB [rgb: [R: 0.42, G: 0.92, B: 0.55]]; ultraviolet _ ImagerColor.ColorFromRGB [rgb: [R: 0.13, G: 0, B: 0.33]]; pink _ ImagerColor.ColorFromRGB [rgb: [R: 0.9, G: 0.45, B: 0.55]]; -- we need a bit more red and less green in it orableBackground _ CDColorsExtras.InitialColor []; black _ ImagerColor.ColorFromRGB [blackRGB]; blue _ ImagerColor.ColorFromRGB [blueRGB]; doubleYellow _ ImagerColor.ColorFromRGB [doubleYellowRGB] END; -- UseSqueezedColours <> layerColorTable: ARRAY CD.Layer OF Color; -- must be set for each task Rule: TYPE ~ PROC [layer: ATOM, colour: REF ANY] RETURNS [next: Rule, sameLayer: ATOM, newColour: Color]; decided: Rule ~ NIL; r1, r2, esc: Color _ NIL; -- to monitor the contents of the registries layerNumberHack: CD.Layer; -- cd registry uses number instead of name LayerColour: PUBLIC PROC [l: CD.Layer] RETURNS [Color] ~ BEGIN RETURN [layerColorTable[l]] END; -- LayerColour MakeConstant: PROC [any: REF ANY] RETURNS [c: Color] ~ BEGIN <> cc: ImagerColor.ConstantColor ~ NARROW [any]; TRUSTED BEGIN c _ LOOPHOLE [ImagerColor.NarrowToOpConstantColor [cc ! Imager.Error => {c _ NIL; ViewerOps.BlinkDisplay; CONTINUE}]] END END; -- MakeConstant ColourName: PROC [c: Color] RETURNS [ROPE] ~ BEGIN <> IF (c = NIL) THEN RETURN ["---"]; IF (ISTYPE [c, ImagerColor.SpecialColor]) THEN BEGIN sc: ImagerColor.SpecialColor ~ NARROW [c, ImagerColor.SpecialColor]; RETURN [sc.name] END; RETURN [NamedColors.HSLToRope [ImagerColorFns.HSLFromRGB[RGBFromColour[c]],3]] END; -- ColourName Decide: PROC [rule: Rule, l: ATOM, c: Color] RETURNS [Color] ~ BEGIN WHILE (rule # decided) DO [rule, l, c] _ rule [l, c] ENDLOOP; InferenceStatus [l, "NIL", "has been inferred"]; RETURN [c] END; -- Decide InferenceStatus: PROC [object: ATOM, rule, status: ROPE] ~ BEGIN msg: ROPE ~ Atom.GetPName[object].Cat [". Deciding rule ", rule, ": ", status]; MessageWindow.Clear; MessageWindow.Append [msg]; IF traceColourInferences THEN TerminalIO.PutF ["%g\n", IO.rope [msg]] END; -- InferenceStatus InferenceResult: PROC [object: ATOM, colour: Color] ~ BEGIN rgb: RGB ~ RGBFromColour [colour]; cmyk: CMYK ~ CMYKFromRGB [rgb]; TerminalIO.PutF ["%l%g.%l ", IO.rope ["b"], IO.atom [object], IO.rope ["B"]]; TerminalIO.PutF ["CNS: (registry 1: %g; registry 2: %g) inferred: %g\n", IO.rope [ColourName [r1]], IO.rope [ColourName [r2]], IO.rope [ColourName [colour]]]; TerminalIO.PutF ["CMYK: [%g, %g, %g, %g]\n", IO.real [cmyk.C], IO.real [cmyk.M], IO.real [cmyk.Y], IO.real [cmyk.K]]; TerminalIO.PutF ["RGB: [%g, %g, %g]\n", IO.real [rgb.R], IO.real [rgb.G], IO.real [rgb.B]] END; -- InferenceResult One: Rule ~ BEGIN InferenceStatus [layer, "One", "registry-1/cmos-b"]; r1 _ newColour _ ImagerColor.Find [Rope.Cat ["Xerox/Research/ChipNDale/CMosB/", Atom.GetPName [layer]]]; IF (newColour # NIL) THEN RETURN [Six, layer, newColour] ELSE RETURN [Two, layer, newColour] END; -- One Two: Rule ~ BEGIN InferenceStatus [layer, "Two", "registry-1/chipndale"]; r1 _ newColour _ ImagerColor.Find [Rope.Cat ["Xerox/Research/ChipNDale/CD/", Atom.GetPName [layer]]]; IF (newColour # NIL) THEN RETURN [Seven, layer, newColour] ELSE RETURN [Five, layer, newColour] END; -- Two Three: Rule ~ BEGIN InferenceStatus [layer, "Three", "registry-1/cmos-b"]; r1 _ newColour _ ImagerColor.Find [Rope.Cat ["Xerox/Research/ChipNDale/CMosB/", Atom.GetPName [layer]]]; IF (newColour # NIL) THEN RETURN [Ten, layer, newColour] ELSE RETURN [Four, layer, newColour] END; -- Three Four: Rule ~ BEGIN InferenceStatus [layer, "Four", "registry-1/chipndale"]; r1 _ newColour _ ImagerColor.Find [Rope.Cat ["Xerox/Research/ChipNDale/CD/", Atom.GetPName [layer]]]; IF (newColour # NIL) THEN RETURN [Ten, layer, newColour] ELSE RETURN [NIL, layer, blackBlack] END; -- Four Five: Rule ~ BEGIN InferenceStatus [layer, "Five", "registry-2"]; r2 _ newColour _ CDColorsExtras.RegisteredColor [layerNumberHack ! CDColorsExtras.ColorNotRegistered => {newColour _ NIL; CONTINUE}]; IF (newColour # NIL) THEN RETURN [Eight, layer, newColour] ELSE RETURN [Eleven, layer, newColour] END; -- Five Six: Rule ~ BEGIN InferenceStatus [layer, "Six", "constant inheritance"]; newColour _ MakeConstant [colour]; IF (newColour # NIL) THEN RETURN [NIL, layer, newColour] ELSE RETURN [Two, layer, newColour] END; -- Six Seven: Rule ~ BEGIN InferenceStatus [layer, "Seven", "constant inheritance"]; newColour _ MakeConstant [colour]; IF (newColour # NIL) THEN RETURN [NIL, layer, newColour] ELSE RETURN [Five, layer, newColour] END; -- Seven Eight: Rule ~ BEGIN InferenceStatus [layer, "Eight", "constant inheritance"]; newColour _ MakeConstant [colour]; IF (newColour # NIL) THEN RETURN [NIL, layer, newColour] ELSE RETURN [Eleven, layer, newColour] END; -- Eight Nine: Rule ~ BEGIN <> InferenceStatus [layer, "Nine", "escape value"]; esc _ newColour _ SELECT layer FROM $nwel => lightYellow, $met => cyan, $met2 => lightMagenta, <> $cut, $comment => blackBlack, $cut2 => blue, $gate => doubleYellow, $xneutral => blackBlack, $xred => red, $xyellow => yellow, $xgreen => green, $xcyan => cyan, $xviolet => violet, $xmagenta => magenta, $xwhite => white, $xbrown => brown, $xorange => orange, $xlime => lime, $xturquise => turquise, $xaqua => aqua, $xultraviolet => ultraviolet, $xpink => pink, $xsmoke => grey, $xblue => blue, ENDCASE => NIL; IF (newColour # NIL) THEN RETURN [NIL, layer, newColour] ELSE RETURN [One, layer, newColour] END; -- Nine Ten: Rule ~ BEGIN InferenceStatus [layer, "Ten", "constant inheritance"]; newColour _ MakeConstant [colour]; IF (newColour # NIL) THEN RETURN [NIL, layer, newColour] ELSE RETURN [NIL, layer, blackBlack] END; -- Ten Eleven: Rule ~ BEGIN InferenceStatus [layer, "Eleven", "no colour"]; RETURN [NIL, layer, undefColour] END; -- Eleven Twelve: Rule ~ BEGIN <> InferenceStatus [layer, "Twelve", "discriminable value"]; IF (currentColourMap = NIL) THEN RETURN [Nine, layer, newColour]; FOR i: CARDINAL IN [0 .. currentColourMap.size) DO IF (currentColourMap[i].layers.GetSize = 1) THEN BEGIN fetched: ATOM; found: BOOL; val: SymTab.Val; [found, val] _ currentColourMap[i].layers.Fetch [Atom.GetPName [layer]]; fetched _ NARROW [val, ATOM]; IF found AND (fetched = layer) THEN BEGIN newColour _ ColorFromRGB [currentColourMap[i].colour, currentColourMap[i].index]; IF (newColour = NIL) THEN ERROR; RETURN [NIL, layer, newColour] END -- found it END -- entry is for a single layer ENDLOOP; RETURN [Nine, layer, newColour] END; -- Twelve SetLayerColourTable: PUBLIC PROC RETURNS [ok: BOOL _ TRUE] ~ BEGIN <> <> <> r1 _ undefColour; IF (undefColour = NIL) THEN undefColour _ Decide [Three, $UndefLayer, NIL]; IF traceColourInferences THEN InferenceResult [$UndefLayer, undefColour]; ok _ (r1 # NIL); FOR i: CD.Layer IN CD.Layer DO layer: ATOM ~ CD.LayerKey [i]; IF (layer = NIL) OR (layerColorTable[i] # NIL) THEN LOOP; IF DoLineArt[] THEN BEGIN IF UseProcessColors[] THEN SELECT layer FROM $met => layerColorTable[i] _ cyanCMYK; $met2 => layerColorTable[i] _ magentaCMYK; $ndif, $pdif => layerColorTable[i] _ greenCMYK; $pol => layerColorTable[i] _ redCMYK; $cut, $cut2 => layerColorTable[i] _ blackCMYK; ENDCASE => layerColorTable[i] _ NIL ELSE SELECT layer FROM $met => -- cyan separation for C28 blue layerColorTable[i] _ cyanCMYK; $met2 => -- yellow separation for M35/2 magenta layerColorTable[i] _ yellowCMYK; $ndif, $pdif => -- black separation for GT4 green layerColorTable[i] _ IF UserProfile.Boolean ["Nectarine.ContinuousTone", FALSE] THEN greenCMYK ELSE blackCMYK; $pol => -- magenta separation for RT6 red layerColorTable[i] _ magentaCMYK; $cut, $cut2 => -- cyan, black, & magenta separations for black layerColorTable[i] _ greenishBlackCMYK; ENDCASE => layerColorTable[i] _ NIL; ok _ TRUE; LOOP END; IF SubColours[] THEN BEGIN usedColour: Color; layerNumberHack _ i; usedColour _ IF obeyToChipNDale THEN Decide [One, layer, NIL] ELSE Decide [Twelve, layer, NIL]; IF traceColourInferences THEN InferenceResult [layer, usedColour]; IF (r1 = NIL) THEN ok _ FALSE; IF (r2 # NIL) AND traceColourInferences THEN BEGIN MessageWindow.Clear; MessageWindow.Append [IO.PutFR ["Substituting color %g for %g\n", IO.rope [ColourName [usedColour]], IO.rope [ColourName [r2]]]] END; IF (usedColour = NIL) THEN break; layerColorTable[i] _ usedColour END ELSE BEGIN IF (layerColorTable[i] # NIL) THEN LOOP; layerColorTable[i] _ CDColorsExtras.RegisteredColor [i ! CDColorsExtras.ColorNotRegistered => {layerColorTable[i] _ undefColour; ok _ FALSE; CONTINUE}]; IF (layerColorTable[i] = undefColour) THEN TerminalIO.PutF ["\nNo color is available from ChipNDale for layer %g\n",IO.atom [layer]]; IF (layerColorTable[i] = NIL) THEN break; END ENDLOOP END; -- SetLayerColourTable ResetLayerColourTable: PUBLIC PROC RETURNS [ok: BOOL _ TRUE] ~ BEGIN <> IF NOT DoLineArt[] THEN UseSimpleColours; FOR i: CD.Layer IN CD.Layer DO layerColorTable[i] _ NIL; currentlyUsedLayers[i] _ FALSE ENDLOOP; blendedColourTable.Erase; ok _ SetLayerColourTable [] END; -- ResetLayerColourTable <> <> blendedColourTable: RefTab.Ref ~ RefTab.Create [magicNumber, Match, Hash]; EachCTEntry: TYPE ~ PROC [colour: Color, layers: LIST OF ATOM]; colourCacheSize: CARDINAL ~ 256; ColourCacheRep: TYPE ~ ARRAY [1 .. colourCacheSize] OF Color _ ALL [NIL]; colourCache: REF ColourCacheRep _ NEW [ColourCacheRep]; ColourTile: PUBLIC PROC [old: Blend, l: CD.Layer] RETURNS [new: Blend] ~ BEGIN <> <> key: BlendKey ~ NEW [Bitset _ old.flavours]; key[l] _ TRUE; new _ NARROW [blendedColourTable.Fetch[key].val, Blend]; IF (new = NIL) THEN BEGIN copy: Blend _ NEW [BlendRec _ [flavours: old.flavours]]; copy.count _ SUCC [old.count]; copy.flavours[l] _ TRUE; copy.used _ TRUE; new _ copy; IF NOT blendedColourTable.Insert [key, copy] THEN ERROR; <> currentlyUsedLayers[l] _ TRUE END ELSE BEGIN new.used _ TRUE; <> END END; -- ColourTile BlendColourForATile: RefTab.EachPairAction ~ BEGIN <> <<[key: Key, val: Value] RETURNS [quit: BOOLEAN _ FALSE]>> components: Blend ~ NARROW [val]; n: REAL _ Float [components.count]; comp: PACKED ARRAY CD.Layer OF BOOLEAN _ components.flavours; mix, v: RGB _ unColour; IF (components.blend # NIL) THEN RETURN [FALSE]; -- caching across sessions SELECT n FROM 0 => ERROR; -- should never have been allocated 1 => IF (currentColourMap = NIL) THEN BEGIN i: CD.Layer _ 0; WHILE NOT comp[i] DO i _ SUCC [i] ENDLOOP; components.blend _ LayerColour [i]; IF (components.blend = NIL) THEN ERROR; RETURN [FALSE] END; ENDCASE => NULL; -- the normal case <> IF (currentColourMap # NIL) THEN BEGIN fetched: ATOM; val: SymTab.Val; found, allFound: BOOL; <> FOR i: CARDINAL IN [0 .. currentColourMap.size) DO <> IF (currentColourMap[i].layers.GetSize # components.count) THEN LOOP; allFound _ TRUE; FOR k: CD.Layer IN CD.Layer DO IF comp[k] THEN BEGIN layer: ATOM ~ CD.LayerKey [k]; [found, val] _ currentColourMap[i].layers.Fetch [Atom.GetPName [layer]]; fetched _ NARROW [val, ATOM]; IF (NOT found) OR (fetched # layer) THEN {allFound _ FALSE; LOOP} END ENDLOOP; IF allFound THEN BEGIN components.index _ currentColourMap[i].index; components.blend _ ColorFromRGB [currentColourMap[i].colour, currentColourMap[i].index]; RETURN [FALSE] END ENDLOOP; IF traceColourInferences THEN BEGIN TerminalIO.PutRope ["\nThere is no colour for"]; FOR k: CD.Layer IN CD.Layer DO IF comp[k] THEN TerminalIO.PutF [" %g", IO.atom [CD.LayerKey [k]]] ENDLOOP; TerminalIO.PutRope ["\n"] END END; <> BEGIN poly, diff, met, met2, cut, cut2, well: CD.Layer _ 0; IF (n = 1) THEN BEGIN i: CD.Layer _ 0; WHILE NOT comp[i] DO i _ SUCC [i] ENDLOOP; components.blend _ LayerColour [i]; IF (components.blend = NIL) THEN ERROR; RETURN [FALSE] END; <> FOR i: CD.Layer IN CD.Layer DO IF comp[i] THEN SELECT CD.LayerKey [i] FROM $pol => poly _ i; $ndif, $pdif => diff _ i; $met => met _ i; $met2 => met2 _ i; $nwel => well _ i; $cut, $comment => cut _ i; $cut2 => {cut _ i; cut2 _ i}; ENDCASE => NULL ENDLOOP; <> IF (cut # 0) THEN components.blend _ LayerColour [cut] ELSE BEGIN -- Assume: all other colours have the same weight. IF (poly # 0) AND (diff # 0) THEN BEGIN -- Handle gates. <> mix _ doubleYellowRGB; comp[poly] _ comp[diff] _ FALSE END; IF (poly # 0) AND (met # 0) AND (diff = 0) THEN BEGIN <> mix _ magentaRGB; n _ n - 1.0; comp[poly] _ comp[met] _ FALSE END; FOR i: CD.Layer IN CD.Layer DO -- Compute mean colour. IF comp[i] THEN BEGIN IF CD.LayerKey[i] = $nwel THEN LOOP; -- ignore wells under material v _ RGBFromColour [layerColorTable[i]]; mix.R _ mix.R + v.R; mix.G _ mix.G + v.G; mix.B _ mix.B + v.B END ENDLOOP; IF (well # 0) THEN BEGIN -- make wells transparent n _ n - 1.0 <> <> <> END; IF (met2 # 0) AND (well # 0) AND (n > 2) THEN BEGIN -- make metal-2 transparent mix.R _ mix.R - 4.0/7.0; mix.B _ mix.B - 4.0/7.0; n _ n - 4.0/7.0 END; mix.R _ mix.R / n; mix.G _ mix.G / n; mix.B _ mix.B / n; components.blend _ ColorFromRGB [mix, 0]; components.index _ 1; components.used _ TRUE END; -- not a contact <> IF (components.blend = NIL) THEN break; END; RETURN [FALSE] END; -- BlendColourForATile BlendTileColours: PUBLIC PROC ~ BEGIN <> [] _ blendedColourTable.Pairs [BlendColourForATile]; END; -- BlendTileColours Hash: RefTab.HashProc ~ BEGIN <> TRUSTED BEGIN RETURN [Checksum.ComputeChecksum [0, SIZE [BlendKey], LOOPHOLE [key]]] END END; -- Hash Match: RefTab.EqualProc ~ BEGIN <> k1: BlendKey ~ NARROW [key1]; k2: BlendKey ~ NARROW [key2]; RETURN [(k1^ = k2^)] END; -- Match NumberOfColours: PUBLIC PROC RETURNS [INT] ~ BEGIN <> n: CARD _ 0; IF DoLineArt[] THEN RETURN [4]; IF SubColours[] THEN BEGIN FOR index: CARDINAL IN [1 .. colourCacheSize] DO IF (colourCache[index] # NIL) THEN n _ n.SUCC ENDLOOP; RETURN [n] END ELSE BEGIN FOR c: CD.Layer IN CD.Layer DO IF (layerColorTable[c] # NIL) THEN n _ n.SUCC; ENDLOOP; RETURN [n] END <> END; -- NumberOfColours DeclareColours: PUBLIC PROC [master: ImagerInterpress.Ref] ~ BEGIN <> <> <> <= 0) THEN>> <> <> <> master.DeclareColor [blackCMYK]; IF DoLineArt[] THEN BEGIN master.DeclareColor [cyanCMYK]; master.DeclareColor [magentaCMYK]; master.DeclareColor [greenCMYK]; IF UseProcessColors[] THEN master.DeclareColor [redCMYK] ELSE BEGIN master.DeclareColor [yellowCMYK]; master.DeclareColor [greenishBlackCMYK] END; RETURN END; IF SubColours[] THEN FOR index: CARDINAL IN [1 .. colourCacheSize] DO IF (colourCache[index] # NIL) THEN master.DeclareColor [colourCache[index]] ENDLOOP ELSE FOR c: CD.Layer IN CD.Layer DO IF (layerColorTable[c] # NIL) THEN master.DeclareColor [layerColorTable[c]] ENDLOOP END; -- DeclareColours IthColour: PUBLIC PROC [i: INT] RETURNS [Color] ~ BEGIN <> RETURN [colourCache[i.ABS]] END; -- IthColour ListColourStatistics: PUBLIC PROC [numberOfTiles: CARD] ~ BEGIN <> totalArea: REAL _ 0.0; -- It is the way it is because of numerical stability. ComputeArea: RefTab.EachPairAction ~ BEGIN data: Blend ~ NARROW [val]; totalArea _ totalArea + Float [data.area] END; -- ComputeArea ListEntry: RefTab.EachPairAction ~ BEGIN data: Blend ~ NARROW [val]; cmyk: CMYK ~ CMYKFromRGB [RGBFromColour [data.blend]]; IF NOT data.used THEN RETURN; IF totalArea = 0.0 THEN totalArea _ 1.0; TerminalIO.PutF ["%g\t%g\t%g\t\t%g\t\t%g\t", IO.real [cmyk.C], IO.real [cmyk.M], IO.real [cmyk.Y], IO.real [cmyk.K], IO.real [Float[data.area] / totalArea]]; FOR i: CD.Layer IN CD.Layer DO IF data.flavours[i] THEN TerminalIO.PutF [" %g", IO.atom [CD.LayerKey[i]]] ENDLOOP; TerminalIO.PutF ["\t-- %g --\n", IO.rope [ColourName[data.blend]]] END; -- ListEntry TerminalIO.PutF ["Statistical data gathered by Nectarine:\n\tSize of color table: %g; number of tiles: %g\n\tColor (CMYK), relative area and layers\n", IO.int [blendedColourTable.GetSize[]], IO.int [numberOfTiles]]; [] _ blendedColourTable.Pairs [ComputeArea]; IF debug THEN BEGIN [] _ blendedColourTable.Pairs [ListEntry]; TerminalIO.PutRope ["Colors with null area were intermediate.\n"] END END; -- ListColourStatistics ResetColourStatistics: PUBLIC PROC ~ BEGIN <> ResetArea: RefTab.EachPairAction ~ {rec: Blend ~ NARROW [val]; rec.area _ 0}; [] _ blendedColourTable.Pairs [ResetArea] END; -- ResetColourStatistics <> <> <<1. Writing colour maps>> ExpandBlendedColourTable: PROC [action: EachCTEntry] ~ BEGIN <> DoEntry: RefTab.EachPairAction ~ BEGIN data: Blend ~ NARROW [val]; layers: LIST OF ATOM; FOR l: CD.Layer IN CD.Layer DO IF data.flavours[l] THEN layers _ CONS [CD.LayerKey[l], layers]; ENDLOOP; action [data.blend, layers] END; -- DoEntry [] _ blendedColourTable.Pairs [DoEntry]; END; -- ExpandBlendedColourTable WriteMap: PUBLIC PROC [fileName: ROPE, msg: IO.STREAM _ NIL] ~ BEGIN <> file: IO.STREAM; i: CARDINAL _ 0; WriteColor: EachCTEntry ~ BEGIN <> rgb: RGB ~ RGBFromColour [colour]; file.PutF ["%g\t%g\t%g\t%g", IO.card [i], IO.card [Round [255.0 * rgb.R]], IO.card [Round [255.0 * rgb.G]], IO.card [Round [255.0 * rgb.B]]]; FOR l: LIST OF ATOM _ layers, l.rest WHILE (l # NIL) DO file.PutF [" %g", IO.atom [l.first]] ENDLOOP; file.PutRope ["\n"]; i _ i.SUCC END; -- WriteColor file _ FS.StreamOpen [fileName: fileName, accessOptions: create, keep: 3, createByteCount: 5000, fileType: FS.tText, extendFileProc: NIL]; file.PutRope ["ColorMap\nonesAreWhite\nBitsPerPixel 8\n"]; ExpandBlendedColourTable [WriteColor]; IF (msg # NIL) THEN msg.PutF ["\nRename pippo _ %g\n", IO.rope [fileName]]; file.Close []; ImportantMessage [fileName] END; -- WriteMap WriteMapCommand: Commander.CommandProc ~ BEGIN <> fn: Args.Arg; cp: FS.ComponentPositions; pippo: BOOL; name: ROPE _ "New.ColorMap"; lastWDir _ cmd.command.Substr [0, FS.ExpandName[cmd.command].cp.base.start-1]; IF (NumberOfColours[] = 0) THEN RETURN [$Failure, "Process some layout first (e.g. NectarineTest, VTIRules)."]; IF (Args.NArgs [cmd] # 0) THEN BEGIN [fn] _ Args.ArgsGet [cmd, "-a%s" ! Args.Error => {argError _ reason; GOTO failure}]; IF fn.ok THEN name _ fn.rope END; [name, cp, pippo] _ FS.ExpandName [name, WDir []]; IF (cp.ext.length = 0) THEN name _ name.Cat [".ColorMap"]; WriteMap [name, cmd.out]; EXITS failure => RETURN [$Failure, argError] END; -- WriteMapCommand <<2. Reading colour maps>> ColourMapEntry: TYPE ~ RECORD [colour: RGB, index: INT, layers: SymTab.Ref]; ColourMapRep: TYPE ~ RECORD [SEQUENCE size: CARDINAL OF ColourMapEntry]; currentColourMap: REF ColourMapRep; -- cache ReadMap: PUBLIC PROC [fileName: ROPE] ~ BEGIN <> rec, file: IO.STREAM; token: ROPE; firstToken: IO.TokenKind; size, i: CARDINAL _ 0; rgb: RGB; cp: FS.ComponentPositions; [fileName, cp, ] _ FS.ExpandName [fileName, WDir []]; IF (cp.ext.length = 0) THEN fileName _ fileName.Cat [".ColorMap"]; file _ FS.StreamOpen [fileName: fileName, wDir: WDir [], extendFileProc: NIL ! FS.Error => GOTO noFile]; DO rec _ IO.RIS [file.GetLineRope [! IO.EndOfStream => {EXIT}; IO.Error => {break}], rec]; [tokenKind: firstToken, token: token] _ rec.GetCedarTokenRope [! IO.EndOfStream => {EXIT}]; IF ((firstToken = tokenDECIMAL) OR ((firstToken = tokenSINGLE) AND (token.Fetch [] = '-))) THEN size _ size.SUCC ENDLOOP; file.SetIndex [0]; currentColourMap _ NEW [ColourMapRep[size]]; blendedColourTable.Erase; FOR i: CARDINAL IN [1 .. colourCacheSize] DO colourCache[i] _ NIL ENDLOOP; DO rec _ IO.RIS [file.GetLineRope [! IO.EndOfStream => {EXIT}], rec]; currentColourMap[i].index _ rec.GetInt [! IO.EndOfStream, IO.Error => {LOOP}]; -- header <<[tokenKind: firstToken, token: token] _ rec.GetCedarTokenRope [! IO.EndOfStream => {LOOP}]; -- there are empty lines>> <> <> <> <> <> <<[] _ Rope.Map [base: r, action: PutChar]>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<[ir, ig, ib] _ Terminal.GetColor [vt, i];>> <> <> <> <> <Users>Beretta.pa>CD>NectarineTune.tioga"];>> <Users>Beretta.pa>CD>NectarineTune.tioga created.\n"]>> <> <> <> <> <> IF NOT DoLineArt[] THEN UseSimpleColours; IF SubColours [] THEN ReadMap [UserProfile.Token ["Nectarine.Palette", "[DATools7.0]Discriminable.ColorMap"]]; Commander.Register [key: "NQuery", proc: QueryRule, doc: doc]; Commander.Register [key: "NWriteColors", proc: WriteMapCommand, doc: "Writes the colors used by Nectarine in a file using the extended color map format.\nSwitch a: file name."]; Commander.Register [key: "NReadColors", proc: ReadMapCommand, doc: "Loads the table of blended colours from a extended color map file.\nSwitch a: file name."]; Commander.Register [key: "NOldColors", proc: ChangeColours, doc: "Do not use (recrerates the colors used in the past). Switch a:\n\t1: obey to ChipNDale\n\t2: simple colors\n\t3: compressed colors\nno switch: used balanced colors.\nSwitch b overrides the default extended color map."] END. <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>>