<> <> <> <> <<>> 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; <> 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: CARDINAL _ IF patchData.interpolationRequest = off THEN 50 ELSE 40; contrastHeight: CARDINAL _ IF 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: REAL _ IF 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 <> 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]; <> Imager.SetColor[context, Imager.white]; Imager.MaskBox[context, strip]; rx _ rx+stripW; }; <> 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: ViewerClasses.ViewerClass _ NEW[ViewerClasses.ViewerClassRec _ [paint: PaintColorPatch, destroy: DestroyColorPatch]]; <<>> <> ViewerOps.RegisterViewerClass[$ColorPatch, colorPatchClass]; END.