<body><div id="__MailbirdStyleContent" style="font-size: 10pt;font-family: Arial;color: #000000">
Hi Nicolas,<div><br></div><div>maybe we can refresh this map in #cleanUp: for the release-building process.</div><div><br></div><div>Best,</div><div>Marcel</div><div class="mb_sig"></div><blockquote class="history_container" type="cite" style="border-left-style:solid;border-width:1px; margin-top:20px; margin-left:0px;padding-left:10px;">
<p style="color: #AAAAAA; margin-top: 10px;">Am 18.05.2019 01:50:44 schrieb David T. Lewis <lewis@mail.msen.com>:</p><div style="font-family:Arial,Helvetica,sans-serif">+1 from me also.<br><br>For consistency checking, a test such as this should be sufficient:<br><br>ColorTest>>testAllColorNamesAreMappedAsRBG<br> "Ensure that all named colors have an entry in the RGBToNames map"<br> Color colorNames do:<br> [ :nm | self deny: (Color fromString: nm) name isNil ]<br><br>I do not see a need for different registration mechanism.<br><br>Dave<br><br><br>On Fri, May 17, 2019 at 09:29:36PM +0200, Nicolas Cellier wrote:<br>> Le ven. 17 mai 2019 ?? 19:33, Chris Cunningham <cunningham.cb@gmail.com> a<br>> ??crit :<br>> <br>> > I like it (Based on reading it only - not loading/testing).<br>> ><br>> > > The new class variable is initialized in postscript.<br>> > > It must be re-initialized each time we change the definition of a named<br>> > Color.<br>> ><br>> > So, each time we change a definition, we have to change the postscript,<br>> > since it is only run on change, right?<br>> > If so, this is worth putting a comment anywhere Color names are defined<br>> > (i.e., those methods and external packages); otherwise we will fail to<br>> > follow this requirement at some point.<br>> ><br>> > -cbc<br>> ><br>> > I was thinking of<br>> 1) adding a test<br>> 2) have some form of auto-correction<br>> (that would be easy in the test, even it feels somehow strange to have<br>> self-correcting tests)<br>> <br>> The symptom if we change the definition of a named Color is that it won't<br>> print itself named (the previous definition will).<br>> Also if we add a new named Color but forget to update the map...<br>> No catastropic consequences. But a comment is indeed welcome in class<br>> comment and #name comment.<br>> <br>> Maybe we could adopt a different way of registering named colors thru a<br>> pragma...<br>> <br>> <br>> > On Fri, May 17, 2019 at 8:58 AM Nicolas Cellier <br>> > nicolas.cellier.aka.nice@gmail.com> wrote:<br>> ><br>> >> No objection?<br>> >><br>> >> Le jeu. 16 mai 2019 ?? 15:14, <commits@source.squeak.org> a ??crit :<br>> >><br>> >>> Nicolas Cellier uploaded a new version of Graphics to project The Inbox:<br>> >>> http://source.squeak.org/inbox/Graphics-nice.408.mcz<br>> >>><br>> >>> ==================== Summary ====================<br>> >>><br>> >>> Name: Graphics-nice.408<br>> >>> Author: nice<br>> >>> Time: 16 May 2019, 3:12:54.000487 pm<br>> >>> UUID: cc271e8f-330d-d649-a848-128e2d849f03<br>> >>> Ancestors: Graphics-mt.406<br>> >>><br>> >>> Use a map rgb->#names rather than iterating thru/performing all known<br>> >>> colorNames.<br>> >>><br>> >>> This is especially useful if we intend to add more color names.<br>> >>> Note that names do not need to be unique.<br>> >>> The first appearing name in colorNames will be used.<br>> >>><br>> >>> Color colorNames collect: [:sym | Color perform: sym].<br>> >>><br>> >>> (Color colorNames reject: [:sym | (Color perform: sym) name = sym])<br>> >>> collect: [:sym | sym -> (Color perform: sym) name].<br>> >>><br>> >>> The new class variable is initialized in postscript.<br>> >>> It must be re-initialized each time we change the definition of a named<br>> >>> Color.<br>> >>><br>> >>> The rgb code has been used as key rather than the Color itself.<br>> >>> This is because it is unique and cheap (SmallInteger).<br>> >>><br>> >>> =============== Diff against Graphics-mt.406 ===============<br>> >>><br>> >>> Item was changed:<br>> >>> Object subclass: #Color<br>> >>> instanceVariableNames: 'rgb cachedDepth cachedBitPattern'<br>> >>> + classVariableNames: 'Black Blue BlueShift Brown CachedColormaps<br>> >>> ColorChart ColorNames ComponentMask ComponentMax Cyan DarkGray Gray<br>> >>> GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps<br>> >>> IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen<br>> >>> LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap Orange<br>> >>> PaleBlue PaleBuff PaleGreen PaleMagenta PaleOrange PalePeach PaleRed<br>> >>> PaleTan PaleYellow PantonePurpleU PureBlue PureCyan PureGreen PureMagenta<br>> >>> PureRed PureYellow RGBToNames RandomStream Red RedShift TranslucentPatterns<br>> >>> Transparent VeryDarkGray VeryLightGray VeryPaleRed VeryVeryDarkGray<br>> >>> VeryVeryLightGray White Yellow'<br>> >>> - classVariableNames: 'Black Blue BlueShift Brown CachedColormaps<br>> >>> ColorChart ColorNames ComponentMask ComponentMax Cyan DarkGray Gray<br>> >>> GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps<br>> >>> IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen<br>> >>> LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap Orange<br>> >>> PaleBlue PaleBuff PaleGreen PaleMagenta PaleOrange PalePeach PaleRed<br>> >>> PaleTan PaleYellow PantonePurpleU PureBlue PureCyan PureGreen PureMagenta<br>> >>> PureRed PureYellow RandomStream Red RedShift TranslucentPatterns<br>> >>> Transparent VeryDarkGray VeryLightGray VeryPaleRed VeryVeryDarkGray<br>> >>> VeryVeryLightGray White Yellow'<br>> >>> poolDictionaries: ''<br>> >>> category: 'Graphics-Primitives'!<br>> >>><br>> >>> !Color commentStamp: '<historical>' prior: 0!<br>> >>> This class represents abstract color, regardless of the depth of<br>> >>> bitmap it will be shown in. At the very last moment a Color is converted<br>> >>> to a pixelValue that depends on the depth of the actual Bitmap inside the<br>> >>> Form it will be used with. The supported depths (in bits) are 1, 2, 4, 8,<br>> >>> 16, and 32. The number of actual colors at these depths are: 2, 4, 16,<br>> >>> 256, 32768, and 16 million. (See comment in BitBlt.) To change the depth<br>> >>> of the Display and set how many colors you can see, execute: (Display<br>> >>> newDepth: 8). (See comment in DisplayMedium)<br>> >>> Color is represented as the amount of light in red, green, and<br>> >>> blue. White is (1.0, 1.0, 1.0) and black is (0, 0, 0). Pure red is (1.0,<br>> >>> 0, 0). These colors are "additive". Think of Color's instance variables<br>> >>> as:<br>> >>> r amount of red, a Float between 0.0 and 1.0.<br>> >>> g amount of green, a Float between 0.0 and 1.0.<br>> >>> b amount of blue, a Float between 0.0 and 1.0.<br>> >>> (But, in fact, the three are encoded as values from 0 to 1023 and<br>> >>> combined in a single integer, rgb. The user does not need to know this.)<br>> >>> Many colors are named. You find a color by name by sending a<br>> >>> message to class Color, for example (Color lightBlue). Also, (Color red:<br>> >>> 0.2 green: 0.6 blue: 1.0) or (Color r: 0.2 g: 0.6 b: 1.0) creates a color.<br>> >>> (see below)<br>> >>> A color is essentially immutable. Once you set red, green, and<br>> >>> blue, you cannot change them. Instead, create a new Color and use it.<br>> >>> Applications such as contour maps and bar graphs will want to<br>> >>> display one of a set of shades based on a number. Convert the range of<br>> >>> this number to an integer from 1 to N. Then call (Color green lightShades:<br>> >>> N) to get an Array of colors from white to green. Use the Array messages<br>> >>> at:, atPin:, or atWrap: to pull out the correct color from the array.<br>> >>> atPin: gives the first (or last) color if the index is out of range.<br>> >>> atWrap: wraps around to the other end if the index is out of range.<br>> >>> Here are some fun things to run in when your screen has color:<br>> >>> Pen new mandala: 30 diameter: Display height-100.<br>> >>> Pen new web "Draw with the mouse, opt-click to end"<br>> >>> Display fillWhite. Pen new hilberts: 5.<br>> >>> Form toothpaste: 30 "Draw with mouse, opt-click to end"<br>> >>> You might also want to try the comment in<br>> >>> Form>class>examples>tinyText...<br>> >>><br>> >>><br>> >>> Messages:<br>> >>> mixed: proportion with: aColor Answer this color mixed with the<br>> >>> given color additively. The proportion, a number between 0.0 and 1.0,<br>> >>> determines what what fraction of the receiver to use in the mix.<br>> >>><br>> >>> + add two colors<br>> >>> - subtract two colors<br>> >>> * multiply the values of r, g, b by a number or an Array<br>> >>> of factors. ((Color named: #white) * 0.3) gives a darkish gray. (aColor *<br>> >>> #(0 0 0.9)) gives a color with slightly less blue.<br>> >>> / divide a color by a factor or an array of three factors.<br>> >>><br>> >>> errorForDepth: d How close the nearest color at this depth<br>> >>> is to this abstract color. Sum of the squares of the RGB differences,<br>> >>> square rooted and normalized to 1.0. Multiply by 100 to get percent.<br>> >>><br>> >>> hue Returns the hue of the color. On a wheel<br>> >>> from 0 to 360 with pure red at 0 and again at 360.<br>> >>> saturation Returns the saturation of the color. 0.0 to 1.0<br>> >>> brightness Returns the brightness of the color. 0.0 to 1.0<br>> >>><br>> >>> name Look to see if this Color has a name.<br>> >>> display Show a swatch of this color tracking the cursor.<br>> >>><br>> >>> lightShades: thisMany An array of thisMany colors from<br>> >>> white to the receiver.<br>> >>> darkShades: thisMany An array of thisMany colors from<br>> >>> black to the receiver. Array is of length num.<br>> >>> mix: color2 shades: thisMany An array of thisMany<br>> >>> colors from the receiver to color2.<br>> >>> wheel: thisMany An array of thisMany colors<br>> >>> around the color wheel starting and ending at the receiver.<br>> >>><br>> >>> pixelValueForDepth: d Returns the bits that appear be in a<br>> >>> Bitmap of this depth for this color. Represents the nearest available<br>> >>> color at this depth. Normal users do not need to know which pixelValue is<br>> >>> used for which color.<br>> >>><br>> >>> Messages to Class Color.<br>> >>> red: r green: g blue: b Return a color with the given r,<br>> >>> g, and b components.<br>> >>> r: g: b: Same as above, for fast typing.<br>> >>><br>> >>> hue: h saturation: s brightness: b Create a color<br>> >>> with the given hue, saturation, and brightness.<br>> >>><br>> >>> pink<br>> >>> blue<br>> >>> red ... Many colors have messages that return an instance of<br>> >>> Color.<br>> >>> canUnderstand: #brown Returns true if #brown is a defined<br>> >>> color.<br>> >>> names An OrderedCollection of the names of the colors.<br>> >>> named: #notAllThatGray put: aColor Add a new color to the<br>> >>> list and create an access message and a class variable for it.<br>> >>> fromUser Shows the palette of colors available at this<br>> >>> display depth. Click anywhere to return the color you clicked on.<br>> >>><br>> >>> hotColdShades: thisMany An array of thisMany colors showing<br>> >>> temperature from blue to red to white hot.<br>> >>><br>> >>> stdColorsForDepth: d An Array of colors available at this<br>> >>> depth. For 16 bit and 32 bits, returns a ColorGenerator. It responds to<br>> >>> at: with a Color for that index, simulating a very big Array.<br>> >>><br>> >>> colorFromPixelValue: value depth: d Returns a Color whose bit<br>> >>> pattern (inside a Bitmap) at this depth is the number specified. Normal<br>> >>> users do not need to use this.<br>> >>><br>> >>> (See also comments in these classes: Form, Bitmap, BitBlt, Pattern,<br>> >>> MaskedForm.)!<br>> >>><br>> >>> Item was changed:<br>> >>> ----- Method: Color class>>initializeNames (in category 'class<br>> >>> initialization') -----<br>> >>> initializeNames<br>> >>> "Name some colors."<br>> >>> "Color initializeNames"<br>> >>><br>> >>> ColorNames := Set new.<br>> >>> self named: #black put: (Color r: 0 g: 0 b: 0).<br>> >>> self named: #veryVeryDarkGray put: (Color r: 0.125 g: 0.125 b:<br>> >>> 0.125).<br>> >>> self named: #veryDarkGray put: (Color r: 0.25 g: 0.25 b: 0.25).<br>> >>> self named: #darkGray put: (Color r: 0.375 g: 0.375 b: 0.375).<br>> >>> self named: #gray put: (Color r: 0.5 g: 0.5 b: 0.5).<br>> >>> self named: #lightGray put: (Color r: 0.625 g: 0.625 b: 0.625).<br>> >>> self named: #veryLightGray put: (Color r: 0.75 g: 0.75 b: 0.75).<br>> >>> self named: #veryVeryLightGray put: (Color r: 0.875 g: 0.875 b:<br>> >>> 0.875).<br>> >>> self named: #white put: (Color r: 1.0 g: 1.0 b: 1.0).<br>> >>> self named: #red put: (Color r: 1.0 g: 0 b: 0).<br>> >>> self named: #yellow put: (Color r: 1.0 g: 1.0 b: 0).<br>> >>> self named: #green put: (Color r: 0 g: 1.0 b: 0).<br>> >>> self named: #cyan put: (Color r: 0 g: 1.0 b: 1.0).<br>> >>> self named: #blue put: (Color r: 0 g: 0 b: 1.0).<br>> >>> self named: #magenta put: (Color r: 1.0 g: 0 b: 1.0).<br>> >>> self named: #brown put: (Color r: 0.6 g: 0.2 b: 0).<br>> >>> self named: #orange put: (Color r: 1.0 g: 0.6 b: 0).<br>> >>> self named: #lightRed put: (Color r: 1.0 g: 0.8 b: 0.8).<br>> >>> self named: #lightYellow put: (Color r: 1.0 g: 1.0 b: 0.8).<br>> >>> self named: #lightGreen put: (Color r: 0.8 g: 1.0 b: 0.6).<br>> >>> self named: #lightCyan put: (Color r: 0.4 g: 1.0 b: 1.0).<br>> >>> self named: #lightBlue put: (Color r: 0.8 g: 1.0 b: 1.0).<br>> >>> self named: #lightMagenta put: (Color r: 1.0 g: 0.8 b: 1.0).<br>> >>> self named: #lightBrown put: (Color r: 1.0 g: 0.6 b: 0.2).<br>> >>> self named: #lightOrange put: (Color r: 1.0 g: 0.8 b: 0.4).<br>> >>> self named: #transparent put: (TranslucentColor new alpha: 0.0).<br>> >>> self named: #paleBuff put: (Color r: 254 g: 250 b: 235 range:<br>> >>> 255).<br>> >>> self named: #paleBlue put: (Color r: 222 g: 249 b: 254 range:<br>> >>> 255).<br>> >>> self named: #paleYellow put: (Color r: 255 g: 255 b: 217 range:<br>> >>> 255).<br>> >>> self named: #paleGreen put: (Color r: 223 g: 255 b: 213 range:<br>> >>> 255).<br>> >>> self named: #paleRed put: (Color r: 255 g: 230 b: 230 range:<br>> >>> 255).<br>> >>> self named: #veryPaleRed put: (Color r: 255 g: 242 b: 242 range:<br>> >>> 255).<br>> >>> self named: #paleTan put: (Color r: 235 g: 224 b: 199 range:<br>> >>> 255).<br>> >>> self named: #paleMagenta put: (Color r: 255 g: 230 b: 255 range:<br>> >>> 255).<br>> >>> self named: #paleOrange put: (Color r: 253 g: 237 b: 215 range:<br>> >>> 255).<br>> >>> self named: #palePeach put: (Color r: 255 g: 237 b: 213 range:<br>> >>> 255).<br>> >>> self named: #pantonePurpleU put: (Color r: 193 g: 81 b: 184<br>> >>> range: 255).<br>> >>> + self initializeNamesMap<br>> >>><br>> >>> !<br>> >>><br>> >>> Item was added:<br>> >>> + ----- Method: Color class>>initializeNamesMap (in category 'class<br>> >>> initialization') -----<br>> >>> + initializeNamesMap<br>> >>> + "enable mapping a color to its name"<br>> >>> + "Color initializeNamesMap"<br>> >>> +<br>> >>> + RGBToNames := Dictionary new.<br>> >>> + self colorNames do: [:sym | (self perform: sym) addName: sym]!<br>> >>><br>> >>> Item was added:<br>> >>> + ----- Method: Color>>addName: (in category 'other') -----<br>> >>> + addName: aSymbol<br>> >>> + "private - associate a name to this color."<br>> >>> +<br>> >>> + | knownNames |<br>> >>> + [(self class respondsTo: aSymbol) and: [(self class perform:<br>> >>> aSymbol) = self]] assert.<br>> >>> + knownNames := RGBToNames at: rgb ifAbsent: [#()].<br>> >>> + (knownNames includes: aSymbol)<br>> >>> + ifFalse: [ RGBToNames at: rgb put: (knownNames copyWith:<br>> >>> aSymbol)]!<br>> >>><br>> >>> Item was changed:<br>> >>> ----- Method: Color>>name (in category 'other') -----<br>> >>> name<br>> >>> + "Return this color's name, or nil if it has no name."<br>> >>> - "Return this color's name, or nil if it has no name. Only<br>> >>> returns a name if it exactly matches the named color."<br>> >>><br>> >>> + ^ (RGBToNames at: rgb ifAbsent: [nil]) ifNotNil: [:names | names<br>> >>> at: 1 ifAbsent: [nil]]!<br>> >>> - ^ self class colorNames detect: [ :name | (Color perform: name)<br>> >>> = self ] ifNone: [ nil ]!<br>> >>><br>> >>> Item was added:<br>> >>> + ----- Method: TranslucentColor>>addName: (in category 'other') -----<br>> >>> + addName: aSymbol<br>> >>> + "private - associate a name to this color.<br>> >>> + Don't do it, Translucent colors are not uniquely identified by<br>> >>> their rgb components"<br>> >>> +<br>> >>> + ^self!<br>> >>><br>> >>> Item was added:<br>> >>> + ----- Method: TranslucentColor>>name (in category 'other') -----<br>> >>> + name<br>> >>> + self = Color transparent ifTrue: [^#transparent].<br>> >>> + ^nil!<br>> >>><br>> >>> Item was changed:<br>> >>> (PackageInfo named: 'Graphics') postscript: '<br>> >>> + "Initialize RGBToName dictionary"<br>> >>> + Color initializeNamesMap.'!<br>> >>> - " Reset DejaVu to current version "<br>> >>> - StrikeFont initialize.'!<br>> >>><br>> >>><br>> >>><br>> >><br>> ><br><br>> <br><br><br></historical></commits@source.squeak.org></cunningham.cb@gmail.com></div></blockquote>
</div></body>