The Inbox: Graphics-nice.408.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

The Inbox: Graphics-nice.408.mcz

commits-2
Nicolas Cellier uploaded a new version of Graphics to project The Inbox:
http://source.squeak.org/inbox/Graphics-nice.408.mcz

==================== Summary ====================

Name: Graphics-nice.408
Author: nice
Time: 16 May 2019, 3:12:54.000487 pm
UUID: cc271e8f-330d-d649-a848-128e2d849f03
Ancestors: Graphics-mt.406

Use a map rgb->#names rather than iterating thru/performing all known colorNames.

This is especially useful if we intend to add more color names.
Note that names do not need to be unique.
The first appearing name in colorNames will be used.

Color colorNames collect: [:sym | Color perform: sym].

(Color colorNames reject: [:sym | (Color perform: sym) name = sym])
        collect: [:sym | sym -> (Color perform: sym) name].
       
The new class variable is initialized in postscript.
It must be re-initialized each time we change the definition of a named Color.

The rgb code has been used as key rather than the Color itself.
This is because it is unique and cheap (SmallInteger).

=============== Diff against Graphics-mt.406 ===============

Item was changed:
  Object subclass: #Color
  instanceVariableNames: 'rgb cachedDepth cachedBitPattern'
+ classVariableNames: 'Black Blue BlueShift Brown CachedColormaps ColorChart ColorNames ComponentMask ComponentMax Cyan DarkGray Gray GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap Orange PaleBlue PaleBuff PaleGreen PaleMagenta PaleOrange PalePeach PaleRed PaleTan PaleYellow PantonePurpleU PureBlue PureCyan PureGreen PureMagenta PureRed PureYellow RGBToNames RandomStream Red RedShift TranslucentPatterns Transparent VeryDarkGray VeryLightGray VeryPaleRed VeryVeryDarkGray VeryVeryLightGray White Yellow'
- classVariableNames: 'Black Blue BlueShift Brown CachedColormaps ColorChart ColorNames ComponentMask ComponentMax Cyan DarkGray Gray GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap Orange PaleBlue PaleBuff PaleGreen PaleMagenta PaleOrange PalePeach PaleRed PaleTan PaleYellow PantonePurpleU PureBlue PureCyan PureGreen PureMagenta PureRed PureYellow RandomStream Red RedShift TranslucentPatterns Transparent VeryDarkGray VeryLightGray VeryPaleRed VeryVeryDarkGray VeryVeryLightGray White Yellow'
  poolDictionaries: ''
  category: 'Graphics-Primitives'!
 
  !Color commentStamp: '<historical>' prior: 0!
  This class represents abstract color, regardless of the depth of bitmap it will be shown in.  At the very last moment a Color is converted to a pixelValue that depends on the depth of the actual Bitmap inside the Form it will be used with.  The supported depths (in bits) are 1, 2, 4, 8, 16, and 32.  The number of actual colors at these depths are: 2, 4, 16, 256, 32768, and 16 million.  (See comment in BitBlt.)  To change the depth of the Display and set how many colors you can see, execute: (Display newDepth: 8).  (See comment in DisplayMedium)
  Color is represented as the amount of light in red, green, and blue.  White is (1.0, 1.0, 1.0) and black is (0, 0, 0).  Pure red is (1.0, 0, 0).  These colors are "additive".  Think of Color's instance variables as:
  r amount of red, a Float between 0.0 and 1.0.
  g amount of green, a Float between 0.0 and 1.0.
  b amount of blue, a Float between 0.0 and 1.0.
  (But, in fact, the three are encoded as values from 0 to 1023 and combined in a single integer, rgb.  The user does not need to know this.)
  Many colors are named.  You find a color by name by sending a message to class Color, for example (Color lightBlue).  Also, (Color red: 0.2 green: 0.6 blue: 1.0) or (Color r: 0.2 g: 0.6 b: 1.0) creates a color. (see below)
  A color is essentially immutable.  Once you set red, green, and blue, you cannot change them.  Instead, create a new Color and use it.
  Applications such as contour maps and bar graphs will want to display one of a set of shades based on a number.  Convert the range of this number to an integer from 1 to N.  Then call (Color green lightShades: N) to get an Array of colors from white to green.  Use the Array messages at:, atPin:, or atWrap: to pull out the correct color from the array.  atPin: gives the first (or last) color if the index is out of range.  atWrap: wraps around to the other end if the index is out of range.
  Here are some fun things to run in when your screen has color:
  Pen new mandala: 30 diameter: Display height-100.
  Pen new web  "Draw with the mouse, opt-click to end"
  Display fillWhite.  Pen new hilberts: 5.
  Form toothpaste: 30  "Draw with mouse, opt-click to end"
  You might also want to try the comment in
  Form>class>examples>tinyText...
 
 
  Messages:
  mixed: proportion with: aColor Answer this color mixed with the given color additively. The proportion, a number between 0.0 and 1.0, determines what what fraction of the receiver to use in the mix.
 
  + add two colors
  - subtract two colors
  * multiply the values of r, g, b by a number or an Array of factors.  ((Color named: #white) * 0.3) gives a darkish gray.  (aColor * #(0 0 0.9)) gives a color with slightly less blue.
  / divide a color by a factor or an array of three factors.
 
  errorForDepth: d     How close the nearest color at this depth is to this abstract color.  Sum of the squares of the RGB differences, square rooted and normalized to 1.0.  Multiply by 100 to get percent.
 
  hue Returns the hue of the color. On a wheel from 0 to 360 with pure red at 0 and again at 360.
  saturation Returns the saturation of the color.  0.0 to 1.0
  brightness Returns the brightness of the color.  0.0 to 1.0
 
  name    Look to see if this Color has a name.
  display Show a swatch of this color tracking the cursor.
 
  lightShades: thisMany An array of thisMany colors from white to the receiver.
  darkShades: thisMany An array of thisMany colors from black to the receiver.  Array is of length num.
  mix: color2 shades: thisMany An array of thisMany colors from the receiver to color2.
  wheel: thisMany An array of thisMany colors around the color wheel starting and ending at the receiver.
 
  pixelValueForDepth: d    Returns the bits that appear be in a Bitmap of this depth for this color.  Represents the nearest available color at this depth.  Normal users do not need to know which pixelValue is used for which color.
 
  Messages to Class Color.
  red: r green: g blue: b Return a color with the given r, g, and b components.
  r: g: b: Same as above, for fast typing.
 
    hue: h saturation: s brightness: b Create a color with the given hue, saturation, and brightness.
 
  pink
    blue
  red ... Many colors have messages that return an instance of Color.
  canUnderstand: #brown  Returns true if #brown is a defined color.
  names An OrderedCollection of the names of the colors.
  named: #notAllThatGray put: aColor    Add a new color to the list and create an access message and a class variable for it.
  fromUser Shows the palette of colors available at this display depth.  Click anywhere to return the color you clicked on.
 
  hotColdShades: thisMany An array of thisMany colors showing temperature from blue to red to white hot.
 
      stdColorsForDepth: d        An Array of colors available at this depth.  For 16 bit and 32 bits, returns a ColorGenerator.  It responds to at: with a Color for that index, simulating a very big Array.
 
     colorFromPixelValue: value depth: d    Returns a Color whose bit pattern (inside a Bitmap) at this depth is the number specified.  Normal users do not need to use this.
 
  (See also comments in these classes: Form, Bitmap, BitBlt, Pattern, MaskedForm.)!

Item was changed:
  ----- Method: Color class>>initializeNames (in category 'class initialization') -----
  initializeNames
  "Name some colors."
  "Color initializeNames"
 
  ColorNames := Set new.
  self named: #black put: (Color r: 0 g: 0 b: 0).
  self named: #veryVeryDarkGray put: (Color r: 0.125 g: 0.125 b: 0.125).
  self named: #veryDarkGray put: (Color r: 0.25 g: 0.25 b: 0.25).
  self named: #darkGray put: (Color r: 0.375 g: 0.375 b: 0.375).
  self named: #gray put: (Color r: 0.5 g: 0.5 b: 0.5).
  self named: #lightGray put: (Color r: 0.625 g: 0.625 b: 0.625).
  self named: #veryLightGray put: (Color r: 0.75 g: 0.75 b: 0.75).
  self named: #veryVeryLightGray put: (Color r: 0.875 g: 0.875 b: 0.875).
  self named: #white put: (Color r: 1.0 g: 1.0 b: 1.0).
  self named: #red put: (Color r: 1.0 g: 0 b: 0).
  self named: #yellow put: (Color r: 1.0 g: 1.0 b: 0).
  self named: #green put: (Color r: 0 g: 1.0 b: 0).
  self named: #cyan put: (Color r: 0 g: 1.0 b: 1.0).
  self named: #blue put: (Color r: 0 g: 0 b: 1.0).
  self named: #magenta put: (Color r: 1.0 g: 0 b: 1.0).
  self named: #brown put: (Color r: 0.6 g: 0.2 b: 0).
  self named: #orange put: (Color r: 1.0 g: 0.6 b: 0).
  self named: #lightRed put: (Color r: 1.0 g: 0.8 b: 0.8).
  self named: #lightYellow put: (Color r: 1.0 g: 1.0 b: 0.8).
  self named: #lightGreen put: (Color r: 0.8 g: 1.0 b: 0.6).
  self named: #lightCyan put: (Color r: 0.4 g: 1.0 b: 1.0).
  self named: #lightBlue put: (Color r: 0.8 g: 1.0 b: 1.0).
  self named: #lightMagenta put: (Color r: 1.0 g: 0.8 b: 1.0).
  self named: #lightBrown put: (Color r: 1.0 g: 0.6 b: 0.2).
  self named: #lightOrange put: (Color r: 1.0 g: 0.8 b: 0.4).
  self named: #transparent put: (TranslucentColor new alpha: 0.0).
  self named: #paleBuff put: (Color r: 254 g: 250 b: 235 range: 255).
  self named: #paleBlue put: (Color r: 222 g: 249 b: 254 range: 255).
  self named: #paleYellow put: (Color r: 255 g: 255 b: 217 range: 255).
  self named: #paleGreen put: (Color r: 223 g: 255 b: 213 range: 255).
  self named: #paleRed put: (Color r: 255 g: 230 b: 230 range: 255).
  self named: #veryPaleRed put: (Color r: 255 g: 242 b: 242 range: 255).
  self named: #paleTan put: (Color r: 235 g: 224 b: 199 range: 255).
  self named: #paleMagenta put: (Color r: 255 g: 230 b: 255 range: 255).
  self named: #paleOrange put: (Color r: 253 g: 237 b: 215 range: 255).
  self named: #palePeach put: (Color r: 255 g: 237 b: 213 range: 255).
  self named: #pantonePurpleU put: (Color r: 193 g: 81 b: 184 range: 255).
+ self initializeNamesMap
 
  !

Item was added:
+ ----- Method: Color class>>initializeNamesMap (in category 'class initialization') -----
+ initializeNamesMap
+ "enable mapping a color to its name"
+ "Color initializeNamesMap"
+
+ RGBToNames := Dictionary new.
+ self colorNames do: [:sym | (self perform: sym) addName: sym]!

Item was added:
+ ----- Method: Color>>addName: (in category 'other') -----
+ addName: aSymbol
+ "private - associate a name to this color."
+
+ | knownNames |
+ [(self class respondsTo: aSymbol) and: [(self class perform: aSymbol) = self]] assert.
+ knownNames := RGBToNames at: rgb ifAbsent: [#()].
+ (knownNames includes: aSymbol)
+ ifFalse: [ RGBToNames at: rgb put: (knownNames copyWith: aSymbol)]!

Item was changed:
  ----- Method: Color>>name (in category 'other') -----
  name
+ "Return this color's name, or nil if it has no name."
- "Return this color's name, or nil if it has no name. Only returns a name if it exactly matches the named color."
 
+ ^ (RGBToNames at: rgb ifAbsent: [nil]) ifNotNil: [:names | names at: 1 ifAbsent: [nil]]!
- ^ self class colorNames detect: [ :name | (Color perform: name) = self ] ifNone: [ nil ]!

Item was added:
+ ----- Method: TranslucentColor>>addName: (in category 'other') -----
+ addName: aSymbol
+ "private - associate a name to this color.
+ Don't do it, Translucent colors are not uniquely identified by their rgb components"
+
+ ^self!

Item was added:
+ ----- Method: TranslucentColor>>name (in category 'other') -----
+ name
+ self = Color transparent ifTrue: [^#transparent].
+ ^nil!

Item was changed:
  (PackageInfo named: 'Graphics') postscript: '
+ "Initialize RGBToName dictionary"
+ Color initializeNamesMap.'!
- " Reset DejaVu to current version "
- StrikeFont initialize.'!


Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Graphics-nice.408.mcz

Nicolas Cellier
No objection?

Le jeu. 16 mai 2019 à 15:14, <[hidden email]> a écrit :
Nicolas Cellier uploaded a new version of Graphics to project The Inbox:
http://source.squeak.org/inbox/Graphics-nice.408.mcz

==================== Summary ====================

Name: Graphics-nice.408
Author: nice
Time: 16 May 2019, 3:12:54.000487 pm
UUID: cc271e8f-330d-d649-a848-128e2d849f03
Ancestors: Graphics-mt.406

Use a map rgb->#names rather than iterating thru/performing all known colorNames.

This is especially useful if we intend to add more color names.
Note that names do not need to be unique.
The first appearing name in colorNames will be used.

Color colorNames collect: [:sym | Color perform: sym].

(Color colorNames reject: [:sym | (Color perform: sym) name = sym])
        collect: [:sym | sym -> (Color perform: sym) name].

The new class variable is initialized in postscript.
It must be re-initialized each time we change the definition of a named Color.

The rgb code has been used as key rather than the Color itself.
This is because it is unique and cheap (SmallInteger).

=============== Diff against Graphics-mt.406 ===============

Item was changed:
  Object subclass: #Color
        instanceVariableNames: 'rgb cachedDepth cachedBitPattern'
+       classVariableNames: 'Black Blue BlueShift Brown CachedColormaps ColorChart ColorNames ComponentMask ComponentMax Cyan DarkGray Gray GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap Orange PaleBlue PaleBuff PaleGreen PaleMagenta PaleOrange PalePeach PaleRed PaleTan PaleYellow PantonePurpleU PureBlue PureCyan PureGreen PureMagenta PureRed PureYellow RGBToNames RandomStream Red RedShift TranslucentPatterns Transparent VeryDarkGray VeryLightGray VeryPaleRed VeryVeryDarkGray VeryVeryLightGray White Yellow'
-       classVariableNames: 'Black Blue BlueShift Brown CachedColormaps ColorChart ColorNames ComponentMask ComponentMax Cyan DarkGray Gray GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap Orange PaleBlue PaleBuff PaleGreen PaleMagenta PaleOrange PalePeach PaleRed PaleTan PaleYellow PantonePurpleU PureBlue PureCyan PureGreen PureMagenta PureRed PureYellow RandomStream Red RedShift TranslucentPatterns Transparent VeryDarkGray VeryLightGray VeryPaleRed VeryVeryDarkGray VeryVeryLightGray White Yellow'
        poolDictionaries: ''
        category: 'Graphics-Primitives'!

  !Color commentStamp: '<historical>' prior: 0!
  This class represents abstract color, regardless of the depth of bitmap it will be shown in.  At the very last moment a Color is converted to a pixelValue that depends on the depth of the actual Bitmap inside the Form it will be used with.  The supported depths (in bits) are 1, 2, 4, 8, 16, and 32.  The number of actual colors at these depths are: 2, 4, 16, 256, 32768, and 16 million.  (See comment in BitBlt.)  To change the depth of the Display and set how many colors you can see, execute: (Display newDepth: 8).  (See comment in DisplayMedium)
        Color is represented as the amount of light in red, green, and blue.  White is (1.0, 1.0, 1.0) and black is (0, 0, 0).  Pure red is (1.0, 0, 0).  These colors are "additive".  Think of Color's instance variables as:
        r       amount of red, a Float between 0.0 and 1.0.
        g       amount of green, a Float between 0.0 and 1.0.
        b       amount of blue, a Float between 0.0 and 1.0.
  (But, in fact, the three are encoded as values from 0 to 1023 and combined in a single integer, rgb.  The user does not need to know this.)
        Many colors are named.  You find a color by name by sending a message to class Color, for example (Color lightBlue).  Also, (Color red: 0.2 green: 0.6 blue: 1.0) or (Color r: 0.2 g: 0.6 b: 1.0) creates a color. (see below)
        A color is essentially immutable.  Once you set red, green, and blue, you cannot change them.  Instead, create a new Color and use it.
        Applications such as contour maps and bar graphs will want to display one of a set of shades based on a number.  Convert the range of this number to an integer from 1 to N.  Then call (Color green lightShades: N) to get an Array of colors from white to green.  Use the Array messages at:, atPin:, or atWrap: to pull out the correct color from the array.  atPin: gives the first (or last) color if the index is out of range.  atWrap: wraps around to the other end if the index is out of range.
        Here are some fun things to run in when your screen has color:
                Pen new mandala: 30 diameter: Display height-100.
                Pen new web  "Draw with the mouse, opt-click to end"
                Display fillWhite.  Pen new hilberts: 5.
                Form toothpaste: 30  "Draw with mouse, opt-click to end"
  You might also want to try the comment in
        Form>class>examples>tinyText...


  Messages:
        mixed: proportion with: aColor  Answer this color mixed with the given color additively. The proportion, a number between 0.0 and 1.0, determines what what fraction of the receiver to use in the mix.

        +       add two colors
        -       subtract two colors
        *       multiply the values of r, g, b by a number or an Array of factors.  ((Color named: #white) * 0.3) gives a darkish gray.  (aColor * #(0 0 0.9)) gives a color with slightly less blue.
        /       divide a color by a factor or an array of three factors.

        errorForDepth: d     How close the nearest color at this depth is to this abstract color.  Sum of the squares of the RGB differences, square rooted and normalized to 1.0.  Multiply by 100 to get percent.

        hue                     Returns the hue of the color. On a wheel from 0 to 360 with pure red at 0 and again at 360.
        saturation      Returns the saturation of the color.  0.0 to 1.0
        brightness      Returns the brightness of the color.  0.0 to 1.0

        name    Look to see if this Color has a name.
        display Show a swatch of this color tracking the cursor.

        lightShades: thisMany           An array of thisMany colors from white to the receiver.
        darkShades: thisMany            An array of thisMany colors from black to the receiver.  Array is of length num.
        mix: color2 shades: thisMany            An array of thisMany colors from the receiver to color2.
        wheel: thisMany                 An array of thisMany colors around the color wheel starting and ending at the receiver.

        pixelValueForDepth: d    Returns the bits that appear be in a Bitmap of this depth for this color.  Represents the nearest available color at this depth.  Normal users do not need to know which pixelValue is used for which color.

  Messages to Class Color.
        red: r green: g blue: b         Return a color with the given r, g, and b components.
        r: g: b:                Same as above, for fast typing.

        hue: h saturation: s brightness: b              Create a color with the given hue, saturation, and brightness.

        pink
        blue
        red ... Many colors have messages that return an instance of Color.
        canUnderstand: #brown     Returns true if #brown is a defined color.
        names           An OrderedCollection of the names of the colors.
        named: #notAllThatGray put: aColor    Add a new color to the list and create an access message and a class variable for it.
        fromUser        Shows the palette of colors available at this display depth.  Click anywhere to return the color you clicked on.

        hotColdShades: thisMany An array of thisMany colors showing temperature from blue to red to white hot.

      stdColorsForDepth: d        An Array of colors available at this depth.  For 16 bit and 32 bits, returns a ColorGenerator.  It responds to at: with a Color for that index, simulating a very big Array.

     colorFromPixelValue: value depth: d    Returns a Color whose bit pattern (inside a Bitmap) at this depth is the number specified.  Normal users do not need to use this.

  (See also comments in these classes: Form, Bitmap, BitBlt, Pattern, MaskedForm.)!

Item was changed:
  ----- Method: Color class>>initializeNames (in category 'class initialization') -----
  initializeNames
        "Name some colors."
        "Color initializeNames"

        ColorNames := Set new.
        self named: #black put: (Color r: 0 g: 0 b: 0).
        self named: #veryVeryDarkGray put: (Color r: 0.125 g: 0.125 b: 0.125).
        self named: #veryDarkGray put: (Color r: 0.25 g: 0.25 b: 0.25).
        self named: #darkGray put: (Color r: 0.375 g: 0.375 b: 0.375).
        self named: #gray put: (Color r: 0.5 g: 0.5 b: 0.5).
        self named: #lightGray put: (Color r: 0.625 g: 0.625 b: 0.625).
        self named: #veryLightGray put: (Color r: 0.75 g: 0.75 b: 0.75).
        self named: #veryVeryLightGray put: (Color r: 0.875 g: 0.875 b: 0.875).
        self named: #white put: (Color r: 1.0 g: 1.0 b: 1.0).
        self named: #red put: (Color r: 1.0 g: 0 b: 0).
        self named: #yellow put: (Color r: 1.0 g: 1.0 b: 0).
        self named: #green put: (Color r: 0 g: 1.0 b: 0).
        self named: #cyan put: (Color r: 0 g: 1.0 b: 1.0).
        self named: #blue put: (Color r: 0 g: 0 b: 1.0).
        self named: #magenta put: (Color r: 1.0 g: 0 b: 1.0).
        self named: #brown put: (Color r: 0.6 g: 0.2 b: 0).
        self named: #orange put: (Color r: 1.0 g: 0.6 b: 0).
        self named: #lightRed put: (Color r: 1.0 g: 0.8 b: 0.8).
        self named: #lightYellow put: (Color r: 1.0 g: 1.0 b: 0.8).
        self named: #lightGreen put: (Color r: 0.8 g: 1.0 b: 0.6).
        self named: #lightCyan put: (Color r: 0.4 g: 1.0 b: 1.0).
        self named: #lightBlue put: (Color r: 0.8 g: 1.0 b: 1.0).
        self named: #lightMagenta put: (Color r: 1.0 g: 0.8 b: 1.0).
        self named: #lightBrown put: (Color r: 1.0 g: 0.6 b: 0.2).
        self named: #lightOrange put: (Color r: 1.0 g: 0.8 b: 0.4).
        self named: #transparent put: (TranslucentColor new alpha: 0.0).
        self named: #paleBuff put: (Color r: 254 g: 250 b: 235 range: 255).
        self named: #paleBlue put: (Color r: 222 g: 249 b: 254 range: 255).
        self named: #paleYellow put: (Color r: 255 g: 255 b: 217 range: 255).
        self named: #paleGreen put: (Color r: 223 g: 255 b: 213 range: 255).
        self named: #paleRed put: (Color r: 255 g: 230 b: 230 range: 255).
        self named: #veryPaleRed put: (Color r: 255 g: 242 b: 242 range: 255).
        self named: #paleTan put: (Color r: 235 g: 224 b: 199 range: 255).
        self named: #paleMagenta put: (Color r: 255 g: 230 b: 255 range: 255).
        self named: #paleOrange put: (Color r: 253 g: 237 b: 215 range: 255).
        self named: #palePeach put: (Color r: 255 g: 237 b: 213 range: 255).
        self named: #pantonePurpleU put: (Color r: 193 g: 81 b: 184 range: 255).
+       self initializeNamesMap

  !

Item was added:
+ ----- Method: Color class>>initializeNamesMap (in category 'class initialization') -----
+ initializeNamesMap
+       "enable mapping a color to its name"
+       "Color initializeNamesMap"
+
+       RGBToNames := Dictionary new.
+       self colorNames do: [:sym | (self perform: sym) addName: sym]!

Item was added:
+ ----- Method: Color>>addName: (in category 'other') -----
+ addName: aSymbol
+       "private - associate a name to this color."
+       
+       | knownNames |
+       [(self class respondsTo: aSymbol) and: [(self class perform: aSymbol) = self]] assert.
+       knownNames := RGBToNames at: rgb ifAbsent: [#()].
+       (knownNames includes: aSymbol)
+               ifFalse: [ RGBToNames at: rgb put: (knownNames copyWith: aSymbol)]!

Item was changed:
  ----- Method: Color>>name (in category 'other') -----
  name
+       "Return this color's name, or nil if it has no name."
-       "Return this color's name, or nil if it has no name. Only returns a name if it exactly matches the named color."

+       ^ (RGBToNames at: rgb ifAbsent: [nil]) ifNotNil: [:names | names at: 1 ifAbsent: [nil]]!
-       ^ self class colorNames detect: [ :name | (Color perform: name) = self ] ifNone: [ nil ]!

Item was added:
+ ----- Method: TranslucentColor>>addName: (in category 'other') -----
+ addName: aSymbol
+       "private - associate a name to this color.
+       Don't do it, Translucent colors are not uniquely identified by their rgb components"
+       
+       ^self!

Item was added:
+ ----- Method: TranslucentColor>>name (in category 'other') -----
+ name
+       self = Color transparent ifTrue: [^#transparent].
+       ^nil!

Item was changed:
  (PackageInfo named: 'Graphics') postscript: '
+ "Initialize RGBToName dictionary"
+ Color initializeNamesMap.'!
- " Reset DejaVu to current version "
- StrikeFont initialize.'!




cbc
Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Graphics-nice.408.mcz

cbc
I like it (Based on reading it only - not loading/testing).

> The new class variable is initialized in postscript.
> It must be re-initialized each time we change the definition of a named Color.

So, each time we change a definition, we have to change the postscript, since it is only run on change, right?
If so, this is worth putting  a comment anywhere Color names are defined (i.e., those methods and external packages); otherwise we will fail to follow this requirement at some point.

-cbc


On Fri, May 17, 2019 at 8:58 AM Nicolas Cellier <[hidden email]> wrote:
No objection?

Le jeu. 16 mai 2019 à 15:14, <[hidden email]> a écrit :
Nicolas Cellier uploaded a new version of Graphics to project The Inbox:
http://source.squeak.org/inbox/Graphics-nice.408.mcz

==================== Summary ====================

Name: Graphics-nice.408
Author: nice
Time: 16 May 2019, 3:12:54.000487 pm
UUID: cc271e8f-330d-d649-a848-128e2d849f03
Ancestors: Graphics-mt.406

Use a map rgb->#names rather than iterating thru/performing all known colorNames.

This is especially useful if we intend to add more color names.
Note that names do not need to be unique.
The first appearing name in colorNames will be used.

Color colorNames collect: [:sym | Color perform: sym].

(Color colorNames reject: [:sym | (Color perform: sym) name = sym])
        collect: [:sym | sym -> (Color perform: sym) name].

The new class variable is initialized in postscript.
It must be re-initialized each time we change the definition of a named Color.

The rgb code has been used as key rather than the Color itself.
This is because it is unique and cheap (SmallInteger).

=============== Diff against Graphics-mt.406 ===============

Item was changed:
  Object subclass: #Color
        instanceVariableNames: 'rgb cachedDepth cachedBitPattern'
+       classVariableNames: 'Black Blue BlueShift Brown CachedColormaps ColorChart ColorNames ComponentMask ComponentMax Cyan DarkGray Gray GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap Orange PaleBlue PaleBuff PaleGreen PaleMagenta PaleOrange PalePeach PaleRed PaleTan PaleYellow PantonePurpleU PureBlue PureCyan PureGreen PureMagenta PureRed PureYellow RGBToNames RandomStream Red RedShift TranslucentPatterns Transparent VeryDarkGray VeryLightGray VeryPaleRed VeryVeryDarkGray VeryVeryLightGray White Yellow'
-       classVariableNames: 'Black Blue BlueShift Brown CachedColormaps ColorChart ColorNames ComponentMask ComponentMax Cyan DarkGray Gray GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap Orange PaleBlue PaleBuff PaleGreen PaleMagenta PaleOrange PalePeach PaleRed PaleTan PaleYellow PantonePurpleU PureBlue PureCyan PureGreen PureMagenta PureRed PureYellow RandomStream Red RedShift TranslucentPatterns Transparent VeryDarkGray VeryLightGray VeryPaleRed VeryVeryDarkGray VeryVeryLightGray White Yellow'
        poolDictionaries: ''
        category: 'Graphics-Primitives'!

  !Color commentStamp: '<historical>' prior: 0!
  This class represents abstract color, regardless of the depth of bitmap it will be shown in.  At the very last moment a Color is converted to a pixelValue that depends on the depth of the actual Bitmap inside the Form it will be used with.  The supported depths (in bits) are 1, 2, 4, 8, 16, and 32.  The number of actual colors at these depths are: 2, 4, 16, 256, 32768, and 16 million.  (See comment in BitBlt.)  To change the depth of the Display and set how many colors you can see, execute: (Display newDepth: 8).  (See comment in DisplayMedium)
        Color is represented as the amount of light in red, green, and blue.  White is (1.0, 1.0, 1.0) and black is (0, 0, 0).  Pure red is (1.0, 0, 0).  These colors are "additive".  Think of Color's instance variables as:
        r       amount of red, a Float between 0.0 and 1.0.
        g       amount of green, a Float between 0.0 and 1.0.
        b       amount of blue, a Float between 0.0 and 1.0.
  (But, in fact, the three are encoded as values from 0 to 1023 and combined in a single integer, rgb.  The user does not need to know this.)
        Many colors are named.  You find a color by name by sending a message to class Color, for example (Color lightBlue).  Also, (Color red: 0.2 green: 0.6 blue: 1.0) or (Color r: 0.2 g: 0.6 b: 1.0) creates a color. (see below)
        A color is essentially immutable.  Once you set red, green, and blue, you cannot change them.  Instead, create a new Color and use it.
        Applications such as contour maps and bar graphs will want to display one of a set of shades based on a number.  Convert the range of this number to an integer from 1 to N.  Then call (Color green lightShades: N) to get an Array of colors from white to green.  Use the Array messages at:, atPin:, or atWrap: to pull out the correct color from the array.  atPin: gives the first (or last) color if the index is out of range.  atWrap: wraps around to the other end if the index is out of range.
        Here are some fun things to run in when your screen has color:
                Pen new mandala: 30 diameter: Display height-100.
                Pen new web  "Draw with the mouse, opt-click to end"
                Display fillWhite.  Pen new hilberts: 5.
                Form toothpaste: 30  "Draw with mouse, opt-click to end"
  You might also want to try the comment in
        Form>class>examples>tinyText...


  Messages:
        mixed: proportion with: aColor  Answer this color mixed with the given color additively. The proportion, a number between 0.0 and 1.0, determines what what fraction of the receiver to use in the mix.

        +       add two colors
        -       subtract two colors
        *       multiply the values of r, g, b by a number or an Array of factors.  ((Color named: #white) * 0.3) gives a darkish gray.  (aColor * #(0 0 0.9)) gives a color with slightly less blue.
        /       divide a color by a factor or an array of three factors.

        errorForDepth: d     How close the nearest color at this depth is to this abstract color.  Sum of the squares of the RGB differences, square rooted and normalized to 1.0.  Multiply by 100 to get percent.

        hue                     Returns the hue of the color. On a wheel from 0 to 360 with pure red at 0 and again at 360.
        saturation      Returns the saturation of the color.  0.0 to 1.0
        brightness      Returns the brightness of the color.  0.0 to 1.0

        name    Look to see if this Color has a name.
        display Show a swatch of this color tracking the cursor.

        lightShades: thisMany           An array of thisMany colors from white to the receiver.
        darkShades: thisMany            An array of thisMany colors from black to the receiver.  Array is of length num.
        mix: color2 shades: thisMany            An array of thisMany colors from the receiver to color2.
        wheel: thisMany                 An array of thisMany colors around the color wheel starting and ending at the receiver.

        pixelValueForDepth: d    Returns the bits that appear be in a Bitmap of this depth for this color.  Represents the nearest available color at this depth.  Normal users do not need to know which pixelValue is used for which color.

  Messages to Class Color.
        red: r green: g blue: b         Return a color with the given r, g, and b components.
        r: g: b:                Same as above, for fast typing.

        hue: h saturation: s brightness: b              Create a color with the given hue, saturation, and brightness.

        pink
        blue
        red ... Many colors have messages that return an instance of Color.
        canUnderstand: #brown     Returns true if #brown is a defined color.
        names           An OrderedCollection of the names of the colors.
        named: #notAllThatGray put: aColor    Add a new color to the list and create an access message and a class variable for it.
        fromUser        Shows the palette of colors available at this display depth.  Click anywhere to return the color you clicked on.

        hotColdShades: thisMany An array of thisMany colors showing temperature from blue to red to white hot.

      stdColorsForDepth: d        An Array of colors available at this depth.  For 16 bit and 32 bits, returns a ColorGenerator.  It responds to at: with a Color for that index, simulating a very big Array.

     colorFromPixelValue: value depth: d    Returns a Color whose bit pattern (inside a Bitmap) at this depth is the number specified.  Normal users do not need to use this.

  (See also comments in these classes: Form, Bitmap, BitBlt, Pattern, MaskedForm.)!

Item was changed:
  ----- Method: Color class>>initializeNames (in category 'class initialization') -----
  initializeNames
        "Name some colors."
        "Color initializeNames"

        ColorNames := Set new.
        self named: #black put: (Color r: 0 g: 0 b: 0).
        self named: #veryVeryDarkGray put: (Color r: 0.125 g: 0.125 b: 0.125).
        self named: #veryDarkGray put: (Color r: 0.25 g: 0.25 b: 0.25).
        self named: #darkGray put: (Color r: 0.375 g: 0.375 b: 0.375).
        self named: #gray put: (Color r: 0.5 g: 0.5 b: 0.5).
        self named: #lightGray put: (Color r: 0.625 g: 0.625 b: 0.625).
        self named: #veryLightGray put: (Color r: 0.75 g: 0.75 b: 0.75).
        self named: #veryVeryLightGray put: (Color r: 0.875 g: 0.875 b: 0.875).
        self named: #white put: (Color r: 1.0 g: 1.0 b: 1.0).
        self named: #red put: (Color r: 1.0 g: 0 b: 0).
        self named: #yellow put: (Color r: 1.0 g: 1.0 b: 0).
        self named: #green put: (Color r: 0 g: 1.0 b: 0).
        self named: #cyan put: (Color r: 0 g: 1.0 b: 1.0).
        self named: #blue put: (Color r: 0 g: 0 b: 1.0).
        self named: #magenta put: (Color r: 1.0 g: 0 b: 1.0).
        self named: #brown put: (Color r: 0.6 g: 0.2 b: 0).
        self named: #orange put: (Color r: 1.0 g: 0.6 b: 0).
        self named: #lightRed put: (Color r: 1.0 g: 0.8 b: 0.8).
        self named: #lightYellow put: (Color r: 1.0 g: 1.0 b: 0.8).
        self named: #lightGreen put: (Color r: 0.8 g: 1.0 b: 0.6).
        self named: #lightCyan put: (Color r: 0.4 g: 1.0 b: 1.0).
        self named: #lightBlue put: (Color r: 0.8 g: 1.0 b: 1.0).
        self named: #lightMagenta put: (Color r: 1.0 g: 0.8 b: 1.0).
        self named: #lightBrown put: (Color r: 1.0 g: 0.6 b: 0.2).
        self named: #lightOrange put: (Color r: 1.0 g: 0.8 b: 0.4).
        self named: #transparent put: (TranslucentColor new alpha: 0.0).
        self named: #paleBuff put: (Color r: 254 g: 250 b: 235 range: 255).
        self named: #paleBlue put: (Color r: 222 g: 249 b: 254 range: 255).
        self named: #paleYellow put: (Color r: 255 g: 255 b: 217 range: 255).
        self named: #paleGreen put: (Color r: 223 g: 255 b: 213 range: 255).
        self named: #paleRed put: (Color r: 255 g: 230 b: 230 range: 255).
        self named: #veryPaleRed put: (Color r: 255 g: 242 b: 242 range: 255).
        self named: #paleTan put: (Color r: 235 g: 224 b: 199 range: 255).
        self named: #paleMagenta put: (Color r: 255 g: 230 b: 255 range: 255).
        self named: #paleOrange put: (Color r: 253 g: 237 b: 215 range: 255).
        self named: #palePeach put: (Color r: 255 g: 237 b: 213 range: 255).
        self named: #pantonePurpleU put: (Color r: 193 g: 81 b: 184 range: 255).
+       self initializeNamesMap

  !

Item was added:
+ ----- Method: Color class>>initializeNamesMap (in category 'class initialization') -----
+ initializeNamesMap
+       "enable mapping a color to its name"
+       "Color initializeNamesMap"
+
+       RGBToNames := Dictionary new.
+       self colorNames do: [:sym | (self perform: sym) addName: sym]!

Item was added:
+ ----- Method: Color>>addName: (in category 'other') -----
+ addName: aSymbol
+       "private - associate a name to this color."
+       
+       | knownNames |
+       [(self class respondsTo: aSymbol) and: [(self class perform: aSymbol) = self]] assert.
+       knownNames := RGBToNames at: rgb ifAbsent: [#()].
+       (knownNames includes: aSymbol)
+               ifFalse: [ RGBToNames at: rgb put: (knownNames copyWith: aSymbol)]!

Item was changed:
  ----- Method: Color>>name (in category 'other') -----
  name
+       "Return this color's name, or nil if it has no name."
-       "Return this color's name, or nil if it has no name. Only returns a name if it exactly matches the named color."

+       ^ (RGBToNames at: rgb ifAbsent: [nil]) ifNotNil: [:names | names at: 1 ifAbsent: [nil]]!
-       ^ self class colorNames detect: [ :name | (Color perform: name) = self ] ifNone: [ nil ]!

Item was added:
+ ----- Method: TranslucentColor>>addName: (in category 'other') -----
+ addName: aSymbol
+       "private - associate a name to this color.
+       Don't do it, Translucent colors are not uniquely identified by their rgb components"
+       
+       ^self!

Item was added:
+ ----- Method: TranslucentColor>>name (in category 'other') -----
+ name
+       self = Color transparent ifTrue: [^#transparent].
+       ^nil!

Item was changed:
  (PackageInfo named: 'Graphics') postscript: '
+ "Initialize RGBToName dictionary"
+ Color initializeNamesMap.'!
- " Reset DejaVu to current version "
- StrikeFont initialize.'!





Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Graphics-nice.408.mcz

Nicolas Cellier


Le ven. 17 mai 2019 à 19:33, Chris Cunningham <[hidden email]> a écrit :
I like it (Based on reading it only - not loading/testing).

> The new class variable is initialized in postscript.
> It must be re-initialized each time we change the definition of a named Color.

So, each time we change a definition, we have to change the postscript, since it is only run on change, right?
If so, this is worth putting  a comment anywhere Color names are defined (i.e., those methods and external packages); otherwise we will fail to follow this requirement at some point.

-cbc

I was thinking of
1) adding a test
2) have some form of auto-correction
(that would be easy in the test, even it feels somehow strange to have self-correcting tests)

The symptom if we change the definition of a named Color is that it won't print itself named (the previous definition will).
Also if we add a new named Color but forget to update the map...
No catastropic consequences. But a comment is indeed welcome in class comment and #name comment.

Maybe we could adopt a different way of registering named colors thru a pragma...


On Fri, May 17, 2019 at 8:58 AM Nicolas Cellier <[hidden email]> wrote:
No objection?

Le jeu. 16 mai 2019 à 15:14, <[hidden email]> a écrit :
Nicolas Cellier uploaded a new version of Graphics to project The Inbox:
http://source.squeak.org/inbox/Graphics-nice.408.mcz

==================== Summary ====================

Name: Graphics-nice.408
Author: nice
Time: 16 May 2019, 3:12:54.000487 pm
UUID: cc271e8f-330d-d649-a848-128e2d849f03
Ancestors: Graphics-mt.406

Use a map rgb->#names rather than iterating thru/performing all known colorNames.

This is especially useful if we intend to add more color names.
Note that names do not need to be unique.
The first appearing name in colorNames will be used.

Color colorNames collect: [:sym | Color perform: sym].

(Color colorNames reject: [:sym | (Color perform: sym) name = sym])
        collect: [:sym | sym -> (Color perform: sym) name].

The new class variable is initialized in postscript.
It must be re-initialized each time we change the definition of a named Color.

The rgb code has been used as key rather than the Color itself.
This is because it is unique and cheap (SmallInteger).

=============== Diff against Graphics-mt.406 ===============

Item was changed:
  Object subclass: #Color
        instanceVariableNames: 'rgb cachedDepth cachedBitPattern'
+       classVariableNames: 'Black Blue BlueShift Brown CachedColormaps ColorChart ColorNames ComponentMask ComponentMax Cyan DarkGray Gray GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap Orange PaleBlue PaleBuff PaleGreen PaleMagenta PaleOrange PalePeach PaleRed PaleTan PaleYellow PantonePurpleU PureBlue PureCyan PureGreen PureMagenta PureRed PureYellow RGBToNames RandomStream Red RedShift TranslucentPatterns Transparent VeryDarkGray VeryLightGray VeryPaleRed VeryVeryDarkGray VeryVeryLightGray White Yellow'
-       classVariableNames: 'Black Blue BlueShift Brown CachedColormaps ColorChart ColorNames ComponentMask ComponentMax Cyan DarkGray Gray GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap Orange PaleBlue PaleBuff PaleGreen PaleMagenta PaleOrange PalePeach PaleRed PaleTan PaleYellow PantonePurpleU PureBlue PureCyan PureGreen PureMagenta PureRed PureYellow RandomStream Red RedShift TranslucentPatterns Transparent VeryDarkGray VeryLightGray VeryPaleRed VeryVeryDarkGray VeryVeryLightGray White Yellow'
        poolDictionaries: ''
        category: 'Graphics-Primitives'!

  !Color commentStamp: '<historical>' prior: 0!
  This class represents abstract color, regardless of the depth of bitmap it will be shown in.  At the very last moment a Color is converted to a pixelValue that depends on the depth of the actual Bitmap inside the Form it will be used with.  The supported depths (in bits) are 1, 2, 4, 8, 16, and 32.  The number of actual colors at these depths are: 2, 4, 16, 256, 32768, and 16 million.  (See comment in BitBlt.)  To change the depth of the Display and set how many colors you can see, execute: (Display newDepth: 8).  (See comment in DisplayMedium)
        Color is represented as the amount of light in red, green, and blue.  White is (1.0, 1.0, 1.0) and black is (0, 0, 0).  Pure red is (1.0, 0, 0).  These colors are "additive".  Think of Color's instance variables as:
        r       amount of red, a Float between 0.0 and 1.0.
        g       amount of green, a Float between 0.0 and 1.0.
        b       amount of blue, a Float between 0.0 and 1.0.
  (But, in fact, the three are encoded as values from 0 to 1023 and combined in a single integer, rgb.  The user does not need to know this.)
        Many colors are named.  You find a color by name by sending a message to class Color, for example (Color lightBlue).  Also, (Color red: 0.2 green: 0.6 blue: 1.0) or (Color r: 0.2 g: 0.6 b: 1.0) creates a color. (see below)
        A color is essentially immutable.  Once you set red, green, and blue, you cannot change them.  Instead, create a new Color and use it.
        Applications such as contour maps and bar graphs will want to display one of a set of shades based on a number.  Convert the range of this number to an integer from 1 to N.  Then call (Color green lightShades: N) to get an Array of colors from white to green.  Use the Array messages at:, atPin:, or atWrap: to pull out the correct color from the array.  atPin: gives the first (or last) color if the index is out of range.  atWrap: wraps around to the other end if the index is out of range.
        Here are some fun things to run in when your screen has color:
                Pen new mandala: 30 diameter: Display height-100.
                Pen new web  "Draw with the mouse, opt-click to end"
                Display fillWhite.  Pen new hilberts: 5.
                Form toothpaste: 30  "Draw with mouse, opt-click to end"
  You might also want to try the comment in
        Form>class>examples>tinyText...


  Messages:
        mixed: proportion with: aColor  Answer this color mixed with the given color additively. The proportion, a number between 0.0 and 1.0, determines what what fraction of the receiver to use in the mix.

        +       add two colors
        -       subtract two colors
        *       multiply the values of r, g, b by a number or an Array of factors.  ((Color named: #white) * 0.3) gives a darkish gray.  (aColor * #(0 0 0.9)) gives a color with slightly less blue.
        /       divide a color by a factor or an array of three factors.

        errorForDepth: d     How close the nearest color at this depth is to this abstract color.  Sum of the squares of the RGB differences, square rooted and normalized to 1.0.  Multiply by 100 to get percent.

        hue                     Returns the hue of the color. On a wheel from 0 to 360 with pure red at 0 and again at 360.
        saturation      Returns the saturation of the color.  0.0 to 1.0
        brightness      Returns the brightness of the color.  0.0 to 1.0

        name    Look to see if this Color has a name.
        display Show a swatch of this color tracking the cursor.

        lightShades: thisMany           An array of thisMany colors from white to the receiver.
        darkShades: thisMany            An array of thisMany colors from black to the receiver.  Array is of length num.
        mix: color2 shades: thisMany            An array of thisMany colors from the receiver to color2.
        wheel: thisMany                 An array of thisMany colors around the color wheel starting and ending at the receiver.

        pixelValueForDepth: d    Returns the bits that appear be in a Bitmap of this depth for this color.  Represents the nearest available color at this depth.  Normal users do not need to know which pixelValue is used for which color.

  Messages to Class Color.
        red: r green: g blue: b         Return a color with the given r, g, and b components.
        r: g: b:                Same as above, for fast typing.

        hue: h saturation: s brightness: b              Create a color with the given hue, saturation, and brightness.

        pink
        blue
        red ... Many colors have messages that return an instance of Color.
        canUnderstand: #brown     Returns true if #brown is a defined color.
        names           An OrderedCollection of the names of the colors.
        named: #notAllThatGray put: aColor    Add a new color to the list and create an access message and a class variable for it.
        fromUser        Shows the palette of colors available at this display depth.  Click anywhere to return the color you clicked on.

        hotColdShades: thisMany An array of thisMany colors showing temperature from blue to red to white hot.

      stdColorsForDepth: d        An Array of colors available at this depth.  For 16 bit and 32 bits, returns a ColorGenerator.  It responds to at: with a Color for that index, simulating a very big Array.

     colorFromPixelValue: value depth: d    Returns a Color whose bit pattern (inside a Bitmap) at this depth is the number specified.  Normal users do not need to use this.

  (See also comments in these classes: Form, Bitmap, BitBlt, Pattern, MaskedForm.)!

Item was changed:
  ----- Method: Color class>>initializeNames (in category 'class initialization') -----
  initializeNames
        "Name some colors."
        "Color initializeNames"

        ColorNames := Set new.
        self named: #black put: (Color r: 0 g: 0 b: 0).
        self named: #veryVeryDarkGray put: (Color r: 0.125 g: 0.125 b: 0.125).
        self named: #veryDarkGray put: (Color r: 0.25 g: 0.25 b: 0.25).
        self named: #darkGray put: (Color r: 0.375 g: 0.375 b: 0.375).
        self named: #gray put: (Color r: 0.5 g: 0.5 b: 0.5).
        self named: #lightGray put: (Color r: 0.625 g: 0.625 b: 0.625).
        self named: #veryLightGray put: (Color r: 0.75 g: 0.75 b: 0.75).
        self named: #veryVeryLightGray put: (Color r: 0.875 g: 0.875 b: 0.875).
        self named: #white put: (Color r: 1.0 g: 1.0 b: 1.0).
        self named: #red put: (Color r: 1.0 g: 0 b: 0).
        self named: #yellow put: (Color r: 1.0 g: 1.0 b: 0).
        self named: #green put: (Color r: 0 g: 1.0 b: 0).
        self named: #cyan put: (Color r: 0 g: 1.0 b: 1.0).
        self named: #blue put: (Color r: 0 g: 0 b: 1.0).
        self named: #magenta put: (Color r: 1.0 g: 0 b: 1.0).
        self named: #brown put: (Color r: 0.6 g: 0.2 b: 0).
        self named: #orange put: (Color r: 1.0 g: 0.6 b: 0).
        self named: #lightRed put: (Color r: 1.0 g: 0.8 b: 0.8).
        self named: #lightYellow put: (Color r: 1.0 g: 1.0 b: 0.8).
        self named: #lightGreen put: (Color r: 0.8 g: 1.0 b: 0.6).
        self named: #lightCyan put: (Color r: 0.4 g: 1.0 b: 1.0).
        self named: #lightBlue put: (Color r: 0.8 g: 1.0 b: 1.0).
        self named: #lightMagenta put: (Color r: 1.0 g: 0.8 b: 1.0).
        self named: #lightBrown put: (Color r: 1.0 g: 0.6 b: 0.2).
        self named: #lightOrange put: (Color r: 1.0 g: 0.8 b: 0.4).
        self named: #transparent put: (TranslucentColor new alpha: 0.0).
        self named: #paleBuff put: (Color r: 254 g: 250 b: 235 range: 255).
        self named: #paleBlue put: (Color r: 222 g: 249 b: 254 range: 255).
        self named: #paleYellow put: (Color r: 255 g: 255 b: 217 range: 255).
        self named: #paleGreen put: (Color r: 223 g: 255 b: 213 range: 255).
        self named: #paleRed put: (Color r: 255 g: 230 b: 230 range: 255).
        self named: #veryPaleRed put: (Color r: 255 g: 242 b: 242 range: 255).
        self named: #paleTan put: (Color r: 235 g: 224 b: 199 range: 255).
        self named: #paleMagenta put: (Color r: 255 g: 230 b: 255 range: 255).
        self named: #paleOrange put: (Color r: 253 g: 237 b: 215 range: 255).
        self named: #palePeach put: (Color r: 255 g: 237 b: 213 range: 255).
        self named: #pantonePurpleU put: (Color r: 193 g: 81 b: 184 range: 255).
+       self initializeNamesMap

  !

Item was added:
+ ----- Method: Color class>>initializeNamesMap (in category 'class initialization') -----
+ initializeNamesMap
+       "enable mapping a color to its name"
+       "Color initializeNamesMap"
+
+       RGBToNames := Dictionary new.
+       self colorNames do: [:sym | (self perform: sym) addName: sym]!

Item was added:
+ ----- Method: Color>>addName: (in category 'other') -----
+ addName: aSymbol
+       "private - associate a name to this color."
+       
+       | knownNames |
+       [(self class respondsTo: aSymbol) and: [(self class perform: aSymbol) = self]] assert.
+       knownNames := RGBToNames at: rgb ifAbsent: [#()].
+       (knownNames includes: aSymbol)
+               ifFalse: [ RGBToNames at: rgb put: (knownNames copyWith: aSymbol)]!

Item was changed:
  ----- Method: Color>>name (in category 'other') -----
  name
+       "Return this color's name, or nil if it has no name."
-       "Return this color's name, or nil if it has no name. Only returns a name if it exactly matches the named color."

+       ^ (RGBToNames at: rgb ifAbsent: [nil]) ifNotNil: [:names | names at: 1 ifAbsent: [nil]]!
-       ^ self class colorNames detect: [ :name | (Color perform: name) = self ] ifNone: [ nil ]!

Item was added:
+ ----- Method: TranslucentColor>>addName: (in category 'other') -----
+ addName: aSymbol
+       "private - associate a name to this color.
+       Don't do it, Translucent colors are not uniquely identified by their rgb components"
+       
+       ^self!

Item was added:
+ ----- Method: TranslucentColor>>name (in category 'other') -----
+ name
+       self = Color transparent ifTrue: [^#transparent].
+       ^nil!

Item was changed:
  (PackageInfo named: 'Graphics') postscript: '
+ "Initialize RGBToName dictionary"
+ Color initializeNamesMap.'!
- " Reset DejaVu to current version "
- StrikeFont initialize.'!






Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Graphics-nice.408.mcz

David T. Lewis
+1 from me also.

For consistency checking, a test such as this should be sufficient:

ColorTest>>testAllColorNamesAreMappedAsRBG
   "Ensure that all named colors have an entry in the RGBToNames map"
   Color colorNames do:
      [ :nm | self deny: (Color fromString: nm) name isNil ]

I do not see a need for different registration mechanism.

Dave


On Fri, May 17, 2019 at 09:29:36PM +0200, Nicolas Cellier wrote:

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

>


Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Graphics-nice.408.mcz

marcel.taeumel
Hi Nicolas,

maybe we can refresh this map in #cleanUp: for the release-building process.

Best,
Marcel

Am 18.05.2019 01:50:44 schrieb David T. Lewis <[hidden email]>:

+1 from me also.

For consistency checking, a test such as this should be sufficient:

ColorTest>>testAllColorNamesAreMappedAsRBG
"Ensure that all named colors have an entry in the RGBToNames map"
Color colorNames do:
[ :nm | self deny: (Color fromString: nm) name isNil ]

I do not see a need for different registration mechanism.

Dave


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

>




Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Graphics-nice.408.mcz

Nicolas Cellier
Hi Marcel,
good idea

Le lun. 20 mai 2019 à 10:05, Marcel Taeumel <[hidden email]> a écrit :
Hi Nicolas,

maybe we can refresh this map in #cleanUp: for the release-building process.

Best,
Marcel

Am 18.05.2019 01:50:44 schrieb David T. Lewis <[hidden email]>:

+1 from me also.

For consistency checking, a test such as this should be sufficient:

ColorTest>>testAllColorNamesAreMappedAsRBG
"Ensure that all named colors have an entry in the RGBToNames map"
Color colorNames do:
[ :nm | self deny: (Color fromString: nm) name isNil ]

I do not see a need for different registration mechanism.

Dave


On Fri, May 17, 2019 at 09:29:36PM +0200, Nicolas Cellier wrote:

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

>