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