<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>