Color.st
changeset 1023 ddbc71885249
parent 1021 291076ae3fe0
child 1144 07f3de59864d
equal deleted inserted replaced
1022:e41ea5762606 1023:ddbc71885249
   262 
   262 
   263     round := 0.
   263     round := 0.
   264 
   264 
   265     dstIndex := 1.
   265     dstIndex := 1.
   266     1 to:nR do:[:sR |
   266     1 to:nR do:[:sR |
   267         red := dR * (sR - 1).
   267 	red := dR * (sR - 1).
   268         1 to:nG do:[:sG |
   268 	1 to:nG do:[:sG |
   269             green := dG * (sG - 1).
   269 	    green := dG * (sG - 1).
   270             1 to:nB do:[:sB |
   270 	    1 to:nB do:[:sB |
   271                 blue := dB * (sB - 1).
   271 		blue := dB * (sB - 1).
   272                 clr := (self red:red green:green blue:blue) exactOn:aDevice.
   272 		clr := (self red:red green:green blue:blue) exactOn:aDevice.
   273                 clr isNil ifTrue:[
   273 		clr isNil ifTrue:[
   274                     round == 0 ifTrue:[
   274 		    round == 0 ifTrue:[
   275                         'COLOR: scavenge to reclaim colors' infoPrintCR.
   275 			'COLOR: scavenge to reclaim colors' infoPrintCR.
   276                         ObjectMemory scavenge.
   276 			ObjectMemory scavenge.
   277                         round := 1.
   277 			round := 1.
   278                         clr := (self red:red green:green blue:blue) exactOn:aDevice.
   278 			clr := (self red:red green:green blue:blue) exactOn:aDevice.
   279                     ].
   279 		    ].
   280                 ].
   280 		].
   281                 clr isNil ifTrue:[
   281 		clr isNil ifTrue:[
   282                     round == 1 ifTrue:[
   282 		    round == 1 ifTrue:[
   283                         'COLOR: collect garbage to reclaim colors' infoPrintCR.
   283 			'COLOR: collect garbage to reclaim colors' infoPrintCR.
   284                         ObjectMemory performLowSpaceCleanup.
   284 			ObjectMemory performLowSpaceCleanup.
   285                         ObjectMemory garbageCollect.
   285 			ObjectMemory garbageCollect.
   286                         round := 2.
   286 			round := 2.
   287                         clr := (self red:red green:green blue:blue) exactOn:aDevice.
   287 			clr := (self red:red green:green blue:blue) exactOn:aDevice.
   288                    ].
   288 		   ].
   289                 ].
   289 		].
   290                 clr isNil ifTrue:[
   290 		clr isNil ifTrue:[
   291                     ColorAllocationFailSignal raiseErrorString:'failed to allocate fix color'.
   291 		    ColorAllocationFailSignal raiseErrorString:'failed to allocate fix color'.
   292                     ^ self
   292 		    ^ self
   293                 ].
   293 		].
   294                 fixColors at:dstIndex put:clr.
   294 		fixColors at:dstIndex put:clr.
   295                 dstIndex := dstIndex + 1
   295 		dstIndex := dstIndex + 1
   296             ]
   296 	    ]
   297         ]
   297 	]
   298     ].
   298     ].
   299     aDevice setFixColors:fixColors
   299     aDevice setFixColors:fixColors
   300                   numRed:nR numGreen:nG numBlue:nB
   300 		  numRed:nR numGreen:nG numBlue:nB
   301 
   301 
   302     "
   302     "
   303      Color getColorsRed:2 green:2 blue:2 on:Display
   303      Color getColorsRed:2 green:2 blue:2 on:Display
   304     "
   304     "
   305 
   305 
   328      dithered images look very poor)."
   328      dithered images look very poor)."
   329 
   329 
   330     |colors white black red green blue|
   330     |colors white black red green blue|
   331 
   331 
   332     (aDevice notNil and:[aDevice ditherColors isNil]) ifTrue:[
   332     (aDevice notNil and:[aDevice ditherColors isNil]) ifTrue:[
   333         white := (self red:100 green:100 blue:100) exactOn:aDevice.
   333 	white := (self red:100 green:100 blue:100) exactOn:aDevice.
   334         black := (self red:0 green:0 blue:0) exactOn:aDevice.
   334 	black := (self red:0 green:0 blue:0) exactOn:aDevice.
   335 
   335 
   336         aDevice hasColors ifTrue:[
   336 	aDevice hasColors ifTrue:[
   337             red := (self red:100 green:0 blue:0) exactOn:aDevice.
   337 	    red := (self red:100 green:0 blue:0) exactOn:aDevice.
   338             green := (self red:0 green:100 blue:0) exactOn:aDevice.
   338 	    green := (self red:0 green:100 blue:0) exactOn:aDevice.
   339             blue := (self red:0 green:0 blue:100) exactOn:aDevice.
   339 	    blue := (self red:0 green:0 blue:100) exactOn:aDevice.
   340         ].
   340 	].
   341 
   341 
   342         aDevice == Display ifTrue:[
   342 	aDevice == Display ifTrue:[
   343             "/ keep those around for the main display
   343 	    "/ keep those around for the main display
   344             White := white.
   344 	    White := white.
   345             Black := black.
   345 	    Black := black.
   346             Red := red.
   346 	    Red := red.
   347             Green := green.
   347 	    Green := green.
   348             Blue := blue
   348 	    Blue := blue
   349         ].
   349 	].
   350 
   350 
   351         aDevice visualType ~~ #TrueColor ifTrue:[
   351 	aDevice visualType ~~ #TrueColor ifTrue:[
   352             aDevice hasColors ifTrue:[
   352 	    aDevice hasColors ifTrue:[
   353 
   353 
   354                 "preallocate some colors for dithering 
   354 		"preallocate some colors for dithering 
   355                  - otherwise, they may not be available when we need them ...
   355 		 - otherwise, they may not be available when we need them ...
   356                  these are: black, white, grey50,
   356 		 these are: black, white, grey50,
   357                             red, green, blue, yellow, cyan and magenta.
   357 			    red, green, blue, yellow, cyan and magenta.
   358                 "
   358 		"
   359 
   359 
   360                 colors := OrderedCollection new.
   360 		colors := OrderedCollection new.
   361                 colors add:((self gray:50) exactOn:aDevice).
   361 		colors add:((self gray:50) exactOn:aDevice).
   362 
   362 
   363                 colors add:white; add:black; add:red; add:green; add:blue.
   363 		colors add:white; add:black; add:red; add:green; add:blue.
   364 
   364 
   365                 colors add:((self red:100 green:100 blue:0) exactOn:aDevice).
   365 		colors add:((self red:100 green:100 blue:0) exactOn:aDevice).
   366                 colors add:((self red:100 green:0 blue:100) exactOn:aDevice).
   366 		colors add:((self red:100 green:0 blue:100) exactOn:aDevice).
   367                 colors add:((self red:0 green:100 blue:100) exactOn:aDevice).
   367 		colors add:((self red:0 green:100 blue:100) exactOn:aDevice).
   368 
   368 
   369                 colors := colors select:[:clr | clr notNil].
   369 		colors := colors select:[:clr | clr notNil].
   370             ].
   370 	    ].
   371 
   371 
   372             aDevice hasGreyscales ifTrue:[
   372 	    aDevice hasGreyscales ifTrue:[
   373                 aDevice hasColors ifFalse:[
   373 		aDevice hasColors ifFalse:[
   374                     colors := OrderedCollection new.
   374 		    colors := OrderedCollection new.
   375                     colors add:((self gray:50) exactOn:aDevice).
   375 		    colors add:((self gray:50) exactOn:aDevice).
   376                     colors add:white; add:black.
   376 		    colors add:white; add:black.
   377 
   377 
   378                 ].
   378 		].
   379                 colors add:((self gray:25) exactOn:aDevice).
   379 		colors add:((self gray:25) exactOn:aDevice).
   380                 colors add:((self gray:33) exactOn:aDevice).
   380 		colors add:((self gray:33) exactOn:aDevice).
   381                 colors add:((self gray:67) exactOn:aDevice).
   381 		colors add:((self gray:67) exactOn:aDevice).
   382                 colors add:((self gray:75) exactOn:aDevice).
   382 		colors add:((self gray:75) exactOn:aDevice).
   383 
   383 
   384                 colors := colors select:[:clr | clr notNil].
   384 		colors := colors select:[:clr | clr notNil].
   385             ].
   385 	    ].
   386 
   386 
   387             colors notNil ifTrue:[  
   387 	    colors notNil ifTrue:[  
   388                 aDevice setDitherColors:(colors asArray).
   388 		aDevice setDitherColors:(colors asArray).
   389             ]
   389 	    ]
   390         ]
   390 	]
   391     ]
   391     ]
   392 
   392 
   393     "Created: 11.7.1996 / 18:09:28 / cg"
   393     "Created: 11.7.1996 / 18:09:28 / cg"
   394     "Modified: 11.7.1996 / 18:27:39 / cg"
   394     "Modified: 11.7.1996 / 18:27:39 / cg"
   395 !
   395 !
   397 initialize
   397 initialize
   398     "setup tracker of known colors and initialize classvars with
   398     "setup tracker of known colors and initialize classvars with
   399      heavily used colors"
   399      heavily used colors"
   400 
   400 
   401     ColorAllocationFailSignal isNil ifTrue:[
   401     ColorAllocationFailSignal isNil ifTrue:[
   402         ColorAllocationFailSignal := ErrorSignal newSignalMayProceed:true.
   402 	ColorAllocationFailSignal := ErrorSignal newSignalMayProceed:true.
   403         ColorAllocationFailSignal nameClass:self message:#colorAllocationFailSignal.
   403 	ColorAllocationFailSignal nameClass:self message:#colorAllocationFailSignal.
   404         ColorAllocationFailSignal notifierString:'color allocation failed'.
   404 	ColorAllocationFailSignal notifierString:'color allocation failed'.
   405     ].
   405     ].
   406 
   406 
   407     Lobby isNil ifTrue:[
   407     Lobby isNil ifTrue:[
   408         MaxValue := 16rFFFF.
   408 	MaxValue := 16rFFFF.
   409 
   409 
   410         Lobby := Registry new.
   410 	Lobby := Registry new.
   411 
   411 
   412         self getPrimaryColors.
   412 	self getPrimaryColors.
   413 
   413 
   414         "want to be informed when returning from snapshot"
   414 	"want to be informed when returning from snapshot"
   415         ObjectMemory addDependent:self.
   415 	ObjectMemory addDependent:self.
   416 
   416 
   417         RetryAllocation := true.
   417 	RetryAllocation := true.
   418 
   418 
   419         DitherBits := self ditherBits
   419 	DitherBits := self ditherBits
   420     ].
   420     ].
   421 
   421 
   422     "Modified: 11.7.1996 / 18:31:39 / cg"
   422     "Modified: 11.7.1996 / 18:31:39 / cg"
   423 !
   423 !
   424 
   424 
   425 update:something with:aParameter from:changedObject
   425 update:something with:aParameter from:changedObject
   426     "handle image restarts and flush any device resource handles"
   426     "handle image restarts and flush any device resource handles"
   427 
   427 
   428     (something == #restarted) ifTrue:[
   428     (something == #restarted) ifTrue:[
   429         self flushDeviceColors
   429 	self flushDeviceColors
   430     ].
   430     ].
   431     (something == #returnFromSnapshot) ifTrue:[
   431     (something == #returnFromSnapshot) ifTrue:[
   432         self getPrimaryColors.
   432 	self getPrimaryColors.
   433 
   433 
   434         Display visualType == #TrueColor ifTrue:[
   434 	Display visualType == #TrueColor ifTrue:[
   435             Display releaseFixColors
   435 	    Display releaseFixColors
   436         ] ifFalse:[
   436 	] ifFalse:[
   437             Display fixColors notNil ifTrue:[
   437 	    Display fixColors notNil ifTrue:[
   438                 ColorAllocationFailSignal handle:[:ex |
   438 		ColorAllocationFailSignal handle:[:ex |
   439                     ex return
   439 		    ex return
   440                 ] do:[
   440 		] do:[
   441                     |nR nG nB|
   441 		    |nR nG nB|
   442 
   442 
   443                     nR := Display numFixRed.
   443 		    nR := Display numFixRed.
   444                     nG := Display numFixGreen.
   444 		    nG := Display numFixGreen.
   445                     nB := Display numFixBlue.
   445 		    nB := Display numFixBlue.
   446                     Display releaseFixColors.
   446 		    Display releaseFixColors.
   447                     self getColorsRed:nR
   447 		    self getColorsRed:nR
   448                                 green:nG
   448 				green:nG
   449                                  blue:nB
   449 				 blue:nB
   450                                    on:Display
   450 				   on:Display
   451                 ]
   451 		]
   452             ]
   452 	    ]
   453         ]
   453 	]
   454     ]
   454     ]
   455 
   455 
   456     "Created: 15.6.1996 / 15:14:03 / cg"
   456     "Created: 15.6.1996 / 15:14:03 / cg"
   457     "Modified: 11.7.1996 / 18:03:38 / cg"
   457     "Modified: 11.7.1996 / 18:03:38 / cg"
   458 ! !
   458 ! !
   785 
   785 
   786     |colors|
   786     |colors|
   787 
   787 
   788     colors := OrderedCollection new.
   788     colors := OrderedCollection new.
   789     Lobby do:[:clr |
   789     Lobby do:[:clr |
   790         (clr graphicsDevice == aDevice and:[clr colorId notNil]) ifTrue:[
   790 	(clr graphicsDevice == aDevice and:[clr colorId notNil]) ifTrue:[
   791             colors add:clr
   791 	    colors add:clr
   792         ]
   792 	]
   793     ].
   793     ].
   794     ^ colors asArray
   794     ^ colors asArray
   795 
   795 
   796     "
   796     "
   797      Color allocatedColorsOn:Display
   797      Color allocatedColorsOn:Display
  1216     rg := (g * 2.0) rounded / 2.0.  "round to 0.5%"
  1216     rg := (g * 2.0) rounded / 2.0.  "round to 0.5%"
  1217     rb := (b / 2) rounded * 2.      "round to 2%"
  1217     rb := (b / 2) rounded * 2.      "round to 2%"
  1218 
  1218 
  1219     minDelta := 100*100*100.
  1219     minDelta := 100*100*100.
  1220     Lobby do:[:aColor |
  1220     Lobby do:[:aColor |
  1221         (aColor graphicsDevice == aDevice) ifTrue:[
  1221 	(aColor graphicsDevice == aDevice) ifTrue:[
  1222 "/            (aColor colorId notNil) ifTrue:[
  1222 "/            (aColor colorId notNil) ifTrue:[
  1223                 dRed := rr - aColor red.
  1223 		dRed := rr - aColor red.
  1224                 dRed < 10 ifTrue:[
  1224 		dRed < 10 ifTrue:[
  1225                     diff := dRed asInteger squared
  1225 		    diff := dRed asInteger squared
  1226                             + (rg - aColor green) asInteger squared
  1226 			    + (rg - aColor green) asInteger squared
  1227                             + (rb - aColor blue) asInteger squared.
  1227 			    + (rb - aColor blue) asInteger squared.
  1228                     diff < minDelta ifTrue:[
  1228 		    diff < minDelta ifTrue:[
  1229                         diff = 0 ifTrue:[
  1229 			diff = 0 ifTrue:[
  1230                             "got it"
  1230 			    "got it"
  1231                             ^ aColor
  1231 			    ^ aColor
  1232                         ].
  1232 			].
  1233                         bestColor := aColor.
  1233 			bestColor := aColor.
  1234                         minDelta := diff
  1234 			minDelta := diff
  1235                     ]
  1235 		    ]
  1236                 ]
  1236 		]
  1237 "/            ]
  1237 "/            ]
  1238         ]
  1238 	]
  1239     ].
  1239     ].
  1240 
  1240 
  1241     "allow an error of 10% per component"
  1241     "allow an error of 10% per component"
  1242     minDelta < (100+100+100) ifTrue:[ ^ bestColor ].
  1242     minDelta < (100+100+100) ifTrue:[ ^ bestColor ].
  1243     ^ nil
  1243     ^ nil
  1960 existingColorScaledRed:r scaledGreen:g scaledBlue:b on:aDevice
  1960 existingColorScaledRed:r scaledGreen:g scaledBlue:b on:aDevice
  1961     "return a device color on aDevice with rgb values
  1961     "return a device color on aDevice with rgb values
  1962      if there is one, nil otherwise."
  1962      if there is one, nil otherwise."
  1963 
  1963 
  1964     Lobby do:[:aColor |
  1964     Lobby do:[:aColor |
  1965         (r == aColor scaledRed) ifTrue:[
  1965 	(r == aColor scaledRed) ifTrue:[
  1966             (g == aColor scaledGreen) ifTrue:[
  1966 	    (g == aColor scaledGreen) ifTrue:[
  1967                 (b == aColor scaledBlue) ifTrue:[
  1967 		(b == aColor scaledBlue) ifTrue:[
  1968                     (aColor graphicsDevice == aDevice) ifTrue:[
  1968 		    (aColor graphicsDevice == aDevice) ifTrue:[
  1969                         ^ aColor
  1969 			^ aColor
  1970                     ]
  1970 		    ]
  1971                 ]
  1971 		]
  1972             ]
  1972 	    ]
  1973         ]
  1973 	]
  1974     ].
  1974     ].
  1975     ^ nil
  1975     ^ nil
  1976 
  1976 
  1977     "Modified: 5.7.1996 / 17:58:15 / cg"
  1977     "Modified: 5.7.1996 / 17:58:15 / cg"
  1978 ! !
  1978 ! !
  2007      Near is defined as having an error less than the argument
  2007      Near is defined as having an error less than the argument
  2008      error (in percent). The error is computed by the color
  2008      error (in percent). The error is computed by the color
  2009      vector distance (which may not be the best possible solution)."
  2009      vector distance (which may not be the best possible solution)."
  2010 
  2010 
  2011     ^ self
  2011     ^ self
  2012         nearestColorScaledRed:(r * MaxValue // 100)
  2012 	nearestColorScaledRed:(r * MaxValue // 100)
  2013                   scaledGreen:(g * MaxValue // 100) 
  2013 		  scaledGreen:(g * MaxValue // 100) 
  2014                    scaledBlue:(b * MaxValue // 100) 
  2014 		   scaledBlue:(b * MaxValue // 100) 
  2015                            on:aDevice 
  2015 			   on:aDevice 
  2016                            in:colors
  2016 			   in:colors
  2017 
  2017 
  2018     "Modified: 11.6.1996 / 18:04:55 / cg"
  2018     "Modified: 11.6.1996 / 18:04:55 / cg"
  2019     "Created: 14.6.1996 / 20:05:13 / cg"
  2019     "Created: 14.6.1996 / 20:05:13 / cg"
  2020 !
  2020 !
  2021 
  2021 
  2068 
  2068 
  2069     "
  2069     "
  2070      if there are preallocated colors, things are much easier ...
  2070      if there are preallocated colors, things are much easier ...
  2071     "
  2071     "
  2072     (cube := aDevice fixColors) notNil ifTrue:[
  2072     (cube := aDevice fixColors) notNil ifTrue:[
  2073         ^ self 
  2073 	^ self 
  2074             nearestColorScaledRed:r 
  2074 	    nearestColorScaledRed:r 
  2075             scaledGreen:g 
  2075 	    scaledGreen:g 
  2076             scaledBlue:b
  2076 	    scaledBlue:b
  2077             inCube:cube
  2077 	    inCube:cube
  2078             numRed:(aDevice numFixRed)
  2078 	    numRed:(aDevice numFixRed)
  2079             numGreen:(aDevice numFixGreen)
  2079 	    numGreen:(aDevice numFixGreen)
  2080             numBlue:(aDevice numFixBlue)
  2080 	    numBlue:(aDevice numFixBlue)
  2081     ].
  2081     ].
  2082 
  2082 
  2083     "
  2083     "
  2084      search in existing colors ...
  2084      search in existing colors ...
  2085     "
  2085     "
  2086     ^ self 
  2086     ^ self 
  2087         nearestColorScaledRed:r 
  2087 	nearestColorScaledRed:r 
  2088         scaledGreen:g 
  2088 	scaledGreen:g 
  2089         scaledBlue:b 
  2089 	scaledBlue:b 
  2090         on:aDevice 
  2090 	on:aDevice 
  2091         in:Lobby
  2091 	in:Lobby
  2092 
  2092 
  2093     "Created: 14.6.1996 / 20:11:18 / cg"
  2093     "Created: 14.6.1996 / 20:11:18 / cg"
  2094     "Modified: 11.7.1996 / 18:20:50 / cg"
  2094     "Modified: 11.7.1996 / 18:20:50 / cg"
  2095 !
  2095 !
  2096 
  2096 
  2102     |delta minDelta bestSoFar|
  2102     |delta minDelta bestSoFar|
  2103 
  2103 
  2104     minDelta := 9999999.
  2104     minDelta := 9999999.
  2105 
  2105 
  2106     colors do:[:aColor |
  2106     colors do:[:aColor |
  2107         |cr cg cb|
  2107 	|cr cg cb|
  2108 
  2108 
  2109         (aColor graphicsDevice == aDevice) ifTrue:[
  2109 	(aColor graphicsDevice == aDevice) ifTrue:[
  2110             aColor colorId notNil ifTrue:[
  2110 	    aColor colorId notNil ifTrue:[
  2111                 delta := aColor deltaFromScaledRed:r scaledGreen:g scaledBlue:b.
  2111 		delta := aColor deltaFromScaledRed:r scaledGreen:g scaledBlue:b.
  2112                 delta < minDelta ifTrue:[
  2112 		delta < minDelta ifTrue:[
  2113                     "
  2113 		    "
  2114                      an exact fit - no need to continue search
  2114 		     an exact fit - no need to continue search
  2115                     "
  2115 		    "
  2116                     delta == 0 ifTrue:[^ aColor].
  2116 		    delta == 0 ifTrue:[^ aColor].
  2117 
  2117 
  2118                     bestSoFar := aColor.
  2118 		    bestSoFar := aColor.
  2119                     minDelta := delta
  2119 		    minDelta := delta
  2120                 ]
  2120 		]
  2121             ]
  2121 	    ]
  2122         ]
  2122 	]
  2123     ].
  2123     ].
  2124 
  2124 
  2125     ^ bestSoFar
  2125     ^ bestSoFar
  2126 
  2126 
  2127     "Created: 11.6.1996 / 18:02:12 / cg"
  2127     "Created: 11.6.1996 / 18:02:12 / cg"
  2141 
  2141 
  2142     "
  2142     "
  2143      if there are preallocated colors, thungs are much easier ...
  2143      if there are preallocated colors, thungs are much easier ...
  2144     "
  2144     "
  2145     (cube := aDevice fixColors) ifTrue:[
  2145     (cube := aDevice fixColors) ifTrue:[
  2146         ^ self 
  2146 	^ self 
  2147             nearestColorScaledRed:r 
  2147 	    nearestColorScaledRed:r 
  2148             scaledGreen:g 
  2148 	    scaledGreen:g 
  2149             scaledBlue:b 
  2149 	    scaledBlue:b 
  2150             inCube:cube
  2150 	    inCube:cube
  2151             numRed:(aDevice numFixRed)
  2151 	    numRed:(aDevice numFixRed)
  2152             numGreen:(aDevice numFixGreen)
  2152 	    numGreen:(aDevice numFixGreen)
  2153             numBlue:(aDevice numFixBlue)
  2153 	    numBlue:(aDevice numFixBlue)
  2154     ].
  2154     ].
  2155 
  2155 
  2156     "
  2156     "
  2157      search in existing colors ...
  2157      search in existing colors ...
  2158     "
  2158     "
  2159     ^ self nearestColorScaledRed:r 
  2159     ^ self nearestColorScaledRed:r 
  2160                      scaledGreen:g 
  2160 		     scaledGreen:g 
  2161                       scaledBlue:b 
  2161 		      scaledBlue:b 
  2162                         on:aDevice 
  2162 			on:aDevice 
  2163                         in:aDevice availableDitherColors
  2163 			in:aDevice availableDitherColors
  2164 
  2164 
  2165     "Created: 14.6.1996 / 20:13:22 / cg"
  2165     "Created: 14.6.1996 / 20:13:22 / cg"
  2166     "Modified: 11.7.1996 / 18:20:14 / cg"
  2166     "Modified: 11.7.1996 / 18:20:14 / cg"
  2167 ! !
  2167 ! !
  2168 
  2168 
  2646     (newColor notNil and:[newColor ditherForm isNil]) ifTrue:[^ newColor].
  2646     (newColor notNil and:[newColor ditherForm isNil]) ifTrue:[^ newColor].
  2647 
  2647 
  2648     "ask that device for the color"
  2648     "ask that device for the color"
  2649     id := aDevice colorScaledRed:r scaledGreen:g scaledBlue:b.
  2649     id := aDevice colorScaledRed:r scaledGreen:g scaledBlue:b.
  2650     id isNil ifTrue:[
  2650     id isNil ifTrue:[
  2651         "/ this is a kludge: scavenge to free unused colors
  2651 	"/ this is a kludge: scavenge to free unused colors
  2652         "/  and try again ...
  2652 	"/  and try again ...
  2653         ObjectMemory scavenge; finalize.
  2653 	ObjectMemory scavenge; finalize.
  2654         id := aDevice colorScaledRed:r scaledGreen:g scaledBlue:b
  2654 	id := aDevice colorScaledRed:r scaledGreen:g scaledBlue:b
  2655     ].
  2655     ].
  2656     id isNil ifTrue:[
  2656     id isNil ifTrue:[
  2657         "no such color - fail"
  2657 	"no such color - fail"
  2658 
  2658 
  2659 "/	'COLOR: no color for ' infoPrint. self displayString infoPrintCR.
  2659 "/      'COLOR: no color for ' infoPrint. self displayString infoPrintCR.
  2660         ^ nil
  2660 	^ nil
  2661     ].
  2661     ].
  2662 
  2662 
  2663     "receiver was not associated - do it now"
  2663     "receiver was not associated - do it now"
  2664     device isNil ifTrue:[
  2664     device isNil ifTrue:[
  2665         device := aDevice.
  2665 	device := aDevice.
  2666         colorId := id.
  2666 	colorId := id.
  2667 
  2667 
  2668         aDevice visualType ~~ #TrueColor ifTrue:[
  2668 	aDevice visualType ~~ #TrueColor ifTrue:[
  2669             Lobby register:self.
  2669 	    Lobby register:self.
  2670         ].
  2670 	].
  2671         ^ self
  2671 	^ self
  2672     ].
  2672     ].
  2673 
  2673 
  2674     "receiver was already associated to another device - need a new color"
  2674     "receiver was already associated to another device - need a new color"
  2675     newColor := (self class basicNew) setScaledRed:r scaledGreen:g scaledBlue:b device:aDevice.
  2675     newColor := (self class basicNew) setScaledRed:r scaledGreen:g scaledBlue:b device:aDevice.
  2676     newColor colorId:id.
  2676     newColor colorId:id.
  2677     aDevice visualType ~~ #TrueColor ifTrue:[
  2677     aDevice visualType ~~ #TrueColor ifTrue:[
  2678         Lobby register:newColor.
  2678 	Lobby register:newColor.
  2679     ].
  2679     ].
  2680     ^ newColor
  2680     ^ newColor
  2681 
  2681 
  2682     "Modified: 17.6.1996 / 16:09:05 / cg"
  2682     "Modified: 17.6.1996 / 16:09:05 / cg"
  2683 !
  2683 !
  2697     newColor notNil ifTrue:[^ newColor].
  2697     newColor notNil ifTrue:[^ newColor].
  2698 
  2698 
  2699     "ask that device for the color"
  2699     "ask that device for the color"
  2700     id := aDevice colorScaledRed:red scaledGreen:green scaledBlue:blue.
  2700     id := aDevice colorScaledRed:red scaledGreen:green scaledBlue:blue.
  2701     id isNil ifTrue:[
  2701     id isNil ifTrue:[
  2702         "this is a kludge: 
  2702 	"this is a kludge: 
  2703             scavenge to possuby free unused colors and try again ...
  2703 	    scavenge to possuby free unused colors and try again ...
  2704             this is a compromise: actually a full GC is required here,
  2704 	    this is a compromise: actually a full GC is required here,
  2705             but that is too expensive.
  2705 	    but that is too expensive.
  2706         "
  2706 	"
  2707 " "
  2707 " "
  2708         ObjectMemory scavenge; finalize.
  2708 	ObjectMemory scavenge; finalize.
  2709         id := aDevice colorScaledRed:red scaledGreen:green scaledBlue:blue
  2709 	id := aDevice colorScaledRed:red scaledGreen:green scaledBlue:blue
  2710 " "
  2710 " "
  2711     ].
  2711     ].
  2712     id isNil ifTrue:[
  2712     id isNil ifTrue:[
  2713         "no color - fail"
  2713 	"no color - fail"
  2714 
  2714 
  2715         ^ nil
  2715 	^ nil
  2716     ].
  2716     ].
  2717 
  2717 
  2718     "receiver was not associated - do it now"
  2718     "receiver was not associated - do it now"
  2719     device isNil ifTrue:[
  2719     device isNil ifTrue:[
  2720         device := aDevice.
  2720 	device := aDevice.
  2721         colorId := id.
  2721 	colorId := id.
  2722 
  2722 
  2723         aDevice visualType ~~ #TrueColor ifTrue:[
  2723 	aDevice visualType ~~ #TrueColor ifTrue:[
  2724             Lobby register:self.
  2724 	    Lobby register:self.
  2725         ].
  2725 	].
  2726         ^ self
  2726 	^ self
  2727     ].
  2727     ].
  2728 
  2728 
  2729     "receiver was already associated to another device - need a new color"
  2729     "receiver was already associated to another device - need a new color"
  2730     newColor := (self class basicNew) setScaledRed:red scaledGreen:green sclaedBlue:blue device:aDevice.
  2730     newColor := (self class basicNew) setScaledRed:red scaledGreen:green sclaedBlue:blue device:aDevice.
  2731     newColor colorId:id.
  2731     newColor colorId:id.
  2732     aDevice visualType ~~ #TrueColor ifTrue:[
  2732     aDevice visualType ~~ #TrueColor ifTrue:[
  2733         Lobby register:newColor.
  2733 	Lobby register:newColor.
  2734     ].
  2734     ].
  2735     ^ newColor
  2735     ^ newColor
  2736 
  2736 
  2737     "Modified: 14.6.1996 / 20:11:22 / cg"
  2737     "Modified: 14.6.1996 / 20:11:22 / cg"
  2738 !
  2738 !
  2750 
  2750 
  2751     "/ the most common case first - someone is validating me
  2751     "/ the most common case first - someone is validating me
  2752     "/ before drawing on aDevice
  2752     "/ before drawing on aDevice
  2753 
  2753 
  2754     aDevice notNil ifTrue:[
  2754     aDevice notNil ifTrue:[
  2755         aDevice == device ifTrue:[
  2755 	aDevice == device ifTrue:[
  2756             colorId notNil ifTrue:[
  2756 	    colorId notNil ifTrue:[
  2757                 ^ self
  2757 		^ self
  2758             ]
  2758 	    ]
  2759         ]
  2759 	]
  2760     ].
  2760     ].
  2761 
  2761 
  2762     "/ a special case for pseudo-colors (0 and 1 in bitmaps)
  2762     "/ a special case for pseudo-colors (0 and 1 in bitmaps)
  2763 
  2763 
  2764     (red isNil and:[colorId notNil]) ifTrue:[^ self].
  2764     (red isNil and:[colorId notNil]) ifTrue:[^ self].
  2766     "/ on high-resolution true-color systems, dont care for dithring and/or
  2766     "/ on high-resolution true-color systems, dont care for dithring and/or
  2767     "/ especially freeing colors
  2767     "/ especially freeing colors
  2768     "/ (no need to remember in Lobby)
  2768     "/ (no need to remember in Lobby)
  2769 
  2769 
  2770     (deviceVisual := aDevice visualType) == #TrueColor ifTrue:[
  2770     (deviceVisual := aDevice visualType) == #TrueColor ifTrue:[
  2771         aDevice depth >= 15 ifTrue:[
  2771 	aDevice depth >= 15 ifTrue:[
  2772             id := aDevice colorScaledRed:red scaledGreen:green scaledBlue:blue.
  2772 	    id := aDevice colorScaledRed:red scaledGreen:green scaledBlue:blue.
  2773             id notNil ifTrue:[
  2773 	    id notNil ifTrue:[
  2774                 device isNil ifTrue:[
  2774 		device isNil ifTrue:[
  2775                     colorId := id.
  2775 		    colorId := id.
  2776                     ditherForm := nil.
  2776 		    ditherForm := nil.
  2777                     ^ self
  2777 		    ^ self
  2778                 ] ifFalse:[
  2778 		] ifFalse:[
  2779                     newColor := (self class basicNew) 
  2779 		    newColor := (self class basicNew) 
  2780                                         setScaledRed:red 
  2780 					setScaledRed:red 
  2781                                         scaledGreen:green 
  2781 					scaledGreen:green 
  2782                                         scaledBlue:blue 
  2782 					scaledBlue:blue 
  2783                                         device:aDevice.
  2783 					device:aDevice.
  2784                     newColor colorId:id.
  2784 		    newColor colorId:id.
  2785                     ^ newColor
  2785 		    ^ newColor
  2786                 ]
  2786 		]
  2787             ] 
  2787 	    ] 
  2788         ] 
  2788 	] 
  2789     ].
  2789     ].
  2790 
  2790 
  2791     "/ want to release color ?
  2791     "/ want to release color ?
  2792 
  2792 
  2793     (aDevice isNil and:[device notNil and:[colorId notNil]]) ifTrue:[
  2793     (aDevice isNil and:[device notNil and:[colorId notNil]]) ifTrue:[
  2794         deviceVisual ~~ #TrueColor ifTrue:[
  2794 	deviceVisual ~~ #TrueColor ifTrue:[
  2795             (device notNil and:[colorId notNil]) ifTrue:[
  2795 	    (device notNil and:[colorId notNil]) ifTrue:[
  2796                 Lobby unregister:self.
  2796 		Lobby unregister:self.
  2797                 device freeColor:colorId
  2797 		device freeColor:colorId
  2798             ].
  2798 	    ].
  2799         ].
  2799 	].
  2800         device := nil.
  2800 	device := nil.
  2801         colorId := nil.
  2801 	colorId := nil.
  2802         ^ self
  2802 	^ self
  2803     ].
  2803     ].
  2804 
  2804 
  2805     "/ round a bit within 1% in red & green, 2% in blue
  2805     "/ round a bit within 1% in red & green, 2% in blue
  2806 
  2806 
  2807     rV := (red / 100.0) rounded * 100.
  2807     rV := (red / 100.0) rounded * 100.
  2810 
  2810 
  2811     "/ if Iam already assigned to that device ...
  2811     "/ if Iam already assigned to that device ...
  2812 
  2812 
  2813     (device == aDevice) ifTrue:[
  2813     (device == aDevice) ifTrue:[
  2814 
  2814 
  2815         "/ mhmh - if I was dithered the last time (not enough colors then)
  2815 	"/ mhmh - if I was dithered the last time (not enough colors then)
  2816         "/ try again - maybe some colors were reclaimed in the meanwhile
  2816 	"/ try again - maybe some colors were reclaimed in the meanwhile
  2817 
  2817 
  2818         (ditherForm notNil 
  2818 	(ditherForm notNil 
  2819          and:[aDevice fixColors isNil
  2819 	 and:[aDevice fixColors isNil
  2820          and:[RetryAllocation]]) ifTrue:[
  2820 	 and:[RetryAllocation]]) ifTrue:[
  2821             aDevice depth > 2 ifTrue:[
  2821 	    aDevice depth > 2 ifTrue:[
  2822                 "
  2822 		"
  2823                  if I was dithered, try again 
  2823 		 if I was dithered, try again 
  2824                  (but there is no chance on b&w displays - so don't try)
  2824 		 (but there is no chance on b&w displays - so don't try)
  2825                 "
  2825 		"
  2826                 id := aDevice colorScaledRed:rV scaledGreen:gV scaledBlue:bV.
  2826 		id := aDevice colorScaledRed:rV scaledGreen:gV scaledBlue:bV.
  2827                 id notNil ifTrue:[
  2827 		id notNil ifTrue:[
  2828                     colorId := id.
  2828 		    colorId := id.
  2829                     ditherForm := nil.
  2829 		    ditherForm := nil.
  2830                     Lobby register:self
  2830 		    Lobby register:self
  2831                 ]
  2831 		]
  2832             ]
  2832 	    ]
  2833         ].
  2833 	].
  2834         ^ self
  2834 	^ self
  2835     ].
  2835     ].
  2836 
  2836 
  2837     newColor := Color existingColorScaledRed:rV scaledGreen:gV scaledBlue:bV on:aDevice.
  2837     newColor := Color existingColorScaledRed:rV scaledGreen:gV scaledBlue:bV on:aDevice.
  2838     newColor notNil ifTrue:[^ newColor].
  2838     newColor notNil ifTrue:[^ newColor].
  2839 
  2839 
  2847     "/ allow an error of 1% in red & green, 2% in blue
  2847     "/ allow an error of 1% in red & green, 2% in blue
  2848 
  2848 
  2849     ((rV - greyV) abs <= 655                    "/ MaxValue // 100
  2849     ((rV - greyV) abs <= 655                    "/ MaxValue // 100
  2850     and:[(gV - greyV) abs <= 655                "/ MaxValue // 100
  2850     and:[(gV - greyV) abs <= 655                "/ MaxValue // 100
  2851     and:[(bV - greyV) abs <= 1310]]) ifTrue:[   "/ MaxValue // 100 * 2
  2851     and:[(bV - greyV) abs <= 1310]]) ifTrue:[   "/ MaxValue // 100 * 2
  2852         rV := gV := bV := greyV.
  2852 	rV := gV := bV := greyV.
  2853     ] ifFalse:[
  2853     ] ifFalse:[
  2854         rV := red. gV := green. bV := blue.
  2854 	rV := red. gV := green. bV := blue.
  2855     ].
  2855     ].
  2856 
  2856 
  2857     aDevice hasColors ifTrue:[
  2857     aDevice hasColors ifTrue:[
  2858         aDevice fixColors isNil ifTrue:[
  2858 	aDevice fixColors isNil ifTrue:[
  2859             "/ ask that device for the exact color
  2859 	    "/ ask that device for the exact color
  2860 
  2860 
  2861             id := aDevice colorScaledRed:rV scaledGreen:gV scaledBlue:bV.
  2861 	    id := aDevice colorScaledRed:rV scaledGreen:gV scaledBlue:bV.
  2862             id isNil ifTrue:[
  2862 	    id isNil ifTrue:[
  2863                 "/ this is a kludge: scavenge to free unused colors
  2863 		"/ this is a kludge: scavenge to free unused colors
  2864                 "/ and try again ...
  2864 		"/ and try again ...
  2865                 ObjectMemory scavenge; finalize.
  2865 		ObjectMemory scavenge; finalize.
  2866                 id := aDevice colorScaledRed:rV scaledGreen:gV scaledBlue:bV
  2866 		id := aDevice colorScaledRed:rV scaledGreen:gV scaledBlue:bV
  2867             ].
  2867 	    ].
  2868 
  2868 
  2869             id isNil ifTrue:[
  2869 	    id isNil ifTrue:[
  2870                 "/ no such color - try color dithers
  2870 		"/ no such color - try color dithers
  2871 
  2871 
  2872                 self ditherRed:rV green:gV blue:bV on:aDevice 
  2872 		self ditherRed:rV green:gV blue:bV on:aDevice 
  2873                           into:[:c :f | newColor := c. form := f].
  2873 			  into:[:c :f | newColor := c. form := f].
  2874                 newColor notNil ifTrue:[^ newColor].
  2874 		newColor notNil ifTrue:[^ newColor].
  2875             ].
  2875 	    ].
  2876         ].
  2876 	].
  2877 
  2877 
  2878         "/ none found ? -> do a hard dither using fixColors
  2878 	"/ none found ? -> do a hard dither using fixColors
  2879 
  2879 
  2880         (id isNil and:[form isNil]) ifTrue:[
  2880 	(id isNil and:[form isNil]) ifTrue:[
  2881             (aDevice fixColors notNil and:[aDevice == Display]) ifTrue:[
  2881 	    (aDevice fixColors notNil and:[aDevice == Display]) ifTrue:[
  2882                 self fixDitherRed:rV green:gV blue:bV on:aDevice 
  2882 		self fixDitherRed:rV green:gV blue:bV on:aDevice 
  2883                              into:[:c :f | newColor := c. form := f].
  2883 			     into:[:c :f | newColor := c. form := f].
  2884                 newColor notNil ifTrue:[^ newColor].
  2884 		newColor notNil ifTrue:[^ newColor].
  2885             ]
  2885 	    ]
  2886         ].
  2886 	].
  2887 
  2887 
  2888         "/ still none found ? -> do a very hard dither using existing colors
  2888 	"/ still none found ? -> do a very hard dither using existing colors
  2889 
  2889 
  2890         (id isNil and:[form isNil]) ifTrue:[
  2890 	(id isNil and:[form isNil]) ifTrue:[
  2891             self complexDitherRed:rV green:gV blue:bV on:aDevice 
  2891 	    self complexDitherRed:rV green:gV blue:bV on:aDevice 
  2892                       into:[:c :f | newColor := c. form := f].
  2892 		      into:[:c :f | newColor := c. form := f].
  2893             newColor notNil ifTrue:[^ newColor].
  2893 	    newColor notNil ifTrue:[^ newColor].
  2894         ].
  2894 	].
  2895     ].
  2895     ].
  2896 
  2896 
  2897     (id isNil and:[form isNil]) ifTrue:[
  2897     (id isNil and:[form isNil]) ifTrue:[
  2898         "still no result - try greying"
  2898 	"still no result - try greying"
  2899 
  2899 
  2900         greyV == 0 ifTrue:[
  2900 	greyV == 0 ifTrue:[
  2901             id := aDevice blackpixel
  2901 	    id := aDevice blackpixel
  2902         ] ifFalse:[
  2902 	] ifFalse:[
  2903             greyV == MaxValue ifTrue:[
  2903 	    greyV == MaxValue ifTrue:[
  2904                 id := aDevice whitepixel
  2904 		id := aDevice whitepixel
  2905             ] ifFalse:[
  2905 	    ] ifFalse:[
  2906                 aDevice hasGrayscales ifTrue:[
  2906 		aDevice hasGrayscales ifTrue:[
  2907                     self ditherGrayFor:(greyV / MaxValue)
  2907 		    self ditherGrayFor:(greyV / MaxValue)
  2908                                     on:aDevice
  2908 				    on:aDevice
  2909                                   into:[:c :f | newColor := c. form := f].
  2909 				  into:[:c :f | newColor := c. form := f].
  2910                     newColor notNil ifTrue:[^ newColor].
  2910 		    newColor notNil ifTrue:[^ newColor].
  2911                 ].
  2911 		].
  2912             ]
  2912 	    ]
  2913         ].
  2913 	].
  2914     ].
  2914     ].
  2915 
  2915 
  2916     device isNil ifTrue:[
  2916     device isNil ifTrue:[
  2917         "/ receiver was not associated - do it now & return mySelf
  2917 	"/ receiver was not associated - do it now & return mySelf
  2918 
  2918 
  2919         device := aDevice.
  2919 	device := aDevice.
  2920         id isNil ifTrue:[
  2920 	id isNil ifTrue:[
  2921             ditherForm := form
  2921 	    ditherForm := form
  2922         ].
  2922 	].
  2923         colorId := id.
  2923 	colorId := id.
  2924 
  2924 
  2925         "/ have to tell Lobby - otherwise it keeps old info around
  2925 	"/ have to tell Lobby - otherwise it keeps old info around
  2926 
  2926 
  2927         id notNil ifTrue:[
  2927 	id notNil ifTrue:[
  2928             deviceVisual ~~ #TrueColor ifTrue:[    
  2928 	    deviceVisual ~~ #TrueColor ifTrue:[    
  2929                 Lobby register:self
  2929 		Lobby register:self
  2930             ]
  2930 	    ]
  2931         ].
  2931 	].
  2932         ^ self
  2932 	^ self
  2933     ].
  2933     ].
  2934 
  2934 
  2935     "/ receiver was already associated to another device
  2935     "/ receiver was already associated to another device
  2936     "/ - need a new color and return it
  2936     "/ - need a new color and return it
  2937 
  2937 
  2938     newColor := (self class basicNew) 
  2938     newColor := (self class basicNew) 
  2939                         setScaledRed:red 
  2939 			setScaledRed:red 
  2940                         scaledGreen:green 
  2940 			scaledGreen:green 
  2941                         scaledBlue:blue 
  2941 			scaledBlue:blue 
  2942                         device:aDevice.
  2942 			device:aDevice.
  2943     id isNil ifTrue:[
  2943     id isNil ifTrue:[
  2944         newColor ditherForm:form
  2944 	newColor ditherForm:form
  2945     ] ifFalse:[
  2945     ] ifFalse:[
  2946         newColor colorId:id.
  2946 	newColor colorId:id.
  2947         deviceVisual ~~ #TrueColor ifTrue:[    
  2947 	deviceVisual ~~ #TrueColor ifTrue:[    
  2948             Lobby register:newColor.
  2948 	    Lobby register:newColor.
  2949         ]
  2949 	]
  2950     ].
  2950     ].
  2951     ^ newColor
  2951     ^ newColor
  2952 
  2952 
  2953     "Created: 16.11.1995 / 20:16:42 / cg"
  2953     "Created: 16.11.1995 / 20:16:42 / cg"
  2954     "Modified: 11.7.1996 / 18:31:12 / cg"
  2954     "Modified: 11.7.1996 / 18:31:12 / cg"
  3119     "get a form and clear it"
  3119     "get a form and clear it"
  3120     f := Form width:4 height:4 depth:(aDevice depth) on:aDevice.
  3120     f := Form width:4 height:4 depth:(aDevice depth) on:aDevice.
  3121     map := IdentityDictionary new.
  3121     map := IdentityDictionary new.
  3122 
  3122 
  3123     0 to:3 do:[:x |
  3123     0 to:3 do:[:x |
  3124         x even ifTrue:[
  3124 	x even ifTrue:[
  3125             dir := 1.
  3125 	    dir := 1.
  3126             start := 0.
  3126 	    start := 0.
  3127             end := 3.
  3127 	    end := 3.
  3128         ] ifFalse:[
  3128 	] ifFalse:[
  3129             dir := -1.
  3129 	    dir := -1.
  3130             start := 3.
  3130 	    start := 3.
  3131             end := 0.
  3131 	    end := 0.
  3132         ].
  3132 	].
  3133         start to:end by:dir do:[:y |
  3133 	start to:end by:dir do:[:y |
  3134             wantR := red + errR. 
  3134 	    wantR := red + errR. 
  3135             wantR > MaxValue ifTrue:[
  3135 	    wantR > MaxValue ifTrue:[
  3136                 wantR := MaxValue
  3136 		wantR := MaxValue
  3137             ] ifFalse:[ wantR < 0 ifTrue:[
  3137 	    ] ifFalse:[ wantR < 0 ifTrue:[
  3138                 wantR := 0
  3138 		wantR := 0
  3139             ]].
  3139 	    ]].
  3140 
  3140 
  3141             wantG := green + errG.
  3141 	    wantG := green + errG.
  3142             wantG > MaxValue ifTrue:[
  3142 	    wantG > MaxValue ifTrue:[
  3143                 wantG := MaxValue
  3143 		wantG := MaxValue
  3144             ] ifFalse:[ wantG < 0 ifTrue:[
  3144 	    ] ifFalse:[ wantG < 0 ifTrue:[
  3145                 wantG := 0
  3145 		wantG := 0
  3146             ]].
  3146 	    ]].
  3147 
  3147 
  3148             wantB := blue + errB.
  3148 	    wantB := blue + errB.
  3149             wantB > MaxValue ifTrue:[
  3149 	    wantB > MaxValue ifTrue:[
  3150                 wantB := MaxValue
  3150 		wantB := MaxValue
  3151             ] ifFalse:[ wantB < 0 ifTrue:[
  3151 	    ] ifFalse:[ wantB < 0 ifTrue:[
  3152                 wantB := 0
  3152 		wantB := 0
  3153             ]].
  3153 	    ]].
  3154 
  3154 
  3155             "find the nearest color"
  3155 	    "find the nearest color"
  3156 
  3156 
  3157 " "
  3157 " "
  3158             clr := Color quickNearestColorScaledRed:wantR scaledGreen:wantG scaledBlue:wantB on:aDevice.
  3158 	    clr := Color quickNearestColorScaledRed:wantR scaledGreen:wantG scaledBlue:wantB on:aDevice.
  3159 " "
  3159 " "
  3160 "
  3160 "
  3161             clr := Color nearestColorScaledRed:wantR green:wantG blue:wantB on:aDevice.
  3161 	    clr := Color nearestColorScaledRed:wantR green:wantG blue:wantB on:aDevice.
  3162 "
  3162 "
  3163             clr isNil ifTrue:[
  3163 	    clr isNil ifTrue:[
  3164                 clr := Color scaledRed:wantR scaledGreen:wantG scaledBlue:wantB.
  3164 		clr := Color scaledRed:wantR scaledGreen:wantG scaledBlue:wantB.
  3165                 clr brightness > 0.5 ifTrue:[
  3165 		clr brightness > 0.5 ifTrue:[
  3166                     clr := Color white on:aDevice
  3166 		    clr := Color white on:aDevice
  3167                 ] ifFalse:[
  3167 		] ifFalse:[
  3168                     clr := Color black on:aDevice
  3168 		    clr := Color black on:aDevice
  3169                 ]
  3169 		]
  3170 "
  3170 "
  3171                 ^ aBlock value:nil value:nil
  3171 		^ aBlock value:nil value:nil
  3172 "
  3172 "
  3173             ].
  3173 	    ].
  3174 
  3174 
  3175             f paint:clr.
  3175 	    f paint:clr.
  3176             f displayPointX:x y:y.
  3176 	    f displayPointX:x y:y.
  3177             map at:clr colorId + 1 put:clr.
  3177 	    map at:clr colorId + 1 put:clr.
  3178 
  3178 
  3179             "compute the new error"
  3179 	    "compute the new error"
  3180             errR := wantR - clr scaledRed.
  3180 	    errR := wantR - clr scaledRed.
  3181             errG := wantG - clr scaledGreen.
  3181 	    errG := wantG - clr scaledGreen.
  3182             errB := wantB - clr scaledBlue.
  3182 	    errB := wantB - clr scaledBlue.
  3183         ].
  3183 	].
  3184     ].
  3184     ].
  3185 
  3185 
  3186     f colorMap:map.
  3186     f colorMap:map.
  3187 "
  3187 "
  3188 'hard dither' printNewline.
  3188 'hard dither' printNewline.
  3617      lastIdx mx 
  3617      lastIdx mx 
  3618      dS   "{ Class: SmallInteger }"
  3618      dS   "{ Class: SmallInteger }"
  3619      cube|
  3619      cube|
  3620 
  3620 
  3621     (cube := aDevice fixColors) notNil ifTrue:[
  3621     (cube := aDevice fixColors) notNil ifTrue:[
  3622         dS := 4.
  3622 	dS := 4.
  3623 
  3623 
  3624         f := Form width:dS height:dS depth:(aDevice depth) on:aDevice.
  3624 	f := Form width:dS height:dS depth:(aDevice depth) on:aDevice.
  3625         f initGC.
  3625 	f initGC.
  3626 
  3626 
  3627         mx := MaxValue asFloat.
  3627 	mx := MaxValue asFloat.
  3628 
  3628 
  3629         nR := aDevice numFixRed.
  3629 	nR := aDevice numFixRed.
  3630         nG := aDevice numFixGreen.
  3630 	nG := aDevice numFixGreen.
  3631         nB := aDevice numFixBlue.
  3631 	nB := aDevice numFixBlue.
  3632 
  3632 
  3633         hR := nR // 2.
  3633 	hR := nR // 2.
  3634         hG := nG // 2.
  3634 	hG := nG // 2.
  3635         hB := nB // 2.
  3635 	hB := nB // 2.
  3636 
  3636 
  3637         eR := eG := eB := 0.
  3637 	eR := eG := eB := 0.
  3638         r := redVal.
  3638 	r := redVal.
  3639         g := greenVal.
  3639 	g := greenVal.
  3640         b := blueVal.
  3640 	b := blueVal.
  3641 
  3641 
  3642         step := -1.
  3642 	step := -1.
  3643 
  3643 
  3644         0 to:dS-1 do:[:y |
  3644 	0 to:dS-1 do:[:y |
  3645             step == -1 ifTrue:[
  3645 	    step == -1 ifTrue:[
  3646                 x1 := 0. x2 := dS-1. step := 1.
  3646 		x1 := 0. x2 := dS-1. step := 1.
  3647             ] ifFalse:[
  3647 	    ] ifFalse:[
  3648                 x1 := dS-1. x2 := 0. step := -1.
  3648 		x1 := dS-1. x2 := 0. step := -1.
  3649             ].
  3649 	    ].
  3650 
  3650 
  3651             x1 to:x2 by:step do:[:x |
  3651 	    x1 to:x2 by:step do:[:x |
  3652                 "/ the nearest along the grid
  3652 		"/ the nearest along the grid
  3653 
  3653 
  3654                 r := redVal + eR.
  3654 		r := redVal + eR.
  3655                 r > MaxValue ifTrue:[r := MaxValue]
  3655 		r > MaxValue ifTrue:[r := MaxValue]
  3656                              ifFalse:[r < 0 ifTrue:[r := 0]].
  3656 			     ifFalse:[r < 0 ifTrue:[r := 0]].
  3657                 g := greenVal + eG.
  3657 		g := greenVal + eG.
  3658                 g > MaxValue ifTrue:[g := MaxValue]
  3658 		g > MaxValue ifTrue:[g := MaxValue]
  3659                              ifFalse:[g < 0 ifTrue:[g := 0]].
  3659 			     ifFalse:[g < 0 ifTrue:[g := 0]].
  3660 
  3660 
  3661                 b := blueVal + eB.
  3661 		b := blueVal + eB.
  3662                 b > MaxValue ifTrue:[b := MaxValue]
  3662 		b > MaxValue ifTrue:[b := MaxValue]
  3663                              ifFalse:[b < 0 ifTrue:[b := 0]].
  3663 			     ifFalse:[b < 0 ifTrue:[b := 0]].
  3664 
  3664 
  3665                 rI := (r * (nR-1) + hR / mx) rounded.
  3665 		rI := (r * (nR-1) + hR / mx) rounded.
  3666                 gI := (g * (nG-1) + hG / mx) rounded .
  3666 		gI := (g * (nG-1) + hG / mx) rounded .
  3667                 bI := (b * (nB-1) + hB / mx) rounded .
  3667 		bI := (b * (nB-1) + hB / mx) rounded .
  3668 
  3668 
  3669                 idx := (((rI * nG) + gI) * nB + bI) + 1.
  3669 		idx := (((rI * nG) + gI) * nB + bI) + 1.
  3670                 clr := (cube at:idx) exactOn:aDevice.
  3670 		clr := (cube at:idx) exactOn:aDevice.
  3671                 lastIdx isNil ifTrue:[lastIdx := idx]
  3671 		lastIdx isNil ifTrue:[lastIdx := idx]
  3672                 ifFalse:[lastIdx ~~ idx ifTrue:[lastIdx := -1]].
  3672 		ifFalse:[lastIdx ~~ idx ifTrue:[lastIdx := -1]].
  3673 
  3673 
  3674                 f foreground:clr.
  3674 		f foreground:clr.
  3675                 f displayPointX:x y:y.
  3675 		f displayPointX:x y:y.
  3676 
  3676 
  3677                 eR := r  - clr scaledRed.
  3677 		eR := r  - clr scaledRed.
  3678                 eG := g  - clr scaledGreen.
  3678 		eG := g  - clr scaledGreen.
  3679                 eB := b  - clr scaledBlue.
  3679 		eB := b  - clr scaledBlue.
  3680             ].
  3680 	    ].
  3681         ].
  3681 	].
  3682         f releaseGC.
  3682 	f releaseGC.
  3683 
  3683 
  3684         lastIdx ~~ -1 ifTrue:[
  3684 	lastIdx ~~ -1 ifTrue:[
  3685             ^ aBlock value:clr value:nil
  3685 	    ^ aBlock value:clr value:nil
  3686         ].
  3686 	].
  3687         ^ aBlock value:nil value:f
  3687 	^ aBlock value:nil value:f
  3688 
  3688 
  3689     ].
  3689     ].
  3690 
  3690 
  3691     ^ aBlock value:nil value:nil
  3691     ^ aBlock value:nil value:nil
  3692 
  3692 
  3913 ! !
  3913 ! !
  3914 
  3914 
  3915 !Color  class methodsFor:'documentation'!
  3915 !Color  class methodsFor:'documentation'!
  3916 
  3916 
  3917 version
  3917 version
  3918     ^ '$Header: /cvs/stx/stx/libview/Color.st,v 1.71 1996-08-15 15:48:57 cg Exp $'
  3918     ^ '$Header: /cvs/stx/stx/libview/Color.st,v 1.72 1996-08-15 16:05:46 cg Exp $'
  3919 ! !
  3919 ! !
  3920 Color initialize!
  3920 Color initialize!