DIRECTORY ColorizeViewPoint, ColorizeViewPointBackdoor, ColorizeViewPointGraphicsCommon, ColorizeViewPointSweep, Convert, Ieee, IO, IPMaster, IPScan, PBasics, Profiles, Rope, SymTab, Vector2; ColorizeViewPointGraphicsCommonImpl: CEDAR PROGRAM IMPORTS ColorizeViewPoint, ColorizeViewPointBackdoor, ColorizeViewPointSweep, Convert, IO, IPMaster, IPScan, PBasics, Profiles, Rope, SymTab EXPORTS ColorizeViewPointGraphicsCommon ~ BEGIN OPEN ColorizeViewPointGraphicsCommon; Colorization: TYPE ~ ColorizeViewPointBackdoor.Colorization; Profile: TYPE ~ Profiles.Profile; ROPE: TYPE ~ Rope.ROPE; SampledColorIPFragments: TYPE ~ ColorizeViewPointBackdoor.SampledColorIPFragments; SampledColorTransformSet: TYPE ~ ColorizeViewPointSweep.SampledColorTransformSet; ASSERTION: TYPE ~ BOOL [TRUE..TRUE]; ColorizeGraphics: PUBLIC PROC [ip: ROPE, subs: SubsInfo, opList: LIST OF Op, getColor: GetColorProc, seqList: LIST OF Seq _ NIL, customOnly: BOOL _ FALSE] RETURNS [colorizedIP: ROPE _ NIL] ~ { PerColorSpecified: IPScan.ScanProc = { color, addendum: ROPE _ NIL; -- addendum follows replacementColor to store it correctly replacementColor: REF; [newMin: min, newMax: max, color: color, addendum: addendum] _ getColor[ip, min, max]; --client defines the piece of the ip to be replaced and what addendum to add after the replacement IF color=NIL THEN RETURN; --client returns NIL if ip segment unrecognized; leave alone replacementColor _ GetReplacementColor[color: color, subs: subs, customOnly: customOnly]; IF ~customOnly AND replacementColor=NIL AND color.Find["\017\317\224\240\347"]#-1 --YES color-- THEN {ColorizeViewPointBackdoor.SetProfileBoolean[profile: subs.palette, key: "AmbushAllYESColors", val: FALSE]; ColorizeViewPointBackdoor.SetProfileBoolean [profile: subs.palette, key: "IP2", val: FALSE]}; --replacementColor=NIL means a YES color isn't getting changed, so don't remove YES operators and don't use 2.0 header IF ~punt AND replacementColor#NIL THEN WITH replacementColor SELECT FROM replacementColor: ROPE => { --Constant color colorizedIP _ colorizedIP.Cat[ip.Substr[start: flushFrom, len: min-flushFrom], replacementColor, addendum]; --replace MakeSampledBlack section w/ replacementColor flushFrom _ max; --reset marker to after original color & ISET section }; replacementColor: REF SampledColorIPFragments => { --Sampled color (sweep) replacement: ROPE _ NARROW[sampledColors.Fetch[key: color].val]; ts: SampledColorTransformSet; pos: INT; SELECT TRUE FROM replacement#NIL => { --Have already spatially resolved this color in ENDCASE below colorizedIP _ colorizedIP.Cat[ip.Substr[start: flushFrom, len: min-flushFrom], replacement, addendum]; --replace MakeSampledBlack section w/ replacement flushFrom _ max; --reset marker to after original color & ISET section }; (([transformSet: ts, finalPos: pos] _ BuildTransformSet[ip: ip, pos: max, remove: replacementColor.removeDefiningObject]).transformSet = nullTransformSet) => SIGNAL ColorizeViewPoint.Warning[$MalformedDefiningObject, "Malformed Sweep defining object"]; --Failure (but on non-failures this branch causes the transformation vector set to be built before going to ENDCASE) ENDCASE => { --build the transform for the pixel array replacement _ Rope.Cat[replacementColor.beforeTransform, ColorizeViewPointSweep.ConstructSweepTransform[ts: ts, sc: replacementColor], replacementColor.afterTransform]; [] _ SymTab.Store[x: sampledColors, key: color, val: replacement]; colorizedIP _ colorizedIP.Cat[ip.Substr[start: flushFrom, len: min-flushFrom], replacement, addendum]; --replace original color and MaskRectangle section with a MakeSampledColor section. MaskRectangle is removed (if "removeDefiningObject" is TRUE) because it is not part of the image; it is only used to define sweep size and angle parms flushFrom _ pos; --throws out the defining rectangle or triangle if "removeDefiningObject" is TRUE, otherwise (default) keeps it. }; }; ENDCASE => ERROR; }; sampledColors: SymTab.Ref ~ SymTab.Create[]; flushFrom: INT _ 0; IPScan.ScanRope[ip: ip, ops: opList, seqs: seqList, action: PerColorSpecified]; colorizedIP _ colorizedIP.Concat[ip.Substr[start: flushFrom, len: ip.Size]]; }; GetReplacementColor: PROC [color: ROPE, subs: SubsInfo, customOnly: BOOL _ FALSE] RETURNS [ipFrag: REF _ NIL] ~ {--customOnly => only look in Custom palette for color lookupColor: REF _ SymTab.Fetch[x: subs.subs, key: color].val; --first time, should be a Color like [25%AC, $CVPPattern]. After that, an already resolved REF IF lookupColor#NIL THEN WITH lookupColor SELECT FROM getVal: Color => { --not previously resolved value: LIST OF ROPE; levelsExceeded: BOOL; [value, levelsExceeded] _ ColorizeViewPointBackdoor.GetRecursiveValue[key: getVal.value, palette: subs.palette, subpaletteList: subs.subpaletteList, mapData: subs.mapData, customOnly: customOnly]; SELECT TRUE FROM value=NIL => { [] _ SymTab.Store[x: subs.subs, key: color, val: NIL];--saves time next time RETURN; }; levelsExceeded => { [] _ SymTab.Store[x: subs.subs, key: color, val: NIL];--saves time next time SIGNAL ColorizeViewPoint.Warning[class: $MalformedPaletteEntry, explanation: IO.PutFR[format: "%g is part of a recursive color definition beyond allowable levels; ignoring it.", v1: [rope[color]]]]; RETURN; }; ENDCASE => { ipFrag _ ColorizeViewPointBackdoor.IPFragmentForColorDefinition[value, subs.palette]; [] _ SymTab.Store[x: subs.subs, key: color, val: ipFrag];--so already done next time }; }; ENDCASE --already resolved before-- => RETURN [lookupColor]; }; nullTransformSet: SampledColorTransformSet ~ ColorizeViewPointSweep.nullTransformSet; BuildTransformSet: PROC [ip: ROPE, pos: INT, remove: BOOL] RETURNS [transformSet: SampledColorTransformSet, finalPos: INT] ~ { Token: PROC RETURNS [IPMaster.Token] ~ { [token: token, next: pos] _ IPMaster.GetToken[encoding: ip, start: pos]; IF token.seq=sequenceInteger THEN { token.type _ num; token.num _ IPMaster.IntFromSequenceData[text: Rope.ToRefText[ip.Substr[pos, token.len]]]; --not bothering to reset token.seq and token.len pos _ pos + token.len; --move pointer beyond sequence; for seqs, pos is not moved by IPMaster.GetToken }; RETURN [token]; }; token: IPMaster.Token; t: SampledColorTransformSet; transformSet _ nullTransformSet; finalPos _ pos; --Return values for error IF Token[].type=num THEN t.offset.x _ token.num ELSE RETURN; --n1 IF Token[].type=num THEN t.offset.y _ token.num ELSE RETURN; --n2 IF Token[].type=op AND token.op=setxy THEN {--occasionally an n1 n2 SETXY is stuck in the way (eg, in Bitmapper graphics frames) IF Token[].type=num THEN t.offset.x _ token.num ELSE RETURN; --n1 again IF Token[].type=num THEN t.offset.y _ token.num ELSE RETURN; --n2 again [] _ Token[]; --advance token to look at next }; SELECT TRUE FROM token.type=num => { --Case I : n3 found t.width.x _ token.num; t.width.y _ 0; IF Token[].type#num THEN RETURN; --looking for n4 else error t.height.x _ 0; t.height.y _ token.num; IF t.width.x<0 AND t.height.y<0 --typical BasicGraphics pattern starts the rectangle farthest from origin and subtracts the length and width; relocate the startpoint closest to origin and add length and width to match ProIllustrator-- THEN { t.offset.x _ t.offset.x+t.width.x; t.offset.y _ t.offset.y+t.height.y; t.width.x _ ABS[t.width.x]; -- height and width positive t.height.y _ ABS[t.height.y]; }; IF Token[].op#maskrectangle THEN RETURN; --end Case1 }; token.type=op AND token.op=moveto => { --Cases II and III - triangles temp: IPMaster.Token; IF Token[].type=num THEN t.width.x _ token.num - t.offset.x ELSE RETURN; --width will be the first leg of the triangle drawn IF Token[].type=num THEN t.width.y _ token.num - t.offset.y ELSE RETURN; IF Token[]--.type#op OR token--.op#lineto THEN RETURN; IF Token[].type=num THEN t.height.x _ token.num - (t.offset.x+t.width.x) ELSE RETURN; --height will be the second leg of the triangle drawn IF Token[].type=num THEN t.height.y _ token.num - (t.offset.y+t.width.y) ELSE RETURN; IF Token[]--.type#op OR token--.op#lineto THEN RETURN; IF (temp _ Token[]).type#num THEN RETURN; --Could be 1 or n1 SELECT Token[].type FROM op => { --Case II IF temp.num#1 OR token.op#makeoutline THEN RETURN; }; num => { --Case III IF t.offset#[x: temp.num, y: token.num] OR Token[]--.type#op OR token--.op#lineto OR Token[]--.type#num OR token--.num#1 OR Token[]--.type#op OR token--.op#makeoutline THEN RETURN; }; ENDCASE => RETURN; IF Token[]--.type#op OR token--.op#maskfill THEN RETURN; --end Cases II and III }; ENDCASE => RETURN; transformSet _ t; IF remove THEN finalPos _ pos; --ELSE finalpos doesn't change }; InvalidGfxKey: PUBLIC ERROR ~ CODE; --Never seen outside GfxPaletteFromProfile: PUBLIC PROC [profile: Profiles.Profile, seqAction: SeqAction, gfxTexture: GfxTextureProc, gfxGray: GfxGrayProc, transparent, opaque: BOOL _ TRUE] ~ {--looks up each pattern in profile, uses callbacks to construct its ip frag PerKey: Profiles.EnumProc = { ENABLE ColorizeViewPoint.Error => { --Map the error to a warning and proceed SIGNAL ColorizeViewPoint.Warning[class: class, explanation: explanation]; GOTO AbandonKey; }; Action: SeqAction ~ { seqAction[key: key, makeSampledBlack: makeSampledBlack, real: real, textured: textured, transparent: transparent] }; IF Rope.Match[pattern: "ForceTo*", object: key, case: FALSE] THEN RETURN; --ignores entries like "ForceTo25%ABD: c1, c15" for color mapping GfxSeqFromKey[ key: key, gfxTexture: gfxTexture, gfxGray: gfxGray, seqAction: Action, transparent: transparent, opaque: opaque ! InvalidGfxKey => GOTO AbandonKey ]; EXITS AbandonKey => NULL; }; Profiles.EnumerateKeys[profile: profile, pattern: "*%*", proc: PerKey]; --patterns have "%" (eg, "0%AE") }; GfxSeqFromKey: PROC [key: ROPE, gfxTexture: GfxTextureProc, gfxGray: GfxGrayProc, seqAction: SeqAction, transparent, opaque: BOOL _ TRUE] ~ { pattern: Pattern _ ALL[0]; setGrayRope: ROPE _ NIL; f: REAL _ 0; textured: BOOL _ FALSE; --TRUE => a texture has been included text: Rope.Text ~ Rope.NewText[size: 64]; msbFirstPart, msbPixelPattern, msbThirdPart: ROPE; --msb=makesampledblack { --Set up the pattern for msbPixelPattern s: IO.STREAM ~ IO.RIS[rope: key]; char: CHAR; DO IncludePattern: PROC [new: Pattern] ~ TRUSTED { FOR k: NAT IN [0..16) DO pattern[k] _ PBasics.BITOR[pattern[k], new[k]]; ENDLOOP; }; KeyBreak: IO.BreakProc = { RETURN [SELECT char FROM IN ['A..'A+GfxTexture.LAST], 'O, 'T => break, IN ['0..'9], '. => other, ENDCASE => sepr --includes '%--]; }; token: ROPE _ IO.GetTokenRope[stream: s, breakProc: KeyBreak ! IO.EndOfStream => EXIT].token; IF token.Size=1 AND (char _ token.Fetch) IN ['A..'Z] THEN { SELECT char FROM IN ['A..'A+GfxTexture.LAST] => { IncludePattern[gfxTexture[char-'A]]; textured _ TRUE; }; 'O => transparent _ FALSE; 'T => opaque _ FALSE; ENDCASE => SIGNAL ColorizeViewPoint.Warning[$MalformedPaletteEntry, IO.PutFR[format: "Character \"%g\" illegal in profile entry", v1: [character[char]]]]; } ELSE { ENABLE Convert.Error => { ERROR ColorizeViewPoint.Error[$MalformedPaletteEntry, IO.PutFR[format: "Illegal key: \"%g\"", v1: [rope[key]]]]; }; f _ (MIN[100.0, MAX[0.0, Convert.RealFromRope[r: token]]])/100.0; --0.0 to 1.0; for tokens betwn 0.0 & 100.0 IncludePattern[gfxGray[f]]; }; ENDLOOP; }; { tI: NAT _ 0; --Index into the REF TEXT FOR i: NAT IN [0..16) DO CharPair: TYPE = MACHINE DEPENDENT RECORD [high, low: CHAR]; [high: text[tI], low: text[tI+1]] _ LOOPHOLE[pattern[i], CharPair]; text[tI+2] _ text[tI+3] _ '\000; tI _ tI+4; ENDLOOP; }; msbFirstPart _ "\017\260\017\260\017\241\017\241\017\241\304\004\000\001\000\020\240\244\017F\240\243\240\245\017\240\017\241\240\242\240\245"; -- 16 16 1 1 1 n SCALE -90 ROTATE CONCAT 0 1 TRANSLATE CONCAT msbPixelPattern _ Rope.Concat["\311D\000\001\000\020" --sequencePackedPixelVector, 68 bytes long, 1 bit/sample, 16 samples/scan line--, text]; msbThirdPart _ "\241\302\304\004\360 \000\036\304\004\017\340\000\036\240\246\017\244\222\240\245"; --MAKEPIXELARRAY n n SCALE2 4 IGET CONCAT IF transparent THEN seqAction[key: key, makeSampledBlack: Rope.Cat[msbFirstPart, msbPixelPattern, msbThirdPart, "\017\241\241\252" --1 MAKESAMPLEDBLACK--], real: f, textured: textured, transparent: TRUE]; IF opaque THEN seqAction[key: key, makeSampledBlack: Rope.Cat[msbFirstPart, msbPixelPattern, msbThirdPart, "\017\240\241\252" --0 MAKESAMPLEDBLACK--], real: f, textured: textured, transparent: FALSE]; }; END. Ò ColorizeViewPointGraphicsCommonImpl.mesa Copyright Ó 1989 by Xerox Corporation. All rights reserved. Eric Nickell, May 30, 1989 10:02:38 am PDT Bob Coleman, July 19, 1990 3:51:50 pm PDT Graphics Common (Basic Graphics/Pro Illustrator/BitMapper) [min: INT, max: INT, op: IPMaster.Op _ nil, seq: IPScan.Seq _ nil, num: INTEGER _ 0, punt: BOOL _ FALSE] This procedure attempts to find an interpress fragment in one of the three forms given below starting at position pos in ip. This will be the fragment used to define a sweep. Acceptable forms include: I: n1 n2 n3 n4 MASKRECTANGLE (rectangle) NOTE rectangles can't be produced by MAKEOUTLINE on four lines II: n1 n2 MOVETO n3 n4 LINETO n5 n6 LINETO 1 MAKEOUTLINE MASKFILL (triangle) III: n1 n2 MOVETO n3 n4 LINETO n5 n6 LINETO n1 n2 LINETO 1 MAKEOUTLINE MASKFILL (triangle) RETURNS a valid SampledColorTransformSet from one of the above forms and a position. The position is (default) the same as coming in, or if "remove" is TRUE, points to after the encoded interpress for the SampledColorTransformSet. If it gets lost, returns [nullTransformSet, pos]. NOTE1: The following code takes the execution order guarantees of Cedar very seriously w.r.t. AND and OR. NOTE2: Every reference to Token[] returns a value of TYPE IPMaster.Token[] to the caller, but also has the side effect of placing that value in the variable token. This is especially important in conjunction with NOTE 1. Interpress represents some large numbers as sequenceIntegers; for convenience change them into type num before returning: The following assumes the BasicGraphics/ProIllustrator coord system of origin at upper left, x right and y down The only successful exit [key: ROPE] RETURNS [quit: BOOL _ FALSE] transparent => permit the transparent form of the MAKESAMPLEDBLACK opaque => permit the opaque form of the MAKESAMPLEDBLACK [char: CHAR] RETURNS [IO.CharClass] f _ MIN[1.0, MAX[0.0, Convert.RealFromRope[r: token]]]; --0.0 to 1.0; for tokens betwn 0.0 & 1.0 Êï•NewlineDelimiter ™™(Icode™K– [size: NAT]šœ)˜)Kšœ-œ ˜Išœ (˜*K–)[rope: ROPE, oldStream: STREAM _ NIL]š œœœœœ ˜!Kšœœ˜ š˜šŸœœœ˜/šœœœ ˜Kšœœ˜/Kšœ˜—K˜—–' -- [char: CHAR] RETURNS [IO.CharClass]šŸœœ˜Kšœœœœ ™#Kšœœœœœœœ  œ˜‚K˜—Kš œœœ/œœ˜]šœœœ œ˜;šœ˜šœœ˜ Kšœ$˜$Kšœ œ˜Kšœ˜—Kšœœ˜Kšœœ˜K–[format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šœœ3œT˜š—Kšœ˜—– [r: ROPE]šœ˜šœ˜K–[format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šœ1œ9˜qKšœ˜—Kšœœœ/ *˜lKšœœœ( (™`K˜Kšœ˜—Kšœ˜—Kšœ˜—šœ˜Kšœœ ˜&šœœœ ˜Kš œ œœ œœ œ˜[s: REF READONLY TEXT, start: NAT _ 0, len: NAT _ 32767]šœ6 ¥L œ˜ŽKš œ¤Qœ¥ ¥ ¥ ¥˜K˜Kšœ œ=¤œ ¤œ¤¥ ¥œ-œ˜ÌKšœœ=¤œ¤œ¤¥ ¥œ-œ˜ÈK˜—K˜—Kš˜K˜J˜—…—0†HG