[squeak-dev] The Inbox: Graphics-mt.528.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Jul 14 14:12:57 UTC 2022


A new version of Graphics was added to project The Inbox:
http://source.squeak.org/inbox/Graphics-mt.528.mcz

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

Name: Graphics-mt.528
Author: mt
Time: 8 July 2022, 1:44:04.359615 pm
UUID: 35713805-bd5f-c745-9b83-a8d102feb209
Ancestors: Graphics-kfr.527

Avoid deprecation warning when trying to parse binary content into a Form via #fromFileNamed: or #fromBinaryStream:.

=============== Diff against Graphics-kfr.527 ===============

Item was removed:
- SystemOrganization addCategory: #'Graphics-Display Objects'!
- SystemOrganization addCategory: #'Graphics-External-Ffenestri'!
- SystemOrganization addCategory: #'Graphics-Files'!
- SystemOrganization addCategory: #'Graphics-Fonts'!
- SystemOrganization addCategory: #'Graphics-Primitives'!
- SystemOrganization addCategory: #'Graphics-Text'!
- SystemOrganization addCategory: #'Graphics-Transformations'!

Item was removed:
- Object subclass: #AbstractFont
- 	instanceVariableNames: ''
- 	classVariableNames: 'ForceNonSubPixelCount'
- 	poolDictionaries: ''
- 	category: 'Graphics-Fonts'!
- 
- !AbstractFont commentStamp: '<historical>' prior: 0!
- AbstractFont defines the generic interface that all fonts need to implement.!

Item was removed:
- ----- Method: AbstractFont class>>emphasisStringFor: (in category 'utilities') -----
- emphasisStringFor: emphasisCode
- 	"Answer a translated string that represents the attributes given in emphasisCode."
- 
- 	| emphases |
- 	emphasisCode = 0 ifTrue: [ ^'Normal' translated ].
- 
- 	emphases := #('Bold' 'Italic' 'Underlined' 'Narrow' 'StruckOut').
- 
- 	^String streamContents: [ :s |
- 		1 to: emphases size do: [ :i |
- 			(emphasisCode bitAt: i) isZero ifFalse: [ s nextPutAll: (emphases at: i) translated; space ] ].
- 		s position isZero ifFalse: [ s skip: -1 ] ]!

Item was removed:
- ----- Method: AbstractFont class>>forceNonSubPixelCount (in category 'utilities') -----
- forceNonSubPixelCount
- 	"Answer the force non-subpixel count"
- 	^ForceNonSubPixelCount ifNil:[ForceNonSubPixelCount := 0]!

Item was removed:
- ----- Method: AbstractFont class>>forceNonSubPixelDuring: (in category 'utilities') -----
- forceNonSubPixelDuring: aBlock
- 	"Forces all font rendering to suppress subpixel anti-aliasing during the execution of aBlock"
- 	ForceNonSubPixelCount ifNil:[ForceNonSubPixelCount := 0].
- 	ForceNonSubPixelCount := ForceNonSubPixelCount + 1.
- 	aBlock ensure:[ForceNonSubPixelCount := ForceNonSubPixelCount - 1]!

Item was removed:
- ----- Method: AbstractFont>>approxWidthOfText: (in category 'measuring') -----
- approxWidthOfText: aText
- "Return the width of aText -- quickly, and a little bit dirty. Used by lists morphs containing Text objects to get a quick, fairly accurate measure of the width of a list item."
- 
-     | w |
-     
-     (aText isNil or: [aText size = 0 ])
-         ifTrue:[^0].
-        
-     w := self
-         widthOfString: aText asString.
- 
-      "If the text has no emphasis, just return the string size.  If it is empasized, 
-     just approximate the width by adding about 20% to the width"   
-     (((aText runLengthFor: 1) = aText size)
-         and: [(aText emphasisAt: 1) = 0 ])
-             ifTrue:[^w]
-             ifFalse:[ ^w * 6 // 5 ]. !

Item was removed:
- ----- Method: AbstractFont>>asNewTextStyle (in category 'converting') -----
- asNewTextStyle
- 	"Answer a new text style where the receiver is the default font. Try to lookup the an existing #textStyle so that TextFontChange can be used in views."
- 	
- 	| newTextStyle |
- 	newTextStyle := self textStyleOrNil
- 		ifNil: [TextStyle fontArray: {self}]
- 		ifNotNil: [:style | style copy].
- 	newTextStyle defaultFontIndex: (newTextStyle fontIndexOfPointSize: self pointSize).	
- 	^ newTextStyle!

Item was removed:
- ----- Method: AbstractFont>>asPointSize: (in category 'converting') -----
- asPointSize: differentPointSize
- 	"Convert the receiver into a different point size. Compared to #pointSize:, this operation does not modify the receiver but tries to lookup another font object or create one on-the-fly."
- 
- 	self pointSize = differentPointSize ifTrue: [^ self].
- 
- 	^ self class
- 		familyName: self familyName
- 		pointSize: differentPointSize
- 		emphasized: self emphasis!

Item was removed:
- ----- Method: AbstractFont>>asRegular (in category 'converting') -----
- asRegular
- 	"Try to lookup the receiver with normal emphasis. If the receiver itself looks bold face, this might be okay. Rely on what is registered on the font family's text style. Not that this is different from #emphasized: with 0, which does nothing."
- 	
- 	self emphasis = 0 ifTrue: [^ self].
- 	^ self textStyleOrNil
- 		ifNil: [self]
- 		ifNotNil: [:style | style fontOfPointSize: self pointSize]!

Item was removed:
- ----- Method: AbstractFont>>ascent (in category 'accessing') -----
- ascent
- 
- 	self subclassResponsibility.
- !

Item was removed:
- ----- Method: AbstractFont>>ascentOf: (in category 'accessing') -----
- ascentOf: aCharacter
- 
- 	^ self ascent.
- !

Item was removed:
- ----- Method: AbstractFont>>baseKern (in category 'accessing') -----
- baseKern
- 	^0!

Item was removed:
- ----- Method: AbstractFont>>basicAscentOf: (in category 'accessing') -----
- basicAscentOf: aCharacter
- 
- 	^ self ascent.
- !

Item was removed:
- ----- Method: AbstractFont>>basicDescentOf: (in category 'accessing') -----
- basicDescentOf: aCharacter
- 
- 	^ self descent.
- !

Item was removed:
- ----- Method: AbstractFont>>basicHasGlyphOf: (in category 'testing') -----
- basicHasGlyphOf: aCharacter
- 
- 	self subclassResponsibility!

Item was removed:
- ----- Method: AbstractFont>>characterFormAt: (in category 'character shapes') -----
- characterFormAt: aCharacter
- 
- 	self subclassResponsibility.!

Item was removed:
- ----- Method: AbstractFont>>characterToGlyphMap (in category 'accessing') -----
- characterToGlyphMap
- 	"Return the character to glyph mapping table. If the table is not provided the character scanner will query the font directly for the width of each individual character."
- 	^nil!

Item was removed:
- ----- Method: AbstractFont>>depth (in category 'accessing') -----
- depth
- 	"Returns the glyphs' color depth."
- 	
- 	self subclassResponsibility.!

Item was removed:
- ----- Method: AbstractFont>>derivativeFonts (in category 'accessing') -----
- derivativeFonts
- 	^#()!

Item was removed:
- ----- Method: AbstractFont>>descent (in category 'accessing') -----
- descent
- 
- 	self subclassResponsibility.
- !

Item was removed:
- ----- Method: AbstractFont>>descentOf: (in category 'accessing') -----
- descentOf: aCharacter
- 
- 	^ self descent.
- !

Item was removed:
- ----- Method: AbstractFont>>displayStrikeoutOn:from:to: (in category 'displaying') -----
- displayStrikeoutOn: aDisplayContext from: baselineStartPoint to: baselineEndPoint
- 	"display the strikeout if appropriate for the receiver"!

Item was removed:
- ----- Method: AbstractFont>>displayString:on:from:to:at:kern: (in category 'displaying') -----
- displayString: aString on: aDisplayContext from: startIndex to: stopIndex at: aPoint kern: kernDelta
- 	"Draw the given string from startIndex to stopIndex 
- 	at aPoint on the (already prepared) display context."
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: AbstractFont>>displayString:on:from:to:at:kern:baselineY: (in category 'displaying') -----
- displayString: aString on: aDisplayContext from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY
- 	"Draw the given string from startIndex to stopIndex 
- 	at aPoint on the (already prepared) display context."
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: AbstractFont>>displayString:on:from:to:at:kern:from:baselineY: (in category 'displaying') -----
- displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta from: fromFont baselineY: baselineY
- 	"I am used as a fallback for fromFont. I should install myself on aBitBlt. The default implementation does not do that but directly uses my usual displaying method."
- 	
- 	self flag: #subclassResponsibility. "mt: Something like #installStrikeFont: or #installTTCFont:."
- 	^ self displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY!

Item was removed:
- ----- Method: AbstractFont>>displayUnderlineOn:from:to: (in category 'displaying') -----
- displayUnderlineOn: aDisplayContext from: baselineStartPoint to: baselineEndPoint
- 	"display the underline if appropriate for the receiver"!

Item was removed:
- ----- Method: AbstractFont>>emphasis (in category 'accessing') -----
- emphasis
- 
- 	^ 0!

Item was removed:
- ----- Method: AbstractFont>>emphasisString (in category 'accessing') -----
- emphasisString
- 	"Answer a translated string that represents the receiver's emphasis."
- 	
- 	^self emphasisStringFor: self emphasis!

Item was removed:
- ----- Method: AbstractFont>>emphasisStringFor: (in category 'accessing') -----
- emphasisStringFor: emphasisCode
- 	"Answer a translated string that represents the attributes given in emphasisCode."
- 	
- 	^self class emphasisStringFor: emphasisCode!

Item was removed:
- ----- Method: AbstractFont>>fallbackFont (in category 'accessing') -----
- fallbackFont
- 	"Answers the fallbackFont for the receiver. Try to use the #defaultFallback but for itself use a synthetic font that maps all characters to question marks."
- 
- 	^ TextStyle defaultFallback textStyleName = self textStyleName
- 		ifTrue: [
- 			FixedFaceFont new errorFont baseFont: self]
- 		ifFalse: [
- 			(TextStyle defaultFallbackFont
- 				emphasized: self emphasis)
- 				asPointSize: self pointSize]!

Item was removed:
- ----- Method: AbstractFont>>fallbackFont: (in category 'initialize-release') -----
- fallbackFont: aFont
- 	"Reset fallback font. Ignore. See #fallbackFont."!

Item was removed:
- ----- Method: AbstractFont>>fallbackTextStyle: (in category 'initialize-release') -----
- fallbackTextStyle: aTextStyle
- 
- "	| fonts f |
- 	fonts := aTextStyle fontArray.
- 	f := fonts first.
- 	f familyName = self familyName ifTrue: [^ self].
- 	1 to: fonts size do: [:i |
- 		self height > (fonts at: i) height ifTrue: [f := fonts at: i].
- 	]."
- 
- 	| fontsToUpdate |
- 	fontsToUpdate := self textStyleOrNil
- 		ifNil: [{self} "not-yet-installed"]
- 		ifNotNil: [:style | style fontArray "all point sizes"].
- 	
- 	fontsToUpdate do: [:font |  "All subfamilies / emphases"
- 		font privateFallbackTextStyle: aTextStyle.
- 		font derivativeFonts do: [:f | f privateFallbackTextStyle: aTextStyle ]].!

Item was removed:
- ----- Method: AbstractFont>>familyName (in category 'accessing') -----
- familyName
- 	"Answer the name to be used as a key in the TextConstants dictionary."
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: AbstractFont>>foregroundColor (in category 'displaying') -----
- foregroundColor
- 	
- 	^ Color black!

Item was removed:
- ----- Method: AbstractFont>>foregroundColor: (in category 'displaying') -----
- foregroundColor: fgColor
- 	"Install the given foreground color. This does nothing for other than TrueType fonts. In StrikeFonts, color installation is bound to BitBlt."!

Item was removed:
- ----- Method: AbstractFont>>formOf: (in category 'character shapes') -----
- formOf: aCharacter
- 
- 	self subclassResponsibility.!

Item was removed:
- ----- Method: AbstractFont>>hasDistinctGlyphsForAll: (in category 'testing') -----
- hasDistinctGlyphsForAll: asciiString
- 	"Answer true if the receiver has glyphs for all the characters
- 	in asciiString and no single glyph is shared by more than one character, false otherwise.
- 	The default behaviour is to answer true, but subclasses may reimplement"
- 	
- 	^true!

Item was removed:
- ----- Method: AbstractFont>>hasFixedWidth (in category 'testing') -----
- hasFixedWidth
- 	"Answer whether the receiver is a monospaced/fixed-width/non-proportional font. See TextStyle class >> #defaultFixed."
- 
- 	^ (self widthOf: $.) = (self widthOf: $w)!

Item was removed:
- ----- Method: AbstractFont>>hasGlyphOf: (in category 'testing') -----
- hasGlyphOf: aCharacter
- 
- 	^ self basicHasGlyphOf: aCharacter!

Item was removed:
- ----- Method: AbstractFont>>hasGlyphsForAll: (in category 'testing') -----
- hasGlyphsForAll: asciiString
- 	"Answer true if the receiver has glyphs for all the characters
- 	in asciiString, false otherwise.
- 	The default behaviour is to answer true, but subclasses may reimplement"
- 	
- 	^true!

Item was removed:
- ----- Method: AbstractFont>>height (in category 'accessing') -----
- height
- 	"Answer the height of the receiver, total of maximum extents of 
- 	characters above and below the baseline."
- 
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: AbstractFont>>installOn:foregroundColor:backgroundColor: (in category 'displaying') -----
- installOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor
- 	"Install the receiver on the given DisplayContext (either BitBlt or Canvas) for further drawing operations."
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: AbstractFont>>isFontSet (in category 'testing') -----
- isFontSet
- 
- 	^ false.
- !

Item was removed:
- ----- Method: AbstractFont>>isPairKerningCapable (in category 'testing') -----
- isPairKerningCapable
- "a hopefully temporary test method; better factoring of scan/measure/display should remove the need for it.
- Only FreeType fonts would currently add this to return true"
- 	^false!

Item was removed:
- ----- Method: AbstractFont>>isRegular (in category 'testing') -----
- isRegular
- 	^false!

Item was removed:
- ----- Method: AbstractFont>>isSubPixelPositioned (in category 'testing') -----
- isSubPixelPositioned
- 	"Answer true if the receiver is currently using subpixel positioned
- 	glyphs, false otherwise. This affects how padded space sizes are calculated
- 	when composing text. 
- 	Currently, only FreeTypeFonts are subPixelPositioned, and only when not
- 	Hinted"
- 	
- 	^false !

Item was removed:
- ----- Method: AbstractFont>>isSymbolFont (in category 'testing') -----
- isSymbolFont
- 	"Answer true if the receiver is a Symbol font, false otherwise.
- 	The default is to answer false, subclasses can reimplement"
- 	
- 	^false!

Item was removed:
- ----- Method: AbstractFont>>isSynthetic (in category 'testing') -----
- isSynthetic
- 	^ false!

Item was removed:
- ----- Method: AbstractFont>>isTTCFont (in category 'testing') -----
- isTTCFont
- 	^false!

Item was removed:
- ----- Method: AbstractFont>>kerningLeft:right: (in category 'kerning') -----
- kerningLeft: leftChar right: rightChar
- 	^0!

Item was removed:
- ----- Method: AbstractFont>>larger (in category 'converting') -----
- larger
- 	"Answer a font that is about 20% larger than the receiver but has the same font family and emphasis. Round to 0.5 points to not yield so many different font instances."
- 	
- 	^ self asPointSize: ((self pointSize asFloat * 1.2) roundTo: 0.5)!

Item was removed:
- ----- Method: AbstractFont>>lineGap (in category 'accessing') -----
- lineGap
- 
- 	^ 2 "pre-rendered legacy fonts"!

Item was removed:
- ----- Method: AbstractFont>>lineGapSlice (in category 'accessing') -----
- lineGapSlice
- 
- 	^ 1 "pre-rendered legacy fonts"!

Item was removed:
- ----- Method: AbstractFont>>lineGrid (in category 'accessing') -----
- lineGrid
- 	"Answer the relative space between lines"
- 
- 	^ self height + self lineGap!

Item was removed:
- ----- Method: AbstractFont>>linearWidthOf: (in category 'measuring') -----
- linearWidthOf: aCharacter
- 	"This is the scaled, unrounded advance width."
- 	^self widthOf: aCharacter!

Item was removed:
- ----- Method: AbstractFont>>maxAscii (in category 'accessing') -----
- maxAscii
- 
- 	self flag: #deprecated.
- 	^ self maxCodePoint!

Item was removed:
- ----- Method: AbstractFont>>maxCodePoint (in category 'accessing') -----
- maxCodePoint
- 	"Answer the largest code point that the receiver can translate into glyphs. Use the range from #minCodePoint to #maxCodePoint to configure a list of #fallbackFont's. Note that subclasses may insert 'holes' via #hasGlyphOf: test such as StrikeFont's internal xTable."
- 	
- 	^ 16r10FFFF "Unicode uses 21-bit but 16r110000 to 16r1FFFFF are not valid code points. See https://www.unicode.org/versions/stats/."!

Item was removed:
- ----- Method: AbstractFont>>minAscii (in category 'accessing') -----
- minAscii
- 
- 	self flag: #deprecated.
- 	^ self minCodePoint!

Item was removed:
- ----- Method: AbstractFont>>minCodePoint (in category 'accessing') -----
- minCodePoint
- 	"Answer the smallest code point that the receiver can translate into glyphs. Use the range from #minCodePoint to #maxCodePoint to configure a list of #fallbackFont's. Note that subclasses may insert 'holes' via #hasGlyphOf: test such as StrikeFont's internal xTable."
- 	
- 	^ 0!

Item was removed:
- ----- Method: AbstractFont>>pixelSize (in category 'accessing') -----
- pixelSize
- 	"Make sure that we don't return a Fraction"
- 	^ (TextStyle pointsToPixels: self pointSize) rounded!

Item was removed:
- ----- Method: AbstractFont>>pixelsPerInch (in category 'accessing') -----
- pixelsPerInch
- 	"Answers the PPI reference for the pre-rendered receiver."
- 	
- 	^ (self height * 72 / self pointSize asFloat) rounded!

Item was removed:
- ----- Method: AbstractFont>>pixelsPerInchChanged (in category 'notifications') -----
- pixelsPerInchChanged
- 	"The definition of TextStyle class>>pixelsPerInch has changed. Do whatever is necessary."!

Item was removed:
- ----- Method: AbstractFont>>pointSize (in category 'accessing') -----
- pointSize
- 	self subclassResponsibility.!

Item was removed:
- ----- Method: AbstractFont>>printShortDescriptionOn: (in category 'printing') -----
- printShortDescriptionOn: aStream
- 	aStream nextPutAll: self familyName!

Item was removed:
- ----- Method: AbstractFont>>privateFallbackTextStyle: (in category 'initialize-release') -----
- privateFallbackTextStyle: aTextStyleOrNil
- 
- 	self fallbackFont: nil. "Rely on lazy initialization of #fallbackFont."!

Item was removed:
- ----- Method: AbstractFont>>releaseCachedState (in category 'caching') -----
- releaseCachedState
- 	!

Item was removed:
- ----- Method: AbstractFont>>reset (in category 'initialize-release') -----
- reset
- 	"Clear all caches."!

Item was removed:
- ----- Method: AbstractFont>>sampleText (in category 'example') -----
- sampleText
- 
- 	| text |
- 	text := self isSymbolFont
- 		ifTrue: [self symbolSample asText]
- 		ifFalse: [Text textSample].
- 	text addAttribute: (TextFontReference toFont: self).
- 	^ text!

Item was removed:
- ----- Method: AbstractFont>>scanByteCharactersFrom:to:in:with:rightX: (in category 'character scanning') -----
- scanByteCharactersFrom: startIndex to: stopIndex in: aByteString with: aCharacterScanner rightX: rightX
- 	"scan a single byte character string"
- 	^aCharacterScanner scanByteCharactersFrom: startIndex to: stopIndex in: aByteString rightX: rightX!

Item was removed:
- ----- Method: AbstractFont>>scanMultibyteCharactersFrom:to:in:with:rightX: (in category 'character scanning') -----
- scanMultibyteCharactersFrom: startIndex to: stopIndex in: aWideString with: aCharacterScanner rightX: rightX
- 	"scan a multibyte character string"
- 	^aCharacterScanner scanMultibyteCharactersFrom: startIndex to: stopIndex in: aWideString rightX: rightX !

Item was removed:
- ----- Method: AbstractFont>>scanMultibyteJapaneseCharactersFrom:to:in:with:rightX: (in category 'character scanning') -----
- scanMultibyteJapaneseCharactersFrom: startIndex to: stopIndex in: aWideString with: aCharacterScanner rightX: rightX
- 	"scan a multibyte Japanese character string"
- 	^aCharacterScanner scanJapaneseCharactersFrom: startIndex to: stopIndex in: aWideString rightX: rightX 
- !

Item was removed:
- ----- Method: AbstractFont>>smaller (in category 'converting') -----
- smaller
- 	"Answer a font that is about 20% smaller than the receiver but has the same font family and emphasis. Round to 0.5 points to not yield so many different font instances."
- 
- 	^ self asPointSize: ((self pointSize asFloat * 0.8) roundTo: 0.5)!

Item was removed:
- ----- Method: AbstractFont>>subfamilyName (in category 'accessing') -----
- subfamilyName
- 
- 	^ self emphasisString!

Item was removed:
- ----- Method: AbstractFont>>symbolSample (in category 'example') -----
- symbolSample
- 	"Variation of Text class >> #symbolSample, which uses the receiver's available code points. This is important for fonts such as Wingdings."
- 	
- 	^ String streamContents: [:stream | | start lineLength character |
- 		lineLength := 0.
- 		(start := self minCodePoint max: 33) to: (self maxCodePoint min: start + 200) do: [:codePoint |
- 			(self hasGlyphOf: (character := Character value: codePoint))
- 				ifTrue: [stream nextPut: character.
- 					((lineLength := lineLength + 1) > 30) ifTrue: [
- 						lineLength := 0.
- 						stream cr]]]]!

Item was removed:
- ----- Method: AbstractFont>>textStyle (in category 'accessing') -----
- textStyle
- 	"Answer an instance of TextStyle that (most likely) includes the receiver. Note that if the receiver is used in more than one style, only answer the most prominent one."
- 
- 	^ self textStyleOrNil ifNil: [TextStyle fontArray: {self}]!

Item was removed:
- ----- Method: AbstractFont>>textStyleName (in category 'accessing') -----
- textStyleName
- 	"Answer the name to be used as a key in the TextConstants dictionary."
- 	^self familyName!

Item was removed:
- ----- Method: AbstractFont>>textStyleOrNil (in category 'accessing') -----
- textStyleOrNil
- 	"Like #textStyle but avoid creating a new style for orphaned fonts."
- 
- 	^ TextStyle named: self textStyleName!

Item was removed:
- ----- Method: AbstractFont>>widthAndKernedWidthOfLeft:right:into: (in category 'kerning') -----
- widthAndKernedWidthOfLeft: leftCharacter right: rightCharacterOrNil into: aTwoElementArray
- 	"Set the first element of aTwoElementArray to the width of leftCharacter and 
- 	the second element to the width of left character when kerned with
- 	rightCharacterOrNil. Answer aTwoElementArray"
- 	"Actually, nearly all users of this actually want just the widthOf the leftCharacter, so we will default to that for speed. See other implementations for more complex cases"
- 
- 	| w |
- 	w := self widthOf: leftCharacter.
- 	aTwoElementArray at: 1 put: w.
- 	aTwoElementArray at: 2 put: w
- 
- "	The old code, and what fonts which have pair-kerning would use - 
- 	w := self widthOf: leftCharacter.
- 	rightCharacterOrNil isNil
- 		ifTrue:[
- 			aTwoElementArray 
- 				at: 1 put: w; 
- 				at: 2 put: w]
- 		ifFalse:[
- 			k := self kerningLeft: leftCharacter right: rightCharacterOrNil.
- 			aTwoElementArray 
- 				at: 1 put: w; 
- 				at: 2 put: w+k].
- 	^aTwoElementArray
- "	!

Item was removed:
- ----- Method: AbstractFont>>widthOf: (in category 'measuring') -----
- widthOf: aCharacter
- 	"Return the width of the given character"
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: AbstractFont>>widthOfByteCharacter: (in category 'measuring') -----
- widthOfByteCharacter: aCharacter
- 	"Return the width of the given character whose codePoint is <= 16rFF."
- 
- 	^ self widthOf: aCharacter!

Item was removed:
- ----- Method: AbstractFont>>widthOfString: (in category 'measuring') -----
- widthOfString: aString
- 	aString ifNil:[^0].
- 	^self widthOfString: aString from: 1 to: aString size.
- "
- 	TextStyle default defaultFont widthOfString: 'zort' 21
- "!

Item was removed:
- ----- Method: AbstractFont>>widthOfString:from:to: (in category 'measuring') -----
- widthOfString: aString from: startIndex to: stopIndex
- 	"Measure the length of the given string between start and stop index."
- 
- 	| resultX |
- 	resultX := 0.
- 	startIndex to: stopIndex do: [:i | 
- 		resultX := resultX + (self widthOf: (aString at: i))].
- 	^ resultX
- 	
- "TODO: Use scanner to support kerning.
- CharacterScanner new
- 	measureString: asString inFont: self
- 	from: startIndex to: stopIndex
- "!

Item was removed:
- ----- Method: AbstractFont>>widthOfStringOrText: (in category 'measuring') -----
- widthOfStringOrText: aStringOrText
-     aStringOrText ifNil:[^0].
-     ^aStringOrText isText
-         ifTrue:[self approxWidthOfText: aStringOrText ]
-         ifFalse:[self widthOfString: aStringOrText ] !

Item was removed:
- ----- Method: AbstractFont>>xTable (in category 'accessing') -----
- xTable
- 	"Return the xTable for the font. The xTable defines the left x-value for each individual glyph in the receiver. If such a table is not provided, the character scanner will ask the font directly for the appropriate width of each individual character."
- 	^nil!

Item was removed:
- GIFReadWriter subclass: #AnimatedGIFReadWriter
- 	instanceVariableNames: 'forms delays comments'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!

Item was removed:
- ----- Method: AnimatedGIFReadWriter class>>basicNew (in category 'instance creation') -----
- basicNew
- 	"Notify that the class is being deprecated."
- 	self deprecated: 'This class is deprecated. Its functionality can be found in the regular GIFReadWriter class instead.'.
- 	^ super basicNew
- 	!

Item was removed:
- ----- Method: AnimatedGIFReadWriter class>>formsFromFileNamed: (in category 'image reading/writing') -----
- formsFromFileNamed: fileName 
- 	| stream |
- 	stream := FileStream readOnlyFileNamed: fileName.
- 	^ self formsFromStream: stream!

Item was removed:
- ----- Method: AnimatedGIFReadWriter class>>formsFromStream: (in category 'image reading/writing') -----
- formsFromStream: stream 
- 	| reader |
- 	reader := self new on: stream reset.
- 	Cursor read
- 		showWhile: [reader allImages.
- 			reader close].
- 	^reader!

Item was removed:
- ----- Method: AnimatedGIFReadWriter class>>typicalFileExtensions (in category 'image reading/writing') -----
- typicalFileExtensions
- 	"Answer a collection of file extensions (lowercase) which files that I can read might commonly have"
- 	^#()!

Item was removed:
- ----- Method: AnimatedGIFReadWriter class>>wantsToHandleGIFs (in category 'image reading/writing') -----
- wantsToHandleGIFs
- 	^ false!

Item was removed:
- ----- Method: AnimatedGIFReadWriter>>allImages (in category 'accessing') -----
- allImages
- 	| body colorTable |
- 	localColorTable := nil.
- 	forms := OrderedCollection new.
- 	delays := OrderedCollection new.
- 	comments := OrderedCollection new.
- 	self readHeader.
- 	[(body := self readBody) == nil]
- 		whileFalse: [colorTable := localColorTable
- 						ifNil: [colorPalette].
- 			transparentIndex
- 				ifNotNil: [transparentIndex + 1 > colorTable size
- 						ifTrue: [colorTable := colorTable forceTo: transparentIndex + 1 paddingWith: Color white].
- 					colorTable at: transparentIndex + 1 put: Color transparent].
- 			body colors: colorTable.
- 			forms add: body].
- 	^ forms!

Item was removed:
- ----- Method: AnimatedGIFReadWriter>>comment: (in category 'private') -----
- comment: aString
- 	comments add: aString!

Item was removed:
- ----- Method: AnimatedGIFReadWriter>>delays (in category 'accessing') -----
- delays
- 	^ delays!

Item was removed:
- ----- Method: AnimatedGIFReadWriter>>forms (in category 'accessing') -----
- forms
- 	^ forms!

Item was removed:
- ----- Method: AnimatedGIFReadWriter>>readBitData (in category 'private-decoding') -----
- readBitData
- 	| form |
- 	form := super readBitData.
- 	form offset: offset.
- 	^form!

Item was removed:
- Object subclass: #AnimatedImageFrame
- 	instanceVariableNames: 'form delay disposal offset interlace'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!
- 
- !AnimatedImageFrame commentStamp: '' prior: 0!
- I am a single frame in a sequence of frames that comprise an animated image. I am designed for use by classes like AnimatedImageMorph and am created during the reading of some image files such as GIFs (see GIFReadWriter).
- 
- I contain a Form describing my image, a delay time in milliseconds that describes how long I should be displayed in a sequence of animated frames, and a disposal symbol that implementors can use when compositing myself in a sequence of frames. 
- 
- See AnimatedImageMorph for examples of how I am used.!

Item was removed:
- ----- Method: AnimatedImageFrame>>defaultDelay (in category 'defaults') -----
- defaultDelay
- 	^ 66!

Item was removed:
- ----- Method: AnimatedImageFrame>>delay (in category 'accessing') -----
- delay
- 	^ delay!

Item was removed:
- ----- Method: AnimatedImageFrame>>delay: (in category 'accessing') -----
- delay: aNumber
- 	delay := aNumber!

Item was removed:
- ----- Method: AnimatedImageFrame>>disposal (in category 'accessing') -----
- disposal
- 	^ disposal!

Item was removed:
- ----- Method: AnimatedImageFrame>>disposal: (in category 'accessing') -----
- disposal: aSymbol
- 	"Disposal must be one of:
- 		#restoreBackground
- 		#leaveCurrent
- 		#restorePreviousState"
- 	"({ #restoreBackground.
- 		#leaveCurrent.
- 		#restorePreviousState } includes: aSymbol) ifTrue: [ 
- 			disposal := aSymbol ]."
- 	disposal := aSymbol!

Item was removed:
- ----- Method: AnimatedImageFrame>>form (in category 'accessing') -----
- form
- 	^ form!

Item was removed:
- ----- Method: AnimatedImageFrame>>form: (in category 'accessing') -----
- form: aForm
- 	form := aForm!

Item was removed:
- ----- Method: AnimatedImageFrame>>initialize (in category 'initialization') -----
- initialize
- 	super initialize.
- 	offset := 0 @ 0.
- 	delay := self defaultDelay.
- 	disposal := #otherDisposal.
- 	interlace := false!

Item was removed:
- ----- Method: AnimatedImageFrame>>interlace (in category 'accessing') -----
- interlace
- 	^ interlace!

Item was removed:
- ----- Method: AnimatedImageFrame>>interlace: (in category 'accessing') -----
- interlace: aBoolean
- 	interlace := aBoolean!

Item was removed:
- ----- Method: AnimatedImageFrame>>offset (in category 'accessing') -----
- offset
- 	^ offset!

Item was removed:
- ----- Method: AnimatedImageFrame>>offset: (in category 'accessing') -----
- offset: aPoint
- 	"This represents the frame form's offset in the
- 	parent image canvas"
- 	offset := aPoint!

Item was removed:
- Object subclass: #BDFFontReader
- 	instanceVariableNames: 'file properties'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Fonts'!
- 
- !BDFFontReader commentStamp: '<historical>' prior: 0!
- I am a conversion utility for reading X11 Bitmap Distribution Format fonts.  My code is derived from the multilingual Squeak changeset written by OHSHIMA Yoshiki (ohshima at is.titech.ac.jp), although all support for fonts with more than 256 glyphs has been ripped out.  See http://www.is.titech.ac.jp/~ohshima/squeak/squeak-multilingual-e.html .
- 
- My class methods contain tools for fetching BDF source files from a well-known archive site, batch conversion to Squeak's .sf2 format, and installation of these fonts as TextStyles.  Also, the legal notices for the standard 75dpi fonts I process this way are included as "x11FontLegalNotices'.!

Item was removed:
- ----- Method: BDFFontReader class>>convertFilesNamed:toFamilyNamed:inDirectoryNamed: (in category 'file creation') -----
- convertFilesNamed: fileName toFamilyNamed: familyName inDirectoryNamed: dirName
- 		"BDFFontReader convertFilesNamed: 'helvR' toFamilyNamed: 'Helvetica' inDirectoryNamed: '' "
- 
- 	"This utility converts X11 BDF font files to Squeak .sf2 StrikeFont files."
- 
- 	"For this utility to work as is, the BDF files must be named 'familyNN.bdf',
- 	and must reside in the directory named by dirName (use '' for the current directory).
- 	The output StrikeFont files will be named familyNN.sf2, and will be placed in the
- 	current directory."
- 
- 	| allFontNames dir |
- 	"Check for matching file names."
- 	dir := dirName isEmpty
- 		ifTrue: [FileDirectory default]
- 		ifFalse: [FileDirectory default directoryNamed: dirName].
- 	allFontNames := dir fileNamesMatching: fileName , '##.bdf'.
- 	allFontNames isEmpty ifTrue: [^ self error: 'No files found like ' , fileName , 'NN.bdf'].
- 	
- 	UIManager default informUserDuring: [:info |
- 		allFontNames do: [:fname | | f sizeChars | 
- 			info value: 'Converting ', familyName, ' BDF file ', fname, ' to SF2 format'.
- 			sizeChars := (fname copyFrom: fileName size + 1 to: fname size) copyUpTo: $. .
- 
- 			f := StrikeFont new readBDFFromFile: (dir fullNameFor: fname) name: familyName, sizeChars.
- 			f writeAsStrike2named: familyName, sizeChars, '.sf2'.
- 		].
- 	]!

Item was removed:
- ----- Method: BDFFontReader class>>convertX11FontsToStrike2 (in category 'resource download') -----
- convertX11FontsToStrike2  "BDFFontReader convertX11FontsToStrike2"
- 	"Given a set of standard X11 BDF font files (probably downloaded via BDFFontReader downloadFonts), produce .sf2 format fonts.  The source and destination directory is the current directory."
- 
- 	"Charter currently tickles a bug in the BDF parser.  Skip it for now."
- 	"self convertFilesNamed: 'charR' toFamilyNamed: 'Charter' inDirectoryNamed: ''."
- 
- 	self convertFilesNamed: 'courR' toFamilyNamed: 'Courier' inDirectoryNamed: ''.
- 	self convertFilesNamed: 'helvR' toFamilyNamed: 'Helvetica' inDirectoryNamed: ''.
- 
- 	self convertFilesNamed: 'lubR' toFamilyNamed: 'LucidaBright' inDirectoryNamed: ''.
- 	self convertFilesNamed: 'luRS' toFamilyNamed: 'Lucida' inDirectoryNamed: ''.
- 	self convertFilesNamed: 'lutRS' toFamilyNamed: 'LucidaTypewriter' inDirectoryNamed: ''.
- 
- 	self convertFilesNamed: 'ncenR' toFamilyNamed: 'NewCenturySchoolbook' inDirectoryNamed: ''.
- 	self convertFilesNamed: 'timR' toFamilyNamed: 'TimesRoman' inDirectoryNamed: ''.!

Item was removed:
- ----- Method: BDFFontReader class>>downloadFonts (in category 'resource download') -----
- downloadFonts  "BDFFontReader downloadFonts"
- 	"Download a standard set of BDF sources from x.org.  
- 	The combined size of these source files is around 1.2M; after conversion 
- 	to .sf2 format they may be deleted."
- 
- 	| heads tails filenames baseUrl basePath |
- 	heads := #( 'charR' 'courR' 'helvR' 'lubR' 'luRS' 'lutRS' 'ncenR' 'timR' ).
- 	tails := #( '08' '10' '12' '14' '18' '24').
- 
- 	filenames := OrderedCollection new.
- 	heads do: [:head |
- 		filenames addAll: (tails collect: [:tail | head , tail , '.bdf'])
- 	].
- 	baseUrl := 'http://cvsweb.xfree86.org/cvsweb/*checkout*/xc/fonts/bdf/75dpi/' asUrl.
- 	basePath := baseUrl path.
- 
- 	filenames do: [:filename |
- 		| document newPath newUrl |
- 		newUrl := baseUrl shallowCopy.
- 		newPath := OrderedCollection newFrom: basePath.
- 
- 		newPath addLast: filename.
- 		newUrl path: newPath.
- 
- 		UIManager default informUser: 'Fetching ' , filename during: 
- 			[document := newUrl retrieveContents].
- 
- 		MultiByteFileStream newFileNamed: filename do: [ :f |
- 			f 
- 				wantsLineEndConversion: true;
- 				nextPutAll: document content ]
- 	].
- !

Item was removed:
- ----- Method: BDFFontReader class>>gettingAndInstallingTheFonts (in category 'documentation') -----
- gettingAndInstallingTheFonts
- 
- 	"Download the 1.3M of BDF font source files from x.org:
- 
- 		BDFFontReader downloadFonts.
- 
- 	Convert them to .sf2 StrikeFont files:
- 
- 		BDFFontReader convertX11FontsToStrike2.
- 
- 	Install them into the system as TextStyles:
- 
- 		BDFFontReader installX11Fonts.
- 
- 	Read the legal notices in 'BDFFontReader x11FontLegalNotices' before
- 	redistributing images containing these fonts."!

Item was removed:
- ----- Method: BDFFontReader class>>installX11Fonts (in category 'resource download') -----
- installX11Fonts "BDFFontReader installX11Fonts"
- 	"Installs previously-converted .sf2 fonts into the TextConstants dictionary.  This makes them available as TextStyles everywhere in the image."
- 
- 	| families |
- 	families := #( 'Courier' 'Helvetica' 'LucidaBright' 'Lucida' 'LucidaTypewriter' 'NewCenturySchoolbook' 'TimesRoman' ).
- 
- 	families do: [:family | | fontArray textStyle |
- 		fontArray := StrikeFont readStrikeFont2Family: family.
- 		textStyle := TextStyle fontArray: fontArray.
- 		TextConstants at: family asSymbol put: textStyle.
- 	].
- !

Item was removed:
- ----- Method: BDFFontReader class>>openFileNamed: (in category 'file creation') -----
- openFileNamed: fileName
- 	^self new openFileNamed: fileName!

Item was removed:
- ----- Method: BDFFontReader>>errorFileFormat (in category 'reading') -----
- errorFileFormat
- 	self error: 'malformed bdf format'!

Item was removed:
- ----- Method: BDFFontReader>>errorUnsupported (in category 'reading') -----
- errorUnsupported
- 	self error: 'unsupported bdf'!

Item was removed:
- ----- Method: BDFFontReader>>getLine (in category 'reading') -----
- getLine
- 	^file nextLine!

Item was removed:
- ----- Method: BDFFontReader>>initialize (in category 'initialize') -----
- initialize
- 	properties := Dictionary new.!

Item was removed:
- ----- Method: BDFFontReader>>openFileNamed: (in category 'initialize') -----
- openFileNamed: fileName
- 	file := MultiByteFileStream readOnlyFileNamed: fileName.
- 	file wantsLineEndConversion: true!

Item was removed:
- ----- Method: BDFFontReader>>read (in category 'reading') -----
- read
- 	| xTable strikeWidth glyphs ascent descent minAscii maxAscii maxWidth chars charsNum height form encoding bbx array width blt lastAscii pointSize ret stream |
- 	form := encoding := bbx := nil.
- 	self readAttributes.
- 	height := Integer readFromString: ((properties at: #FONTBOUNDINGBOX) at: 2).
- 	ascent := Integer readFromString: (properties at: #'FONT_ASCENT') first.
- 	descent := Integer readFromString: (properties at: #'FONT_DESCENT') first.
- 	pointSize := (Integer readFromString: (properties at: #'POINT_SIZE') first) // 10.
- 	
- 	maxWidth := 0.
- 	minAscii := 9999.
- 	strikeWidth := 0.
- 	maxAscii := 0.
- 
- 	charsNum := Integer readFromString: (properties at: #CHARS) first.
- 	chars := Set new: charsNum.
- 
- 	1 to: charsNum do: [:i |
- 		array := self readOneCharacter.
- 		stream := ReadStream on: array.
- 		form := stream next.
- 		encoding := stream next.
- 		bbx := stream next.
- 		form ifNotNil: [
- 			width := bbx at: 1.
- 			maxWidth := maxWidth max: width.
- 			minAscii := minAscii min: encoding.
- 			maxAscii := maxAscii max: encoding.
- 			strikeWidth := strikeWidth + width.
- 			chars add: array.
- 		].
- 	].
- 
- 	chars := chars sorted: [:x :y | (x at: 2) <= (y at: 2)].
- 	charsNum := chars size. "undefined encodings make this different"
- 
- 	charsNum > 256 ifTrue: [
- 		"it should be 94x94 charset, and should be fixed width font"
- 		strikeWidth := 94*94*maxWidth.
- 		maxAscii := 94*94.
- 		minAscii := 0.
- 		xTable := XTableForFixedFont new.
- 		xTable maxAscii: 94*94.
- 		xTable width: maxWidth.
- 	] ifFalse: [
- 		xTable := (Array new: 258) atAllPut: 0.
- 	].
- 
- 	glyphs := Form extent: strikeWidth at height.
- 	blt := BitBlt toForm: glyphs.
- 	lastAscii := 0.
- 	
- 	charsNum > 256 ifTrue: [
- 		1 to: charsNum do: [:i |
- 			stream := ReadStream on: (chars at: i).
- 			form := stream next.
- 			encoding := stream next.
- 			bbx := stream next.
- 			encoding := ((encoding // 256) - 33) * 94 + ((encoding \\ 256) - 33).
- 			blt copy: ((encoding * maxWidth)@0 extent: maxWidth at height)
- 				from: 0 at 0 in: form.
- 		].
- 	] ifFalse: [
- 		1 to: charsNum do: [:i |
- 			stream := ReadStream on: (chars at: i).
- 			form := stream next.
- 			encoding := stream next.
- 			bbx := stream next.
- 			lastAscii+1 to: encoding-1 do: [:a | xTable at: a+2 put: (xTable at: a+1)].
- 			blt copy: (((xTable at: encoding+1)@(ascent - (bbx at: 2) - (bbx at: 4)))
- 					extent: (bbx at: 1)@(bbx at: 2))
- 				from: 0 at 0 in: form.
- 			xTable at: encoding+2 put: (xTable at: encoding+1)+(bbx at: 1).
- 			lastAscii := encoding.
- 		]
- 	].
- 
- 	ret := Array new: 8.
- 	ret at: 1 put: xTable.
- 	ret at: 2 put: glyphs.
- 	ret at: 3 put: minAscii.
- 	ret at: 4 put: maxAscii.
- 	ret at: 5 put: maxWidth.
- 	ret at: 6 put: ascent.
- 	ret at: 7 put: descent.
- 	ret at: 8 put: pointSize.
- 	^ret.
- " ^{xTable. glyphs. minAscii. maxAscii. maxWidth. ascent. descent. pointSize}"
- !

Item was removed:
- ----- Method: BDFFontReader>>readAttributes (in category 'reading') -----
- readAttributes
- 	| str a |
- 	"I don't handle double-quotes correctly, but it works"
- 	file reset.
- 	[file atEnd] whileFalse: [
- 		str := self getLine.
- 		(str beginsWith: 'STARTCHAR') ifTrue: [file skip: (0 - str size - 1). ^self].
- 		a := str substrings.
- 		properties at: a first asSymbol put: a allButFirst.
- 	].
- 	self error: 'file seems corrupted'.!

Item was removed:
- ----- Method: BDFFontReader>>readChars (in category 'reading') -----
- readChars
- 	| strikeWidth ascent descent minAscii maxAscii maxWidth chars charsNum height form encoding bbx array width pointSize stream |
- 	form := encoding := bbx := nil.
- 	self readAttributes.
- 	height := Integer readFromString: ((properties at: #FONTBOUNDINGBOX) at: 2).
- 	ascent := Integer readFromString: (properties at: #'FONT_ASCENT') first.
- 	descent := Integer readFromString: (properties at: #'FONT_DESCENT') first.
- 	pointSize := (Integer readFromString: (properties at: #'POINT_SIZE') first) // 10.
- 	
- 	maxWidth := 0.
- 	minAscii := 9999.
- 	strikeWidth := 0.
- 	maxAscii := 0.
- 
- 	charsNum := Integer readFromString: (properties at: #CHARS) first.
- 	chars := Set new: charsNum.
- 
- 	1 to: charsNum do: [:i |
- 		array := self readOneCharacter.
- 		stream := ReadStream on: array.
- 		form := stream next.
- 		encoding := stream next.
- 		bbx := stream next.
- 		form ifNotNil: [
- 			width := bbx at: 1.
- 			maxWidth := maxWidth max: width.
- 			minAscii := minAscii min: encoding.
- 			maxAscii := maxAscii max: encoding.
- 			strikeWidth := strikeWidth + width.
- 			chars add: array.
- 		].
- 	].
- 
- 	^chars sorted: [:x :y | (x at: 2) <= (y at: 2)]!

Item was removed:
- ----- Method: BDFFontReader>>readOneCharacter (in category 'reading') -----
- readOneCharacter
- 	| str a encoding bbx form bits hi low pos |
- 	((str := self getLine) beginsWith: 'ENDFONT') ifTrue: [^ {nil. nil. nil}].
- 	(str beginsWith: 'STARTCHAR') ifFalse: [self errorFileFormat].
- 	((str := self getLine) beginsWith: 'ENCODING') ifFalse: [self errorFileFormat].
- 	encoding := Integer readFromString: str substrings second.
- 	(self getLine beginsWith: 'SWIDTH') ifFalse: [self errorFileFormat].
- 	(self getLine beginsWith: 'DWIDTH') ifFalse: [self errorFileFormat].
- 	
- 	((str := self getLine) beginsWith: 'BBX') ifFalse: [self errorFileFormat].
- 	a := str substrings.
- 	bbx := (2 to: 5) collect: [:i | Integer readFromString: (a at: i)].
- 	((str := self getLine) beginsWith: 'ATTRIBUTES') ifTrue: [str := self getLine].
- 	(str beginsWith: 'BITMAP') ifFalse: [self errorFileFormat].
- 
- 	form := Form extent: (bbx at: 1)@(bbx at: 2).
- 	bits := form bits.
- 	pos := 0.
- 	1 to: (bbx at: 2) do: [:t |
- 		1 to: (((bbx at: 1) - 1) // 8 + 1) do: [:i |
- 			hi := (('0123456789ABCDEF' indexOf: (file next asUppercase)) - 1) bitShift: 4.
- 			low := ('0123456789ABCDEF' indexOf: (file next asUppercase)) - 1.
- 			
- 			bits byteAt: (pos+i) put: (hi+low).
- 		].
- 		file next ~= Character cr ifTrue: [self errorFileFormat].
- 		pos := pos + ((((bbx at: 1) // 32) + 1) * 4).
- 	].
- 
- 	(self getLine beginsWith: 'ENDCHAR') ifFalse: [self errorFileFormat].
- 
- 	encoding < 0 ifTrue: [^{nil. nil. nil}].
- 	^{form. encoding. bbx}.
- 	
- 	
- 	!

Item was removed:
- ImageReadWriter subclass: #BMPReadWriter
- 	instanceVariableNames: 'bfType bfSize bfOffBits biSize biWidth biHeight biPlanes biBitCount biCompression biSizeImage biXPelsPerMeter biYPelsPerMeter biClrUsed biClrImportant'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!

Item was removed:
- ----- Method: BMPReadWriter class>>displayAllFrom: (in category 'testing') -----
- displayAllFrom: fd
- 	"BMPReadWriter displayAllFrom: FileDirectory default"
- 	fd fileNames do:[:fName|
- 		(fName endsWith: '.bmp') ifTrue:[
- 			[(Form fromBinaryStream: (fd readOnlyFileNamed: fName)) display.
- 			Display forceDisplayUpdate] on: Error do:[:nix|].
- 		].
- 	].
- 	fd directoryNames do:[:fdName|
- 		self displayAllFrom: (fd directoryNamed: fdName)
- 	].!

Item was removed:
- ----- Method: BMPReadWriter class>>readAllFrom: (in category 'testing') -----
- readAllFrom: fd
- 	"MessageTally spyOn:[BMPReadWriter readAllFrom: FileDirectory default]"
- 	fd fileNames do:[:fName|
- 		(fName endsWith: '.bmp') ifTrue:[
- 			[Form fromBinaryStream: (fd readOnlyFileNamed: fName)] ifError: [].
- 		].
- 	].
- 	fd directoryNames do:[:fdName|
- 		self readAllFrom: (fd directoryNamed: fdName)
- 	].!

Item was removed:
- ----- Method: BMPReadWriter class>>typicalFileExtensions (in category 'image reading/writing') -----
- typicalFileExtensions
- 	"Answer a collection of file extensions (lowercase) which files that I can read might commonly have"
- 	^#('bmp')!

Item was removed:
- ----- Method: BMPReadWriter>>nextImage (in category 'reading') -----
- nextImage
- 	| colors |
- 	stream binary.
- 	self readHeader.
- 	biBitCount = 24 ifTrue:[^self read24BmpFile].
- 	"read the color map"
- 	colors := self readColorMap.
- 	^self readIndexedBmpFile: colors!

Item was removed:
- ----- Method: BMPReadWriter>>nextPutImage: (in category 'writing') -----
- nextPutImage: aForm
- 	| bhSize rowBytes rgb data colorValues depth image ppw scanLineLen pixline |
- 	depth := aForm depth.
- 	depth := #(1 4 8 32 ) detect: [ :each | each >= depth].
- 	image := aForm asFormOfDepth: depth.
- 	image unhibernate.
- 	bhSize := 14.  "# bytes in file header"
- 	biSize := 40.  "info header size in bytes"
- 	biWidth := image width.
- 	biHeight := image height.
- 	biClrUsed := depth = 32 ifTrue: [0] ifFalse:[1 << depth].  "No. color table entries"
- 	bfOffBits := biSize + bhSize + (4*biClrUsed).
- 	rowBytes := ((depth min: 24) * biWidth + 31 // 32) * 4.
- 	biSizeImage := biHeight * rowBytes.
- 
- 	"Write the file header"
- 	stream position: 0.
- 	stream nextLittleEndianNumber: 2 put: 19778.  "bfType = BM"
- 	stream nextLittleEndianNumber: 4 put: bfOffBits + biSizeImage.  "Entire file size in bytes"
- 	stream nextLittleEndianNumber: 4 put: 0.  "bfReserved"
- 	stream nextLittleEndianNumber: 4 put: bfOffBits.  "Offset of bitmap data from start of hdr (and file)"
- 
- 	"Write the bitmap info header"
- 	stream position: bhSize.
- 	stream nextLittleEndianNumber: 4 put: biSize.  "info header size in bytes"
- 	stream nextLittleEndianNumber: 4 put: image width.  "biWidth"
- 	stream nextLittleEndianNumber: 4 put: image height.  "biHeight"
- 	stream nextLittleEndianNumber: 2 put: 1.  "biPlanes"
- 	stream nextLittleEndianNumber: 2 put: (depth min: 24).  "biBitCount"
- 	stream nextLittleEndianNumber: 4 put: 0.  "biCompression"
- 	stream nextLittleEndianNumber: 4 put: biSizeImage.  "size of image section in bytes"
- 	stream nextLittleEndianNumber: 4 put: 2800.  "biXPelsPerMeter"
- 	stream nextLittleEndianNumber: 4 put: 2800.  "biYPelsPerMeter"
- 	stream nextLittleEndianNumber: 4 put: biClrUsed.
- 	stream nextLittleEndianNumber: 4 put: 0.  "biClrImportant"
- 	biClrUsed > 0 ifTrue: [
- 		"write color map; this works for ColorForms, too"
- 		colorValues := image colormapIfNeededForDepth: 32.
- 		1 to: biClrUsed do: [:i |
- 			rgb := colorValues at: i.
- 			0 to: 24 by: 8 do: [:j | stream nextPut: (rgb >> j bitAnd: 16rFF)]]].
- 
- 	depth < 32 ifTrue: [
- 		"depth = 1, 4 or 8."
- 		data := image bits asByteArray.
- 		ppw := 32 // depth.
- 		scanLineLen := biWidth + ppw - 1 // ppw * 4.  "# of bytes in line"
- 		1 to: biHeight do: [:i |
- 			stream next: scanLineLen putAll: data startingAt: (biHeight-i)*scanLineLen+1.
- 		].
- 	] ifFalse: [
- 		data := image bits.
- 		pixline := ByteArray new: (((biWidth * 3 + 3) // 4) * 4).
- 		1 to: biHeight do:[:i |
- 			self store24BitBmpLine: pixline from: data startingAt: (biHeight-i)*biWidth+1 width: biWidth.
- 			stream nextPutAll: pixline.
- 		].
- 	].
- 	stream position = (bfOffBits + biSizeImage) ifFalse: [self error: 'Write failure' translated].
- 	stream close.!

Item was removed:
- ----- Method: BMPReadWriter>>read24BmpFile (in category 'reading') -----
- read24BmpFile
- 	"Read 24-bit pixel data from the given a BMP stream."
- 	| form formBits pixelLine bitsIndex bitBlt |
- 	form := Form extent: biWidth at biHeight depth: 32.
- 	pixelLine := ByteArray new: (((24 * biWidth) + 31) // 32) * 4.
- 	bitsIndex := form height - 1 * biWidth + 1.
- 	formBits := form bits.
- 	1 to: biHeight do: [:i |
- 		pixelLine := stream nextInto: pixelLine.
- 		self read24BmpLine: pixelLine into: formBits startingAt: bitsIndex width: biWidth.
- 		bitsIndex := bitsIndex - biWidth.
- 	].
- 	bitBlt := BitBlt toForm: form.
- 	bitBlt combinationRule: 7 "bitOr:with:".
- 	bitBlt halftoneForm: (Bitmap with: 16rFF000000).
- 	bitBlt copyBits.
- 	^ form
- !

Item was removed:
- ----- Method: BMPReadWriter>>read24BmpLine:into:startingAt:width: (in category 'reading') -----
- read24BmpLine: pixelLine into: formBits startingAt: formBitsIndex width: width
- 	"Swizzles the bytes in a 24bpp scanline and fills in the given 32bpp form bits.
- 	Ensures that color black is represented as 16rFF000001 so that Form paint
- 	works properly."
- 
- 	| pixIndex rgb bitsIndex |
- 	<primitive: 'primitiveRead24BmpLine' module:'BMPReadWriterPlugin'>
- 	pixIndex := 0. "pre-increment"
- 	bitsIndex := formBitsIndex-1. "pre-increment"
- 	1 to: width do: [:j |
- 		rgb := 
- 			(pixelLine at: (pixIndex := pixIndex+1)) +
- 			((pixelLine at: (pixIndex := pixIndex+1)) bitShift: 8) +
- 			((pixelLine at: (pixIndex := pixIndex+1)) bitShift: 16).
- 		rgb = 0 ifTrue:[rgb := 16rFF000001] ifFalse:[rgb := rgb + 16rFF000000].
- 		formBits at: (bitsIndex := bitsIndex+1) put: rgb.
- 	].
- !

Item was removed:
- ----- Method: BMPReadWriter>>readColorMap (in category 'reading') -----
- readColorMap
- 	"Read colorCount BMP color map entries from the given binary stream. Answer an array of Colors."
- 	| colorCount colors maxLevel b g r ccStream |
- 	colorCount := (bfOffBits - 54) // 4.
- 	"Note: some programs (e.g. Photoshop 4.0) apparently do not set colorCount; assume that any data between the end of the header and the start of the pixel data is the color map"
- 	biBitCount >= 16 ifTrue:[^nil].
- 	colorCount = 0 ifTrue: [ "this BMP file does not have a color map"
- 		"default monochrome color map"
- 		biBitCount = 1 ifTrue: [^ Array with: Color white with: Color black].
- 		"default gray-scale color map"
- 		maxLevel := (2 raisedTo: biBitCount) - 1.
- 		^ (0 to: maxLevel) collect: [:level | Color gray: (level asFloat / maxLevel)]].
- 	ccStream := ReadStream on: (stream next: colorCount*4).
- 	colors := Array new: colorCount.
- 	1 to: colorCount do: [:i |
- 		b := ccStream next.
- 		g := ccStream next.
- 		r := ccStream next.
- 		ccStream next. "skip reserved"
- 		colors at: i put: (Color r: r g: g b: b range: 255)].
- 	^ colors
- !

Item was removed:
- ----- Method: BMPReadWriter>>readHeader (in category 'reading') -----
- readHeader
- 	| reserved |
- 	bfType := stream nextLittleEndianNumber: 2.
- 	bfSize := stream nextLittleEndianNumber: 4.
- 	reserved := stream nextLittleEndianNumber: 4.
- 	bfOffBits := stream nextLittleEndianNumber: 4.
- 	biSize := stream nextLittleEndianNumber: 4.
- 	biWidth := stream nextLittleEndianNumber: 4.
- 	biHeight := stream nextLittleEndianNumber: 4.
- 	biPlanes := stream nextLittleEndianNumber: 2.
- 	biBitCount := stream nextLittleEndianNumber: 2.
- 	biCompression := stream nextLittleEndianNumber: 4.
- 	biSizeImage := stream nextLittleEndianNumber: 4.
- 	biXPelsPerMeter := stream nextLittleEndianNumber: 4.
- 	biYPelsPerMeter := stream nextLittleEndianNumber: 4.
- 	biClrUsed := stream nextLittleEndianNumber: 4.
- 	biClrImportant := stream nextLittleEndianNumber: 4.
- !

Item was removed:
- ----- Method: BMPReadWriter>>readIndexedBmpFile: (in category 'reading') -----
- readIndexedBmpFile: colors
- 	"Read uncompressed pixel data of depth d from the given BMP stream, where d is 1, 4, 8, or 16"
- 	| form bytesPerRow pixelData pixelLine startIndex map bitBlt mask |
- 	colors 
- 		ifNil:[form := Form extent: biWidth at biHeight depth: biBitCount]
- 		ifNotNil:[form := ColorForm extent: biWidth at biHeight depth: biBitCount.
- 				form colors: colors].
- 	bytesPerRow := (((biBitCount* biWidth) + 31) // 32) * 4.
- 	pixelData := ByteArray new: bytesPerRow * biHeight.
- 	biHeight to: 1 by: -1 do: [:y |
- 		pixelLine := stream next: bytesPerRow.
- 		startIndex := ((y - 1) * bytesPerRow) + 1.
- 		pixelData 
- 			replaceFrom: startIndex 
- 			to: startIndex + bytesPerRow - 1 
- 			with: pixelLine 
- 			startingAt: 1].
- 	form bits copyFromByteArray: pixelData.
- 	biBitCount = 16 ifTrue:[
- 		map := ColorMap shifts: #(8 -8 0 0) masks: #(16rFF 16rFF00 0 0).
- 		mask := 16r80008000.
- 	].
- 	biBitCount = 32 ifTrue:[
- 		map := ColorMap shifts: #(24 8 -8 -24) masks: #(16rFF 16rFF00 16rFF0000 16rFF000000).
- 		mask := 16rFF000000.
- 	].
- 	map ifNotNil:[
- 		bitBlt := BitBlt toForm: form.
- 		bitBlt sourceForm: form.
- 		bitBlt colorMap: map.
- 		bitBlt combinationRule: Form over.
- 		bitBlt copyBits.
- 	].
- 	mask ifNotNil:[
- 		bitBlt := BitBlt toForm: form.
- 		bitBlt combinationRule: 7 "bitOr:with:".
- 		bitBlt halftoneForm: (Bitmap with: mask).
- 		bitBlt copyBits.
- 	].
- 	^ form
- !

Item was removed:
- ----- Method: BMPReadWriter>>store24BitBmpLine:from:startingAt:width: (in category 'writing') -----
- store24BitBmpLine: pixelLine from: formBits startingAt: formBitsIndex width: width
- 	"Stores a single scanline containing 32bpp RGBA values in a 24bpp scanline.
- 	Swizzles the bytes as needed."
- 
- 	| pixIndex rgb bitsIndex |
- 	<primitive: 'primitiveWrite24BmpLine' module:'BMPReadWriterPlugin'>
- 	pixIndex := 0. "pre-increment"
- 	bitsIndex := formBitsIndex-1. "pre-increment"
- 	1 to: width do: [:j |
- 		rgb := (formBits at: (bitsIndex := bitsIndex+1)) bitAnd: 16rFFFFFF.
- 		pixelLine at: (pixIndex := pixIndex+1) put: (rgb bitAnd: 255).
- 		pixelLine at: (pixIndex := pixIndex+1) put: ((rgb bitShift: -8) bitAnd: 255).
- 		pixelLine at: (pixIndex := pixIndex+1) put: ((rgb bitShift: -16) bitAnd: 255).
- 	].
- !

Item was removed:
- ----- Method: BMPReadWriter>>understandsImageFormat (in category 'testing') -----
- understandsImageFormat
- 	stream size < 54 ifTrue:[^false]. "min size = BITMAPFILEHEADER+BITMAPINFOHEADER"
- 	self readHeader.
- 	bfType = 19778 "BM" ifFalse:[^false].
- 	biSize = 40 ifFalse:[^false].
- 	biPlanes = 1 ifFalse:[^false].
- 	bfSize <= stream size ifFalse:[^false].
- 	biCompression = 0 ifFalse:[^false].
- 	^true!

Item was removed:
- Object subclass: #BitBlt
- 	instanceVariableNames: 'destForm sourceForm halftoneForm combinationRule destX destY width height sourceX sourceY clipX clipY clipWidth clipHeight colorMap'
- 	classVariableNames: 'CachedFontColorMaps ColorConvertingMaps SubPixelRenderColorFonts SubPixelRenderFonts'
- 	poolDictionaries: ''
- 	category: 'Graphics-Primitives'!
- 
- !BitBlt commentStamp: 'nice 12/27/2020 16:53' prior: 0!
- WARNING: BitBlt's shape cannot be modified since WarpBlt relies on the exact layout. Important primitives will break if you fail to heed this warning.
- 
- I represent a block transfer (BLT) of pixels from one Form ( the sourceForm) into a rectangle (destX, destY, width, height) of the destinationForm, as modified by a combination rule, a possible halftoneForm and a possible color map.
- 
- The source of pixels may be a similar rectangle (at sourceX, sourceY) in the sourceForm, or the halftoneForm, or both.  If both are specified, their pixel values are combined by a logical AND function prior to any further combination rule processing. The halftoneForm may be an actual Form or a simple WordArray of 32 bit values usually intended to represent Color values. In either case the 'top' of the form is effectively aligned with the top of the destinationForm and for each scanline the destination y modulo the size of the halftoneForm gives the index of the word to use. This makes it easy to make horizontal stripes, for example.
- 
- In any case, the pixels from the source (AND'd with the halftone, remember) are combined with those of the destination by as specified by the combinationRules below- 
- 	name	rule		result 
- 
- 					0	always 0
- 	and				1	src AND dst
- 					2	src AND not(dst)
- 	over			3	src only
- 	erase			4	not(src) AND& dst
- 					5 	dst only
- 	reverse		6	src XOR dst
- 	under			7	src OR dst
- 					8	not(src) AND not(dst)
- 					9	not(src) XOR dst
- 					10	not(dst)
- 					11	src OR not(dst)
- 					12	not(src)
- 					13	not(src) OR dst
- 					14	not(src) OR not(dst)
- 					15	always 1
- (You can find an interesting explanation of how this comes to be in http://dev-docs.atariforge.org/files/BLiTTER_1-25-1990.pdf - which interestingly fails to mention any connection to Smalltalk and PARC.)
-  Forms may be of different depths, see the comment in class Form.
- 
- In addition to the original 16 combination rules invented for monochrome Forms, this BitBlt supports
- 					16	fails (to simulate paint bits)
- 					17	fails (to simulate erase bits)
- 					18	sourceWord + destinationWord
- 					19	sourceWord - destinationWord
- 					20	rgbAdd: sourceWord with: destinationWord.  Sum of color components
- 					21	rgbSub: sourceWord with: destinationWord.  Difference of color components
- 					22	OLDrgbDiff: sourceWord with: destinationWord.  Sum of abs of differences in components
- 					23	OLDtallyIntoMap: destinationWord.  Tallies pixValues into a colorMap
- 							these old versions don't do bitwise dest clipping.  Use 32 and 33 now.
- 	blend			24	alphaBlend: sourceWord with: destinationWord.  32-bit source and dest only. Blend sourceWord 
- 							with destinationWord, assuming both are 32-bit pixels. The source is assumed to have 255*alpha
- 							in the high 8 bits of each pixel, while the high 8 bits of the destinationWord will be ignored.
- 							The blend produced is alpha*source + (1-alpha)*dest, with the computation being performed
- 							independently on each color component.  The high byte of the result will be 0.
- 	paint			25	pixPaint: sourceWord with: destinationWord.  Wherever the sourceForm is non-zero, it replaces
- 							the destination.  Can be used with a 1-bit source color mapped to (0, FFFFFFFF), and a fillColor 
- 							to fill the dest with that color wherever the source is 1.
- 	erase1BitShape	26	pixMask: sourceWord with: destinationWord.  Like pixPaint, but fills with 0.
- 					27	rgbMax: sourceWord with: destinationWord.  Max of each color component.
- 					28	rgbMin: sourceWord with: destinationWord.  Min of each color component.
- 					29	rgbMin: sourceWord bitInvert32 with: destinationWord.  Min with (max-source)
- 	blendAlpha		30	alphaBlendConst: sourceWord with: destinationWord.  alpha is an arg. works in 16 bits. Blend
- 							sourceWord with destinationWord using a constant alpha. Alpha is encoded as 0 meaning
- 							0.0, and 255 meaning 1.0. The blend produced is alpha*source + (1.0-alpha)*dest, with
- 							the computation being performed independently on each color component. 
- 	paintAlpha		31	alphaPaintConst: sourceWord with: destinationWord.  alpha is an arg. works in 16 bits.
- 					32	rgbDiff: sourceWord with: destinationWord.  Sum of abs of differences in components
- 					33	tallyIntoMap: destinationWord.  Tallies pixValues into a colorMap - Those tallied are exactly 
- 							those in the destination rectangle.  Note that the source should be specified == destination,
- 							in order for the proper color map checks  be performed at setup.
- 	blendAlphaScaled	34	alphaBlendScaled: srcWord with: dstWord. Alpha blend of scaled srcWord and destWord. In contrast
- 							to alphaBlend:with: the color produced is srcColor + (1-srcAlpha) * dstColor
- 					35	& 36 not used
- 	rgbMul			37	rgbMul: srcWord with: dstWord. 
- 					38	pixSwap: srcWord with: dstWord.
- 					39	pixClear: srcWord with: dstWord. Clear all pixels in destinationWord for which the pixels of 
- 							sourceWord have the same values. Used to clear areas of some constant color to zero.
- 					40	fixAlpha: srcWord with: dstWord. For any non-zero pixel value in destinationWord with zero alpha 
- 							channel take the alpha from sourceWord and fill it in. Intended for fixing alpha channels left at 
- 							zero during 16->32 bpp conversions.
- 					41	rgbComponentAlpha: srcWord with: dstWord.
- 					42	alphaScale: srcWord with: dstWord. Pre-scale the destWord (i.e. multiply rgb components by alpha channel)
- 					43	alphaUncale: srcWord with: dstWord. Un-scale the destWord (i.e. divide rgb components by alpha channel)
- 					44	alphaBlendUnscaled: srcWord with: dstWord. Alpha blend of unscaled srcWord and destWord.
- 							In contrast to alphaBlendScaled:with: the color produced is (srcAlpha*srcColor + (1-srcAlpha) * dstColor)/resultAlpha
- 							where resultAlpha is srcAlpha + destAlpha*(1-srcAlpha)
- 							This is equivalent to operations 42 + 34 + 43 (aphaScale, alphaBlendScaled, alphaUnscale)
- 
- Any transfer specified is further clipped by the specified clipping rectangle (clipX, clipY, clipWidth, clipHeight), and also by the bounds of the source and destination forms.
- 	To make a small Form repeat and fill a big form, use an InfiniteForm as the source.
- 
- Pixels copied from a source to a destination whose pixels have a different depth are converted based on the optional colorMap.  If colorMap is nil, then conversion to more bits is done by filling the new high-order bits with zero, and conversion to fewer bits is done by truncating the lost high-order bits.  
- 
- The colorMap, if specified, must be a either word array (ie Bitmap) with 2^n elements, where n is the pixel depth of the source, or a fully specified ColorMap which may contain a lookup table (ie Bitmap) and/or four separate masks and shifts which are applied to the pixels. For every source pixel, BitBlt will first perform masking and shifting and then index the lookup table, and select the corresponding pixelValue and mask it to the destination pixel size before storing.
- 	When blitting from a 32 or 16 bit deep Form to one 8 bits or less, the default is truncation.  This will produce very strange colors, since truncation of the high bits does not produce the nearest encoded color.  Supply a 512 long colorMap, and red, green, and blue will be shifted down to 3 bits each, and mapped.  The message copybits...stdColors will use the best map to the standard colors for destinations of depths 8, 4, 2 and 1.  Two other sized of colorMaps are allowed, 4096 (4 bits per color) and 32786 (five bits per color).
- 	Normal blits between 16 and 32 bit forms truncates or pads the colors automatically to provide the best preservation of colors.
- 	Colors can be remapped at the same depth.  Sometimes a Form is in terms of colors that are not the standard colors for this depth, for example in a GIF file.  Convert the Form to a MaskedForm and send colorMap: the list of colors that the picture is in terms of. (Note also that a Form can be copied to itself, and transformed in the process, if a non-nil colorMap is supplied.)!

Item was removed:
- ----- Method: BitBlt class>>alphaBlendDemo (in category 'examples') -----
- alphaBlendDemo
- 	"To run this demo, use...
- 		Display restoreAfter: [BitBlt alphaBlendDemo]	
- 	Displays 10 alphas, then lets you paint.  Option-Click to stop painting."
- 
- 	"This code exhibits alpha blending in any display depth by performing
- 	the blend in an off-screen buffer with 32-bit pixels, and then copying
- 	the result back onto the screen with an appropriate color map. - tk 3/10/97"
- 	
- 	"This version uses a sliding buffer for painting that keeps pixels in 32 bits
- 	as long as they are in the buffer, so as not to lose info by converting down
- 	to display resolution and back up to 32 bits at each operation. - di 3/15/97"
- 
- 	| brush buff dispToBuff buffToDisplay mapDto32 map32toD prevP p brushToBuff theta buffRect buffSize buffToBuff brushRect delta newBuffRect updateRect |  
- 
- 	"compute color maps if needed"
- 	Display depth <= 8 ifTrue: [
- 		mapDto32 := Color cachedColormapFrom: Display depth to: 32.
- 		map32toD := Color cachedColormapFrom: 32 to: Display depth].
- 
- 	"display 10 different alphas, across top of screen"
- 	buff := Form extent: 500 at 50 depth: 32.
- 	dispToBuff := BitBlt toForm: buff.
- 	dispToBuff colorMap: mapDto32.
- 	dispToBuff copyFrom: (50 at 10 extent: 500 at 50) in: Display to: 0 at 0.
- 	1 to: 10 do: [:i | dispToBuff fill: (50*(i-1)@0 extent: 50 at 50)
- 						fillColor: (Color red alpha: i/10)
- 						rule: Form blend].
- 	buffToDisplay := BitBlt toForm: Display.
- 	buffToDisplay colorMap: map32toD.
- 	buffToDisplay copyFrom: buff boundingBox in: buff to: 50 at 10.
- 
- 	"Create a brush with radially varying alpha"
- 	brush := Form extent: 30 at 30 depth: 32.
- 	1 to: 5 do: 
- 		[:i | brush fillShape: (Form dotOfSize: brush width*(6-i)//5)
- 				fillColor: (Color red alpha: 0.02 * i - 0.01)
- 				at: brush extent // 2].
- 
- 	"Now paint with the brush using alpha blending."
- 	buffSize := 100.
- 	buff := Form extent: brush extent + buffSize depth: 32.  "Travelling 32-bit buffer"
- 	dispToBuff := BitBlt toForm: buff.  "This is from Display to buff"
- 	dispToBuff colorMap: mapDto32.
- 	brushToBuff := BitBlt toForm: buff.  "This is from brush to buff"
- 	brushToBuff sourceForm: brush; sourceOrigin: 0 at 0.
- 	brushToBuff combinationRule: Form blend.
- 	buffToBuff := BitBlt toForm: buff.  "This is for slewing the buffer"
- 
- 	[Sensor yellowButtonPressed] whileFalse:
- 		[prevP := nil.
- 		buffRect := Sensor cursorPoint - (buffSize // 2) extent: buff extent.
- 		dispToBuff copyFrom: buffRect in: Display to: 0 at 0.
- 		[Sensor redButtonPressed] whileTrue:
- 			["Here is the painting loop"
- 			p := Sensor cursorPoint - (brush extent // 2).
- 			(prevP == nil or: [prevP ~= p]) ifTrue:
- 				[prevP == nil ifTrue: [prevP := p].
- 				(p dist: prevP) > buffSize ifTrue:
- 					["Stroke too long to fit in buffer -- clip to buffer,
- 						and next time through will do more of it"
- 					theta := (p-prevP) theta.
- 					p := ((theta cos at theta sin) * buffSize asFloat + prevP) truncated].
- 				brushRect := p extent: brush extent.
- 				(buffRect containsRect: brushRect) ifFalse:
- 					["Brush is out of buffer region.  Scroll the buffer,
- 						and fill vacated regions from the display"
- 					delta := brushRect amountToTranslateWithin: buffRect.
- 					buffToBuff copyFrom: buff boundingBox in: buff to: delta.
- 					newBuffRect := buffRect translateBy: delta negated.
- 					(newBuffRect areasOutside: buffRect) do:
- 						[:r | dispToBuff copyFrom: r in: Display to: r origin - newBuffRect origin].
- 					buffRect := newBuffRect].
- 
- 				"Interpolate from prevP to p..."
- 				brushToBuff drawFrom: prevP - buffRect origin
- 									to: p - buffRect origin
- 									withFirstPoint: false.
- 
- 				"Update (only) the altered pixels of the destination"
- 				updateRect := (p min: prevP) corner: (p max: prevP) + brush extent.
- 				buffToDisplay copy: updateRect from: updateRect origin - buffRect origin in: buff.
- 				prevP := p]]]!

Item was removed:
- ----- Method: BitBlt class>>antiAliasDemo (in category 'examples') -----
- antiAliasDemo 
- 	"To run this demo, use...
- 		Display restoreAfter: [BitBlt antiAliasDemo]
- 	Goes immediately into on-screen paint mode.  Option-Click to stop painting."
- 
- 	"This code exhibits alpha blending in any display depth by performing
- 	the blend in an off-screen buffer with 32-bit pixels, and then copying
- 	the result back onto the screen with an appropriate color map. - tk 3/10/97"
- 	
- 	"This version uses a sliding buffer for painting that keeps pixels in 32 bits
- 	as long as they are in the buffer, so as not to lose info by converting down
- 	to display resolution and back up to 32 bits at each operation. - di 3/15/97"
- 	
- 	"This version also uses WarpBlt to paint into twice as large a buffer,
- 	and then use smoothing when reducing back down to the display.
- 	In fact this same routine will now work for 3x3 soothing as well.
- 	Remove the statements 'buff displayAt: 0 at 0' to hide the buffer. - di 3/19/97"
- 
- 	| brush buff dispToBuff buffToDisplay mapDto32 map32toD prevP p brushToBuff theta buffRect buffSize buffToBuff brushRect delta newBuffRect updateRect scale p0 |  
- 	"compute color maps if needed"
- 	Display depth <= 8 ifTrue: [
- 		mapDto32 := Color cachedColormapFrom: Display depth to: 32.
- 		map32toD := Color cachedColormapFrom: 32 to: Display depth].
- 
- 	"Create a brush with radially varying alpha"
- 	brush := Form extent: 3 at 3 depth: 32.
- 	brush fill: brush boundingBox fillColor: (Color red alpha: 0.05).
- 	brush fill: (1 at 1 extent: 1 at 1) fillColor: (Color red alpha: 0.2).
- 
- 	scale := 2.  "Actual drawing happens at this magnification"
- 	"Scale brush up for painting in magnified buffer"
- 	brush := brush magnify: brush boundingBox by: scale.
- 
- 	"Now paint with the brush using alpha blending."
- 	buffSize := 100.
- 	buff := Form extent: (brush extent + buffSize) * scale depth: 32.  "Travelling 32-bit buffer"
- 	dispToBuff := (WarpBlt toForm: buff)  "From Display to buff - magnify by 2"
- 		sourceForm: Display;
- 		colorMap: mapDto32;
- 		combinationRule: Form over.
- 	brushToBuff := (BitBlt toForm: buff)  "From brush to buff"
- 		sourceForm: brush;
- 		sourceOrigin: 0 at 0;
- 		combinationRule: Form blend.
- 	buffToDisplay := (WarpBlt toForm: Display)  "From buff to Display - shrink by 2"
- 		sourceForm: buff;
- 		colorMap: map32toD;
- 		cellSize: scale;  "...and use smoothing"
- 		combinationRule: Form over.
- 	buffToBuff := BitBlt toForm: buff.  "This is for slewing the buffer"
- 
- 	[Sensor yellowButtonPressed] whileFalse:
- 		[prevP := nil.
- 		buffRect := Sensor cursorPoint - (buff extent // scale // 2) extent: buff extent // scale.
- 		p0 := (buff extent // 2) - (buffRect extent // 2).
- 		dispToBuff copyQuad: buffRect innerCorners toRect: buff boundingBox.
- buff displayAt: 0 at 0.  "** remove to hide sliding buffer **"
- 		[Sensor redButtonPressed] whileTrue:
- 			["Here is the painting loop"
- 			p := Sensor cursorPoint - buffRect origin + p0.  "p, prevP are rel to buff origin"
- 			(prevP == nil or: [prevP ~= p]) ifTrue:
- 				[prevP == nil ifTrue: [prevP := p].
- 				(p dist: prevP) > (buffSize-1) ifTrue:
- 					["Stroke too long to fit in buffer -- clip to buffer,
- 						and next time through will do more of it"
- 					theta := (p-prevP) theta.
- 					p := ((theta cos at theta sin) * (buffSize-2) asFloat + prevP) truncated].
- 				brushRect := p extent: brush extent.
- 				((buff boundingBox insetBy: scale) containsRect: brushRect) ifFalse:
- 					["Brush is out of buffer region.  Scroll the buffer,
- 						and fill vacated regions from the display"
- 					delta := (brushRect amountToTranslateWithin: (buff boundingBox insetBy: scale)) // scale.
- 					buffToBuff copyFrom: buff boundingBox in: buff to: delta*scale.
- 					newBuffRect := buffRect translateBy: delta negated.
- 					p := p translateBy: delta*scale.
- 					prevP := prevP translateBy: delta*scale.
- 					(newBuffRect areasOutside: buffRect) do:
- 						[:r | dispToBuff copyQuad: r innerCorners toRect: (r origin - newBuffRect origin*scale extent: r extent*scale)].
- 					buffRect := newBuffRect].
- 
- 				"Interpolate from prevP to p..."
- 				brushToBuff drawFrom: prevP to: p withFirstPoint: false.
- buff displayAt: 0 at 0.  "** remove to hide sliding buffer **"
- 
- 				"Update (only) the altered pixels of the destination"
- 				updateRect := (p min: prevP) corner: (p max: prevP) + brush extent.
- 				updateRect := updateRect origin // scale * scale
- 						corner: updateRect corner + scale // scale * scale.
- 				buffToDisplay copyQuad: updateRect innerCorners
- 							toRect: (updateRect origin // scale + buffRect origin
- 										extent: updateRect extent // scale).
- 				prevP := p]]]!

Item was removed:
- ----- Method: BitBlt class>>benchDiffsFrom:to: (in category 'benchmarks') -----
- benchDiffsFrom: before to: afterwards
- 	"Given two outputs of BitBlt>>benchmark show the relative improvements."
- 	| old new log oldLine newLine oldVal newVal improvement |
- 	log := WriteStream on: String new.
- 	old := ReadStream on: before.
- 	new := ReadStream on: afterwards.
- 	[old atEnd or:[new atEnd]] whileFalse:[
- 		oldLine := old nextLine.
- 		newLine := new nextLine.
- 		(oldLine includes: Character tab) ifTrue:[
- 			oldLine := ReadStream on: oldLine.
- 			newLine := ReadStream on: newLine.
- 			Transcript cr; show: (oldLine upTo: Character tab); tab.
- 			log cr; nextPutAll: (newLine upTo: Character tab); tab.
- 
- 			[oldLine skipSeparators. newLine skipSeparators.
- 			oldLine atEnd] whileFalse:[
- 				oldVal := Integer readFrom: oldLine.
- 				newVal := Integer readFrom: newLine.
- 				improvement := oldVal asFloat / newVal asFloat roundTo: 0.01.
- 				Transcript show: improvement printString; tab; tab.
- 				log print: improvement; tab; tab].
- 		] ifFalse:[
- 			Transcript cr; show: oldLine.
- 			log cr; nextPutAll: oldLine.
- 		].
- 	].
- 	^log contents!

Item was removed:
- ----- Method: BitBlt class>>benchmark (in category 'benchmarks') -----
- benchmark		"BitBlt benchmark"
- 	"Run a benchmark on different combinations rules, source/destination depths and BitBlt modes. Note: This benchmark doesn't give you any 'absolute' value - it is intended only for benchmarking improvements in the bitblt code and nothing else.
- 	Attention: *this*may*take*a*while*"
- 	| destRect log |
- 	log := WriteStream on: String new.
- 	destRect := 0 at 0 extent: 600 at 600.
- 	"Form paint/Form over - the most common rules"
- 	#( 25 3 ) do:[:rule|
- 		Transcript cr; show:'---- Combination rule: ', rule printString,' ----'.
- 		log cr; nextPutAll:'---- Combination rule: ', rule printString,' ----'.
- 		#(1 2 4 8 16 32) do:[:destDepth| | dest |
- 			dest := nil.
- 			dest := Form extent: destRect extent depth: destDepth.
- 			Transcript cr.
- 			log cr.
- 			#(1 2 4 8 16 32) do:[:sourceDepth| | t source bb |
- 				Transcript cr; show: sourceDepth printString, ' => ', destDepth printString.
- 				log cr; nextPutAll: sourceDepth printString, ' => ', destDepth printString.
- 				source := nil. bb := nil.
- 				source := Form extent: destRect extent depth: sourceDepth.
- 				(source getCanvas) fillOval: dest boundingBox color: Color yellow borderWidth: 30 borderColor: Color black.
- 				bb := WarpBlt toForm: dest.
- 				bb sourceForm: source.
- 				bb sourceRect: source boundingBox.
- 				bb destRect: dest boundingBox.
- 				bb colorMap: (source colormapIfNeededFor: dest).
- 				bb combinationRule: rule.
- 
- 				"Measure speed of copyBits"
- 				t := Time millisecondsToRun:[bb copyBits].
- 				Transcript tab; show: t printString.
- 				log tab; nextPutAll: t printString.
- 
- 				bb sourceForm: source destRect: source boundingBox.
- 
- 				"Measure speed of 1x1 warpBits"
- 				bb cellSize: 1.
- 				t := Time millisecondsToRun:[bb warpBits].
- 				Transcript tab; show: t printString.
- 				log tab; nextPutAll: t printString.
- 
- 				"Measure speed of 2x2 warpBits"
- 				bb cellSize: 2.
- 				t := Time millisecondsToRun:[bb warpBits].
- 				Transcript tab; show: t printString.
- 				log tab; nextPutAll: t printString.
- 
- 				"Measure speed of 3x3 warpBits"
- 				bb cellSize: 3.
- 				t := Time millisecondsToRun:[bb warpBits].
- 				Transcript tab; show: t printString.
- 				log tab; nextPutAll: t printString.
- 			].
- 		].
- 	].
- 	^log contents!

Item was removed:
- ----- Method: BitBlt class>>benchmark2 (in category 'benchmarks') -----
- benchmark2		"BitBlt benchmark"
- 	"Run a benchmark on different combinations rules, source/destination depths and BitBlt modes. Note: This benchmark doesn't give you any 'absolute' value - it is intended only for benchmarking improvements in the bitblt code and nothing else.
- 	Attention: *this*may*take*a*while*"
- 	| destRect log |
- 	log := WriteStream on: String new.
- 	destRect := 0 at 0 extent: 600 at 600.
- 	"Form paint/Form over - the most common rules"
- 	#( 25 3 ) do:[:rule|
- 		Transcript cr; show:'---- Combination rule: ', rule printString,' ----'.
- 		log cr; nextPutAll:'---- Combination rule: ', rule printString,' ----'.
- 		#(1 2 4 8 16 32) do:[:destDepth| | dest |
- 			dest := nil.
- 			dest := Form extent: destRect extent depth: destDepth.
- 			Transcript cr.
- 			log cr.
- 			#(1 2 4 8 16 32) do:[:sourceDepth| | t bb source |
- 				Transcript cr; show: sourceDepth printString, ' => ', destDepth printString.
- 				log cr; nextPutAll: sourceDepth printString, ' => ', destDepth printString.
- 				source := nil. bb := nil.
- 				source := Form extent: destRect extent depth: sourceDepth.
- 				(source getCanvas) fillOval: dest boundingBox color: Color yellow borderWidth: 30 borderColor: Color black.
- 				bb := WarpBlt toForm: dest.
- 				bb sourceForm: source.
- 				bb sourceRect: source boundingBox.
- 				bb destRect: dest boundingBox.
- 				bb colorMap: (source colormapIfNeededFor: dest).
- 				bb combinationRule: rule.
- 
- 				"Measure speed of copyBits"
- 				t := Time millisecondsToRun:[1 to: 10 do:[:i| bb copyBits]].
- 				Transcript tab; show: t printString.
- 				log tab; nextPutAll: t printString.
- 
- 				bb sourceForm: source destRect: source boundingBox.
- 
- 				"Measure speed of 1x1 warpBits"
- 				bb cellSize: 1.
- 				t := Time millisecondsToRun:[1 to: 4 do:[:i| bb warpBits]].
- 				Transcript tab; show: t printString.
- 				log tab; nextPutAll: t printString.
- 
- 				"Measure speed of 2x2 warpBits"
- 				bb cellSize: 2.
- 				t := Time millisecondsToRun:[bb warpBits].
- 				Transcript tab; show: t printString.
- 				log tab; nextPutAll: t printString.
- 
- 				"Measure speed of 3x3 warpBits"
- 				bb cellSize: 3.
- 				t := Time millisecondsToRun:[bb warpBits].
- 				Transcript tab; show: t printString.
- 				log tab; nextPutAll: t printString.
- 			].
- 		].
- 	].
- 	^log contents!

Item was removed:
- ----- Method: BitBlt class>>benchmark3 (in category 'benchmarks') -----
- benchmark3		"BitBlt benchmark"
- 	"Run a benchmark on different combinations rules, source/destination depths and BitBlt modes. Note: This benchmark doesn't give you any 'absolute' value - it is intended only for benchmarking improvements in the bitblt code and nothing else.
- 	Attention: *this*may*take*a*while*"
- 	| destRect log |
- 	log := WriteStream on: String new.
- 	destRect := 0 at 0 extent: 600 at 600.
- 	"Form paint/Form over - the most common rules"
- 	#( 25 3 ) do:[:rule|
- 		Transcript cr; show:'---- Combination rule: ', rule printString,' ----'.
- 		log cr; nextPutAll:'---- Combination rule: ', rule printString,' ----'.
- 		#(1 2 4 8 16 32) do:[:destDepth| | dest |
- 			dest := nil.
- 			dest := Form extent: destRect extent depth: destDepth.
- 			Transcript cr.
- 			log cr.
- 			#(1 2 4 8 16 32) do:[:sourceDepth| | t source bb |
- 				Transcript cr; show: sourceDepth printString, ' => ', destDepth printString.
- 				log cr; nextPutAll: sourceDepth printString, ' => ', destDepth printString.
- 				source := nil. bb := nil.
- 				source := Form extent: destRect extent depth: sourceDepth.
- 				(source getCanvas) fillOval: dest boundingBox color: Color yellow borderWidth: 30 borderColor: Color black.
- 				bb := WarpBlt toForm: dest.
- 				bb sourceForm: source.
- 				bb sourceRect: source boundingBox.
- 				bb destRect: dest boundingBox.
- 				bb colorMap: (source colormapIfNeededFor: dest).
- 				bb combinationRule: rule.
- 
- 				"Measure speed of copyBits"
- 				t := Time millisecondsToRun:[1 to: 10 do:[:i| bb copyBits]].
- 				Transcript tab; show: t printString.
- 				log tab; nextPutAll: t printString.
- 
- 				bb sourceForm: source destRect: source boundingBox.
- 
- 				"Measure speed of 1x1 warpBits"
- 				bb cellSize: 1.
- 				t := Time millisecondsToRun:[1 to: 4 do:[:i| bb warpBits]].
- 				Transcript tab; show: t printString.
- 				log tab; nextPutAll: t printString.
- 
- 				"Measure speed of 2x2 warpBits"
- 				bb cellSize: 2.
- 				t := Time millisecondsToRun:[bb warpBits].
- 				Transcript tab; show: t printString.
- 				log tab; nextPutAll: t printString.
- 
- 				"Measure speed of 3x3 warpBits"
- 				bb cellSize: 3.
- 				t := Time millisecondsToRun:[bb warpBits].
- 				Transcript tab; show: t printString.
- 				log tab; nextPutAll: t printString.
- 			].
- 		].
- 	].
- 	^log contents!

Item was removed:
- ----- Method: BitBlt class>>bitPeekerFromForm: (in category 'instance creation') -----
- bitPeekerFromForm: sourceForm
- 	"Answer an instance to be used extract individual pixels from the given Form. The destination for a 1x1 copyBits will be the low order bits of (bits at: 1)."
- 	| pixPerWord |
- 	pixPerWord := 32 // sourceForm depth.
- 	sourceForm unhibernate.
- 	^ self destForm: (Form extent: pixPerWord at 1 depth: sourceForm depth)
- 	 	sourceForm: sourceForm
- 		halftoneForm: nil
- 		combinationRule: Form over
- 		destOrigin: (pixPerWord - 1)@0
- 		sourceOrigin: 0 at 0
- 		extent: 1 at 1
- 		clipRect: (0 at 0 extent: pixPerWord at 1)
- !

Item was removed:
- ----- Method: BitBlt class>>bitPokerToForm: (in category 'instance creation') -----
- bitPokerToForm: destForm
- 	"Answer an instance to be used for valueAt: aPoint put: pixValue.
- 	The source for a 1x1 copyBits will be the low order of (bits at: 1)"
- 	| pixPerWord |
- 	pixPerWord := 32//destForm depth.
- 	destForm unhibernate.
- 	^ self destForm: destForm
- 	 	sourceForm: (Form extent: pixPerWord at 1 depth: destForm depth)
- 		halftoneForm: nil combinationRule: Form over
- 		destOrigin: 0 at 0 sourceOrigin: (pixPerWord-1)@0
- 		extent: 1 at 1 clipRect: (0 at 0 extent: destForm extent)
- !

Item was removed:
- ----- Method: BitBlt class>>cleanUp (in category 'class initialization') -----
- cleanUp
- 	"Flush caches"
- 
- 	self recreateColorMaps.!

Item was removed:
- ----- Method: BitBlt class>>current (in category 'instance creation') -----
- current
- 	"Return the class currently to be used for BitBlt"
- 	^self!

Item was removed:
- ----- Method: BitBlt class>>destForm:sourceForm:fillColor:combinationRule:destOrigin:sourceOrigin:extent:clipRect: (in category 'instance creation') -----
- destForm: df sourceForm: sf fillColor: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect 
- 	"Answer an instance of me with values set according to the arguments."
- 
- 	^ self new
- 		setDestForm: df
- 		sourceForm: sf
- 		fillColor: hf
- 		combinationRule: cr
- 		destOrigin: destOrigin
- 		sourceOrigin: sourceOrigin
- 		extent: extent
- 		clipRect: clipRect!

Item was removed:
- ----- Method: BitBlt class>>destForm:sourceForm:halftoneForm:combinationRule:destOrigin:sourceOrigin:extent:clipRect: (in category 'instance creation') -----
- destForm: df sourceForm: sf halftoneForm: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect 
- 	"Answer an instance of me with values set according to the arguments."
- 
- 	^ self new
- 		setDestForm: df
- 		sourceForm: sf
- 		fillColor: hf
- 		combinationRule: cr
- 		destOrigin: destOrigin
- 		sourceOrigin: sourceOrigin
- 		extent: extent
- 		clipRect: clipRect!

Item was removed:
- ----- Method: BitBlt class>>exampleAt:rule:fillColor: (in category 'private') -----
- exampleAt: originPoint rule: rule fillColor: mask 
- 	"This builds a source and destination form and copies the source to the
- 	destination using the specifed rule and mask. It is called from the method
- 	named exampleOne. Only works with Display depth of 1"
- 
- 	^self exampleOn: Display at: originPoint rule: rule fillColor: mask
- 
- 	"BitBlt exampleAt: 100 at 100 rule: 0 fillColor: nil"!

Item was removed:
- ----- Method: BitBlt class>>exampleColorMap (in category 'examples') -----
- exampleColorMap	"BitBlt exampleColorMap"
- 	"This example shows what one can do with the fixed part of a color map. The color map, as setup below, rotates the bits of a pixel all the way around. Thus you'll get a (sometime strange looking ;-) animation of colors which will end up exactly the way it looked at the beginning. The example is given to make you understand that the masks and shifts can be used for a lot more than simply color converting pixels. In this example, for instance, we use only two of the four independent shifters."
- 	| cc bb |
- 	cc := ColorMap masks: {
- 		1 << (Display depth-1). "mask out high bit of color component"
- 		1 << (Display depth-1) - 1. "mask all other bits"
- 		0.
- 		0}
- 		shifts: {
- 			1 - Display depth. "shift right to bottom most position"
- 			1. "shift all other pixels one bit left"
- 			0.
- 			0}.
- 	bb := BitBlt toForm: Display.
- 	bb 
- 		sourceForm: Display;
- 		combinationRule: 3;
- 		colorMap: cc.
- 	1 to: Display depth do:[:i|
- 		bb copyBits.
- 		Display forceDisplayUpdate.
- 	].
- !

Item was removed:
- ----- Method: BitBlt class>>exampleOn:at:rule:fillColor: (in category 'private') -----
- exampleOn: destinationForm at: originPoint rule: rule fillColor: mask 
- 	"This builds a source and destination form and copies the source to the
- 	destination using the specifed rule and mask. It is called from the method
- 	named exampleOne. Only works with Display depth of 1"
- 
- 	| s d border aBitBlt | 
- 	border:=Form extent: 32 at 32.
- 	border fillBlack.
- 	border fill: (1 at 1 extent: 30 at 30) fillColor: Color white.
- 	s := Form extent: 32 at 32.
- 	s fillWhite.
- 	s fillBlack: (7 at 7 corner: 25 at 25).
- 	d := Form extent: 32 at 32.
- 	d fillWhite.
- 	d fillBlack: (0 at 0 corner: 32 at 16).
- 
- 	s displayOn: destinationForm at: originPoint.
- 	border displayOn: destinationForm at: originPoint rule: Form under.
- 	d displayOn: destinationForm at: originPoint + (s width @0).
- 	border displayOn: destinationForm at: originPoint + (s width @0) rule: Form under.
- 
- 	d displayOn: destinationForm at: originPoint + (s extent // (2 @ 1)). 
- 	aBitBlt := BitBlt
- 				destForm: destinationForm
- 				sourceForm: s
- 				fillColor: mask
- 				combinationRule: rule
- 				destOrigin: originPoint + (s extent // (2 @ 1))
- 				sourceOrigin: 0 @ 0
- 				extent: s extent
- 				clipRect: destinationForm computeBoundingBox.
- 	aBitBlt copyBits.
- 	border 
- 		displayOn: destinationForm at: originPoint + (s extent // (2 @ 1))
- 		rule: Form under.
- 
- 	"BitBlt exampleOn: Display at: 100 at 100 rule: 0 fillColor: nil"  !

Item was removed:
- ----- Method: BitBlt class>>exampleOne (in category 'examples') -----
- exampleOne
- 	"This tests BitBlt by displaying the result of all sixteen combination rules that BitBlt is capable of using. (Please see the comment in BitBlt for the meaning of the combination rules). This only works at Display depth of 1. (Rule 15 does not work?)"
- 	| pathClass path displayDepth destination |
- 
- 	(Display supportsDisplayDepth: 1)
- 		ifTrue:
- 			[displayDepth := Display depth.
- 			 Display newDepth: 1.
- 			 destination := Display]
- 		ifFalse:
- 			[destination := Form extent: 480 @ 400 depth: 1].
- 
- 	(Smalltalk hasClassNamed: #Path)
- 		ifTrue: [pathClass := Smalltalk at: #Path]
- 		ifFalse: [^self inform: 'MVC class Path not present in this image'].
- 	path := pathClass new.
- 	0 to: 3 do: [:i | 0 to: 3 do: [:j | path add: j * 100 @ (i * 75)]].
- 	destination fillWhite.
- 	path := path translateBy: 60 @ 40.
- 	1 to: 16 do:
- 		[:index |
- 		BitBlt
- 			exampleOn: destination
- 			at: (path at: index)
- 			rule: index - 1
- 			fillColor: nil].
- 
- 	destination ~~ Display ifTrue:
- 		[destination displayOn: Display at: 0 asPoint].
- 	[Sensor anyButtonPressed] whileFalse: [].
- 	displayDepth ifNotNil: [Display newDepth: displayDepth].
- 
- 	"BitBlt exampleOne"!

Item was removed:
- ----- Method: BitBlt class>>exampleTwo (in category 'examples') -----
- exampleTwo
- 	"This is to test painting with a gray tone. It also tests that the seaming with gray patterns is correct in the microcode. Lets you paint for a while and then automatically stops. This only works at Depth of 1."
- 	| f aBitBlt displayDepth |
- 	"create a small black Form source as a brush. "
- 	displayDepth := Display depth.
- 	Display newDepth: 1.
- 	f := Form extent: 20 @ 20.
- 	f fillBlack.
- 	"create a BitBlt which will OR gray into the display. "
- 	aBitBlt := BitBlt
- 		destForm: Display
- 		sourceForm: f
- 		fillColor: Color gray
- 		combinationRule: Form over
- 		destOrigin: Sensor cursorPoint
- 		sourceOrigin: 0 @ 0
- 		extent: f extent
- 		clipRect: Display computeBoundingBox.
- 	"paint the gray Form on the screen for a while. "
- 	[Sensor anyButtonPressed] whileFalse: 
- 		[aBitBlt destOrigin: Sensor cursorPoint.
- 		aBitBlt copyBits].
- 	Display newDepth: displayDepth.
- 	"BitBlt exampleTwo"!

Item was removed:
- ----- Method: BitBlt class>>initialize (in category 'class initialization') -----
- initialize
- 	self recreateColorMaps!

Item was removed:
- ----- Method: BitBlt class>>recreateColorMaps (in category 'private') -----
- recreateColorMaps
- 	CachedFontColorMaps := ColorConvertingMaps := nil!

Item was removed:
- ----- Method: BitBlt class>>subPixelRenderColorFonts (in category 'preferences') -----
- subPixelRenderColorFonts
- 
- 	<preference: 'Subpixel font rendering for color fonts'
- 	category: 'Graphics'
- 	description: 'If true, non-black opaque fonts are rendered using subpixel combination rules by BitBlt. Subpixel font rendering has to be enabled to take effect.'
- 	type: #Boolean>
- 	^SubPixelRenderColorFonts ifNil: [ true ]
- 
- 	!

Item was removed:
- ----- Method: BitBlt class>>subPixelRenderColorFonts: (in category 'preferences') -----
- subPixelRenderColorFonts: aBoolean
- 
- 	SubPixelRenderColorFonts := aBoolean
- 
- 	!

Item was removed:
- ----- Method: BitBlt class>>subPixelRenderFonts (in category 'preferences') -----
- subPixelRenderFonts
- 
- 	<preference: 'Subpixel font rendering'
- 	category: 'Graphics'
- 	description: 'If true, black fonts are rendered using subpixel combination rules by BitBlt.'
- 	type: #Boolean>
- 	^SubPixelRenderFonts ifNil: [ true ]
- 
- 	!

Item was removed:
- ----- Method: BitBlt class>>subPixelRenderFonts: (in category 'preferences') -----
- subPixelRenderFonts: aBoolean
- 
- 	SubPixelRenderFonts := aBoolean
- 
- 	!

Item was removed:
- ----- Method: BitBlt class>>toForm: (in category 'instance creation') -----
- toForm: aForm
- 	^ self new setDestForm: aForm!

Item was removed:
- ----- Method: BitBlt>>basicDisplayString:from:to:at:strikeFont:kern: (in category 'copying') -----
- basicDisplayString: aString from: startIndex to: stopIndex at: aPoint strikeFont: font kern: kernDelta
- 
- 	destY := aPoint y.
- 	destX := aPoint x.
- 
- 	"the following are not really needed, but theBitBlt primitive will fail if not set"
- 	sourceX ifNil: [sourceX := 100].
- 	width ifNil: [width := 100].
- 
- 	self primDisplayString: aString from: startIndex to: stopIndex
- 			map: font characterToGlyphMap xTable: font xTable
- 			kern: kernDelta.
- 	^ destX at destY.
- !

Item was removed:
- ----- Method: BitBlt>>cachedFontColormapFrom:to: (in category 'private') -----
- cachedFontColormapFrom: sourceDepth to: destDepth
- 
- 	| srcIndex map |
- 	CachedFontColorMaps class == Array 
- 		ifFalse: [CachedFontColorMaps := (1 to: 9) collect: [:i | Array new: 32]].
- 	srcIndex := sourceDepth.
- 	sourceDepth > 8 ifTrue: [srcIndex := 9].
- 	(map := (CachedFontColorMaps at: srcIndex) at: destDepth) ~~ nil ifTrue: [^ map].
- 
- 	map := (Color cachedColormapFrom: sourceDepth to: destDepth) copy.
- 	(CachedFontColorMaps at: srcIndex) at: destDepth put: map.
- 	^ map
- !

Item was removed:
- ----- Method: BitBlt>>clipBy: (in category 'accessing') -----
- clipBy: aRectangle
- 	| aPoint right bottom |
- 	right := clipX + clipWidth.
- 	bottom := clipY + clipHeight.
- 	aPoint := aRectangle origin.
- 	aPoint x > clipX ifTrue:[clipX := aPoint x].
- 	aPoint y > clipY ifTrue:[clipY := aPoint y].
- 	aPoint := aRectangle corner.
- 	aPoint x < right ifTrue:[right := aPoint x].
- 	aPoint y < bottom ifTrue:[bottom := aPoint y].
- 	clipWidth := right - clipX.
- 	clipHeight := bottom - clipY.
- 	clipWidth < 0 ifTrue:[clipWidth := 0].
- 	clipHeight < 0 ifTrue:[clipHeight := 0].!

Item was removed:
- ----- Method: BitBlt>>clipByX1:y1:x2:y2: (in category 'accessing') -----
- clipByX1: x1 y1: y1 x2: x2 y2: y2
- 	| right bottom |
- 	right := clipX + clipWidth.
- 	bottom := clipY + clipHeight.
- 	x1 > clipX ifTrue:[clipX := x1].
- 	y1 > clipY ifTrue:[clipY := y1].
- 	x2 < right ifTrue:[right := x2].
- 	y2 < bottom ifTrue:[bottom := y2].
- 	clipWidth := right - clipX.
- 	clipHeight := bottom - clipY.
- 	clipWidth < 0 ifTrue:[clipWidth := 0].
- 	clipHeight < 0 ifTrue:[clipHeight := 0].!

Item was removed:
- ----- Method: BitBlt>>clipHeight (in category 'accessing') -----
- clipHeight
- 	^clipHeight!

Item was removed:
- ----- Method: BitBlt>>clipHeight: (in category 'accessing') -----
- clipHeight: anInteger 
- 	"Set the receiver's clipping area height to be the argument, anInteger."
- 
- 	clipHeight := anInteger!

Item was removed:
- ----- Method: BitBlt>>clipRange (in category 'private') -----
- clipRange
- 	"clip and adjust source origin and extent appropriately"
- 	"first in x"
- 	| sx sy dx dy bbW bbH |
- 	"fill in the lazy state if needed"
- 	destX ifNil:[destX := 0].
- 	destY ifNil:[destY := 0].
- 	width ifNil:[width := destForm width].
- 	height ifNil:[height := destForm height].
- 	sourceX ifNil:[sourceX := 0].
- 	sourceY ifNil:[sourceY := 0].
- 	clipX ifNil:[clipX := 0].
- 	clipY ifNil:[clipY := 0].
- 	clipWidth ifNil:[clipWidth := destForm width].
- 	clipHeight ifNil:[clipHeight := destForm height].
- 
- 	destX >= clipX
- 		ifTrue: [sx := sourceX.
- 				dx := destX.
- 				bbW := width]
- 		ifFalse: [sx := sourceX + (clipX - destX).
- 				bbW := width - (clipX - destX).
- 				dx := clipX].
- 	(dx + bbW) > (clipX + clipWidth)
- 		ifTrue: [bbW := bbW - ((dx + bbW) - (clipX + clipWidth))].
- 	"then in y"
- 	destY >= clipY
- 		ifTrue: [sy := sourceY.
- 				dy := destY.
- 				bbH := height]
- 		ifFalse: [sy := sourceY + clipY - destY.
- 				bbH := height - (clipY - destY).
- 				dy := clipY].
- 	(dy + bbH) > (clipY + clipHeight)
- 		ifTrue: [bbH := bbH - ((dy + bbH) - (clipY + clipHeight))].
- 	sourceForm ifNotNil:[
- 		sx < 0
- 			ifTrue: [dx := dx - sx.
- 					bbW := bbW + sx.
- 					sx := 0].
- 		sx + bbW > sourceForm width
- 			ifTrue: [bbW := bbW - (sx + bbW - sourceForm width)].
- 		sy < 0
- 			ifTrue: [dy := dy - sy.
- 					bbH := bbH + sy.
- 					sy := 0].
- 		sy + bbH > sourceForm height
- 			ifTrue: [bbH := bbH - (sy + bbH - sourceForm height)].
- 	].
- 	(bbW <= 0 or:[bbH <= 0]) ifTrue:[
- 		sourceX := sourceY := destX := destY := clipX := clipY := width := height := clipWidth := clipHeight := 0.
- 		^true].
- 	(sx = sourceX 
- 		and:[sy = sourceY 
- 		and:[dx = destX 
- 		and:[dy = destY 
- 		and:[bbW = width 
- 		and:[bbH = height]]]]]) ifTrue:[^false].
- 	sourceX := sx.
- 	sourceY := sy.
- 	destX := dx.
- 	destY := dy.
- 	width := bbW.
- 	height := bbH.
- 	^true!

Item was removed:
- ----- Method: BitBlt>>clipRect (in category 'accessing') -----
- clipRect
- 	"Answer the receiver's clipping area rectangle."
- 
- 	^clipX @ clipY extent: clipWidth @ clipHeight!

Item was removed:
- ----- Method: BitBlt>>clipRect: (in category 'accessing') -----
- clipRect: aRectangle 
- 	"Set the receiver's clipping area rectangle to be the argument, aRectangle."
- 
- 	clipX := aRectangle left truncated.
- 	clipY := aRectangle top truncated.
- 	clipWidth := aRectangle right truncated - clipX.
- 	clipHeight := aRectangle bottom truncated - clipY.!

Item was removed:
- ----- Method: BitBlt>>clipWidth (in category 'accessing') -----
- clipWidth
- 	^clipWidth!

Item was removed:
- ----- Method: BitBlt>>clipWidth: (in category 'accessing') -----
- clipWidth: anInteger 
- 	"Set the receiver's clipping area width to be the argument, anInteger."
- 
- 	clipWidth := anInteger!

Item was removed:
- ----- Method: BitBlt>>clipX (in category 'accessing') -----
- clipX
- 	^clipX!

Item was removed:
- ----- Method: BitBlt>>clipX: (in category 'accessing') -----
- clipX: anInteger 
- 	"Set the receiver's clipping area top left x coordinate to be the argument, 
- 	anInteger."
- 
- 	clipX := anInteger!

Item was removed:
- ----- Method: BitBlt>>clipY (in category 'accessing') -----
- clipY
- 	^clipY!

Item was removed:
- ----- Method: BitBlt>>clipY: (in category 'accessing') -----
- clipY: anInteger 
- 	"Set the receiver's clipping area top left y coordinate to be the argument, 
- 	anInteger."
- 
- 	clipY := anInteger!

Item was removed:
- ----- Method: BitBlt>>color (in category 'accessing') -----
- color
- 	"Return the current fill color as a Color.  
- 	 Gives the wrong answer if the halftoneForm is a complex pattern of more than one word."
- 
- 	halftoneForm ifNil: [^ Color black].
- 	^ Color colorFromPixelValue: halftoneForm first depth: destForm depth!

Item was removed:
- ----- Method: BitBlt>>colorConvertingMap:from:to:keepSubPixelAA: (in category 'private') -----
- colorConvertingMap: targetColor from: sourceDepth to: destDepth keepSubPixelAA: keepSubPix
- 
- 	| srcIndex map mapsForSource mapsForSourceAndDest |
- 	ColorConvertingMaps class == Array 
- 		ifFalse: [ColorConvertingMaps := (1 to: 10) collect: [:i | Array new: 32]].
- 		
- 	srcIndex := sourceDepth.
- 	sourceDepth > 8 ifTrue: [ srcIndex := keepSubPix ifTrue: [9] ifFalse: [10] ].
- 	mapsForSource := ColorConvertingMaps at: srcIndex.
- 	mapsForSourceAndDest := (mapsForSource at: destDepth) ifNil: [ mapsForSource at: destDepth put: Dictionary new ].
- 	
- 	map := mapsForSourceAndDest at: targetColor ifAbsentPut: [
- 		Color computeColorConvertingMap: targetColor from: sourceDepth to: destDepth keepSubPixelAA: keepSubPix ].
- 
- 	^ map!

Item was removed:
- ----- Method: BitBlt>>colorMap (in category 'accessing') -----
- colorMap
- 	^ colorMap!

Item was removed:
- ----- Method: BitBlt>>colorMap: (in category 'accessing') -----
- colorMap: map
- 	"See last part of BitBlt comment. 6/18/96 tk"
- 	colorMap := map.!

Item was removed:
- ----- Method: BitBlt>>combinationRule (in category 'accessing') -----
- combinationRule
- 	"Answer the receiver's combinationRule"
- 	
- 	^combinationRule!

Item was removed:
- ----- Method: BitBlt>>combinationRule: (in category 'accessing') -----
- combinationRule: anInteger 
- 	"Set the receiver's combination rule to be the argument, anInteger, a 
- 	number in the range 0-15."
- 
- 	combinationRule := anInteger!

Item was removed:
- ----- Method: BitBlt>>copy:from:in: (in category 'copying') -----
- copy: destRectangle from: sourcePt in: srcForm
- 	| destOrigin |
- 	sourceForm := srcForm.
- 	halftoneForm := nil.
- 	combinationRule := 3.  "store"
- 	destOrigin := destRectangle origin.
- 	destX := destOrigin x.
- 	destY := destOrigin y.
- 	sourceX := sourcePt x.
- 	sourceY := sourcePt y.
- 	width := destRectangle width.
- 	height := destRectangle height.
- 	self copyBits!

Item was removed:
- ----- Method: BitBlt>>copy:from:in:fillColor:rule: (in category 'copying') -----
- copy: destRectangle from: sourcePt in: srcForm fillColor: hf rule: rule
- 	"Specify a Color to fill, not a Form. 6/18/96 tk"  
- 	| destOrigin |
- 	sourceForm := srcForm.
- 	self fillColor: hf.	"sets halftoneForm"
- 	combinationRule := rule.
- 	destOrigin := destRectangle origin.
- 	destX := destOrigin x.
- 	destY := destOrigin y.
- 	sourceX := sourcePt x.
- 	sourceY := sourcePt y.
- 	width := destRectangle width.
- 	height := destRectangle height.
- 	srcForm == nil ifFalse:
- 		[colorMap := srcForm colormapIfNeededFor: destForm].
- 	^ self copyBits!

Item was removed:
- ----- Method: BitBlt>>copy:from:in:halftoneForm:rule: (in category 'copying') -----
- copy: destRectangle from: sourcePt in: srcForm halftoneForm: hf rule: rule 
- 	| destOrigin |
- 	sourceForm := srcForm.
- 	self fillColor: hf.		"sets halftoneForm"
- 	combinationRule := rule.
- 	destOrigin := destRectangle origin.
- 	destX := destOrigin x.
- 	destY := destOrigin y.
- 	sourceX := sourcePt x.
- 	sourceY := sourcePt y.
- 	width := destRectangle width.
- 	height := destRectangle height.
- 	self copyBits!

Item was removed:
- ----- Method: BitBlt>>copyBits (in category 'copying') -----
- copyBits
- 	"Primitive. Perform the movement of bits from the source form to the 
- 	destination form. Fail if any variables are not of the right type (Integer, 
- 	Float, or Form) or if the combination rule is not implemented. 
- 
- 	NOTE THAT this method has the side effect of showing the copied bits on
- 	screen if the destination form happens to be Display. The mechanism is
- 	similar to calling #primShowRectLeft:right:top:bottom: manually.
- 
- 	In addition to the original 16 combination rules, this BitBlt supports
- 	16	fail (to simulate paint)
- 	17	fail (to simulate mask)
- 	18	sourceWord + destinationWord
- 	19	sourceWord - destinationWord
- 	20	rgbAdd: sourceWord with: destinationWord
- 	21	rgbSub: sourceWord with: destinationWord
- 	22	rgbDiff: sourceWord with: destinationWord
- 	23	tallyIntoMap: destinationWord
- 	24	alphaBlend: sourceWord with: destinationWord
- 	25	pixPaint: sourceWord with: destinationWord
- 	26	pixMask: sourceWord with: destinationWord
- 	27	rgbMax: sourceWord with: destinationWord
- 	28	rgbMin: sourceWord with: destinationWord
- 	29	rgbMin: sourceWord bitInvert32 with: destinationWord
- "
- 	<primitive: 'primitiveCopyBits' module: 'BitBltPlugin' error: ec>
- 
- 	(combinationRule >= 30 and: [combinationRule <= 31]) ifTrue:
- 		["No alpha specified -- re-run with alpha = 1.0"
- 		^ self copyBitsTranslucent: 255].
- 	"Check for object movement during a surface callback, compressed source, destination or halftone forms.
- 	 Simply retry."
- 	(ec == #'object moved'
- 	 or: [(sourceForm isForm and: [sourceForm unhibernate])
- 	 or: [(destForm isForm and: [destForm unhibernate])
- 	 or: [halftoneForm isForm and: [halftoneForm unhibernate]]]]) ifTrue:
- 		[^self copyBits].
- 
- 	"Check for unimplmented rules"
- 	combinationRule = Form oldPaint ifTrue: [^self paintBits].
- 	combinationRule = Form oldErase1bitShape ifTrue: [^self eraseBits].
- 
- 	"Check if BitBlt doesn't support full color maps"
- 	(colorMap notNil and: [colorMap isColormap]) ifTrue:
- 		[colorMap := colorMap colors.
- 		^self copyBits].
- 	"Check if clipping got way out of range"
- 	self clipRange.
- 	"Convert all numeric parameters to integers and try again."
- 	self roundVariables.
- 	^self copyBitsAgain!

Item was removed:
- ----- Method: BitBlt>>copyBitsAgain (in category 'private') -----
- copyBitsAgain
- 	"Primitive. See BitBlt|copyBits, also a Primitive. Essential. See Object
- 	documentation whatIsAPrimitive."
- 
- 	<primitive: 'primitiveCopyBits' module: 'BitBltPlugin' error: ec>
- 	self primitiveFailed!

Item was removed:
- ----- Method: BitBlt>>copyBitsFrom:to:at: (in category 'private') -----
- copyBitsFrom: x0 to: x1 at: y
- 	destX := x0.
- 	destY := y.
- 	sourceX := x0.
- 	width := (x1 - x0).
- 	self copyBits.!

Item was removed:
- ----- Method: BitBlt>>copyBitsTranslucent: (in category 'copying') -----
- copyBitsTranslucent: factor
- 	"This entry point to BitBlt supplies an extra argument to specify translucency
- 	for operations 30 and 31.  The argument must be an integer between 0 and 255."
- 
- 	<primitive: 'primitiveCopyBits' module: 'BitBltPlugin'>
- 
- 	"Check for compressed source, destination or halftone forms"
- 	((sourceForm isForm) and: [sourceForm unhibernate])
- 		ifTrue: [^ self copyBitsTranslucent: factor].
- 	((destForm isForm) and: [destForm unhibernate])
- 		ifTrue: [^ self copyBitsTranslucent: factor].
- 	((halftoneForm isForm) and: [halftoneForm unhibernate])
- 		ifTrue: [^ self copyBitsTranslucent: factor].
- 
- 	self primitiveFailed  "Later do nicer error recovery -- share copyBits recovery"!

Item was removed:
- ----- Method: BitBlt>>copyForm:to:rule: (in category 'copying') -----
- copyForm: srcForm to: destPt rule: rule
- 	^ self copyForm: srcForm to: destPt rule: rule
- 		colorMap: (srcForm colormapIfNeededFor: destForm)!

Item was removed:
- ----- Method: BitBlt>>copyForm:to:rule:color: (in category 'copying') -----
- copyForm: srcForm to: destPt rule: rule color: color
- 	sourceForm := srcForm.
- 	halftoneForm := color.
- 	combinationRule := rule.
- 	destX := destPt x + sourceForm offset x.
- 	destY := destPt y + sourceForm offset y.
- 	sourceX := 0.
- 	sourceY := 0.
- 	width := sourceForm width.
- 	height := sourceForm height.
- 	self copyBits!

Item was removed:
- ----- Method: BitBlt>>copyForm:to:rule:colorMap: (in category 'copying') -----
- copyForm: srcForm to: destPt rule: rule colorMap: map
- 	sourceForm := srcForm.
- 	halftoneForm := nil.
- 	combinationRule := rule.
- 	destX := destPt x + sourceForm offset x.
- 	destY := destPt y + sourceForm offset y.
- 	sourceX := 0.
- 	sourceY := 0.
- 	width := sourceForm width.
- 	height := sourceForm height.
- 	colorMap := map.
- 	self copyBits!

Item was removed:
- ----- Method: BitBlt>>copyForm:to:rule:fillColor: (in category 'copying') -----
- copyForm: srcForm to: destPt rule: rule fillColor: color
- 	sourceForm := srcForm.
- 	self fillColor: color.	"sets halftoneForm"
- 	combinationRule := rule.
- 	destX := destPt x + sourceForm offset x.
- 	destY := destPt y + sourceForm offset y.
- 	sourceX := 0.
- 	sourceY := 0.
- 	width := sourceForm width.
- 	height := sourceForm height.
- 	self copyBits!

Item was removed:
- ----- Method: BitBlt>>copyFrom:in:to: (in category 'copying') -----
- copyFrom: sourceRectangle in: srcForm to: destPt
- 	| sourceOrigin |
- 	sourceForm := srcForm.
- 	halftoneForm := nil.
- 	combinationRule := 3.  "store"
- 	destX := destPt x.
- 	destY := destPt y.
- 	sourceOrigin := sourceRectangle origin.
- 	sourceX := sourceOrigin x.
- 	sourceY := sourceOrigin y.
- 	width := sourceRectangle width.
- 	height := sourceRectangle height.
- 	colorMap := srcForm colormapIfNeededFor: destForm.
- 	self copyBits!

Item was removed:
- ----- Method: BitBlt>>destForm (in category 'accessing') -----
- destForm
- 	^ destForm!

Item was removed:
- ----- Method: BitBlt>>destOrigin: (in category 'accessing') -----
- destOrigin: aPoint 
- 	"Set the receiver's destination top left coordinates to be those of the 
- 	argument, aPoint."
- 
- 	destX := aPoint x.
- 	destY := aPoint y!

Item was removed:
- ----- Method: BitBlt>>destRect (in category 'accessing') -----
- destRect
- 	"The rectangle we are about to blit to or just blitted to.  "
- 
- 	^ destX @ destY extent: width @ height!

Item was removed:
- ----- Method: BitBlt>>destRect: (in category 'accessing') -----
- destRect: aRectangle 
- 	"Set the receiver's destination form top left coordinates to be the origin of 
- 	the argument, aRectangle, and set the width and height of the receiver's 
- 	destination form to be the width and height of aRectangle."
- 
- 	destX := aRectangle left.
- 	destY := aRectangle top.
- 	width := aRectangle width.
- 	height := aRectangle height!

Item was removed:
- ----- Method: BitBlt>>destX: (in category 'accessing') -----
- destX: anInteger 
- 	"Set the top left x coordinate of the receiver's destination form to be the 
- 	argument, anInteger."
- 
- 	destX := anInteger!

Item was removed:
- ----- Method: BitBlt>>destX:destY:width:height: (in category 'accessing') -----
- destX: x destY: y width: w height: h
- 	"Combined init message saves 3 sends from DisplayScanner"
- 	destX := x.
- 	destY := y.
- 	width := w.
- 	height := h.!

Item was removed:
- ----- Method: BitBlt>>destY: (in category 'accessing') -----
- destY: anInteger 
- 	"Set the top left y coordinate of the receiver's destination form to be the 
- 	argument, anInteger."
- 
- 	destY := anInteger!

Item was removed:
- ----- Method: BitBlt>>displayGlyph:at:left:right:font: (in category 'copying') -----
- displayGlyph: aForm at: aPoint left: leftX right: rightX font: aFont
- 	"Display a glyph in a multi-lingual font. Do 2 pass rendering if necessary.
- 	This happens when #installStrikeFont:foregroundColor:backgroundColor: sets rule 37 (rgbMul).
- 	the desired effect is to do two bitblt calls. The first one is with rule 37 and special colormap.
- 	The second one is rule 34, with a colormap for applying the requested foreground color.
- 	This two together do component alpha blending, i.e. alpha blend red, green and blue separatedly.
- 	This is needed for arbitrary color over abitrary background text with subpixel AA."
- 
- 	| prevRule secondPassMap |
- 	self sourceForm: aForm.
- 	destX := aPoint x.
- 	destY := aPoint y.
- 	sourceX := leftX.
- 	sourceY := 0.
- 	width := rightX - leftX.
- 	height := aFont height.
- 	combinationRule = 37 ifTrue:[
- 		"We need to do a second pass. The colormap set is for use in the second pass."
- 		secondPassMap := colorMap.
- 		colorMap := sourceForm depth = destForm depth
- 			ifFalse: [ self cachedFontColormapFrom: sourceForm depth to: destForm depth ].
- 		self copyBits.
- 		prevRule := combinationRule.
- 		combinationRule := 20. "rgbAdd"
- 		colorMap := secondPassMap.
- 		self copyBits.
- 		combinationRule := prevRule.
- 	] ifFalse:[self copyBits].!

Item was removed:
- ----- Method: BitBlt>>displayString:from:to:at:strikeFont:kern: (in category 'copying') -----
- displayString: aString from: startIndex to: stopIndex at: aPoint strikeFont: font kern: kernDelta
- 	"If required, do a second pass with new rule and colorMap.
- 	This happens when #installStrikeFont:foregroundColor:backgroundColor: sets rule 37 (rgbMul).
- 	the desired effect is to do two bitblt calls. The first one is with rule 37 and special colormap.
- 	The second one is rule 34, with a colormap for applying the requested foreground color.
- 	This two together do component alpha blending, i.e. alpha blend red, green and blue separatedly.
- 	This is needed for arbitrary color over abitrary background text with subpixel AA."
- 
- 	| answer prevRule secondPassMap |
- 	"If combinationRule is rgbMul, we might need the special two-pass technique for component alpha blending.
- 	If not, do it simply"
- 	combinationRule = 37 "rgbMul" ifFalse: [
- 		^self basicDisplayString: aString from: startIndex to: stopIndex at: aPoint strikeFont: font kern: kernDelta ].
- 	
- 	"We need to do a second pass. The colormap set is for use in the second pass."
- 	secondPassMap := colorMap.
- 	colorMap := sourceForm depth ~= destForm depth
- 		ifTrue: [ self cachedFontColormapFrom: sourceForm depth to: destForm depth ].
- 	answer := self basicDisplayString: aString from: startIndex to: stopIndex at: aPoint strikeFont: font kern: kernDelta.
- 	colorMap := secondPassMap.
- 	secondPassMap ifNotNil: [
- 		prevRule := combinationRule.
- 		combinationRule := 20. "rgbAdd"
- 		self basicDisplayString: aString from: startIndex to: stopIndex at: aPoint strikeFont: font kern: kernDelta.
- 		combinationRule := prevRule ].
- 	^answer!

Item was removed:
- ----- Method: BitBlt>>drawFrom:to: (in category 'line drawing') -----
- drawFrom: startPoint to: stopPoint 
- 	
- 	 ^ self drawFrom: startPoint to: stopPoint withFirstPoint: true!

Item was removed:
- ----- Method: BitBlt>>drawFrom:to:withFirstPoint: (in category 'line drawing') -----
- drawFrom: startPoint to: stopPoint withFirstPoint: drawFirstPoint
- 	"Draw a line whose end points are startPoint and stopPoint.
- 	The line is formed by repeatedly calling copyBits at every
- 	point along the line.  If drawFirstPoint is false, then omit
- 	the first point so as not to overstrike at line junctions."
- 	| offset point1 point2 forwards |
- 	"Always draw down, or at least left-to-right"
- 	forwards := (startPoint y = stopPoint y and: [startPoint x < stopPoint x])
- 				or: [startPoint y < stopPoint y].
- 	forwards
- 		ifTrue: [point1 := startPoint. point2 := stopPoint]
- 		ifFalse: [point1 := stopPoint. point2 := startPoint].
- 	sourceForm == nil ifTrue:
- 		[destX := point1 x.
- 		destY := point1 y]
- 		ifFalse:
- 		[width := sourceForm width.
- 		height := sourceForm height.
- 		offset := sourceForm offset.
- 		destX := (point1 x + offset x) rounded.
- 		destY := (point1 y + offset y) rounded].
- 
- 	"Note that if not forwards, then the first point is the last and vice versa.
- 	We agree to always paint stopPoint, and to optionally paint startPoint."
- 	(drawFirstPoint or: [forwards == false  "ie this is stopPoint"])
- 		ifTrue: [self copyBits].
- 	self drawLoopX: (point2 x - point1 x) rounded 
- 				  Y: (point2 y - point1 y) rounded.
- 	(drawFirstPoint or: [forwards  "ie this is stopPoint"])
- 		ifTrue: [self copyBits].
- !

Item was removed:
- ----- Method: BitBlt>>drawLoopX:Y: (in category 'line drawing') -----
- drawLoopX: xDelta Y: yDelta 
- 	"Primitive. Implements the Bresenham plotting algorithm (IBM Systems
- 	Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and
- 	maintains a potential, P. When P's sign changes, it is time to move in
- 	the minor direction as well. This particular version does not write the
- 	first and last points, so that these can be called for as needed in client code.
- 	Optional. See Object documentation whatIsAPrimitive."
- 	| dx dy px py P |
- 	<primitive: 'primitiveDrawLoop' module: 'BitBltPlugin'>
- 	dx := xDelta sign.
- 	dy := yDelta sign.
- 	px := yDelta abs.
- 	py := xDelta abs.
- 	"self copyBits."
- 	py > px
- 		ifTrue: 
- 			["more horizontal"
- 			P := py // 2.
- 			1 to: py do: 
- 				[:i |
- 				destX := destX + dx.
- 				(P := P - px) < 0 ifTrue: 
- 						[destY := destY + dy.
- 						P := P + py].
- 				i < py ifTrue: [self copyBits]]]
- 		ifFalse: 
- 			["more vertical"
- 			P := px // 2.
- 			1 to: px do:
- 				[:i |
- 				destY := destY + dy.
- 				(P := P - py) < 0 ifTrue: 
- 						[destX := destX + dx.
- 						P := P + px].
- 				i < px ifTrue: [self copyBits]]]!

Item was removed:
- ----- Method: BitBlt>>eraseBits (in category 'private') -----
- eraseBits
- 	"Perform the erase operation, which puts 0's in the destination
- 	wherever the source (which is assumed to be just 1 bit deep)
- 	has a 1.  This requires the colorMap to be set in order to AND
- 	all 1's into the destFrom pixels regardless of their size."
- 	| oldMask oldMap |
- 	oldMask := halftoneForm.
- 	halftoneForm := nil.
- 	oldMap := colorMap.
- 	self colorMap: (Bitmap with: 0 with: 16rFFFFFFFF).
- 	combinationRule := Form erase.
- 	self copyBits. 		"Erase the dest wherever the source is 1"
- 	halftoneForm := oldMask.	"already converted to a Bitmap"
- 	colorMap := oldMap!

Item was removed:
- ----- Method: BitBlt>>fill:fillColor:rule: (in category 'copying') -----
- fill: destRect fillColor: grayForm rule: rule
- 	"Fill with a Color, not a Form. 6/18/96 tk"
- 	sourceForm := nil.
- 	self fillColor: grayForm.		"sets halftoneForm"
- 	combinationRule := rule.
- 	destX := destRect left.
- 	destY := destRect top.
- 	sourceX := 0.
- 	sourceY := 0.
- 	width := destRect width.
- 	height := destRect height.
- 	self copyBits!

Item was removed:
- ----- Method: BitBlt>>fillColor (in category 'accessing') -----
- fillColor
- 	^ halftoneForm!

Item was removed:
- ----- Method: BitBlt>>fillColor: (in category 'accessing') -----
- fillColor: aColorOrPattern 
- 	"The destForm will be filled with this color or pattern of colors.  May be an old Color, a new type Color, a Bitmap (see BitBlt comment), a Pattern, or a Form.  6/18/96 tk"
- 
- 	aColorOrPattern == nil ifTrue: [halftoneForm := nil. ^ self].
- 	destForm == nil ifTrue: [self error: 'Must set destForm first'].
- 	halftoneForm := destForm bitPatternFor: aColorOrPattern !

Item was removed:
- ----- Method: BitBlt>>getPluginName (in category 'private') -----
- getPluginName
- 	"Private. Return the name of the plugin representing BitBlt.
- 	Used for dynamically switching between different BB representations only."
- 	^'BitBltPlugin'!

Item was removed:
- ----- Method: BitBlt>>halftoneForm (in category 'accessing') -----
- halftoneForm
- 	"Returns the receivers half tone form. See class commment."
- 	
- 	^halftoneForm!

Item was removed:
- ----- Method: BitBlt>>halftoneForm: (in category 'accessing') -----
- halftoneForm: aBitmap
- 	"Sets the receivers half tone form. See class commment."
- 	
- 	halftoneForm := aBitmap
- 	
-  !

Item was removed:
- ----- Method: BitBlt>>height: (in category 'accessing') -----
- height: anInteger 
- 	"Set the receiver's destination form height to be the argument, anInteger."
- 
- 	height := anInteger!

Item was removed:
- ----- Method: BitBlt>>installStrikeFont: (in category 'private') -----
- installStrikeFont: aStrikeFont
- 
- 	^ self installStrikeFont: aStrikeFont foregroundColor: Color black backgroundColor: Color transparent!

Item was removed:
- ----- Method: BitBlt>>installStrikeFont:foregroundColor:backgroundColor: (in category 'private') -----
- installStrikeFont: aStrikeFont foregroundColor: foregroundColor backgroundColor: backgroundColor
- 	| lastSourceDepth targetColor |
- 	sourceForm ifNotNil:[lastSourceDepth := sourceForm depth].
- 	sourceForm := aStrikeFont glyphs.
- 
- 	"Ignore any halftone pattern since we use a color map approach here"
- 	halftoneForm := nil.
- 	sourceY := 0.
- 	height := aStrikeFont height.
- 
- 	sourceForm depth = 1 ifTrue: [
- 		self combinationRule: Form paint.
- 		(colorMap notNil and:[lastSourceDepth = sourceForm depth]) ifFalse: [
- 			"Set up color map for a different source depth (color font)"
- 			"Uses caching for reasonable efficiency"
- 			colorMap := self cachedFontColormapFrom: sourceForm depth to: destForm depth.
- 			colorMap at: 1 put: (destForm pixelValueFor: backgroundColor)].
- 		colorMap at: 2 put: (destForm pixelValueFor: foregroundColor).
- 	]
- 	ifFalse: [
- 		(self class subPixelRenderFonts and: [ foregroundColor = Color black
- 			"Only use rgbMul with opaque colors as alpha values get lost for translucent colors."
- 			or: [ self class subPixelRenderColorFonts and: [foregroundColor isOpaque] ]]) ifTrue: [
- 			destForm depth > 8 ifTrue: [
- 				"rgbMul is equivalent to component alpha blend if text is black (only faster, hehe)"
- 				self combinationRule: Form rgbMul.
- 				colorMap := (destForm depth = 32 or: [ (foregroundColor = Color black) not ]) ifTrue: [
- 					"rgbMul / rgbAdd IS component alpha blend for any color of text (neat trick, eh!!)"
- 					"This colorMap is to be used on the second pass with rule 20 (rgbAdd)
- 					See #displayString:from:to:at:strikeFont:kern:"
- 					"Note: In 32bpp we always need the second pass, as the source could have transparent pixels, and we need to add to the alpha channel"
- 					self colorConvertingMap: foregroundColor from: sourceForm depth to: destForm depth keepSubPixelAA: true]]
- 			ifFalse: [
- 				self combinationRule: Form paint.
- 				targetColor := foregroundColor = Color black ifFalse: [ foregroundColor ].
- 				colorMap := self colorConvertingMap: targetColor from: sourceForm depth to: destForm depth keepSubPixelAA: true]
- 		]
- 		ifFalse: [
- 			"Do not use rule 34 for 16bpp display. TTCFont uses it, but it builds a glyphs cache for each color used!!"
- 			self combinationRule: (destForm depth = 32 ifTrue: [Form blendAlphaScaled] ifFalse: [Form paint]).
- 			colorMap := self colorConvertingMap: foregroundColor from: sourceForm depth to: destForm depth keepSubPixelAA: false
- 		]
- 	].!

Item was removed:
- ----- Method: BitBlt>>installTTCFont: (in category 'private') -----
- installTTCFont: aTTCFont
- 
- 	^ self installTTCFont: aTTCFont foregroundColor: Color black backgroundColor: Color transparent!

Item was removed:
- ----- Method: BitBlt>>installTTCFont:foregroundColor:backgroundColor: (in category 'private') -----
- installTTCFont: aTTCFont foregroundColor: foregroundColor backgroundColor: backgroundColor
- 	"Set up the parameters.  Since the glyphs in a TTCFont is 32bit depth form, it tries to use rule=34 to get better AA result if possible."
- 
- 	((aTTCFont depth = 32)) ifTrue: [
- 		destForm depth <= 8 ifTrue: [
- 			self colorMap: (self cachedFontColormapFrom: aTTCFont depth to: destForm depth).
- 			self combinationRule: Form paint.
- 		] ifFalse: [
- 			self colorMap: nil.
- 			self combinationRule: 34.
- 		].
- 		halftoneForm := nil.
- 		sourceY := 0.
- 		height := aTTCFont height.
- 	].
- !

Item was removed:
- ----- Method: BitBlt>>paintBits (in category 'private') -----
- paintBits
- 	"Perform the paint operation, which requires two calls to BitBlt."
- 	| color oldMap saveRule |
- 	sourceForm depth = 1 ifFalse: 
- 		[^ self halt: 'paint operation is only defined for 1-bit deep sourceForms'].
- 	saveRule := combinationRule.
- 	color := halftoneForm.  halftoneForm := nil.
- 	oldMap := colorMap.
- 	"Map 1's to ALL ones, not just one"
- 	self colorMap: (Bitmap with: 0 with: 16rFFFFFFFF).
- 	combinationRule := Form erase.
- 	self copyBits. 		"Erase the dest wherever the source is 1"
- 	halftoneForm := color.
- 	combinationRule := Form under.
- 	self copyBits.	"then OR, with whatever color, into the hole"
- 	colorMap := oldMap.
- 	combinationRule := saveRule
- 
- " | dot |
- dot := Form dotOfSize: 32.
- ((BitBlt destForm: Display
- 		sourceForm: dot
- 		fillColor: Color lightGray
- 		combinationRule: Form paint
- 		destOrigin: Sensor cursorPoint
- 		sourceOrigin: 0 at 0
- 		extent: dot extent
- 		clipRect: Display boundingBox)
- 		colorMap: (Bitmap with: 0 with: 16rFFFFFFFF)) copyBits"!

Item was removed:
- ----- Method: BitBlt>>pixelAt: (in category 'copying') -----
- pixelAt: aPoint
- 	"Assumes this BitBlt has been set up specially (see the init message,
- 	BitBlt bitPeekerFromForm:.  Returns the pixel at aPoint."
- 	sourceX := aPoint x.
- 	sourceY := aPoint y.
- 	destForm unhibernate. "before poking"
- 	destForm bits at: 1 put: 0.  "Just to be sure"
- 	self copyBits.
- 	^ destForm bits at: 1!

Item was removed:
- ----- Method: BitBlt>>pixelAt:put: (in category 'copying') -----
- pixelAt: aPoint put: pixelValue
- 	"Assumes this BitBlt has been set up specially (see the init message,
- 	BitBlt bitPokerToForm:.  Overwrites the pixel at aPoint."
- 	destX := aPoint x.
- 	destY := aPoint y.
- 	sourceForm unhibernate. "before poking"
- 	sourceForm bits at: 1 put: pixelValue.
- 	self copyBits
- "
- | bb |
- bb := (BitBlt bitPokerToForm: Display).
- [Sensor anyButtonPressed] whileFalse:
- 	[bb pixelAt: Sensor cursorPoint put: 55]
- "!

Item was removed:
- ----- Method: BitBlt>>primCompareColor:to:test: (in category 'private') -----
- primCompareColor: colorValueA to: colorValueB test: testID
- 	"Call the prim that compares pixel color values and can tell if two Forms that overlap in some manner when composited are touching colors as defined by the testID.
- "
- 	<primitive: 'primitiveCompareColors' module: 'BitBltPlugin'>
- 	"to signal failure without an error we'll return -1"
- 	^-1!

Item was removed:
- ----- Method: BitBlt>>primDisplayString:from:to:map:xTable:kern: (in category 'private') -----
- primDisplayString: aString from: startIndex to: stopIndex map: glyphMap xTable: xTable kern: kernDelta
- 	| ascii |
- 	<primitive:'primitiveDisplayString' module:'BitBltPlugin'>
- 
- 	((sourceForm isForm) and: [sourceForm unhibernate])
- 		ifTrue: [^ self primDisplayString: aString from: startIndex to: stopIndex map: glyphMap xTable: xTable kern: kernDelta].
- 	((destForm isForm) and: [destForm unhibernate])
- 		ifTrue: [^ self primDisplayString: aString from: startIndex to: stopIndex map: glyphMap xTable: xTable kern: kernDelta].
- 	((halftoneForm isForm) and: [halftoneForm unhibernate])
- 		ifTrue: [^ self primDisplayString: aString from: startIndex to: stopIndex map: glyphMap xTable: xTable kern: kernDelta].
- 
- 	startIndex to: stopIndex do:[:charIndex|
- 		ascii := (aString at: charIndex) asciiValue.
- 		glyphMap ifNotNil:[ascii := glyphMap at: ascii+1].
- 		sourceX := xTable at: ascii + 1.
- 		width := (xTable at: ascii + 2) - sourceX.
- 		self copyBits.
- 		destX := destX + width + kernDelta.
- 	].!

Item was removed:
- ----- Method: BitBlt>>roundVariables (in category 'private') -----
- roundVariables
- 
- 	| maxVal minVal |
- 	maxVal := SmallInteger maxVal.
- 	minVal := SmallInteger minVal.
- 	destX := destX asInteger min: maxVal max: minVal.
- 	destY := destY asInteger min: maxVal max: minVal.
- 	width := width asInteger min: maxVal max: minVal.
- 	height := height asInteger min: maxVal max: minVal.
- 	sourceX := sourceX asInteger min: maxVal max: minVal.
- 	sourceY := sourceY asInteger min: maxVal max: minVal.
- 	clipX := clipX asInteger min: maxVal max: minVal.
- 	clipY := clipY asInteger min: maxVal max: minVal.
- 	clipWidth := clipWidth asInteger min: maxVal max: minVal.
- 	clipHeight := clipHeight asInteger min: maxVal max: minVal.
- !

Item was removed:
- ----- Method: BitBlt>>setDestForm: (in category 'private') -----
- setDestForm: df
- 	| bb |
- 	bb := df boundingBox.
- 	destForm := df.
- 	clipX := bb left.
- 	clipY := bb top.
- 	clipWidth := bb width.
- 	clipHeight := bb height!

Item was removed:
- ----- Method: BitBlt>>setDestForm:sourceForm:fillColor:combinationRule:destOrigin:sourceOrigin:extent:clipRect: (in category 'private') -----
- setDestForm: df sourceForm: sf fillColor: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect
- 
- 	| aPoint |
- 	destForm := df.
- 	sourceForm := sf.
- 	self fillColor: hf.	"sets halftoneForm"
- 	combinationRule := cr.
- 	destX := destOrigin x.
- 	destY := destOrigin y.
- 	sourceX := sourceOrigin x.
- 	sourceY := sourceOrigin y.
- 	width := extent x.
- 	height := extent y.
- 	aPoint := clipRect origin.
- 	clipX := aPoint x.
- 	clipY := aPoint y.
- 	aPoint := clipRect corner.
- 	clipWidth := aPoint x - clipX.
- 	clipHeight := aPoint y - clipY.
- 	sourceForm == nil ifFalse:
- 		[colorMap := sourceForm colormapIfNeededFor: destForm]!

Item was removed:
- ----- Method: BitBlt>>sourceForm (in category 'accessing') -----
- sourceForm
- 
- 	^ sourceForm!

Item was removed:
- ----- Method: BitBlt>>sourceForm: (in category 'accessing') -----
- sourceForm: aForm 
- 	"Set the receiver's source form to be the argument, aForm."
- 
- 	sourceForm := aForm!

Item was removed:
- ----- Method: BitBlt>>sourceOrigin: (in category 'accessing') -----
- sourceOrigin: aPoint 
- 	"Set the receiver's source form coordinates to be those of the argument, 
- 	aPoint."
- 
- 	sourceX := aPoint x.
- 	sourceY := aPoint y!

Item was removed:
- ----- Method: BitBlt>>sourceRect: (in category 'accessing') -----
- sourceRect: aRectangle 
- 	"Set the receiver's source form top left x and y, width and height to be 
- 	the top left coordinate and extent of the argument, aRectangle."
- 
- 	sourceX := aRectangle left.
- 	sourceY := aRectangle top.
- 	width := aRectangle width.
- 	height := aRectangle height!

Item was removed:
- ----- Method: BitBlt>>sourceX: (in category 'accessing') -----
- sourceX: anInteger 
- 	"Set the receiver's source form top left x to be the argument, anInteger."
- 
- 	sourceX := anInteger!

Item was removed:
- ----- Method: BitBlt>>sourceY: (in category 'accessing') -----
- sourceY: anInteger 
- 	"Set the receiver's source form top left y to be the argument, anInteger."
- 
- 	sourceY := anInteger!

Item was removed:
- ----- Method: BitBlt>>tallyMap (in category 'accessing') -----
- tallyMap
- 	"Return the map used for tallying pixels"
- 	^colorMap!

Item was removed:
- ----- Method: BitBlt>>tallyMap: (in category 'accessing') -----
- tallyMap: aBitmap
- 	"Install the map used for tallying pixels"
- 	colorMap := aBitmap!

Item was removed:
- ----- Method: BitBlt>>width: (in category 'accessing') -----
- width: anInteger 
- 	"Set the receiver's destination form width to be the argument, anInteger."
- 
- 	width := anInteger!

Item was removed:
- DisplayScanner subclass: #BitBltDisplayScanner
- 	instanceVariableNames: 'bitBlt fillBlt'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Text'!
- 
- !BitBltDisplayScanner commentStamp: 'nice 10/12/2013 01:36' prior: 0!
- A BitBltDisplayScanner displays characters on Screen or other Form with help of a BitBlt.
- 
- Instance Variables
- 	bitBlt:		<BitBlt>
- 	fillBlt:		<BitBlt>
- 
- bitBlt
- 	- the object which knows how to copy bits from one Form (the font glyph data) to another (the destination Form)
- 
- fillBlt
- 	- another object for copying form bits, initialized for displaying the background.
- 
- !

Item was removed:
- ----- Method: BitBltDisplayScanner class>>defaultFont (in category 'queries') -----
- defaultFont
- 	^ TextStyle defaultFont!

Item was removed:
- ----- Method: BitBltDisplayScanner>>displayEmbeddedForm:at: (in category 'displaying') -----
- displayEmbeddedForm: aForm at: aPoint
- 
- 	aForm 
- 		displayOn: bitBlt destForm 
- 		at: aPoint
- 		clippingBox: bitBlt clipRect
- 		rule: Form blend
- 		fillColor: Color white !

Item was removed:
- ----- Method: BitBltDisplayScanner>>displayString:from:to:at: (in category 'displaying') -----
- displayString: string from: startIndex to: stopIndex at: aPoint
- 	
- 	font 
- 		displayString: string 
- 		on: bitBlt 
- 		from: startIndex 
- 		to: stopIndex 
- 		at: aPoint 
- 		kern: kern!

Item was removed:
- ----- Method: BitBltDisplayScanner>>fillTextBackground (in category 'displaying') -----
- fillTextBackground
- 	fillBlt == nil ifFalse:
- 		["Not right"
- 		fillBlt destX: line left destY: lineY
- 			width: line width left height: line lineHeight; copyBits].!

Item was removed:
- ----- Method: BitBltDisplayScanner>>plainTab (in category 'stop conditions') -----
- plainTab
- 	| nextDestX |
-  	nextDestX := super plainTab.
- 	fillBlt == nil ifFalse:
- 		[fillBlt destX: destX destY: destY width: nextDestX - destX height: font height; copyBits].
- 	^nextDestX!

Item was removed:
- ----- Method: BitBltDisplayScanner>>setDestForm: (in category 'private') -----
- setDestForm: df
- 	bitBlt setDestForm: df.!

Item was removed:
- ----- Method: BitBltDisplayScanner>>setFont (in category 'private') -----
- setFont 
- 	super setFont.  "Sets font and emphasis bits, and maybe foregroundColor"
- 	font installOn: bitBlt foregroundColor: foregroundColor backgroundColor: Color transparent!

Item was removed:
- ----- Method: BitBltDisplayScanner>>setPort: (in category 'private') -----
- setPort: aBitBlt
- 	"Install the BitBlt to use"
- 	bitBlt := aBitBlt.
- 	bitBlt sourceX: 0; width: 0.	"Init BitBlt so that the first call to a primitive will not fail"
- 	bitBlt sourceForm: nil. "Make sure font installation won't be confused"
- !

Item was removed:
- ----- Method: BitBltDisplayScanner>>text:textStyle:foreground:background:fillBlt:ignoreColorChanges: (in category 'private') -----
- text: t textStyle: ts foreground: foreColor background: backColor fillBlt: blt ignoreColorChanges: shadowMode
- 	text := t.
- 	textStyle := ts. 
- 	foregroundColor := defaultTextColor := foreColor.
- 	(backgroundColor := backColor) isTransparent ifFalse:
- 		[fillBlt := blt.
- 		fillBlt fillColor: backgroundColor].
- 	ignoreColorChanges := shadowMode!

Item was removed:
- ArrayedCollection variableWordSubclass: #Bitmap
- 	instanceVariableNames: ''
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Primitives'!
- 
- !Bitmap commentStamp: '<historical>' prior: 0!
- My instances provide contiguous storage of bits, primarily to hold the graphical data of Forms. Forms and their subclasses provide the additional structural information as to how the bits should be interpreted in two dimensions.!

Item was removed:
- ----- Method: Bitmap class>>decodeIntFrom: (in category 'instance creation') -----
- decodeIntFrom: s
- 	"Decode an integer in stream s as follows...
- 		0-223	0-223
- 		224-254	(0-30)*256 + next byte (0-7935)
- 		255		next 4 bytes	"		
- 	| int |
- 	int := s next.
- 	int <= 223 ifTrue: [^ int].
- 	int <= 254 ifTrue: [^ (int-224)*256 + s next].
- 	int := s next.
- 	1 to: 3 do: [:j | int := (int bitShift: 8) + s next].
- 	^ int!

Item was removed:
- ----- Method: Bitmap class>>decompressFromByteArray: (in category 'instance creation') -----
- decompressFromByteArray: byteArray
- 	| s bitmap size |
- 	s := ReadStream on: byteArray.
- 	size := self decodeIntFrom: s.
- 	bitmap := self new: size.
- 	bitmap decompress: bitmap fromByteArray: byteArray at: s position+1.
- 	^ bitmap!

Item was removed:
- ----- Method: Bitmap class>>newFromStream: (in category 'instance creation') -----
- newFromStream: s
- 	| len |
- 	s next = 16r80 ifTrue:
- 		["New compressed format"
- 		len := self decodeIntFrom: s.
- 		^ Bitmap decompressFromByteArray: (s nextInto: (ByteArray new: len))].
- 	s skip: -1.
- 	len := s nextInt32.
- 	len <= 0
- 		ifTrue: ["Old compressed format"
- 				^ (self new: len negated) readCompressedFrom: s]
- 		ifFalse: ["Old raw data format"
- 				^ s nextWordsInto: (self new: len)]!

Item was removed:
- ----- Method: Bitmap class>>swapBytesIn:from:to: (in category 'utilities') -----
- swapBytesIn: aNonPointerThing from: start to: stop
- 	"Perform a bigEndian/littleEndian byte reversal of my words.
- 	We only intend this for non-pointer arrays.  Do nothing if I contain pointers."
- 	| hack blt |
- 	"The implementation is a hack, but fast for large ranges"
- 	hack := Form new hackBits: aNonPointerThing.
- 	blt := (BitBlt toForm: hack) sourceForm: hack.
- 	blt combinationRule: Form reverse.  "XOR"
- 	blt sourceY: start-1; destY: start-1; height: stop-start+1; width: 1.
- 	blt sourceX: 0; destX: 3; copyBits.  "Exchange bytes 0 and 3"
- 	blt sourceX: 3; destX: 0; copyBits.
- 	blt sourceX: 0; destX: 3; copyBits.
- 	blt sourceX: 1; destX: 2; copyBits.  "Exchange bytes 1 and 2"
- 	blt sourceX: 2; destX: 1; copyBits.
- 	blt sourceX: 1; destX: 2; copyBits.
- !

Item was removed:
- ----- Method: Bitmap>>asByteArray (in category 'converting') -----
- asByteArray
- 	"Faster way to make a byte array from me.
- 	copyFromByteArray: makes equal Bitmap."
- 	| f bytes hack |
- 	f := Form extent: 4 at self size depth: 8 bits: self.
- 	bytes := ByteArray new: self size * 4.
- 	hack := Form new hackBits: bytes.
- 	Smalltalk isLittleEndian ifTrue:[hack swapEndianness].
- 	hack copyBits: f boundingBox
- 		from: f
- 		at: (0 at 0)
- 		clippingBox: hack boundingBox
- 		rule: Form over
- 		fillColor: nil
- 		map: nil.
- 
- 	"f displayOn: hack."
- 	^ bytes.
- !

Item was removed:
- ----- Method: Bitmap>>atAllPut: (in category 'accessing') -----
- atAllPut: value
- 	"Fill the receiver, an indexable bytes or words object, with the given positive integer. The range of possible fill values is [0..255] for byte arrays and [0..(2^32 - 1)] for word arrays."
- 	<primitive: 145>
- 	super atAllPut: value.!

Item was removed:
- ----- Method: Bitmap>>bitPatternForDepth: (in category 'accessing') -----
- bitPatternForDepth: depth
- 	"The raw call on BitBlt needs a Bitmap to represent this color.  I already am Bitmap like.  I am already adjusted for a specific depth.  Interpret me as an array of (32/depth) Color pixelValues.  BitBlt aligns the first element of this array with the top scanline of the destinationForm, the second with the second, and so on, cycling through the color array as necessary. 6/18/96 tk"
- 
- 	^ self!

Item was removed:
- ----- Method: Bitmap>>byteAt: (in category 'accessing') -----
- byteAt: byteAddress
- 	"Extract a byte from a Bitmap.  Note that this is a byte address and it is one-order.  For repeated use, create an instance of BitBlt and use pixelAt:.  See Form pixelAt:  7/1/96 tk"
- 	| lowBits |
- 	lowBits := byteAddress - 1 bitAnd: 3.
- 	^((self at: byteAddress - 1 - lowBits // 4 + 1)
- 		bitShift: (lowBits - 3) * 8)
- 		bitAnd: 16rFF!

Item was removed:
- ----- Method: Bitmap>>byteAt:put: (in category 'accessing') -----
- byteAt: byteAddress put: byte
- 	"Insert a byte into a Bitmap.  Note that this is a byte address and it is one-order.  For repeated use, create an instance of BitBlt and use pixelAt:put:.  See Form pixelAt:put:  7/1/96 tk"
- 	| longWord shift lowBits longAddr |
- 	(byte < 0 or:[byte > 255]) ifTrue:[^self errorImproperStore].
- 	lowBits := byteAddress - 1 bitAnd: 3.
- 	longWord := self at: (longAddr := (byteAddress - 1 - lowBits) // 4 + 1).
- 	shift := (3 - lowBits) * 8.
- 	longWord := longWord - (longWord bitAnd: (16rFF bitShift: shift)) 
- 		+ (byte bitShift: shift).
- 	self at: longAddr put: longWord.
- 	^ byte!

Item was removed:
- ----- Method: Bitmap>>byteSize (in category 'accessing') -----
- byteSize
- 	^self size * 4!

Item was removed:
- ----- Method: Bitmap>>compress:toByteArray: (in category 'filing') -----
- compress: bm toByteArray: ba
- 	"Store a run-coded compression of the receiver into the byteArray ba,
- 	and return the last index stored into. ba is assumed to be large enough.
- 	The encoding is as follows...
- 		S {N D}*.
- 		S is the size of the original bitmap, followed by run-coded pairs.
- 		N is a run-length * 4 + data code.
- 		D, the data, depends on the data code...
- 			0	skip N words, D is absent
- 			1	N words with all 4 bytes = D (1 byte)
- 			2	N words all = D (4 bytes)
- 			3	N words follow in D (4N bytes)
- 		S and N are encoded as follows...
- 			0-223	0-223
- 			224-254	(0-30)*256 + next byte (0-7935)
- 			255		next 4 bytes"		
- 	| size k word j lowByte eqBytes i |
- 	<primitive: 'primitiveCompressToByteArray' module: 'MiscPrimitivePlugin'>
- 	<var: #bm declareC: 'int *bm'>
- 	<var: #ba declareC: 'unsigned char *ba'>
- 	size := bm size.
- 	i := self encodeInt: size in: ba at: 1.
- 	k := 1.
- 	[k <= size] whileTrue:
- 		[word := bm at: k.
- 		lowByte := word bitAnd: 16rFF.
- 		eqBytes := ((word >> 8) bitAnd: 16rFF) = lowByte
- 				and: [((word >> 16) bitAnd: 16rFF) = lowByte
- 				and: [((word >> 24) bitAnd: 16rFF) = lowByte]].
- 		j := k.
- 		[j < size and: [word = (bm at: j+1)]]  "scan for = words..."
- 			whileTrue: [j := j+1].
- 		j > k ifTrue:
- 			["We have two or more = words, ending at j"
- 			eqBytes
- 				ifTrue: ["Actually words of = bytes"
- 						i := self encodeInt: j-k+1*4+1 in: ba at: i.
- 						ba at: i put: lowByte.  i := i+1]
- 				ifFalse: [i := self encodeInt: j-k+1*4+2 in: ba at: i.
- 						i := self encodeBytesOf: word in: ba at: i].
- 			k := j+1]
- 			ifFalse:
- 			["Check for word of 4 = bytes"
- 			eqBytes ifTrue:
- 				["Note 1 word of 4 = bytes"
- 				i := self encodeInt: 1*4+1 in: ba at: i.
- 				ba at: i put: lowByte.  i := i+1.
- 				k := k + 1]
- 				ifFalse:
- 				["Finally, check for junk"
- 				[j < size and: [(bm at: j) ~= (bm at: j+1)]]  "scan for ~= words..."
- 					whileTrue: [j := j+1].
- 				j = size ifTrue: [j := j + 1].
- 				"We have one or more unmatching words, ending at j-1"
- 				i := self encodeInt: j-k*4+3 in: ba at: i.
- 				k to: j-1 do:
- 					[:m | i := self encodeBytesOf: (bm at: m) in: ba at: i].
- 				k := j]]].
- 	^ i - 1  "number of bytes actually stored"
- "
- Space check:
-  | n rawBytes myBytes b |
- n := rawBytes := myBytes := 0.
- Form allInstancesDo:
- 	[:f | f unhibernate.
- 	b := f bits.
- 	n := n + 1.
- 	rawBytes := rawBytes + (b size*4).
- 	myBytes := myBytes + (b compressToByteArray size).
- 	f hibernate].
- Array with: n with: rawBytes with: myBytes
- ColorForms: (116 230324 160318 )
- Forms: (113 1887808 1325055 )
- 
- Integerity check:
- Form allInstances do:
- 	[:f | f unhibernate.
- 	f bits = (Bitmap decompressFromByteArray: f bits compressToByteArray)
- 		ifFalse: [self halt].
- 	f hibernate]
- 
- Speed test:
- MessageTally spyOn: [Form allInstances do:
- 	[:f | Bitmap decompressFromByteArray: f bits compressToByteArray]]
- "!

Item was removed:
- ----- Method: Bitmap>>compressGZip (in category 'filing') -----
- compressGZip
- 	| ba hackwa hackba blt rowsAtATime sourceOrigin rowsRemaining bufferStream gZipStream |
- 
- "just hacking around to see if further compression would help Nebraska"
- 
- 	bufferStream := WriteStream on: (ByteArray new: 5000).
- 	gZipStream := GZipWriteStream on: bufferStream.
- 
- 	ba := nil.
- 	rowsAtATime := 20000.		"or 80000 bytes"
- 	hackwa := Form new hackBits: self.
- 	sourceOrigin := 0 at 0.
- 	[(rowsRemaining := hackwa height - sourceOrigin y) > 0] whileTrue: [
- 		rowsAtATime := rowsAtATime min: rowsRemaining.
- 		(ba isNil or: [ba size ~= (rowsAtATime * 4)]) ifTrue: [
- 			ba := ByteArray new: rowsAtATime * 4.
- 			hackba := Form new hackBits: ba.
- 			blt := (BitBlt toForm: hackba) sourceForm: hackwa.
- 		].
- 		blt 
- 			combinationRule: Form over;
- 			sourceOrigin: sourceOrigin;
- 			destX: 0 destY: 0 width: 4 height: rowsAtATime;
- 			copyBits.
- 		"bufferStream nextPutAll: ba."
- 		sourceOrigin := sourceOrigin x @ (sourceOrigin y + rowsAtATime).
- 	].
- 	gZipStream close.
- 	^bufferStream contents
- !

Item was removed:
- ----- Method: Bitmap>>compressToByteArray (in category 'filing') -----
- compressToByteArray
- 	"Return a run-coded compression of this bitmap into a byteArray"		
- 	| byteArray lastByte |
- 	"Without skip codes, it is unlikely that the compressed bitmap will be any larger than was the original.  The run-code cases are...
- 	N >= 1 words of equal bytes:  4N bytes -> 2 bytes (at worst 4 -> 2)
- 	N > 1 equal words:  4N bytes -> 5 bytes (at worst 8 -> 5)
- 	N > 1 unequal words:  4N bytes -> 4N + M, where M is the number of bytes required to encode the run length.
- 
- The worst that can happen is that the method begins with unequal words, and than has interspersed occurrences of a word with equal bytes.  Thus we require a run-length at the beginning, and after every interspersed word of equal bytes.  However, each of these saves 2 bytes, so it must be followed by a run of 1984 (7936//4) or more (for which M jumps from 2 to 5) to add any extra overhead.  Therefore the worst case is a series of runs of 1984 or more, with single interspersed words of equal bytes.  At each break we save 2 bytes, but add 5.  Thus the overhead would be no more than 5 (encoded size) + 2 (first run len) + (S//1984*3)."
- 	
- "NOTE: This code is copied in Form hibernate for reasons given there."
- 	byteArray := ByteArray new: (self size*4) + 7 + (self size//1984*3).
- 	lastByte := self compress: self toByteArray: byteArray.
- 	^ byteArray copyFrom: 1 to: lastByte!

Item was removed:
- ----- Method: Bitmap>>copyFromByteArray: (in category 'accessing') -----
- copyFromByteArray: byteArray 
- 	"This method should work with either byte orderings"
- 
- 	| myHack byteHack |
- 	myHack := Form new hackBits: self.
- 	byteHack := Form new hackBits: byteArray.
- 	Smalltalk  isLittleEndian ifTrue: [byteHack swapEndianness].
- 	byteHack displayOn: myHack!

Item was removed:
- ----- Method: Bitmap>>decompress:fromByteArray:at: (in category 'filing') -----
- decompress: bm fromByteArray: ba at: index
- 	"Decompress the body of a byteArray encoded by compressToByteArray (qv)...
- 	The format is simply a sequence of run-coded pairs, {N D}*.
- 		N is a run-length * 4 + data code.
- 		D, the data, depends on the data code...
- 			0	skip N words, D is absent
- 				(could be used to skip from one raster line to the next)
- 			1	N words with all 4 bytes = D (1 byte)
- 			2	N words all = D (4 bytes)
- 			3	N words follow in D (4N bytes)
- 		S and N are encoded as follows (see decodeIntFrom:)...
- 			0-223	0-223
- 			224-254	(0-30)*256 + next byte (0-7935)
- 			255		next 4 bytes"	
- 	"NOTE:  If fed with garbage, this routine could read past the end of ba, but it should fail before writing past the ned of bm."
- 	| i code n anInt data end k pastEnd |
- 	<primitive: 'primitiveDecompressFromByteArray' module: 'MiscPrimitivePlugin'>
- 	<var: #bm type: 'int *'>
- 	<var: #ba type: 'unsigned char *'>
- 	<var: #anInt type: 'unsigned int'> "Force the type, otherwise it is inferred as unsigned char because assigned from ba"
- 	<var: #data type: 'unsigned int'>
- 	i := index.  "byteArray read index"
- 	end := ba size.
- 	k := 1.  "bitmap write index"
- 	pastEnd := bm size + 1.
- 	[i <= end] whileTrue:
- 		["Decode next run start N"
- 		anInt := ba at: i.  i := i+1.
- 		anInt <= 223 ifFalse:
- 			[anInt <= 254
- 				ifTrue: [anInt := (anInt-224)*256 + (ba at: i).  i := i+1]
- 				ifFalse: [anInt := 0.
- 						1 to: 4 do: [:j | anInt := (anInt bitShift: 8) + (ba at: i).  i := i+1]]].
- 		n := anInt >> 2.
- 		(k + n) > pastEnd ifTrue: [^ self primitiveFail].
- 		code := anInt bitAnd: 3.
- 		code = 0 ifTrue: ["skip"].
- 		code = 1 ifTrue: ["n consecutive words of 4 bytes = the following byte"
- 						data := ba at: i.  i := i+1.
- 						data := data bitOr: (data bitShift: 8).
- 						data := data bitOr: (data bitShift: 16).
- 						1 to: n do: [:j | bm at: k put: data.  k := k+1]].
- 		code = 2 ifTrue: ["n consecutive words = 4 following bytes"
- 						data := 0.
- 						1 to: 4 do: [:j | data := (data bitShift: 8) bitOr: (ba at: i).  i := i+1].
- 						1 to: n do: [:j | bm at: k put: data.  k := k+1]].
- 		code = 3 ifTrue: ["n consecutive words from the data..."
- 						1 to: n do:
- 							[:m | data := 0.
- 							1 to: 4 do: [:j | data := (data bitShift: 8) bitOr: (ba at: i).  i := i+1].
- 							bm at: k put: data.  k := k+1]]]!

Item was removed:
- ----- Method: Bitmap>>defaultElement (in category 'accessing') -----
- defaultElement
- 	"Return the default element of the receiver"
- 	^0!

Item was removed:
- ----- Method: Bitmap>>encodeBytesOf:in:at: (in category 'filing') -----
- encodeBytesOf: anInt in: ba at: i
- 	"Copy the integer anInt into byteArray ba at index i, and return the next index"
- 
- 	<inline: true>
- 	<var: #ba declareC: 'unsigned char *ba'>
- 	0 to: 3 do:
- 		[:j | ba at: i+j put: (anInt >> (3-j*8) bitAnd: 16rFF)].
- 	^ i+4!

Item was removed:
- ----- Method: Bitmap>>encodeInt: (in category 'filing') -----
- encodeInt: int
- 	"Encode the integer int as per encodeInt:in:at:, and return it as a ByteArray"
- 	| byteArray next |
- 	byteArray := ByteArray new: 5.
- 	next := self encodeInt: int in: byteArray at: 1.
- 	^ byteArray copyFrom: 1 to: next - 1
- !

Item was removed:
- ----- Method: Bitmap>>encodeInt:in:at: (in category 'filing') -----
- encodeInt: anInt in: ba at: i
- 	"Encode the integer anInt in byteArray ba at index i, and return the next index.
- 	The encoding is as follows...
- 		0-223	0-223
- 		224-254	(0-30)*256 + next byte (0-7935)
- 		255		next 4 bytes"		
- 
- 	<inline: true>
- 	<var: #ba declareC: 'unsigned char *ba'>
- 	anInt <= 223 ifTrue: [ba at: i put: anInt. ^ i+1].
- 	anInt <= 7935 ifTrue: [ba at: i put: anInt//256+224. ba at: i+1 put: anInt\\256.  ^ i+2].
- 	ba at: i put: 255.
- 	^ self encodeBytesOf: anInt in: ba at: i+1!

Item was removed:
- ----- Method: Bitmap>>fromByteStream: (in category 'initialize-release') -----
- fromByteStream: aStream 
- 	"Initialize the array of bits by reading integers from the argument, 
- 	aStream."
- 	aStream nextWordsInto: self!

Item was removed:
- ----- Method: Bitmap>>integerAt: (in category 'accessing') -----
- integerAt: index
- 	"Return the integer at the given index"
- 	| word |
- 	<primitive: 165>
- 	word := self basicAt: index.
- 	word < 16r3FFFFFFF ifTrue:[^word]. "Avoid LargeInteger computations"
- 	^word >= 16r80000000	"Negative?!!"
- 		ifTrue:["word - 16r100000000"
- 				(word bitInvert32 + 1) negated]
- 		ifFalse:[word]!

Item was removed:
- ----- Method: Bitmap>>integerAt:put: (in category 'accessing') -----
- integerAt: index put: anInteger
- 	"Store the integer at the given index"
- 	| word |
- 	<primitive: 166>
- 	anInteger < 0
- 		ifTrue:["word := 16r100000000 + anInteger"
- 				word := (anInteger + 1) negated bitInvert32]
- 		ifFalse:[word := anInteger].
- 	self  basicAt: index put: word.
- 	^anInteger!

Item was removed:
- ----- Method: Bitmap>>isColormap (in category 'testing') -----
- isColormap
- 	"Bitmaps were used as color maps for BitBlt.
- 	This method allows to recognize real color maps."
- 	^false!

Item was removed:
- ----- Method: Bitmap>>pixelValueForDepth: (in category 'accessing') -----
- pixelValueForDepth: depth
- 	"Self is being used to represent a single color.  Answer bits that appear in ONE pixel of this color in a Bitmap of the given depth. The depth must be one of 1, 2, 4, 8, 16, or 32.  Returns an integer.  First pixel only.  "
- 
- 	^ (self at: 1) bitAnd: (1 bitShift: depth) - 1!

Item was removed:
- ----- Method: Bitmap>>primFill: (in category 'accessing') -----
- primFill: aPositiveInteger
- 	"Fill the receiver, an indexable bytes or words object, with the given positive integer. The range of possible fill values is [0..255] for byte arrays and [0..(2^32 - 1)] for word arrays."
- 
- 	<primitive: 145>
- 	self errorImproperStore.!

Item was removed:
- ----- Method: Bitmap>>printOn: (in category 'printing') -----
- printOn: aStream
- 	self printNameOn: aStream.
- 	aStream nextPutAll: ' of length '; print: self size!

Item was removed:
- ----- Method: Bitmap>>readCompressedFrom: (in category 'filing') -----
- readCompressedFrom: strm
- 	"Decompress an old-style run-coded stream into this bitmap:
- 		[0 means end of runs]
- 		[n = 1..127] [(n+3) copies of next byte]
- 		[n = 128..191] [(n-127) next bytes as is]
- 		[n = 192..255] [(n-190) copies of next 4 bytes]"
- 	| n byte out outBuff bytes |
- 	out := WriteStream on: (outBuff := ByteArray new: self size*4).
- 	[(n := strm next) > 0] whileTrue:
- 		[(n between: 1 and: 127) ifTrue:
- 			[byte := strm next.
- 			1 to: n+3 do: [:i | out nextPut: byte]].
- 		(n between: 128 and: 191) ifTrue:
- 			[1 to: n-127 do: [:i | out nextPut: strm next]].
- 		(n between: 192 and: 255) ifTrue:
- 			[bytes := (1 to: 4) collect: [:i | strm next].
- 			1 to: n-190 do: [:i | bytes do: [:b | out nextPut: b]]]].
- 	out position = outBuff size ifFalse: [self error: 'Decompression size error'].
- 	"Copy the final byteArray into self"
- 	self copyFromByteArray: outBuff.!

Item was removed:
- ----- Method: Bitmap>>replaceFrom:to:with:startingAt: (in category 'accessing') -----
- replaceFrom: start to: stop with: replacement startingAt: repStart 
- 	"Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
- 	<primitive: 105>
- 	super replaceFrom: start to: stop with: replacement startingAt: repStart!

Item was removed:
- ----- Method: Bitmap>>restoreEndianness (in category 'filing') -----
- restoreEndianness
- 	"This word object was just read in from a stream.  Bitmaps are always compressed and serialized in a machine-independent way.  Do not correct the Endianness."
- 
- 	"^ self"
- !

Item was removed:
- ----- Method: Bitmap>>storeBits:to:on: (in category 'filing') -----
- storeBits: startBit to: stopBit on: aStream 
- 	"Store my bits as a hex string, breaking the lines every 100 bytes or 
- 	so to comply with the maximum line length limits of Postscript (255 
- 	bytes). "
- 	| lineWidth |
- 	lineWidth := 0.
- 	self
- 		do: [:word | 
- 			startBit
- 				to: stopBit
- 				by: -4
- 				do: [:shift | 
- 					aStream nextPut: (word >> shift bitAnd: 15) asHexDigit.
- 					lineWidth := lineWidth + 1].
- 			(lineWidth > 100)
- 				ifTrue: [aStream cr.
- 					lineWidth := 0]].
- 	lineWidth > 0 ifTrue: [ aStream cr ].!

Item was removed:
- ----- Method: Bitmap>>writeOn: (in category 'filing') -----
- writeOn: aStream 
- 	"Store the array of bits onto the argument, aStream. A leading byte of 16r80 identifies this as compressed by compressToByteArray (qv)."
- 
- 	| b |
- 	aStream nextPut: 16r80.
- 	b := self compressToByteArray.
- 	aStream
- 		nextPutAll: (self encodeInt: b size);
- 		nextPutAll: b.
- !

Item was removed:
- ----- Method: Bitmap>>writeUncompressedOn: (in category 'filing') -----
- writeUncompressedOn: aStream 
- 	"Store the array of bits onto the argument, aStream.
- 	(leading byte ~= 16r80) identifies this as raw bits (uncompressed)."
- 
- 	aStream nextInt32Put: self size.
- 	aStream nextPutAll: self
- !

Item was removed:
- ----- Method: ByteString>>scanCharactersFrom:to:with:rightX:font: (in category '*Graphics-Text') -----
- scanCharactersFrom: startIndex to: stopIndex with: aCharacterScanner rightX: rightX  font: aFont
- 	"NB: strongly consider getting almost all these parameters from the scanner"
- 	"Since I'm a byte char string, I know that we have to scan single-byte characters and don't have to handle encodings etc"
- 	startIndex > stopIndex
- 		ifTrue: [^aCharacterScanner handleEndOfRunAt: stopIndex].
- 	^aFont scanByteCharactersFrom: startIndex to: stopIndex in: self with: aCharacterScanner rightX: rightX!

Item was removed:
- ----- Method: ByteSymbol>>scanCharactersFrom:to:with:rightX:font: (in category '*Graphics-Text') -----
- scanCharactersFrom: startIndex to: stopIndex with: aCharacterScanner rightX: rightX  font: aFont
- 	"NB: strongly consider getting almost all these parameters from the scanner"
- 	"Since I'm a byte char string, I know that we have to scan single-byte characters and don't have to handle encodings etc"
- 	startIndex > stopIndex
- 		ifTrue: [^aCharacterScanner handleEndOfRunAt: stopIndex].
- 	^aFont scanByteCharactersFrom: startIndex to: stopIndex in: self with: aCharacterScanner rightX: rightX!

Item was removed:
- Rectangle subclass: #CharacterBlock
- 	instanceVariableNames: 'stringIndex text textLine'
- 	classVariableNames: ''
- 	poolDictionaries: 'TextConstants'
- 	category: 'Graphics-Text'!
- 
- !CharacterBlock commentStamp: 'mtf 5/15/2010 12:44' prior: 0!
- I describe the location of one character displayed on the screen. My instances are used to return the results of methods:
- 	Paragraph characterBlockAtPoint: aPoint and
- 	Paragraph characterBlockForIndex: stringIndex.
- Any recomposition or movement of a Paragraph can make the information I store stale.
- 
- text (Text): The text where my character is from
- stringIndex (Integer): The index of my character in the text, starting from 1
- textLine (TextLine): The displayed line my character is on
- origin (Point): The top-left corner of the area allocated for displaying my
- 		character's glyph, in pixels, counting right then down from the
- 		top-left corner of the text display area, and starting from 0 at 0
- corner (Point): The bottom-right corner of the area allocated for displaying my
- 		character's glyph, in pixels, counting right then down from the
- 		top-left corner of the text display area, and starting from 0 at 0
- !

Item was removed:
- ----- Method: CharacterBlock>>< (in category 'comparing') -----
- < aCharacterBlock 
- 	"Answer whether the string index of the receiver precedes that of 
- 	aCharacterBlock."
- 
- 	^stringIndex < aCharacterBlock stringIndex!

Item was removed:
- ----- Method: CharacterBlock>><= (in category 'comparing') -----
- <= aCharacterBlock 
- 	"Answer whether the string index of the receiver does not come after that 
- 	of aCharacterBlock."
- 
- 	^(self > aCharacterBlock) not!

Item was removed:
- ----- Method: CharacterBlock>>= (in category 'comparing') -----
- = aCharacterBlock
- 
- 	self species = aCharacterBlock species
- 		ifTrue: [^stringIndex = aCharacterBlock stringIndex]
- 		ifFalse: [^false]!

Item was removed:
- ----- Method: CharacterBlock>>> (in category 'comparing') -----
- > aCharacterBlock 
- 	"Answer whether the string index of the receiver comes after that of 
- 	aCharacterBlock."
- 
- 	^aCharacterBlock < self!

Item was removed:
- ----- Method: CharacterBlock>>>= (in category 'comparing') -----
- >= aCharacterBlock 
- 	"Answer whether the string index of the receiver does not precede that of 
- 	aCharacterBlock."
- 
- 	^(self < aCharacterBlock) not!

Item was removed:
- ----- Method: CharacterBlock>>max: (in category 'comparing') -----
- max: aCharacterBlock
- 	aCharacterBlock ifNil:[^self].
- 	^aCharacterBlock > self
- 		ifTrue:[ aCharacterBlock]
- 		ifFalse:[self].!

Item was removed:
- ----- Method: CharacterBlock>>min: (in category 'comparing') -----
- min: aCharacterBlock
- 	aCharacterBlock ifNil:[^self].
- 	^aCharacterBlock < self
- 		ifTrue:[ aCharacterBlock]
- 		ifFalse:[self].!

Item was removed:
- ----- Method: CharacterBlock>>moveBy: (in category 'private') -----
- moveBy: aPoint 
- 	"Change the corner positions of the receiver so that its area translates by 
- 	the amount defined by the argument, aPoint."
- 
- 	origin := origin + aPoint.
- 	corner := corner + aPoint!

Item was removed:
- ----- Method: CharacterBlock>>printOn: (in category 'printing') -----
- printOn: aStream
- 
- 	aStream nextPutAll: 'a CharacterBlock with index '.
- 	stringIndex printOn: aStream.
- 	(text ~~ nil and: [text size> 0 and: [stringIndex between: 1 and: text size]])
- 		ifTrue: [aStream nextPutAll: ' and character '.
- 				(text at: stringIndex) printOn: aStream].
- 	aStream nextPutAll: ' and rectangle '.
- 	super printOn: aStream.
- 	textLine ifNotNil: [aStream cr; nextPutAll: ' in '.
- 				textLine printOn: aStream].
- !

Item was removed:
- ----- Method: CharacterBlock>>stringIndex (in category 'accessing') -----
- stringIndex
- 	"Answer the position of the receiver in the string it indexes."
- 
- 	^stringIndex!

Item was removed:
- ----- Method: CharacterBlock>>stringIndex:text:topLeft:extent: (in category 'private') -----
- stringIndex: anInteger text: aText topLeft: topLeft extent: extent
- 
- 	stringIndex := anInteger.
- 	text := aText.
- 	super setOrigin: topLeft corner: topLeft + extent !

Item was removed:
- ----- Method: CharacterBlock>>textLine (in category 'accessing') -----
- textLine
- 	^ textLine!

Item was removed:
- ----- Method: CharacterBlock>>textLine: (in category 'accessing') -----
- textLine: aLine
- 	textLine := aLine!

Item was removed:
- CharacterScanner subclass: #CharacterBlockScanner
- 	instanceVariableNames: 'characterPoint characterIndex nextLeftMargin specialWidth lastCharacterWidth'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Text'!
- 
- !CharacterBlockScanner commentStamp: 'nice 10/6/2013 22:04' prior: 0!
- A CharacterScanner does scan text to compute the CharacterBlock for a character specified by its index in the text or its proximity to the cursor location. The CharacterBlock stores information both about character layout and character index in the text.
- 
- This class is essential for selecting text with the mouse or with arrow keys.
- 
- Instance Variables
- 	characterIndex:		<Integer | nil>
- 	characterPoint:		<Point>
- 	lastCharacterWidth:		<Number | nil>
- 	nextLeftMargin:		<Number>
- 	specialWidth:		<Number | nil>
- 
- characterIndex
- 	- the index of character for which the layout information is searched, or nil when the layout is searched by cursor location
- 
- characterPoint
- 	- the cursor location for which nearest character index and layout are searched.
- 
- lastCharacterWidth
- 	- a number indicating the width of last character being processed.
- 	Note that this variable is left to nil during the inner scan loop, and only set on stopConditions.
- 
- nextLeftMargin
- 	- a number specifying the distance between left of composition zone and left of first character for the next line.
- 
- specialWidth
- 	- a number holding the width of an embedded object if any, or nil if none.
- !

Item was removed:
- ----- Method: CharacterBlockScanner>>characterBlockAtPoint:index:in: (in category 'scanning') -----
- characterBlockAtPoint: aPoint index: index in: textLine
- 	"This method is the Morphic characterBlock finder.  It combines
- 	MVC's characterBlockAtPoint:, -ForIndex:, and buildCharacterBlockIn:"
- 	| runLength lineStop stopCondition |
- 	line := textLine.
- 	rightMargin := line rightMargin.
- 	lastIndex := line first.
- 	self setStopConditions.		"also sets font"
- 	characterIndex := index.  " == nil means scanning for point"
- 	characterPoint := aPoint.
- 	(characterPoint isNil or: [characterPoint y > line bottom])
- 		ifTrue: [characterPoint := line bottomRight].
- 	destX := leftMargin := line leftMarginForAlignment: alignment.
- 	destY := line top.
- 	(text isEmpty or: [(characterPoint y < destY or: [characterPoint x < destX])
- 				or: [characterIndex notNil and: [characterIndex < line first]]])
- 		ifTrue:	[^ (CharacterBlock new stringIndex: line first text: text
- 					topLeft: destX at destY extent: 0 @ textStyle lineGrid)
- 					textLine: line].
- 	runLength := text runLengthFor: line first.
- 	lineStop := characterIndex	"scanning for index"
- 		ifNil: [ line last ].			"scanning for point"
- 	runStopIndex := lastIndex + (runLength - 1) min: lineStop.
- 	lastCharacterWidth := 0.
- 	spaceCount := 0.
- 
- 	[
- 		stopCondition := self scanCharactersFrom: lastIndex to: runStopIndex
- 			in: text string rightX: characterPoint x.
- 		"see setStopConditions for stopping conditions for character block operations."
- 		self perform: stopCondition
- 	] whileFalse.
- 	characterIndex
- 		ifNil: ["Result for characterBlockAtPoint: "
- 				^ (CharacterBlock new
- 					stringIndex: lastIndex
- 					text: text topLeft: characterPoint + (font descentKern @ 0)
- 					extent: lastCharacterWidth @ line lineHeight - (font baseKern @ 0))
- 							textLine: line]
- 		ifNotNil: ["Result for characterBlockForIndex: "
- 				^ (CharacterBlock new
- 					stringIndex: characterIndex
- 					text: text topLeft: characterPoint + ((font descentKern) - kern @ 0)
- 					extent: lastCharacterWidth @ line lineHeight)
- 							textLine: line]!

Item was removed:
- ----- Method: CharacterBlockScanner>>cr (in category 'stop conditions') -----
- cr 
- 	"Answer a CharacterBlock that specifies the current location of the mouse 
- 	relative to a carriage return stop condition that has just been 
- 	encountered. The ParagraphEditor convention is to denote selections by 
- 	CharacterBlocks, sometimes including the carriage return (cursor is at 
- 	the end) and sometimes not (cursor is in the middle of the text)."
- 
- 	((characterIndex ~= nil
- 		and: [characterIndex > text size])
- 			or: [(line last = text size)
- 				and: [(destY + line lineHeight) < characterPoint y]])
- 		ifTrue:	["When off end of string, give data for next character"
- 				destY := destY +  line lineHeight.
- 				characterPoint := (nextLeftMargin ifNil: [leftMargin]) @ destY.
- 				(lastIndex < text size and: [(text at: lastIndex) = CR and: [(text at: lastIndex+1) = Character lf]])
- 					ifTrue: [lastIndex := lastIndex + 2]
- 					ifFalse: [lastIndex := lastIndex + 1].
- 				lastCharacterWidth := 0.
- 				^ true].
- 		characterPoint := destX @ destY.
- 		lastCharacterWidth := rightMargin - destX.
- 		^true!

Item was removed:
- ----- Method: CharacterBlockScanner>>crossedX (in category 'stop conditions') -----
- crossedX
- 	"Text display has wrapping. The scanner just found a character past the x 
- 	location of the cursor. We know that the cursor is pointing at a character 
- 	or before one."
- 
- 	self retrieveLastCharacterWidth.
- 	
- 	characterPoint x <= (destX + (lastCharacterWidth // 2))
- 		ifTrue:	[characterPoint := destX @ destY.
- 				^true].
- 	lastIndex >= line last 
- 		ifTrue:	[characterPoint := destX @ destY.
- 				^true].
- 
- 	"Pointing past middle of a character, return the next character."
- 	lastIndex := lastIndex + 1.
- 	characterPoint := destX + lastCharacterWidth + kern @ destY.
- 	^ true!

Item was removed:
- ----- Method: CharacterBlockScanner>>endOfRun (in category 'stop conditions') -----
- endOfRun
- 	"Before arriving at the cursor location, the selection has encountered an 
- 	end of run. Answer false if the selection continues, true otherwise. Set 
- 	up indexes for building the appropriate CharacterBlock."
- 
- 	| runLength lineStop |
- 	
- 	(((characterIndex ~~ nil and:
- 		[runStopIndex < characterIndex and: [runStopIndex < text size]])
- 			or:	[characterIndex == nil and: [lastIndex < line last]]) or: [
- 				((lastIndex < line last)
- 				and: [((text at: lastIndex) leadingChar ~= (text at: lastIndex+1) leadingChar)
- 					and: [lastIndex ~= characterIndex]])])
- 		ifTrue:	["We're really at the end of a real run."
- 				runLength := text runLengthFor: (lastIndex := lastIndex + 1).
- 				lineStop := characterIndex	"scanning for index"
- 						ifNil: [line last].		"scanning for point".
- 				(runStopIndex := lastIndex + (runLength - 1)) > lineStop
- 					ifTrue: [runStopIndex := lineStop].
- 				self setStopConditions.
- 				^false].
- 
- 	self retrieveLastCharacterWidth.
- 		
- 	(characterIndex == nil and: [lastIndex = line last])
- 		ifTrue: [characterPoint x > (destX + (lastCharacterWidth // 2))
- 			ifTrue:
- 				[ "Correct for clicking right half of last character in line
- 				means selecting AFTER the char"
- 				lastIndex := lastIndex + 1.
- 				lastCharacterWidth := 0.
- 				characterPoint := destX + lastCharacterWidth @ destY.
- 				^true]].
- 
- 	characterPoint := destX @ destY.
- 	characterIndex ~~ nil
- 		ifTrue:	["If scanning for an index and we've stopped on that index,
- 				then we back destX off by the width of the character stopped on
- 				(it will be pointing at the right side of the character) and return"
- 				runStopIndex = characterIndex
- 					ifTrue:	[characterPoint := destX - lastCharacterWidth @ destY.
- 							^true].
- 				"Otherwise the requested index was greater than the length of the
- 				string.  Return string size + 1 as index, indicate further that off the
- 				string by setting character to nil and the extent to 0."
- 				lastIndex :=  lastIndex + 1.
- 				lastCharacterWidth := 0.
- 				^true].
- 
- 	"Scanning for a point and either off the end of the line or off the end of the string."
- 	runStopIndex = text size
- 		ifTrue:	["off end of string"
- 				lastIndex :=  lastIndex + 1.
- 				lastCharacterWidth := 0.
- 				^true].
- 	"just off end of line without crossing x"
- 	lastIndex := lastIndex + 1.
- 	^true!

Item was removed:
- ----- Method: CharacterBlockScanner>>indentationLevel: (in category 'text attributes') -----
- indentationLevel: anInteger
- 	super indentationLevel: anInteger.
- 	nextLeftMargin := leftMargin.
- 	indentationLevel timesRepeat: [
- 		nextLeftMargin := textStyle nextTabXFrom: nextLeftMargin
- 					leftMargin: leftMargin
- 					rightMargin: rightMargin]!

Item was removed:
- ----- Method: CharacterBlockScanner>>paddedSpace (in category 'stop conditions') -----
- paddedSpace
- 	"When the line is justified, the spaces will not be the same as the font's 
- 	space character. A padding of extra space must be considered in trying 
- 	to find which character the cursor is pointing at. Answer whether the 
- 	scanning has crossed the cursor."
- 
- 	| pad |
- 	spaceCount := spaceCount + 1.
- 	pad := line justifiedPadFor: spaceCount font: font.
- 	lastCharacterWidth := spaceWidth + pad.
- 	(destX + lastCharacterWidth)  >= characterPoint x
- 		ifTrue:
- 			[^self crossedX].
- 	lastIndex := lastIndex + 1.
- 	destX := destX + lastCharacterWidth + kern.
- 	pendingKernX := 0.
- 	^ false
- !

Item was removed:
- ----- Method: CharacterBlockScanner>>placeEmbeddedObjectFrom: (in category 'private') -----
- placeEmbeddedObjectFrom: aTextAttribute
- 	
- 	| width anchoredMorphOrForm textAnchorProperties |
- 	anchoredMorphOrForm := aTextAttribute anchoredMorph.
- 	textAnchorProperties := self textAnchorPropertiesFor: anchoredMorphOrForm.
- 	
- 	textAnchorProperties anchorLayout == #document ifTrue: [^ true].
- 	width := textAnchorProperties consumesHorizontalSpace 
- 		ifTrue: [anchoredMorphOrForm width + textAnchorProperties horizontalPadding]
- 		ifFalse: [0].
- 	
- 	lastCharacterWidth := width.	
- 	
- 	(destX + width > characterPoint x) ifTrue: [^false].
- 	destX := destX + width + kern.
- 	^ true!

Item was removed:
- ----- Method: CharacterBlockScanner>>retrieveLastCharacterWidth (in category 'private') -----
- retrieveLastCharacterWidth
- 	| lastCharacter |
- 	lastIndex > text size ifTrue: [^lastCharacterWidth := 0].
- 	lastCharacter := text at: lastIndex.
- 	(lastCharacter charCode >= 256 or: [(stopConditions at: lastCharacter charCode + 1) isNil])
- 		ifTrue: [lastCharacterWidth := font widthOf: (text at: lastIndex)].
- 	"if last character was a stop condition, then the width is already set"
- 	^lastCharacterWidth!

Item was removed:
- ----- Method: CharacterBlockScanner>>setFont (in category 'stop conditions') -----
- setFont
- 	super setFont!

Item was removed:
- ----- Method: CharacterBlockScanner>>tab (in category 'stop conditions') -----
- tab
- 	| nextDestX |
- 	nextDestX := self plainTab.
- 	lastCharacterWidth := nextDestX - destX max: 0.
- 	nextDestX >= characterPoint x
- 		ifTrue: 
- 			[^ self crossedX].
- 	destX := nextDestX.
- 	lastIndex := lastIndex + 1.
- 	^false!

Item was removed:
- Object subclass: #CharacterScanner
- 	instanceVariableNames: 'destX lastIndex xTable map destY stopConditions text textStyle alignment leftMargin rightMargin font line runStopIndex spaceCount spaceWidth emphasisCode kern indentationLevel wantsColumnBreaks pendingKernX'
- 	classVariableNames: 'ColumnBreakStopConditions CompositionStopConditions DefaultStopConditions MeasuringStopConditions PaddedSpaceCondition'
- 	poolDictionaries: 'TextConstants'
- 	category: 'Graphics-Text'!
- 
- !CharacterScanner commentStamp: 'nice 10/22/2013 20:04' prior: 0!
- A CharacterScanner holds the state associated with scanning text. Subclasses scan characters for specified purposes, such as computing a CharacterBlock or placing characters into Forms.
- 
- Instance Variables
- 	alignment:		<Integer>
- 	destX:		<Number>
- 	destY:		<Number>
- 	emphasisCode:		<Object>
- 	font:		<AbstractFont>
- 	indentationLevel:		<Integer>
- 	kern:		<Number>
- 	lastIndex:		<Integer>
- 	leftMargin:		<Number>
- 	line:		<TextLine>
- 	map:		<Array>
- 	pendingKernX:		<Number>
- 	rightMargin:		<Number>
- 	runStopIndex:		<Integer>
- 	spaceCount:		<Integer>
- 	spaceWidth:		<Number>
- 	stopConditions:		<Array>
- 	text:		<Text>
- 	textStyle:		<TextStyle>
- 	wantsColumnBreaks:		<Boolean>
- 	xTable:		<Array>
- 
- alignment
- 	- an Integer encoding the alignment of text
- 
- destX
- 	- horizontal position for next character (distance from left of composition area)
- 
- destY
- 	- vertical position for next character (distance from top of composition area)
- 
- emphasisCode
- 	- an Integer encoding the current text emphasis to use (bold, italic, ...)
- 
- font
- 	- the current font used for measuring/composing/displaying characters
- 
- indentationLevel
- 	- an Integer specifying a number of leading tabs to be inserted at beginning of new lines
- 
- kern
- 	- a Number specifying additional horizontal spacing to place between characters (spacing is reduced when kern is negative)
- 
- lastIndex
- 	- the Integer index of next character to be processed in the text
- 
- leftMargin
- 	- a Number specifying the distance between left of composition zone and left of first character in the line.
- 
- line
- 	- an object holding information about the line currently being displayed (like first and last index in text).
- 	Note: this is either a TextLine in Morphic, or TextLineInterval for ST80 compatibility
- 
- map
- 	- an array mapping character code to glyph position.
- 	This is used by primitive 103 only, in case of ByteString.
- 
- pendingKernX
- 	- a Number to be added to horizontal spacing of next char if ever it is in the same font than previous one.
- 	The inner scan loop is interrupted by a change of text run.
- 	But some changes won't change the font, so the kerning must be remembered and applied later.
- 
- rightMargin
- 	- a Number specifying the distance between right of composition zone and right of last character in the line.
- 
- runStopIndex
- 	- the Integer index of last character in current text run.
- 
- spaceCount
- 	- the number of spaces encoutered so far in current line. This is useful for adjusting the spacing in cas of Justified alignment.
- 
- spaceWidth
- 	- the width of space character in current font.
- 
- stopConditions
- 	- an Array mapping a table of characters codes for which special actions are to be taken.
- 	These are typically control characters like carriage return or horizontal tab.
- 
- text
- 	- the text to be measured/composed/displayed
- 
- textStyle
- 	- an object holding a context for the text style (which set of font to use, which margins, etc...)
- 
- wantsColumnBreaks
- 	- a Boolean indicating whether some special handling for multiple columns is requested.
- 	THIS ONLY MAKES SENSE IN CompositionScanner AND SHOULD BE MOVED TO THE SUBCLASS
- 	
- xTable
- 	- an array mapping character code to glyph x coordinate in form.
- 	This is used by primitive 103 only, in case of ByteString.
- 	
- Implementation note: accelerated Character scanning with primitive 103 requires following order for 5 first instance variables, please don't alter:
- destX lastIndex xTable map destY
- !

Item was removed:
- ----- Method: CharacterScanner class>>initialize (in category 'class initialization') -----
- initialize
- "
- 	CharacterScanner initialize
- "
- 	| a |
- 	a := Array new: 258.
- 	a at: 1 + 1 put: #embeddedObject.
- 	a at: Tab asciiValue + 1 put: #tab.
- 	a at: CR asciiValue + 1 put: #cr.
- 	a at: Character lf asciiValue + 1 put: #cr.
- 	"Note: following two codes are used only by primitive 103 for accelerated Character scanning"
- 	a at: 257 put: #endOfRun.
- 	a at: 258 put: #crossedX.
- 	
- 	DefaultStopConditions := a copy.
- 
- 	CompositionStopConditions := a copy.
- 	CompositionStopConditions at: Space asciiValue + 1 put: #space.
- 	ColumnBreakStopConditions := CompositionStopConditions copy.
- 	ColumnBreakStopConditions at: Character characterForColumnBreak asciiValue + 1 put: #columnBreak.
- 
- 	PaddedSpaceCondition := a copy.
- 	PaddedSpaceCondition at: Space asciiValue + 1 put: #paddedSpace.
- 
- 	MeasuringStopConditions := (Array new: 258)
- 		at: 257 put: #endOfRun;
- 		at: 258 put: #crossedX;
- 		yourself!

Item was removed:
- ----- Method: CharacterScanner>>addEmphasis: (in category 'text attributes') -----
- addEmphasis: code
- 	"Set the bold-ital-under-strike emphasis."
- 	emphasisCode := emphasisCode bitOr: code!

Item was removed:
- ----- Method: CharacterScanner>>addKern: (in category 'text attributes') -----
- addKern: kernDelta
- 	"Set the current kern amount."
- 	kern := kern + kernDelta!

Item was removed:
- ----- Method: CharacterScanner>>advanceIfFirstCharOfLine (in category 'private') -----
- advanceIfFirstCharOfLine
- 	lastIndex = line first
- 		ifTrue:
- 			[destX := destX + pendingKernX + (font widthOf: (text at: line first)).
- 			lastIndex := lastIndex + 1.
- 			pendingKernX := 0].!

Item was removed:
- ----- Method: CharacterScanner>>basicScanByteCharactersFrom:to:in:rightX: (in category 'scanning') -----
- basicScanByteCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX 
- 	"This is a scanning method for single-byte characters in a ByteString
- 	a font that does not do character-pair kerning."
- 	
- 	| codePointPlusOne nextDestX char |
- 	lastIndex := startIndex.
- 	[lastIndex <= stopIndex]
- 		whileTrue: [
- 			"get the character value"
- 			char := sourceString at: lastIndex.
- 			codePointPlusOne := char asInteger + 1.
- 			"if there is an entry in 'stops' for this value, return it"
- 			(stopConditions at: codePointPlusOne)
- 				ifNotNil: [^ stopConditions at: codePointPlusOne].
- 			"bump nextDestX by the width of the current character"
- 			nextDestX := destX + (font widthOfByteCharacter: char).
- 			"if the next x is past the right edge, return crossedX"
- 			nextDestX > rightX
- 				ifTrue: [^#crossedX].
- 			"update destX and incorporate thr kernDelta"
- 			destX := nextDestX + kern.
- 			lastIndex := lastIndex + 1].
- 	^self handleEndOfRunAt: stopIndex
- 
- !

Item was removed:
- ----- Method: CharacterScanner>>columnBreak (in category 'stop conditions') -----
- columnBreak
- 
- 	pendingKernX := 0.
- 	^true!

Item was removed:
- ----- Method: CharacterScanner>>embeddedObject (in category 'stop conditions') -----
- embeddedObject
- 
- 	| previousAttributes newAttributes |
- 	pendingKernX := 0.
- 	"If a text anchor was already at the previous index, it was already dealt with"
- 	previousAttributes := lastIndex > 1 ifTrue: [text attributesAt: lastIndex - 1] ifFalse: [#()].
- 	newAttributes := (text attributesAt: lastIndex) copyWithoutAll: previousAttributes.
- 	(newAttributes reject: [:each | each anchoredMorph isNil])
- 		ifNotEmpty: [:attributes | (self placeEmbeddedObjectsFrom: attributes) ifTrue: [^ true]].
- 	self setFont.
-  
- 	"Note: if ever several objects are embedded on same character, only indent lastIndex once"
- 	lastIndex := lastIndex + 1.
- 	^ false!

Item was removed:
- ----- Method: CharacterScanner>>handleEndOfRunAt: (in category 'scanner methods') -----
- handleEndOfRunAt: stopIndex
- 	" make sure the lastIndex is set to stopIndex and then return the stopCondition for endOfRun; important for  a couple of outside users"
- 
- 	lastIndex := stopIndex.
- 	^#endOfRun!

Item was removed:
- ----- Method: CharacterScanner>>handleIndentation (in category 'private') -----
- handleIndentation
- 	self indentationLevel timesRepeat: [
- 		destX := self plainTab]!

Item was removed:
- ----- Method: CharacterScanner>>indentationLevel (in category 'private') -----
- indentationLevel
- 	"return the number of tabs that are currently being placed at the beginning of each line"
- 	^indentationLevel ifNil:[0]!

Item was removed:
- ----- Method: CharacterScanner>>indentationLevel: (in category 'text attributes') -----
- indentationLevel: anInteger
- 	"set the number of tabs to put at the beginning of each line"
- 	indentationLevel := anInteger!

Item was removed:
- ----- Method: CharacterScanner>>initialize (in category 'initialize') -----
- initialize
- 	destX := destY := leftMargin := 0.!

Item was removed:
- ----- Method: CharacterScanner>>leadingTab (in category 'private') -----
- leadingTab
- 	"return true if only tabs lie to the left"
- 	line first to: lastIndex do:
- 		[:i | (text at: i) == Tab ifFalse: [^ false]].
- 	^ true!

Item was removed:
- ----- Method: CharacterScanner>>measureString:inFont:from:to: (in category 'scanning') -----
- measureString: aString inFont: aFont from: startIndex to: stopIndex
- 	"Measure aString width in given font aFont.
- 	The string shall not include line breaking, tab or other control character."
- 	destX := destY := lastIndex := 0.
- 	pendingKernX := 0.
- 	font := aFont.
- 	kern := 0 - font baseKern.
- 	spaceWidth := font widthOf: Space.
- 	stopConditions := MeasuringStopConditions.
- 	self scanCharactersFrom: startIndex to: stopIndex in: aString rightX: 999999.
- 	^destX!

Item was removed:
- ----- Method: CharacterScanner>>placeEmbeddedObjectFrom: (in category 'private-text-anchor') -----
- placeEmbeddedObjectFrom: aTextAttribute
- 	"Place the anchoredMorph or return false if it cannot be placed"
- 	^ true!

Item was removed:
- ----- Method: CharacterScanner>>placeEmbeddedObjectsFrom: (in category 'private-text-anchor') -----
- placeEmbeddedObjectsFrom: textAttributes
- 	textAttributes do: [:attr |
- 		"Try to placeEmbeddedObject: - if it answers false, then there's no place left"
- 		(self placeEmbeddedObjectFrom: attr) ifFalse: [^ self crossedX]].
- 	^ false!

Item was removed:
- ----- Method: CharacterScanner>>plainTab (in category 'private') -----
- plainTab
- 	"This is the basic method of adjusting destX for a tab.
- 	Answer the next destX"
- 	pendingKernX := 0.
- 	^(alignment = Justified and: [self leadingTab not])
- 		ifTrue:		"embedded tabs in justified text are weird"
- 			[destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX]
- 		ifFalse: 
- 			[textStyle nextTabXFrom: destX
- 				leftMargin: leftMargin
- 				rightMargin: rightMargin].!

Item was removed:
- ----- Method: CharacterScanner>>primScanCharactersFrom:to:in:rightX:stopConditions:kern: (in category 'scanning') -----
- primScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta
- 	"Primitive. This is the inner loop of text display--but see #scanCharactersFrom:to:in:rightX: which would get the string, stopConditions and displaying from the instance. March through sourceString from startIndex to stopIndex. If any character is flagged with a non-nil entry in stops, then return the corresponding value. Determine width of each character from xTable, indexed by map. If destX would exceed rightX, then return stops at: 258. Advance destX by the width of the character. If stopIndex has been reached, then return stops at: 257. 
- 	
- 	Optional. See Object documentation whatIsAPrimitive.
- 	
- 	NOTE THAT this primitive does only work for our legacy StrikeFont because #setActualFont: needs #xTable and #characterToGlyphMap, which are both not available for TTCFont this way and thus we end up calling #widthOf: manually on the font."
- 	
- 	<primitive: 103>
- 	^self basicScanByteCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX 
- 	
- "Here are some sketchy benchmarks to illustrate the performance issue regarding the use of TrueType fonts:
- 
- 1) TTCFont only; with primitive fail
-  '1,160 per second. 865 microseconds per run. 0.44 % GC time.' 
- 
- 2) TTCFont only; without primitive fail
-  '5,730 per second. 175 microseconds per run. 6.12 % GC time.' 
- 
- 3) StrikeFont only; using primitive 103
-  '29,700 per second. 33.6 microseconds per run. 1.11978 % GC time.' 
- 
- 4) StrikeFont only; without primitive 103
-  '13,900 per second. 71.7 microseconds per run. 1.17976 % GC time.' 
- 
- "!

Item was removed:
- ----- Method: CharacterScanner>>scanByteCharactersFrom:to:in:rightX: (in category 'scanning') -----
- scanByteCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX 
- "this is a scanning method for
- single byte characters in a ByteString
- a font that does not do character-pair kerning"
- 	^self primScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stopConditions kern: kern
- !

Item was removed:
- ----- Method: CharacterScanner>>scanCharactersFrom:to:in:rightX: (in category 'scanning') -----
- scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX 
- 	^sourceString scanCharactersFrom: startIndex to: stopIndex with: self rightX: rightX font: font!

Item was removed:
- ----- Method: CharacterScanner>>scanCharactersFrom:to:in:rightX:stopConditions:kern: (in category 'scanning') -----
- scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta 
- 	^sourceString scanCharactersFrom: startIndex to: stopIndex with: self rightX: rightX font: font!

Item was removed:
- ----- Method: CharacterScanner>>scanKernableByteCharactersFrom:to:in:rightX: (in category 'scanning') -----
- scanKernableByteCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX 
- "this is a scanning method for
- single byte characters in a ByteString
- a font that does do character-pair kerning via widthAndKernedWidthOfLeft:right:into:"
- 	| ascii nextDestX char floatDestX widthAndKernedWidth nextCharOrNil atEndOfRun |
- 	lastIndex := startIndex.
- 	floatDestX := destX.
- 	widthAndKernedWidth := Array new: 2.
- 	atEndOfRun := false.
- 	[lastIndex <= stopIndex]
- 		whileTrue: [
- 			"get the character value"
- 			char := sourceString at: lastIndex.
- 			ascii := char asciiValue + 1.
- 			"if there is an entry in 'stops' for this value, return it"
- 			(stopConditions at: ascii)
- 				ifNotNil: [^ stopConditions at: ascii].
- 			"get the next character..."
- 			nextCharOrNil := lastIndex + 1 <= stopIndex
- 						ifTrue: [sourceString at: lastIndex + 1]
- 						ifFalse: ["if we're at or past the stopIndex, see if there is anything in the full string"
- 							atEndOfRun := true.
- 							lastIndex + 1 <= sourceString size
- 								ifTrue: [sourceString at: lastIndex + 1]].
- 			"get the font's kerning info for the pair of current character and next character"
- 			"for almost all fonts in common use this is a waste of time since they don't support pair kerning and both values are #widthOf: char"
- 			font
- 				widthAndKernedWidthOfLeft: char
- 				right: nextCharOrNil
- 				into: widthAndKernedWidth.
- 			"bump nextDestX by the width of the current character"
- 			nextDestX := floatDestX
- 						+ (widthAndKernedWidth at: 1).
- 			"if the next x is past the right edge, return crossedX"
- 			nextDestX > rightX
- 				ifTrue: [^ #crossedX].
- 			"bump floatDestX by the *kerned* width of the current
- 			character, which is where the *next* char will go"
- 			floatDestX := floatDestX + kern
- 						+ (widthAndKernedWidth at: 2).
- 			"if we are at the end of this run we keep track of the
- 			character-kern-delta for possible later use and then rather
- 			insanely remove that character-kern-delta from floatDestX,
- 			making it equivalent to (old floatDestX) + kernDelta +
- 			width-of-character - no idea why"
- 			atEndOfRun
- 				ifTrue: [pendingKernX := (widthAndKernedWidth at: 2)
- 								- (widthAndKernedWidth at: 1).
- 					floatDestX := floatDestX - pendingKernX].
- 			"save the next x for next time around the loop"
- 			destX := floatDestX.
- 			lastIndex := lastIndex + 1].
- 	^self handleEndOfRunAt: stopIndex
- !

Item was removed:
- ----- Method: CharacterScanner>>setActualFont: (in category 'text attributes') -----
- setActualFont: aFont
- 	"Set the basal font to an isolated font reference."
- 
- 	xTable := aFont xTable.
- 	map := aFont characterToGlyphMap.
- 	font := aFont.!

Item was removed:
- ----- Method: CharacterScanner>>setAlignment: (in category 'text attributes') -----
- setAlignment: style
- 	alignment := style.
- 	!

Item was removed:
- ----- Method: CharacterScanner>>setFont (in category 'private') -----
- setFont
- 	| priorFont |
- 	"Set the font and other emphasis."
- 	priorFont := font.
- 	text ifNotNil:[
- 		emphasisCode := 0.
- 		kern := 0.
- 		indentationLevel := 0.
- 		alignment := textStyle alignment.
- 		font := nil.
- 		(text attributesAt: lastIndex forStyle: textStyle)
- 			do: [:att | att emphasizeScanner: self]].
- 	font ifNil: [self setFont: textStyle defaultFontIndex].
- 	self setActualFont: (font emphasized: emphasisCode).
- 	priorFont 
- 		ifNotNil: [
- 			font = priorFont 
- 				ifTrue:[
- 					"font is the same, perhaps the color has changed?
- 					We still want kerning between chars of the same
- 					font, but of different color. So add any pending kern to destX"
- 					destX := destX + (pendingKernX ifNil:[0])].
- 			destX := destX + priorFont descentKern].
- 	pendingKernX := 0. "clear any pending kern so there is no danger of it being added twice"
- 	destX := destX - font descentKern.
- 	"NOTE: next statement should be removed when clipping works"
- 	leftMargin ifNotNil: [destX := destX max: leftMargin].
- 	kern := kern - font baseKern.
- 
- 	"Install various parameters from the font."
- 	spaceWidth := font widthOf: Space.!

Item was removed:
- ----- Method: CharacterScanner>>setFont: (in category 'text attributes') -----
- setFont: fontNumber
- 	"Set the font by number from the textStyle."
- 
- 	self setActualFont: (textStyle fontAt: fontNumber)!

Item was removed:
- ----- Method: CharacterScanner>>setStopConditions (in category 'private') -----
- setStopConditions
- 	"Set the font and the stop conditions for the current run."
- 	
- 	self setFont.
- 	stopConditions := alignment = Justified
- 		ifTrue: [PaddedSpaceCondition]
- 		ifFalse: [DefaultStopConditions]!

Item was removed:
- ----- Method: CharacterScanner>>text:textStyle: (in category 'private') -----
- text: t textStyle: ts
- 	text := t.
- 	textStyle := ts!

Item was removed:
- ----- Method: CharacterScanner>>textAnchorPropertiesFor: (in category 'private-text-anchor') -----
- textAnchorPropertiesFor: aMorphOrForm
- 
- 	^ aMorphOrForm textAnchorProperties!

Item was removed:
- ----- Method: CharacterScanner>>textColor: (in category 'text attributes') -----
- textColor: ignored
- 	"Overridden in DisplayScanner"!

Item was removed:
- 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'
- 	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 removed:
- ----- Method: Color class>>aluminum (in category 'named colors - crayons') -----
- aluminum
- 
- 	^ Color r: 153/255 g: 153/255 b: 153/255!

Item was removed:
- ----- Method: Color class>>aqua (in category 'named colors - crayons') -----
- aqua
- 
- 	^ Color r: 0.0 g: 128/255 b: 1.0!

Item was removed:
- ----- Method: Color class>>asparagus (in category 'named colors - crayons') -----
- asparagus
- 
- 	^ Color r: 128/255 g: 128/255 b: 0.0!

Item was removed:
- ----- Method: Color class>>banana (in category 'named colors - crayons') -----
- banana
- 
- 	^ Color r: 1.0 g: 1.0 b: 102/255!

Item was removed:
- ----- Method: Color class>>black (in category 'named colors') -----
- black
- 	^Black!

Item was removed:
- ----- Method: Color class>>blue (in category 'named colors') -----
- blue
- 	^Blue!

Item was removed:
- ----- Method: Color class>>blueberry (in category 'named colors - crayons') -----
- blueberry
- 
- 	^ Color r: 0.0 g: 0.0 b: 1.0!

Item was removed:
- ----- Method: Color class>>brown (in category 'named colors') -----
- brown
- 	^Brown!

Item was removed:
- ----- Method: Color class>>bubblegum (in category 'named colors - crayons') -----
- bubblegum
- 
- 	^ Color r: 1.0 g: 102/255 b: 1.0!

Item was removed:
- ----- Method: Color class>>cachedColormapFrom:to: (in category 'colormaps') -----
- cachedColormapFrom: sourceDepth to: destDepth
- 	"Return a cached colormap for mapping between the given depths. Always return a real colormap, not nil; this allows the client to get an identity colormap that can then be copied and modified to do color transformations."
- 	"Note: This method returns a shared, cached colormap to save time and space. Clients that need to modify a colormap returned by this method should make a copy and modify that!!"
- 	"Note: The colormap cache may be cleared by evaluating 'Color shutDown'."
- 
- 	| srcIndex map |
- 	CachedColormaps class == Array ifFalse: [CachedColormaps := (1 to: 9) collect: [:i | Array new: 32]].
- 	srcIndex := sourceDepth.
- 	sourceDepth > 8 ifTrue: [srcIndex := 9].
- 	(map := (CachedColormaps at: srcIndex) at: destDepth) ~~ nil ifTrue: [^ map].
- 
- 	map := self computeColormapFrom: sourceDepth to: destDepth.
- 	(CachedColormaps at: srcIndex) at: destDepth put: map.
- 	^ map
- !

Item was removed:
- ----- Method: Color class>>cantaloupe (in category 'named colors - crayons') -----
- cantaloupe
- 
- 	^ Color r: 1.0 g: 204/255 b: 102/255!

Item was removed:
- ----- Method: Color class>>carnation (in category 'named colors - crayons') -----
- carnation
- 
- 	^ Color r: 1.0 g: 111/255 b: 207/255!

Item was removed:
- ----- Method: Color class>>cayenne (in category 'named colors - crayons') -----
- cayenne
- 
- 	^ Color r: 128/255 g: 0.0 b: 0.0!

Item was removed:
- ----- Method: Color class>>cleanUp: (in category 'class initialization') -----
- cleanUp: aggressive
- 	self initializeNamesMap!

Item was removed:
- ----- Method: Color class>>clover (in category 'named colors - crayons') -----
- clover
- 
- 	^ Color r: 0.0 g: 128/255 b: 0.0!

Item was removed:
- ----- Method: Color class>>colorFrom: (in category 'instance creation') -----
- colorFrom: parm
- 	"Return an instantiated color from parm.  If parm is already a color, return it, else return the result of my performing it if it's a symbol or, if it is a list, it can either be an array of three numbers, which will be interpreted as RGB values, or a list of symbols, the first of which is sent to me and then the others of which are in turn sent to the prior result, thus allowing entries of the form #(blue darker).  Else just return the thing"
- 
- 	| aColor firstParm |
- 	(parm isKindOf: Color) ifTrue: [^ parm].
- 	(parm isSymbol) ifTrue: [^ self perform: parm].
- 	(parm isString) ifTrue: [^ self fromString: parm].
- 	((parm isKindOf: SequenceableCollection) and: [parm size > 0])
- 		ifTrue:
- 			[firstParm := parm first.
- 			(firstParm isKindOf: Number) ifTrue:
- 				[^ self fromRgbTriplet: parm].
- 			aColor := self colorFrom: firstParm.
- 			parm withIndexDo:
- 				[:sym :ind | ind > 1 ifTrue:
- 					[aColor := aColor perform: sym]].
- 			^ aColor].
- 	^ parm
- 
- "
- Color colorFrom: #(blue darker)
- Color colorFrom: Color blue darker
- Color colorFrom: #blue
- Color colorFrom: #(0.0 0.0 1.0)
- "!

Item was removed:
- ----- Method: Color class>>colorFromPixelValue:depth: (in category 'instance creation') -----
- colorFromPixelValue: p depth: d
- 	"Convert a pixel value for the given display depth into a color."
- 	"Details: For depths of 8 or less, the pixel value is simply looked up in a table. For greater depths, the color components are extracted and converted into a color."
- 
- 	| r g b alpha |
- 	d = 8 ifTrue: [^ IndexedColors at: (p bitAnd: 16rFF) + 1].
- 	d = 4 ifTrue: [^ IndexedColors at: (p bitAnd: 16r0F) + 1].
- 	d = 2 ifTrue: [^ IndexedColors at: (p bitAnd: 16r03) + 1].
- 	d = 1 ifTrue: [^ IndexedColors at: (p bitAnd: 16r01) + 1].
- 
- 	(d = 16) | (d = 15) ifTrue: [
- 		"five bits per component"
- 		r := (p bitShift: -10) bitAnd: 16r1F.
- 		g := (p bitShift: -5) bitAnd: 16r1F.
- 		b := p bitAnd: 16r1F.
- 		(r = 0 and: [g = 0]) ifTrue: [
- 			b = 0 ifTrue: [^Color transparent].
- 			b = 1 ifTrue: [^Color black]].
- 		^ Color r: r g: g b: b range: 31].
- 
- 	d = 32 ifTrue: [
- 		"eight bits per component; 8 bits of alpha"
- 		r := (p bitShift: -16) bitAnd: 16rFF.
- 		g := (p bitShift: -8) bitAnd: 16rFF.
- 		b := p bitAnd: 16rFF.
- 		alpha := p bitShift: -24.
- 		alpha = 0 ifTrue: [^Color transparent].
- 		(r = 0 and: [g = 0 and: [b = 0]])  ifTrue: [^Color transparent].
- 		alpha < 255
- 			ifTrue: [^ (Color r: r g: g b: b range: 255) alpha: (alpha asFloat / 255.0)]
- 			ifFalse: [^ (Color r: r g: g b: b range: 255)]].
- 
- 	d = 12 ifTrue: [
- 		"four bits per component"
- 		r := (p bitShift: -8) bitAnd: 16rF.
- 		g := (p bitShift: -4) bitAnd: 16rF.
- 		b := p bitAnd: 16rF.
- 		^ Color r: r g: g b: b range: 15].
- 
- 	d = 9 ifTrue: [
- 		"three bits per component"
- 		r := (p bitShift: -6) bitAnd: 16r7.
- 		g := (p bitShift: -3) bitAnd: 16r7.
- 		b := p bitAnd: 16r7.
- 		^ Color r: r g: g b: b range: 7].
- 
- 	self error: 'unknown pixel depth: ', d printString
- !

Item was removed:
- ----- Method: Color class>>colorMapIfNeededFrom:to: (in category 'colormaps') -----
- colorMapIfNeededFrom: sourceDepth to: destDepth
- 	"Return a colormap for mapping between the given depths, or nil if no colormap is needed."
- 	"Note: This method returns a shared, cached colormap to save time and space. Clients that need to modify a colormap returned by this method should make a copy and modify that!!"
- 
- 	sourceDepth = destDepth ifTrue: [^ nil].  "not needed if depths are the same"
- 
- 	(sourceDepth >= 16) & (destDepth >= 16) ifTrue: [
- 		"mapping is done in BitBlt by zero-filling or truncating each color component"
- 		^ nil].
- 
- 	^ Color cachedColormapFrom: sourceDepth to: destDepth
- !

Item was removed:
- ----- Method: Color class>>colorNames (in category 'other') -----
- colorNames
- 	"Return a collection of color names."
- 
- 	^ ColorNames asArray, self orderedCrayonColorNames!

Item was removed:
- ----- Method: Color class>>colorRampForDepth:extent: (in category 'examples') -----
- colorRampForDepth: depth extent: aPoint
- 	"Returns a form of the given size showing R, G, B, and gray ramps for the given depth. Useful for testing color conversions between different depths."
- 	"(Color colorRampForDepth: Display depth extent: 256 at 80) display"
- 	"(Color colorRampForDepth: 32 extent: 256 at 80) displayOn: Display at: 0 at 0 rule: Form paint"
- 
- 	| f dx dy r |
- 	f := Form extent: aPoint depth: depth.
- 	dx := aPoint x // 256.
- 	dy := aPoint y // 4.
- 	0 to: 255 do: [:i |
- 		r := (dx * i)@0 extent: dx at dy.
- 		f fill: r fillColor: (Color r: i g: 0 b: 0 range: 255).
- 		r := r translateBy: 0 at dy.
- 		f fill: r fillColor: (Color r: 0 g: i b: 0 range: 255).
- 		r := r translateBy: 0 at dy.
- 		f fill: r fillColor: (Color r: 0 g: 0 b: i range: 255).
- 		r := r translateBy: 0 at dy.
- 		f fill: r fillColor: (Color r: i g: i b: i range: 255)].
- 	^ f
- !

Item was removed:
- ----- Method: Color class>>colorTest:extent:colorMapper: (in category 'color from user') -----
- colorTest: depth extent: chartExtent colorMapper: colorMapper
- 	"Create a palette of colors sorted horizontally by hue and vertically by lightness. Useful for eyeballing the color gamut of the display, or for choosing a color interactively."
- 	"Note: It is slow to build this palette, so it should be cached for quick access."
- 	"(Color colorTest: 32 extent: 570 at 180 colorMapper: [:c | c]) display"
- 	"(Color colorTest: 32 extent: 570 at 180 colorMapper:
- 		[:c | Color
- 			r: (c red * 7) asInteger / 7
- 			g: (c green * 7) asInteger / 7
- 			b: (c blue * 3) asInteger / 3]) display"
- 	"(Color colorTest: 32 extent: 570 at 180 colorMapper:
- 		[:c | Color
- 			r: (c red * 5) asInteger / 5
- 			g: (c green * 5) asInteger / 5
- 			b: (c blue * 5) asInteger / 5]) display"
- 	"(Color colorTest: 32 extent: 570 at 180 colorMapper:
- 		[:c | Color
- 			r: (c red * 15) asInteger / 15
- 			g: (c green * 15) asInteger / 15
- 			b: (c blue * 15) asInteger / 15]) display"
- 	"(Color colorTest: 32 extent: 570 at 180 colorMapper:
- 		[:c | Color
- 			r: (c red * 31) asInteger / 31
- 			g: (c green * 31) asInteger / 31
- 			b: (c blue * 31) asInteger / 31]) display"
- 
- 	| startHue palette transHt vSteps transCaption grayWidth hSteps y c x |
- 	palette := Form extent: chartExtent depth: depth.
- 	transCaption := "(DisplayText text: 'no color' asText textStyle: (TextConstants at: #ComicPlain)) form storeString"
- 		(Form extent: 34 at 9 depth: 1
- 			fromArray: #(0 0 256 0 256 0 3808663859 2147483648 2491688266 2147483648 2491688266 0 2491688266 0 2466486578 0 0 0)
- 			offset: 0 at 0).
- 	transHt := transCaption height.
- 	palette fillWhite: (0 at 0 extent: palette width at transHt).
- 	palette fillBlack: (0 at transHt extent: palette width at 1).
- 	transCaption displayOn: palette at: palette boundingBox topCenter - ((transCaption width // 2)@0).
- 	grayWidth := 10.
- 	startHue := 338.0.
- 	vSteps := palette height - transHt // 2.
- 	hSteps := palette width - grayWidth.
- 	x := 0.
- 	startHue to: startHue + 360.0 by: 360.0/hSteps do: [:h | | basicHue |
- 		basicHue := Color h: h asFloat s: 1.0 v: 1.0.
- 		y := transHt+1.
- 		0 to: vSteps do: [:n |
-  			c := basicHue mixed: (n asFloat / vSteps asFloat) with: Color white.
- 			c := colorMapper value: c.
- 			palette fill: (x at y extent: 1 at 1) fillColor: c.
- 			y := y + 1].
- 		1 to: vSteps do: [:n |
-  			c := Color black mixed: (n asFloat / vSteps asFloat) with: basicHue.
- 			c := colorMapper value: c.
- 			palette fill: (x at y extent: 1 at 1) fillColor: c.
- 			y := y + 1].
- 		x := x + 1].
- 	y := transHt + 1.
- 	1 to: vSteps * 2 do: [:n |
-  		c := Color black mixed: (n asFloat / (vSteps*2) asFloat) with: Color white.
- 		c := colorMapper value: c.
- 		palette fill: (x at y extent: 10 at 1) fillColor: c.
- 		y := y + 1].
- 	^ palette
- !

Item was removed:
- ----- Method: Color class>>computeColorConvertingMap:from:to:keepSubPixelAA: (in category 'colormaps') -----
- computeColorConvertingMap: targetColor from: sourceDepth to: destDepth keepSubPixelAA: keepSubPix
- 
- 	sourceDepth < 16 ifTrue: [
- 		"source is 1-, 2-, 4-, or 8-bit indexed color.
- 		Assumed not to include subpixelAA"
- 		^ self computeIndexedColorConvertingMap: targetColor from: sourceDepth to: destDepth
- 	] ifFalse: [
- 		"source is 16-bit or 32-bit RGB.
- 		Might include subpixelAA"
- 		^ self computeRGBColorConvertingMap: targetColor to: destDepth keepSubPixelAA: keepSubPix
- 	]!

Item was removed:
- ----- Method: Color class>>computeColormapFrom:to: (in category 'colormaps') -----
- computeColormapFrom: sourceDepth to: destDepth
- 	"Compute a colorMap for translating between the given depths. A colormap is a Bitmap whose entries contain the pixel values for the destination depth. Typical clients use cachedColormapFrom:to: instead."
- 
- 	| map bitsPerColor |
- 	sourceDepth < 16 ifTrue: [
- 		"source is 1-, 2-, 4-, or 8-bit indexed color"
- 		map := (IndexedColors copyFrom: 1 to: (1 bitShift: sourceDepth))
- 					collect: [:c | c pixelValueForDepth: destDepth].
- 		map := map as: Bitmap.
- 	] ifFalse: [
- 		"source is 16-bit or 32-bit RGB"
- 		destDepth > 8
- 			ifTrue: [bitsPerColor := 5]  "retain maximum color resolution"
- 			ifFalse: [bitsPerColor := 4].
- 		map := self computeRGBColormapFor: destDepth bitsPerColor: bitsPerColor].
- 
- 	"Note: zero is transparent except when source depth is one-bit deep"
- 	sourceDepth > 1 ifTrue: [map at: 1 put: 0].
- 	^ map
- !

Item was removed:
- ----- Method: Color class>>computeIndexedColorConvertingMap:from:to: (in category 'colormaps') -----
- computeIndexedColorConvertingMap: targetColor from: sourceDepth to: destDepth
- 	| map |
- 	
- 	map := (IndexedColors copyFrom: 1 to: (1 bitShift: sourceDepth)) collect: [ :cc | | f c | 
- 		f := 1.0 - (cc red + cc green + cc blue / 3.0 ).
- 		c := targetColor notNil
- 			ifTrue: [
- 				destDepth = 32
- 					ifTrue: [ targetColor * f alpha: f]
- 					ifFalse: [ targetColor alphaMixed: f*1.5 with: Color white ]]
- 			ifFalse: [ cc ].
- 		destDepth = 32
- 			ifTrue: [ c pixelValueForDepth: destDepth]
- 			ifFalse: [
- 				f = 0.0
- 					ifTrue: [ 0 ]
- 					ifFalse: [ c pixelValueForDepth: destDepth ]]].
- 	map := map as: Bitmap.
- 	^map!

Item was removed:
- ----- Method: Color class>>computeRGBColorConvertingMap:to:keepSubPixelAA: (in category 'colormaps') -----
- computeRGBColorConvertingMap: targetColor to: destDepth keepSubPixelAA: keepSubPix
- 	"Builds a colormap intended to convert from subpixelAA black values to targetColor values.
- 	keepSubPix
- 		ifTrue: [ Answer colors that also include subpixelAA ]
- 		ifFalse: [ 
- 			Take fullpixel luminance level. Apply it to targetColor.
- 			I.e. answer colors with NO subpixelAA ]"
- 
- 	| mask map c bitsPerColor r g b f v |
- 
- 	destDepth > 8
- 		ifTrue: [bitsPerColor := 5]  "retain maximum color resolution"
- 		ifFalse: [bitsPerColor := 4].
- 	"Usually a bit less is enough, but make it configurable"
- 	bitsPerColor := bitsPerColor min: Preferences aaFontsColormapDepth.
- 	mask := (1 bitShift: bitsPerColor) - 1.
- 	map := Bitmap new: (1 bitShift: (3 * bitsPerColor)).
- 	0 to: map size - 1 do: [:i |
- 		r := (i bitShift: 0 - (2 * bitsPerColor)) bitAnd: mask.
- 		g := (i bitShift: 0 - bitsPerColor) bitAnd: mask.
- 		b := (i bitShift: 0) bitAnd: mask.
- 		f := 1.0 - (r + g + b / 3.0 / mask).
- 		c := targetColor notNil
- 			ifTrue: [
- 				(keepSubPix and: [destDepth > 8]) ifTrue: [
- 						Color
- 							r: 1.0 - (r/mask) * targetColor red
- 							g: 1.0 - (g/mask) * targetColor green
- 							b: 1.0 - (b/mask) * targetColor blue
- 							alpha: f	* targetColor alpha "alpha will be ignored below, in #pixelValueForDepth: if destDepth ~= 32" ]
- 				ifFalse: [
- 					destDepth = 32
- 						ifTrue: [ targetColor * f alpha: f * targetColor alpha ]
- 						ifFalse: [ targetColor alphaMixed: f*1.5 with: Color white ]]]
- 			ifFalse: [ Color r: r g: g b: b range: mask].	"This is currently used only to keep some SubPixelAA on destDepth = 8, using a single pass of rule 25"
- 		v := destDepth = 32
- 			ifTrue: [ c pixelValueForDepth: destDepth]
- 			ifFalse: [
- 				f < 0.1
- 					ifTrue: [ 0 ]
- 					ifFalse: [ c pixelValueForDepth: destDepth ]].
- 		map at: i + 1 put: v ].
- 	^ map!

Item was removed:
- ----- Method: Color class>>computeRGBColormapFor:bitsPerColor: (in category 'colormaps') -----
- computeRGBColormapFor: destDepth bitsPerColor: bitsPerColor
- 	"Compute a colorMap for translating from 16-bit or 32-bit RGB color to the given depth, using the given number of of bits per color component."
- 
- 	| mask map c |
- 	(#(3 4 5) includes: bitsPerColor)
- 		ifFalse: [self error: 'BitBlt only supports 3, 4, or 5 bits per color component'].
- 	mask := (1 bitShift: bitsPerColor) - 1.
- 	map := Bitmap new: (1 bitShift: (3 * bitsPerColor)).
- 	0 to: map size - 1 do: [:i |
- 		c := Color
- 			r: ((i bitShift: 0 - (2 * bitsPerColor)) bitAnd: mask)
- 			g: ((i bitShift: 0 - bitsPerColor) bitAnd: mask)
- 			b: ((i bitShift: 0) bitAnd: mask)
- 			range: mask.
- 		map at: i + 1 put: (c pixelValueForDepth: destDepth)].
- 
- 	map at: 1 put: (Color transparent pixelWordForDepth: destDepth).  "zero always transparent"
- 	^ map
- !

Item was removed:
- ----- Method: Color class>>cyan (in category 'named colors') -----
- cyan
- 	^Cyan!

Item was removed:
- ----- Method: Color class>>darkGray (in category 'named colors') -----
- darkGray
- 	^DarkGray!

Item was removed:
- ----- Method: Color class>>eggplant (in category 'named colors - crayons') -----
- eggplant
- 
- 	^ Color r: 64/255 g: 0.0 b: 128/255!

Item was removed:
- ----- Method: Color class>>fern (in category 'named colors - crayons') -----
- fern
- 
- 	^ Color r: 64/255 g: 128/255 b: 0.0!

Item was removed:
- ----- Method: Color class>>flora (in category 'named colors - crayons') -----
- flora
- 
- 	^ Color r: 102/255 g: 1.0 b: 102/255!

Item was removed:
- ----- Method: Color class>>fromArray: (in category 'instance creation') -----
- fromArray: colorDef
- 	colorDef size = 3
- 			ifTrue: [^self r: (colorDef at: 1) g: (colorDef at: 2) b: (colorDef at: 3)].
- 	colorDef size = 0
- 			ifTrue: [^Color transparent].
- 	colorDef size = 4
- 			ifTrue: [^(TranslucentColor r: (colorDef at: 1) g: (colorDef at: 2) b: (colorDef at: 3)) alpha: (colorDef at: 4)].
- 	self error: 'Undefined color definition'!

Item was removed:
- ----- Method: Color class>>fromColorref: (in category 'instance creation') -----
- fromColorref: aColorref 
- 	| red green blue |
- 	red := aColorref bitAnd: 16rFF.
- 	green := (aColorref bitAnd: 16rFF00)
- 				>> 8.
- 	blue := (aColorref bitAnd: 16rFF0000)
- 				>> 16.
- 	^ self r: red g: green b: blue range: 255.!

Item was removed:
- ----- Method: Color class>>fromHTMLString: (in category 'other') -----
- fromHTMLString: aColorHex
- 	"Do not call this method directly, call Color>>#fromString: instead as it is more generic"
- 
- 	| green red blue resultColor |
- 	red := (Integer readFrom: (aColorHex first: 2) base: 16).
- 	green := (Integer readFrom: (aColorHex copyFrom: 3 to: 4) base: 16).
- 	blue := (Integer readFrom: (aColorHex copyFrom: 5 to: 6) base: 16).
- 	resultColor := self r: red g: green b: blue range: 255.
- 	^ (aColorHex size = 8) 
- 		ifTrue: [resultColor alpha: ((Integer readFrom: (aColorHex last: 2) base: 16) / 255)]
- 		ifFalse: [resultColor]!

Item was removed:
- ----- Method: Color class>>fromRGBString: (in category 'other') -----
- fromRGBString: rgb
- 	"Do not call this method directly, call Color>>#fromString: instead as it is more generic"
- 	
- 	| green red blue |
- 	red := (Integer readFrom:(rgb at: 1)) min: 255 max: 0.
- 	green := (Integer readFrom:(rgb at: 2)) min: 255 max: 0.
- 	blue := (Integer readFrom:(rgb at: 3)) min: 255 max: 0.
- 	^self r: red g: green b: blue range: 255!

Item was removed:
- ----- Method: Color class>>fromRgbTriplet: (in category 'instance creation') -----
- fromRgbTriplet: list
- 	^ self r: list first g: list second b: list last!

Item was removed:
- ----- Method: Color class>>fromString: (in category 'instance creation') -----
- fromString: aString
- 	"for HTML color spec: #FFCCAA or white/black/red/other name, or an r,g,b triplet string"
- 	"Color fromString: '#FFCCAA'.
- 	 Color fromString: 'white'.
- 	 Color fromString: 'orange'
- 	 Color fromString: '126,42,33' "
- 	
- 	| aColorHex rgb|
- 	aString isEmptyOrNil ifTrue: [ ^self white ].
- 	aString first = $#
- 		ifTrue: [ aColorHex := aString allButFirst ]
- 		ifFalse: [ aColorHex := aString ].
- 	
- 	"is the string a 6 digit hex number?"
- 	((aColorHex size = 6 or: [aColorHex size = 8]) and: [ 
- 		aColorHex allSatisfy: [ :each | '0123456789ABCDEFabcdef' includes: each ] ])
- 			ifTrue: [^ self fromHTMLString: aColorHex ].
- 	
- 	"is the string in the form a,b,c ?"
- 	rgb := aColorHex findTokens: $, .
- 	rgb size = 3 ifTrue: [^ self fromRGBString: rgb].
- 	
- 	"try to match aColorHex with known named colors, case insensitive"
- 	^self perform: (ColorNames detect: [:colorSymbol | aColorHex sameAs: colorSymbol] ifNone: [ #white ])!

Item was removed:
- ----- Method: Color class>>fromUser (in category 'color from user') -----
- fromUser
- 	"Displays a color palette of colors, waits for a mouse click, and returns the selected color. Any pixel on the Display can be chosen, not just those in the color palette."
- 	"Note: Since the color chart is cached, you may need to do 'ColorChart := nil' after changing the oldColorPaletteForDepth:extent: method."
- 	"Color fromUser"
- 
- 	| d startPt save tr oldColor c here s |
- 	d := Display depth.
- 	((ColorChart == nil) or: [ColorChart depth ~= Display depth]) 
- 		ifTrue: [ColorChart := self oldColorPaletteForDepth: d extent: (2 * 144)@80].
- 	Sensor cursorPoint y < Display center y 
- 		ifTrue: [startPt := 0@(Display boundingBox bottom - ColorChart height)]
- 		ifFalse: [startPt := 0 at 0].
- 
- 	save := Form fromDisplay: (startPt extent: ColorChart extent).
- 	ColorChart displayAt: startPt.
- 	tr := ColorChart extent - (50 at 19) corner: ColorChart extent.
- 	tr := tr translateBy: startPt.
- 
- 	oldColor := nil.
- 	[Sensor anyButtonPressed] whileFalse: [
- 		c := Display colorAt: (here := Sensor cursorPoint).
- 		(tr containsPoint: here)
- 			ifFalse: [Display fill: (0 at 61+startPt extent: 20 at 19) fillColor: c]
- 			ifTrue: [
- 				c := Color transparent.
- 				Display fill: (0 at 61+startPt extent: 20 at 19) fillColor: Color white].
- 		c = oldColor ifFalse: [
- 			Display fillWhite: (20 at 61 + startPt extent: 135 at 19).
- 			c isTransparent
- 				ifTrue: [s := 'transparent']
- 				ifFalse: [s := c shortPrintString.
- 						s := s copyFrom: 7 to: s size - 1].
- 			s displayAt: 20 at 61 + startPt.
- 			oldColor := c]].
- 	save displayAt: startPt.
- 	Sensor waitNoButton.
- 	^ c
- !

Item was removed:
- ----- Method: Color class>>grape (in category 'named colors - crayons') -----
- grape
- 
- 	^ Color r: 128/255 g: 0.0 b: 1.0!

Item was removed:
- ----- Method: Color class>>gray (in category 'named colors') -----
- gray
- 	^Gray!

Item was removed:
- ----- Method: Color class>>gray: (in category 'instance creation') -----
- gray: brightness
- 	"Return a gray shade with the given brightness in the range [0.0..1.0]."
- 
- 	^ self basicNew setRed: brightness green: brightness blue: brightness
- !

Item was removed:
- ----- Method: Color class>>green (in category 'named colors') -----
- green
- 	^Green!

Item was removed:
- ----- Method: Color class>>h:s:v: (in category 'instance creation') -----
- h: hue s: saturation v: brightness
- 	"Create a color with the given hue, saturation, and brightness. Hue is given as the angle in degrees of the color on the color circle where red is zero degrees. Saturation and brightness are numbers in [0.0..1.0] where larger values are more saturated or brighter colors. For example, (Color h: 0 s: 1 v: 1) is pure red."
- 	"Note: By convention, brightness is abbreviated 'v' to to avoid confusion with blue."
- 
- 	^ self basicNew setHue: hue saturation: saturation brightness: brightness!

Item was removed:
- ----- Method: Color class>>h:s:v:alpha: (in category 'instance creation') -----
- h: h s: s v: v alpha: alpha
- 
- 	^ (self h: h s: s v: v) alpha: alpha!

Item was removed:
- ----- Method: Color class>>honeydew (in category 'named colors - crayons') -----
- honeydew
- 
- 	^ Color r: 204/255 g: 1.0 b: 102/255!

Item was removed:
- ----- Method: Color class>>hotColdShades: (in category 'examples') -----
- hotColdShades: thisMany
- 	"An array of thisMany colors showing temperature from blue to red to white hot.  (Later improve this by swinging in hue.)  "
- 	"Color showColors: (Color hotColdShades: 25)"
- 
- 	| n s1 s2 s3 s4 s5 |
- 	thisMany < 5 ifTrue: [^ self error: 'must be at least 5 shades'].
- 	n := thisMany // 5.
- 	s1 := self white mix: self yellow shades: (thisMany - (n*4)).
- 	s2 := self yellow mix: self red shades: n+1.
- 	s2 := s2 copyFrom: 2 to: n+1.
- 	s3 := self red mix: self green darker shades: n+1.
- 	s3 := s3 copyFrom: 2 to: n+1.
- 	s4 := self green darker mix: self blue shades: n+1.
- 	s4 := s4 copyFrom: 2 to: n+1.
- 	s5 := self blue mix: self black shades: n+1.
- 	s5 := s5 copyFrom: 2 to: n+1.
- 	^ s1, s2, s3, s4, s5
- !

Item was removed:
- ----- Method: Color class>>ice (in category 'named colors - crayons') -----
- ice
- 
- 	^ Color r: 102/255 g: 1.0 b: 1.0!

Item was removed:
- ----- Method: Color class>>indexedColors (in category 'other') -----
- indexedColors
- 
- 	^ IndexedColors!

Item was removed:
- ----- Method: Color class>>initialize (in category 'class initialization') -----
- initialize
- 	"Color initialize"
- 
- 	"Details: Externally, the red, green, and blue components of color
- 	are floats in the range [0.0..1.0]. Internally, they are represented
- 	as integers in the range [0..ComponentMask] packing into a
- 	small integer to save space and to allow fast hashing and
- 	equality testing.
- 
- 	For a general description of color representations for computer
- 	graphics, including the relationship between the RGB and HSV
- 	color models used here, see Chapter 17 of Foley and van Dam,
- 	Fundamentals of Interactive Computer Graphics, Addison-Wesley,
- 	1982."
- 
- 	ComponentMask := 1023.
- 	HalfComponentMask := 512.  "used to round up in integer calculations"
- 	ComponentMax := 1023.0.  "a Float used to normalize components"
- 	RedShift := 20.
- 	GreenShift := 10.
- 	BlueShift := 0.
- 
- 	PureRed		 := self r: 1 g: 0 b: 0.
- 	PureGreen	 := self r: 0 g: 1 b: 0.
- 	PureBlue	 := self r: 0 g: 0 b: 1.
- 	PureYellow	 := self r: 1 g: 1 b: 0.
- 	PureCyan	 := self r: 0 g: 1 b: 1.
- 	PureMagenta := self r: 1 g: 0 b: 1.
- 
- 	RandomStream := Random new.
- 
- 	self initializeIndexedColors.
- 	self initializeGrayToIndexMap.
- 	self initializeNames.
- 	self initializeHighLights.
- !

Item was removed:
- ----- Method: Color class>>initializeGrayToIndexMap (in category 'class initialization') -----
- initializeGrayToIndexMap
- 	"Build an array of gray values available in the 8-bit colormap. This array is indexed by a gray level between black (1) and white (256) and returns the pixel value for the corresponding gray level."
- 	"Note: This method must be called after initializeIndexedColors, since it uses IndexedColors."
- 	"Color initializeGrayToIndexMap"
- 
- 	| grayLevels grayIndices c distToClosest dist indexOfClosest |
- 	"record the level and index of each gray in the 8-bit color table"
- 	grayLevels := OrderedCollection new.
- 	grayIndices := OrderedCollection new.
- 	"Note: skip the first entry, which is reserved for transparent"
- 	2 to: IndexedColors size do: [:i |
- 		c := IndexedColors at: i.
- 		c saturation = 0.0 ifTrue: [  "c is a gray"
- 			grayLevels add: (c privateBlue) >> 2.  "top 8 bits; R, G, and B are the same"
- 			grayIndices add: i - 1]].  "pixel values are zero-based"
- 	grayLevels := grayLevels asArray.
- 	grayIndices := grayIndices asArray.
- 
- 	"for each gray level in [0..255], select the closest match"
- 	GrayToIndexMap := ByteArray new: 256.
- 	0 to: 255 do: [:level |
- 		distToClosest := 10000.  "greater than distance to any real gray"
- 		1 to: grayLevels size do: [:i |
- 			dist := (level - (grayLevels at: i)) abs.
- 			dist < distToClosest ifTrue: [
- 				distToClosest := dist.
- 				indexOfClosest := grayIndices at: i]].
- 		GrayToIndexMap at: (level + 1) put: indexOfClosest].
- !

Item was removed:
- ----- Method: Color class>>initializeHighLights (in category 'class initialization') -----
- initializeHighLights
- 	"Create a set of Bitmaps for quickly reversing areas of the screen without converting colors. "
- 	"Color initializeHighLights"
- 
- 	| t |
- 	t := Array new: 32.
- 	t at: 1 put: (Bitmap with: 16rFFFFFFFF).
- 	t at: 2 put: (Bitmap with: 16rFFFFFFFF).
- 	t at: 4 put: (Bitmap with: 16r55555555).
- 	t at: 8 put: (Bitmap with: 16r7070707).
- 	t at: 16 put: (Bitmap with: 16rFFFFFFFF).
- 	t at: 32 put: (Bitmap with: 16rFFFFFFFF).
- 	HighLightBitmaps := t.
- !

Item was removed:
- ----- Method: Color class>>initializeIndexedColors (in category 'class initialization') -----
- initializeIndexedColors
- 	"Build an array of colors corresponding to the fixed colormap used
- 	 for display depths of 1, 2, 4, or 8 bits."
- 	"Color initializeIndexedColors"
- 
- 	| a index grayVal |
- 	a := Array new: 256.
- 
- 	"1-bit colors (monochrome)"
- 	a at: 1 put: (Color r: 1.0 g: 1.0 b: 1.0).		"white or transparent"
- 	a at: 2 put: (Color r: 0.0 g: 0.0 b: 0.0).	"black"
- 
- 	"additional colors for 2-bit color"
- 	a at: 3 put: (Color r: 1.0 g: 1.0 b: 1.0).	"opaque white"
- 	a at: 4 put: (Color r: 0.5 g: 0.5 b: 0.5).	"1/2 gray"
- 
- 	"additional colors for 4-bit color"
- 	a at:  5 put: (Color r: 1.0 g: 0.0 b: 0.0).	"red"
- 	a at:  6 put: (Color r: 0.0 g: 1.0 b: 0.0).	"green"
- 	a at:  7 put: (Color r: 0.0 g: 0.0 b: 1.0).	"blue"
- 	a at:  8 put: (Color r: 0.0 g: 1.0 b: 1.0).	"cyan"
- 	a at:  9 put: (Color r: 1.0 g: 1.0 b: 0.0).	"yellow"
- 	a at: 10 put: (Color r: 1.0 g: 0.0 b: 1.0).	"magenta"
- 
- 	a at: 11 put: (Color r: 0.125 g: 0.125 b: 0.125).		"1/8 gray"
- 	a at: 12 put: (Color r: 0.25 g: 0.25 b: 0.25).		"2/8 gray"
- 	a at: 13 put: (Color r: 0.375 g: 0.375 b: 0.375).		"3/8 gray"
- 	a at: 14 put: (Color r: 0.625 g: 0.625 b: 0.625).		"5/8 gray"
- 	a at: 15 put: (Color r: 0.75 g: 0.75 b: 0.75).		"6/8 gray"
- 	a at: 16 put: (Color r: 0.875 g: 0.875 b: 0.875).		"7/8 gray"
- 
- 	"additional colors for 8-bit color"
- 	"24 more shades of gray (1/32 increments but not repeating 1/8 increments)"
- 	index := 17.
- 	1 to: 31 do: [:v |
- 		(v \\ 4) = 0 ifFalse: [
- 			grayVal := v / 32.0.
- 			a at: index put: (Color r: grayVal g: grayVal b: grayVal).
- 			index := index + 1]].
- 
- 	"The remainder of color table defines a color cube with six steps
- 	 for each primary color. Note that the corners of this cube repeat
- 	 previous colors, but this simplifies the mapping between RGB colors
- 	 and color map indices. This color cube spans indices 40 through 255
- 	 (indices 41-256 in this 1-based array)."
- 	0 to: 5 do: [:r |
- 		0 to: 5 do: [:g |
- 			0 to: 5 do: [:b |
- 				index := 41 + ((36 * r) + (6 * b) + g).
- 				index > 256 ifTrue: [
- 					self error: 'index out of range in color table compuation'].
- 				a at: index put: (Color r: r g: g b: b range: 5)]]].
- 
- 	IndexedColors := a.
- !

Item was removed:
- ----- 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 removed:
- ----- 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 removed:
- ----- Method: Color class>>initializeTranslucentPatterns (in category 'class initialization') -----
- initializeTranslucentPatterns
- 	"Color initializeTranslucentPatterns"
- 	
- 	TranslucentPatterns := Array new: 8.
- 	#(1 2 4 8) do:[:d| | pattern patternList mask bits |
- 		patternList := Array new: 5.
- 		mask := (1 bitShift: d) - 1.
- 		bits := 2 * d.
- 		[bits >= 32] whileFalse: [
- 			mask := mask bitOr: (mask bitShift: bits).  "double the length of mask"
- 			bits := bits + bits].
- 		"0% pattern"
- 		pattern := Bitmap with: 0 with: 0.
- 		patternList at: 1 put: pattern.
- 		"25% pattern"
- 		pattern := Bitmap with: mask with: 0.
- 		patternList at: 2 put: pattern.
- 		"50% pattern"
- 		pattern := Bitmap with: mask with: mask bitInvert32.
- 		patternList at: 3 put: pattern.
- 		"75% pattern"
- 		pattern := Bitmap with: mask with: 16rFFFFFFFF.
- 		patternList at: 4 put: pattern.
- 		"100% pattern"
- 		pattern := Bitmap with: 16rFFFFFFFF with: 16rFFFFFFFF.
- 		patternList at: 5 put: pattern.
- 		TranslucentPatterns at: d put: patternList.
- 	].!

Item was removed:
- ----- Method: Color class>>iron (in category 'named colors - crayons') -----
- iron
- 
- 	^ Color r: 76/255 g: 76/255 b: 76/255!

Item was removed:
- ----- Method: Color class>>lavender (in category 'named colors - crayons') -----
- lavender
- 
- 	^ Color r: 204/255 g: 102/255 b: 1.0!

Item was removed:
- ----- Method: Color class>>lead (in category 'named colors - crayons') -----
- lead
- 
- 	^ Color r: 25/255 g: 25/255 b: 25/255!

Item was removed:
- ----- Method: Color class>>lemon (in category 'named colors - crayons') -----
- lemon
- 
- 	^ Color r: 1.0 g: 1.0 b: 0.0!

Item was removed:
- ----- Method: Color class>>licorice (in category 'named colors - crayons') -----
- licorice
- 
- 	^ Color r: 0.0 g: 0.0 b: 0.0!

Item was removed:
- ----- Method: Color class>>lightBlue (in category 'named colors') -----
- lightBlue
- 	^LightBlue!

Item was removed:
- ----- Method: Color class>>lightBrown (in category 'named colors') -----
- lightBrown
- 	^LightBrown!

Item was removed:
- ----- Method: Color class>>lightCyan (in category 'named colors') -----
- lightCyan
- 	^LightCyan!

Item was removed:
- ----- Method: Color class>>lightGray (in category 'named colors') -----
- lightGray
- 	^LightGray!

Item was removed:
- ----- Method: Color class>>lightGreen (in category 'named colors') -----
- lightGreen
- 	^LightGreen!

Item was removed:
- ----- Method: Color class>>lightMagenta (in category 'named colors') -----
- lightMagenta
- 	^LightMagenta!

Item was removed:
- ----- Method: Color class>>lightOrange (in category 'named colors') -----
- lightOrange
- 	^LightOrange!

Item was removed:
- ----- Method: Color class>>lightRed (in category 'named colors') -----
- lightRed
- 	^LightRed!

Item was removed:
- ----- Method: Color class>>lightYellow (in category 'named colors') -----
- lightYellow
- 	^LightYellow!

Item was removed:
- ----- Method: Color class>>lime (in category 'named colors - crayons') -----
- lime
- 
- 	^ Color r: 128/255 g: 1.0 b: 0.0!

Item was removed:
- ----- Method: Color class>>magenta (in category 'named colors') -----
- magenta
- 	^Magenta!

Item was removed:
- ----- Method: Color class>>magnesium (in category 'named colors - crayons') -----
- magnesium
- 
- 	^ Color r: 179/255 g: 179/255 b: 179/255!

Item was removed:
- ----- Method: Color class>>maraschino (in category 'named colors - crayons') -----
- maraschino
- 
- 	^ Color r: 1.0 g: 0.0 b: 0.0!

Item was removed:
- ----- Method: Color class>>maroon (in category 'named colors - crayons') -----
- maroon
- 
- 	^ Color r: 128/255 g: 0.0 b: 64/255!

Item was removed:
- ----- Method: Color class>>maskingMap: (in category 'other') -----
- maskingMap: depth
- 	"Return a color map that maps all colors except transparent to words of all ones. Used to create a mask for a Form whose transparent pixel value is zero. Cache the most recently used map."
- 
- 	| sizeNeeded |
- 	depth <= 8
- 		ifTrue: [sizeNeeded := 1 bitShift: depth]
- 		ifFalse: [sizeNeeded := 4096].
- 
- 	(MaskingMap == nil or: [MaskingMap size ~= sizeNeeded]) ifTrue:
- 		[MaskingMap := Bitmap new: sizeNeeded withAll: 16rFFFFFFFF.
- 		MaskingMap at: 1 put: 0.  "transparent"].
- 
- 	^ MaskingMap
- !

Item was removed:
- ----- Method: Color class>>mercury (in category 'named colors - crayons') -----
- mercury
- 
- 	^ Color r: 230.0 g: 230.0 b: 230.0!

Item was removed:
- ----- Method: Color class>>midnight (in category 'named colors - crayons') -----
- midnight
- 
- 	^ Color r: 0.0 g: 0.0 b: 128/255!

Item was removed:
- ----- Method: Color class>>mocha (in category 'named colors - crayons') -----
- mocha
- 
- 	^ Color r: 128/255 g: 64/255 b: 0.0!

Item was removed:
- ----- Method: Color class>>moss (in category 'named colors - crayons') -----
- moss
- 
- 	^ Color r: 0.0 g: 128/255 b: 64/255!

Item was removed:
- ----- Method: Color class>>named: (in category 'instance creation') -----
- named: colorName
- 
- 	| colorSym result |
- 	(colorSym := Symbol lookup: colorName) ifNil: [^ nil].
- 	result := (self class canUnderstand: colorSym)
- 		ifTrue: [self perform: colorSym]
- 		ifFalse: [self classPool at: colorSym ifAbsent: nil].
- 	^ result isColor ifTrue: [result]!

Item was removed:
- ----- Method: Color class>>named:put: (in category 'class initialization') -----
- named: newName put: aColor
- 	"Add a new color to the list and create an access message and a class variable for it.  The name should start with a lowercase letter.  (The class variable will start with an uppercase letter.)  (Color colorNames) returns a list of all color names.  "
- 	| str cap sym accessor csym |
- 	(aColor isKindOf: self) ifFalse: [^ self error: 'not a Color'].
- 	str := newName asString.
- 	sym := str asSymbol.
- 	cap := str capitalized.
- 	csym := cap asSymbol.
- 	(self class canUnderstand: sym) ifFalse: [
- 		"define access message"
- 		accessor := str, (String with: Character cr with: Character tab), 			'^', cap.
- 		self class compile: accessor
- 			classified: 'named colors'].
- 	(self classPool includesKey: csym) ifFalse: [
- 		self addClassVarName: cap].
- 	ColorNames add: sym.
- 	^ self classPool at: csym put: aColor!

Item was removed:
- ----- Method: Color class>>new (in category 'instance creation') -----
- new
- 
- 	^ self r: 0.0 g: 0.0 b: 0.0!

Item was removed:
- ----- Method: Color class>>nickel (in category 'named colors - crayons') -----
- nickel
- 
- 	^ Color r: 128/255 g: 128/255 b: 128/255!

Item was removed:
- ----- Method: Color class>>ocean (in category 'named colors - crayons') -----
- ocean
- 
- 	^ Color r: 0.0 g: 64/255 b: 128/255!

Item was removed:
- ----- Method: Color class>>oldColorPaletteForDepth:extent: (in category 'color from user') -----
- oldColorPaletteForDepth: depth extent: paletteExtent
- 	"Returns a form of the given size showing a color palette for the given depth."
- 	"(Color oldColorPaletteForDepth: Display depth extent: 720 at 100) display"
- 
- 	| c p f nSteps rect w h q |
- 	f := Form extent: paletteExtent depth: depth.
- 	f fill: f boundingBox fillColor: Color white.
- 	nSteps := depth > 8 ifTrue: [12] ifFalse: [6].
- 	w := paletteExtent x // (nSteps * nSteps).
- 	h := paletteExtent y - 20 // nSteps.
- 	0 to: nSteps-1 do: [:r |
- 		0 to: nSteps-1 do: [:g |
- 			0 to: nSteps-1 do: [:b |
- 				c := Color r: r g: g b: b range: nSteps - 1.
- 				rect := ((r * nSteps * w) + (b * w)) @ (g * h) extent: w@(h + 1).
- 				f fill: rect fillColor: c]]].
- 	q := Quadrangle origin: paletteExtent - (50 at 19) corner: paletteExtent.
- 	q displayOn: f.
- 	'Trans.' displayOn: f at: q origin + (9 at 1).
- 
- 	w := ((paletteExtent x - q width - 130) // 64) max: 1.
- 	p := paletteExtent x - q width - (64 * w) - 1 @ (paletteExtent y - 19).
- 	0 to: 63 do:
- 		[:v | c := Color r: v g: v b: v range: 63.
- 		f fill: ((v * w)@0 + p extent: (w + 1)@19) fillColor: c].
- 	^ f
- !

Item was removed:
- ----- Method: Color class>>orange (in category 'named colors') -----
- orange
- 	^Orange!

Item was removed:
- ----- Method: Color class>>orchid (in category 'named colors - crayons') -----
- orchid
- 
- 	^ Color r: 102/255 g: 102/255 b: 1.0!

Item was removed:
- ----- Method: Color class>>orderedCrayonColorNames (in category 'other') -----
- orderedCrayonColorNames
- 	
- 	^ #(cantaloupe honeydew spindrift sky lavender carnation licorice snow salmon banana flora ice orchid bubblegum lead mercury tangerine lime seaFoam aqua grape strawberry tungsten silver maraschino lemon spring turquoise blueberry magenta iron magnesium mocha fern moss ocean eggplant maroon steel aluminum cayenne asparagus clover teal midnight plum tin nickel)!

Item was removed:
- ----- Method: Color class>>orderedCrayonColors (in category 'other') -----
- orderedCrayonColors
- 	"self orderedCrayonColors explore."
- 	
- 	^ OrderedDictionary newFrom: (self orderedCrayonColorNames collect: [:ea | ea -> (self perform: ea)])!

Item was removed:
- ----- Method: Color class>>paleBlue (in category 'named colors') -----
- paleBlue
- 	^PaleBlue!

Item was removed:
- ----- Method: Color class>>paleBuff (in category 'named colors') -----
- paleBuff
- 	^PaleBuff!

Item was removed:
- ----- Method: Color class>>paleGreen (in category 'named colors') -----
- paleGreen
- 	^PaleGreen!

Item was removed:
- ----- Method: Color class>>paleMagenta (in category 'named colors') -----
- paleMagenta
- 	^PaleMagenta!

Item was removed:
- ----- Method: Color class>>paleOrange (in category 'named colors') -----
- paleOrange
- 	^PaleOrange!

Item was removed:
- ----- Method: Color class>>palePeach (in category 'named colors') -----
- palePeach
- 	^PalePeach!

Item was removed:
- ----- Method: Color class>>paleRed (in category 'named colors') -----
- paleRed
- 	^PaleRed!

Item was removed:
- ----- Method: Color class>>paleTan (in category 'named colors') -----
- paleTan
- 	^PaleTan!

Item was removed:
- ----- Method: Color class>>paleYellow (in category 'named colors') -----
- paleYellow
- 	^PaleYellow!

Item was removed:
- ----- Method: Color class>>pantonePurpleU (in category 'named colors') -----
- pantonePurpleU
- 	^PantonePurpleU!

Item was removed:
- ----- Method: Color class>>pixelScreenForDepth: (in category 'other') -----
- pixelScreenForDepth: depth
- 	"Return a 50% stipple containing alternating pixels of all-zeros and all-ones to be used as a mask at the given depth."
- 
- 	| mask bits |
- 	mask := (1 bitShift: depth) - 1.
- 	bits := 2 * depth.
- 	[bits >= 32] whileFalse: [
- 		mask := mask bitOr: (mask bitShift: bits).  "double the length of mask"
- 		bits := bits + bits].
- 	^ Bitmap with: mask with: mask bitInvert32
- !

Item was removed:
- ----- Method: Color class>>plum (in category 'named colors - crayons') -----
- plum
- 
- 	^ Color r: 128/255 g: 0.0 b: 128/255!

Item was removed:
- ----- Method: Color class>>quickHighLight: (in category 'other') -----
- quickHighLight: depth
- 	"Quickly return a Bitblt-ready raw colorValue for highlighting areas.  6/22/96 tk"
- 
- 	^ HighLightBitmaps at: depth!

Item was removed:
- ----- Method: Color class>>r:g:b: (in category 'instance creation') -----
- r: r g: g b: b
- 	"Return a color with the given r, g, and b components in the range [0.0..1.0]."
- 
- 	^ self basicNew setRed: r green: g blue: b
- !

Item was removed:
- ----- Method: Color class>>r:g:b:alpha: (in category 'instance creation') -----
- r: r g: g b: b alpha: alpha
- 
- 	^ (self r: r g: g b: b) alpha: alpha!

Item was removed:
- ----- Method: Color class>>r:g:b:range: (in category 'instance creation') -----
- r: r g: g b: b range: range
- 	"Return a color with the given r, g, and b components specified as integers in the range [0..r]. This avoids the floating point arithmetic in the red:green:blue: message and is thus a bit faster for certain applications (such as computing a sequence of colors for a palette)."
- 
- 	^ self basicNew setRed: r green: g blue: b range: range!

Item was removed:
- ----- Method: Color class>>random (in category 'instance creation') -----
- random
- 	"Return a random color that isn't too dark or under-saturated."
- 
- 	^ self basicNew
- 		setHue: (360.0 * RandomStream next)
- 		saturation: (0.3 + (RandomStream next * 0.7))
- 		brightness: (0.4 + (RandomStream next * 0.6))!

Item was removed:
- ----- Method: Color class>>red (in category 'named colors') -----
- red
- 	^Red!

Item was removed:
- ----- Method: Color class>>salmon (in category 'named colors - crayons') -----
- salmon
- 
- 	^ Color r: 1.0 g: 102/255 b: 102/255!

Item was removed:
- ----- Method: Color class>>seaFoam (in category 'named colors - crayons') -----
- seaFoam
- 
- 	^ Color r: 0.0 g: 1.0 b: 128/255!

Item was removed:
- ----- Method: Color class>>showColorCube (in category 'examples') -----
- showColorCube
- 	"Show a 12x12x12 color cube."
- 	"Color showColorCube"
- 
- 	0 to: 11 do: [:r |
- 		0 to: 11 do: [:g |
- 			0 to: 11 do: [:b |	
- 				Display fill: (((r*60) + (b*5)) @ (g*5) extent: 5 at 5)
- 					fillColor: (Color r: r g: g b: b range: 11)]]].
- !

Item was removed:
- ----- Method: Color class>>showColors: (in category 'examples') -----
- showColors: colorList
- 	"Display the given collection of colors across the top of the Display."
- 
- 	| w r |
- 	w := Display width // colorList size.
- 	r := 0 at 0 extent: w@((w min: 30) max: 10).
- 	colorList do: [:c |
- 		Display fill: r fillColor: c.
- 		r := r translateBy: w at 0].
- !

Item was removed:
- ----- Method: Color class>>showHSVPalettes (in category 'examples') -----
- showHSVPalettes
- 	"Shows a palette of hues, varying the saturation and brightness for each one. Best results are with depths 16 and 32."
- 	"Color showHSVPalettes"
- 
- 	| left top c |
- 	left := top := 0.
- 	0 to: 179 by: 15 do: [:h |
- 		0 to: 10 do: [:s |
- 			left := (h * 4) + (s * 4).
- 			0 to: 10 do: [:v |
- 				c := Color h: h s: s asFloat / 10.0 v: v asFloat / 10.0.
- 				top := (v * 4).
- 				Display fill: (left at top extent: 4 at 4) fillColor: c.
- 
- 				c := Color h: h + 180 s: s asFloat / 10.0 v: v asFloat / 10.0.
- 				top := (v * 4) + 50.
- 				Display fill: (left at top extent: 4 at 4) fillColor: c]]].
- !

Item was removed:
- ----- Method: Color class>>showHuesInteractively (in category 'examples') -----
- showHuesInteractively
- 	"Shows a palette of hues at a (saturation, brightness) point determined by the mouse position. Click the mouse button to exit and return the selected (saturation, brightness) point."
- 	"Color showHuesInteractively"
- 
- 	| p s v |
- 	[Sensor anyButtonPressed] whileFalse: [
- 		p := Sensor cursorPoint.
- 		s := p x asFloat / 300.0.
- 		v := p y asFloat / 300.0.
- 		self showColors: (self wheel: 12 saturation: s brightness: v)].
- 	^ (s min: 1.0) @ (v min: 1.0)!

Item was removed:
- ----- Method: Color class>>shutDown (in category 'other') -----
- shutDown
- 	"Color shutDown"
- 
- 	ColorChart := nil.		"Palette of colors for the user to pick from"
- 	CachedColormaps := nil.	"Maps to translate between color depths"
- 	MaskingMap := nil.		"Maps all colors except transparent to black for creating a mask"
- !

Item was removed:
- ----- Method: Color class>>silver (in category 'named colors - crayons') -----
- silver
- 
- 	^ Color r: 204/255 g: 204/255 b: 204/255!

Item was removed:
- ----- Method: Color class>>sky (in category 'named colors - crayons') -----
- sky
- 
- 	^ Color r: 102/255 g: 204/255 b: 1.0!

Item was removed:
- ----- Method: Color class>>snow (in category 'named colors - crayons') -----
- snow
- 
- 	^ Color r: 1.0 g: 1.0 b: 1.0!

Item was removed:
- ----- Method: Color class>>spindrift (in category 'named colors - crayons') -----
- spindrift
- 
- 	^ Color r: 102/255 g: 1.0 b: 204/255!

Item was removed:
- ----- Method: Color class>>spring (in category 'named colors - crayons') -----
- spring
- 
- 	^ Color r: 0.0 g: 1.0 b: 0.0!

Item was removed:
- ----- Method: Color class>>steel (in category 'named colors - crayons') -----
- steel
- 
- 	^ Color r: 102/255 g: 102/255 b: 102/255!

Item was removed:
- ----- Method: Color class>>strawberry (in category 'named colors - crayons') -----
- strawberry
- 
- 	^ Color r: 1.0 g: 0.0 b: 128/255!

Item was removed:
- ----- Method: Color class>>tan (in category 'named colors') -----
- tan
- 	^  Color r: 0.8 g: 0.8 b: 0.5!

Item was removed:
- ----- Method: Color class>>tangerine (in category 'named colors - crayons') -----
- tangerine
- 
- 	^ Color r: 1.0 g: 128/255 b: 0.0!

Item was removed:
- ----- Method: Color class>>teal (in category 'named colors - crayons') -----
- teal
- 
- 	^ Color r: 0.0 g: 128/255 b: 128/255!

Item was removed:
- ----- Method: Color class>>tin (in category 'named colors - crayons') -----
- tin
- 
- 	^ Color r: 127/255 g: 127/255 b: 127/255!

Item was removed:
- ----- Method: Color class>>translucentMaskFor:depth: (in category 'other') -----
- translucentMaskFor: alphaValue depth: d
- 	"Return a pattern representing a mask usable for stipple transparency"
- 	^(TranslucentPatterns at: d) at: ((alphaValue min: 1.0 max: 0.0) * 4) rounded + 1!

Item was removed:
- ----- Method: Color class>>transparent (in category 'named colors') -----
- transparent
- 	^Transparent!

Item was removed:
- ----- Method: Color class>>tungsten (in category 'named colors - crayons') -----
- tungsten
- 
- 	^ Color r: 51/255 g: 51/255 b: 51/255!

Item was removed:
- ----- Method: Color class>>turquoise (in category 'named colors - crayons') -----
- turquoise
- 
- 	^ Color r: 0.0 g: 1.0 b: 1.0!

Item was removed:
- ----- Method: Color class>>veryDarkGray (in category 'named colors') -----
- veryDarkGray
- 	^VeryDarkGray!

Item was removed:
- ----- Method: Color class>>veryLightGray (in category 'named colors') -----
- veryLightGray
- 	^VeryLightGray!

Item was removed:
- ----- Method: Color class>>veryPaleRed (in category 'named colors') -----
- veryPaleRed
- 	^VeryPaleRed!

Item was removed:
- ----- Method: Color class>>veryVeryDarkGray (in category 'named colors') -----
- veryVeryDarkGray
- 	^VeryVeryDarkGray!

Item was removed:
- ----- Method: Color class>>veryVeryLightGray (in category 'named colors') -----
- veryVeryLightGray
- 	^VeryVeryLightGray!

Item was removed:
- ----- Method: Color class>>wheel: (in category 'examples') -----
- wheel: thisMany
- 	"Return a collection of thisMany colors evenly spaced around the color wheel."
- 	"Color showColors: (Color wheel: 12)"
- 
- 	^ Color wheel: thisMany saturation: 0.9 brightness: 0.7
- !

Item was removed:
- ----- Method: Color class>>wheel:saturation:brightness: (in category 'examples') -----
- wheel: thisMany saturation: s brightness: v
- 	"Return a collection of thisMany colors evenly spaced around the color wheel, all of the given saturation and brightness."
- 	"Color showColors: (Color wheel: 12 saturation: 0.4 brightness: 1.0)"
- 	"Color showColors: (Color wheel: 12 saturation: 0.8 brightness: 0.5)"
- 
- 	^ (Color h: 0.0 s: s v: v) wheel: thisMany
- !

Item was removed:
- ----- Method: Color class>>white (in category 'named colors') -----
- white
- 	^White!

Item was removed:
- ----- Method: Color class>>yellow (in category 'named colors') -----
- yellow
- 	^Yellow!

Item was removed:
- ----- Method: Color>>* (in category 'transformations') -----
- * aNumberOrArray
- 	"Answer this color with its RGB multiplied by the given number, or
- 	 multiply this color's RGB values by the corresponding entries in the
- 	given array."
- 	"(Color brown * 2) display"
- 	"(Color brown * #(1 0 1)) display"
- 	| multipliers |
- 	multipliers := aNumberOrArray isCollection
- 		ifTrue: [aNumberOrArray]
- 		ifFalse:
- 			[Array
- 				with: aNumberOrArray
- 				with: aNumberOrArray
- 				with: aNumberOrArray].
- 
- 	^ Color basicNew
- 		setPrivateRed: (self privateRed * multipliers first) asInteger
- 		green: (self privateGreen * multipliers second) asInteger
- 		blue: (self privateBlue * multipliers third) asInteger.!

Item was removed:
- ----- Method: Color>>+ (in category 'transformations') -----
- + aColor
- 	"Answer this color mixed with the given color in an additive color space.  "
- 	"(Color blue + Color green) display"
- 
- 	^ Color basicNew
- 		setPrivateRed: self privateRed + aColor privateRed
- 		green: self privateGreen + aColor privateGreen
- 		blue: self privateBlue + aColor  privateBlue
- !

Item was removed:
- ----- Method: Color>>- (in category 'transformations') -----
- - aColor
- 	"Answer aColor is subtracted from the given color in an additive color space.  "
- 	"(Color white - Color red) display"
- 
- 	^ Color basicNew
- 		setPrivateRed: self privateRed - aColor privateRed
- 		green: self privateGreen - aColor privateGreen
- 		blue: self privateBlue - aColor  privateBlue
- !

Item was removed:
- ----- Method: Color>>/ (in category 'transformations') -----
- / aNumber
- 	"Answer this color with its RGB divided by the given number. "
- 	"(Color red / 2) display"
- 
- 	^ Color basicNew
- 		setPrivateRed: (self privateRed / aNumber) asInteger
- 		green: (self privateGreen / aNumber) asInteger
- 		blue: (self privateBlue / aNumber) asInteger
- !

Item was removed:
- ----- Method: Color>>= (in category 'comparing') -----
- = aColor
- 	"Return true if the receiver equals the given color. This method handles TranslucentColors, too."
- 
- 	aColor isColor ifFalse: [^ false].
- 	^ aColor privateRGB = rgb and:
- 		[aColor privateAlpha = self privateAlpha]
- !

Item was removed:
- ----- Method: Color>>addFillStyleMenuItems:hand:from: (in category 'Morphic menu') -----
- addFillStyleMenuItems: aMenu hand: aHand from: aMorph
- 	"Add the items for changing the current fill style of the receiver"
- 	aMenu add: 'change color...' translated target: self selector: #changeColorIn:event: argument: aMorph!

Item was removed:
- ----- 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 removed:
- ----- Method: Color>>adjustBrightness: (in category 'transformations') -----
- adjustBrightness: brightness
- 	"Adjust the relative brightness of this color. (lowest value is 0.005 so that hue information is not lost)"
- 
- 	^ Color
- 		h: self hue
- 		s: self saturation
- 		v: (self brightness + brightness min: 1.0 max: 0.005)
- 		alpha: self alpha!

Item was removed:
- ----- Method: Color>>adjustSaturation:brightness: (in category 'transformations') -----
- adjustSaturation: saturation brightness: brightness
- 	"Adjust the relative saturation and brightness of this color. (lowest value is 0.005 so that hue information is not lost)"
- 
- 	^ Color
- 		h: self hue
- 		s: (self saturation + saturation min: 1.0 max: 0.005)
- 		v: (self brightness + brightness min: 1.0 max: 0.005)
- 		alpha: self alpha!

Item was removed:
- ----- Method: Color>>alpha (in category 'accessing') -----
- alpha
- 	"Return the opacity ('alpha') value of opaque so that normal colors can be compared to TransparentColors."
- 
- 	^ 1.0
- !

Item was removed:
- ----- Method: Color>>alpha: (in category 'transformations') -----
- alpha: alphaValue 
- 	"Answer a new Color with the given amount of opacity ('alpha')."
- 
- 	alphaValue = 1.0
- 		ifFalse: [^ TranslucentColor basicNew setRgb: rgb alpha: alphaValue]!

Item was removed:
- ----- Method: Color>>alphaMixed:with: (in category 'transformations') -----
- alphaMixed: proportion with: aColor 
- 	"Answer this color mixed with the given color. The proportion, a number 
- 	between 0.0 and 1.0, determines what what fraction of the receiver to  
- 	use in the mix. For example, 0.9 would yield a color close to the  
- 	receiver. This method uses RGB interpolation; HSV interpolation can lead 
- 	to surprises.  Mixes the alphas (for transparency) also."
- 
- 	| frac1 frac2 |
- 	frac1 := proportion asFloat min: 1.0 max: 0.0.
- 	frac2 := 1.0 - frac1.
- 	^ Color
- 		r: self red * frac1 + (aColor red * frac2)
- 		g: self green * frac1 + (aColor green * frac2)
- 		b: self blue * frac1 + (aColor blue * frac2)
- 		alpha: self alpha * frac1 + (aColor alpha * frac2)!

Item was removed:
- ----- Method: Color>>asColor (in category 'conversions') -----
- asColor
- 	"Convert the receiver into a color"
- 	^self!

Item was removed:
- ----- Method: Color>>asColorref (in category 'conversions') -----
- asColorref
- 	"Convert the receiver into a colorref"
- 	^ (self red * 255) rounded + ((self green * 255) rounded << 8) + ((self blue * 255) rounded << 16)!

Item was removed:
- ----- Method: Color>>asHTMLColor (in category 'conversions') -----
- asHTMLColor
- 	| s |
- 	s := '#000000' copy.
- 	s at: 2 put: (Character digitValue: ((rgb bitShift: -6 - RedShift) bitAnd: 15)).
- 	s at: 3 put: (Character digitValue: ((rgb bitShift: -2 - RedShift) bitAnd: 15)).
- 	s at: 4 put: (Character digitValue: ((rgb bitShift: -6 - GreenShift) bitAnd: 15)).
- 	s at: 5 put: (Character digitValue: ((rgb bitShift: -2 - GreenShift) bitAnd: 15)).
- 	s at: 6 put: (Character digitValue: ((rgb bitShift: -6 - BlueShift) bitAnd: 15)).
- 	s at: 7 put: (Character digitValue: ((rgb bitShift: -2 - BlueShift) bitAnd: 15)).
- 	^ s!

Item was removed:
- ----- Method: Color>>asNontranslucentColor (in category 'conversions') -----
- asNontranslucentColor
- 	^ self!

Item was removed:
- ----- Method: Color>>atLeastAsLuminentAs: (in category 'transformations') -----
- atLeastAsLuminentAs: aFloat
- 
- 	| revisedColor |
- 	revisedColor := self.
- 	[revisedColor luminance < aFloat] whileTrue: [revisedColor := revisedColor slightlyLighter].
- 	^revisedColor
- !

Item was removed:
- ----- Method: Color>>atMostAsLuminentAs: (in category 'transformations') -----
- atMostAsLuminentAs: aFloat
- 
- 	| revisedColor |
- 	revisedColor := self.
- 	[revisedColor luminance > aFloat] whileTrue: [revisedColor := revisedColor slightlyDarker].
- 	^revisedColor
- !

Item was removed:
- ----- Method: Color>>attemptToMutateError (in category 'private') -----
- attemptToMutateError
- 	"A color is immutable. Once a color's red, green, and blue have been initialized, you cannot change them. Instead, create a new Color and use it."
- 
- 	self error: 'Color objects are immutable once created'
- !

Item was removed:
- ----- Method: Color>>balancedPatternForDepth: (in category 'conversions') -----
- balancedPatternForDepth: depth
- 	"A generalization of bitPatternForDepth: as it exists.  Generates a 2x2 stipple of color.
- 	The topLeft and bottomRight pixel are closest approx to this color"
- 	| pv1 pv2 mask1 mask2 pv3 c |
- 	(depth == cachedDepth and:[cachedBitPattern size = 2]) ifTrue: [^ cachedBitPattern].
- 	(depth between: 4 and: 16) ifFalse: [^ self bitPatternForDepth: depth].
- 	cachedDepth := depth.
- 	pv1 := self pixelValueForDepth: depth.
- "
- 	Subtract error due to pv1 to get pv2.
- 	pv2 := (self - (err1 := (Color colorFromPixelValue: pv1 depth: depth) - self))
- 						pixelValueForDepth: depth.
- 	Subtract error due to 2 pv1's and pv2 to get pv3.
- 	pv3 := (self - err1 - err1 - ((Color colorFromPixelValue: pv2 depth: depth) - self))
- 						pixelValueForDepth: depth.
- "
- 	"Above two statements computed faster by the following..."
- 	pv2 := (c := self - ((Color colorFromPixelValue: pv1 depth: depth) - self))
- 						pixelValueForDepth: depth.
- 	pv3 := (c + (c - (Color colorFromPixelValue: pv2 depth: depth)))
- 						pixelValueForDepth: depth.
- 
- 	"Return to a 2-word bitmap that encodes a 2x2 stipple of the given pixelValues."
- 	mask1 := (#(- - -	
- 			16r01010101 - - -			"replicates every other 4 bits"
- 			16r00010001 - - - - - - -	"replicates every other 8 bits"
- 			16r00000001) at: depth).	"replicates every other 16 bits"
- 	mask2 := (#(- - -	
- 			16r10101010 - - -			"replicates the other 4 bits"
- 			16r01000100 - - - - - - -	"replicates the other 8 bits"
- 			16r00010000) at: depth).	"replicates the other 16 bits"
- 	^ cachedBitPattern := Bitmap with: (mask1*pv1) + (mask2*pv2) with: (mask1*pv3) + (mask2*pv1)!

Item was removed:
- ----- Method: Color>>bitPatternForDepth: (in category 'conversions') -----
- bitPatternForDepth: depth
- 	"Return a Bitmap, possibly containing a stipple pattern, that best represents this color at the given depth. BitBlt calls this method to convert colors into Bitmaps. The resulting Bitmap may be multiple words to represent a stipple pattern of several lines.  "
- 	"See also:	pixelValueAtDepth:	-- value for single pixel
- 				pixelWordAtDepth:	-- a 32-bit word filled with the pixel value"
- 	"Details: The pattern for the most recently requested depth is cached."
- 	"Note for depths > 2, there are stippled and non-stippled versions (generated with #balancedPatternForDepth: and #bitPatternForDepth:, respectively). The stippled versions don't work with the window bit caching of StandardSystemView, so we make sure that for these depths, only unstippled patterns are returned"
- 
- 	(depth == cachedDepth and: [depth <= 2 or: [cachedBitPattern size = 1]]) ifTrue: [^ cachedBitPattern].
- 	cachedDepth := depth.
- 
- 	depth > 2 ifTrue: [^ cachedBitPattern := Bitmap with: (self pixelWordForDepth: depth)].
- 	depth = 1 ifTrue: [^ cachedBitPattern := self halfTonePattern1].
- 	depth = 2 ifTrue: [^ cachedBitPattern := self halfTonePattern2].
- !

Item was removed:
- ----- Method: Color>>blacker (in category 'transformations') -----
- blacker
- 
- 	^ self alphaMixed: 0.8333 with: Color black
- !

Item was removed:
- ----- Method: Color>>blue (in category 'accessing') -----
- blue
- 	"Return the blue component of this color, a float in the range [0.0..1.0]."
- 
- 	^ self privateBlue asFloat / ComponentMax!

Item was removed:
- ----- Method: Color>>brightness (in category 'accessing') -----
- brightness
- 	"Return the brightness of this color, a float in the range [0.0..1.0]."
- 
- 	^ ((self privateRed max:
- 	    self privateGreen) max:
- 	    self privateBlue) asFloat / ComponentMax!

Item was removed:
- ----- Method: Color>>byteEncode: (in category 'printing') -----
- byteEncode: aStream
- 
- 	aStream
- 		print: '(';
- 		print: self species name;
- 		print: ' r: ';
- 		write: (self red roundTo: 0.001);
- 		print: ' g: ';
- 		write: (self green roundTo: 0.001);
- 		print: ' b: ';
- 		write: (self blue roundTo: 0.001) ;
- 		print: ')'.
- !

Item was removed:
- ----- Method: Color>>changeColorIn:event: (in category 'Morphic menu') -----
- changeColorIn: aMorph event: evt
- 	"Note: This is just a workaround to make sure we don't use the old color inst var"
- 	aMorph changeColorTarget: aMorph selector: #fillStyle: originalColor: self hand: evt hand!

Item was removed:
- ----- Method: Color>>closestPixelValue1 (in category 'conversions') -----
- closestPixelValue1
- 	"Return the nearest approximation to this color for a monochrome Form."
- 
- 	"fast special cases"
- 	rgb = 0 ifTrue: [^ 1].  "black"
- 	rgb = 16r3FFFFFFF ifTrue: [^ 0].  "white"
- 
- 	self luminance > 0.5
- 		ifTrue: [^ 0]  "white"
- 		ifFalse: [^ 1].  "black"
- !

Item was removed:
- ----- Method: Color>>closestPixelValue2 (in category 'conversions') -----
- closestPixelValue2
- 	"Return the nearest approximation to this color for a 2-bit deep Form."
- 
- 	| lum |
- 	"fast special cases"
- 	rgb = 0 ifTrue: [^ 1].  "black"
- 	rgb = 16r3FFFFFFF ifTrue: [^ 2].  "opaque white"
- 
- 	lum := self luminance.
- 	lum < 0.2 ifTrue: [^ 1].  "black"
- 	lum > 0.6 ifTrue: [^ 2].  "opaque white"
- 	^ 3  "50% gray"
- !

Item was removed:
- ----- Method: Color>>closestPixelValue4 (in category 'conversions') -----
- closestPixelValue4
- 	"Return the nearest approximation to this color for a 4-bit deep Form."
- 
- 	| bIndex |
- 	"fast special cases"
- 	rgb = 0 ifTrue: [^ 1].  "black"
- 	rgb = 16r3FFFFFFF ifTrue: [^ 2].  "opaque white"
- 
- 	rgb = PureRed privateRGB ifTrue: [^ 4].
- 	rgb = PureGreen privateRGB ifTrue: [^ 5].
- 	rgb = PureBlue privateRGB ifTrue: [^ 6].
- 	rgb = PureCyan privateRGB ifTrue: [^ 7].
- 	rgb = PureYellow privateRGB ifTrue: [^ 8].
- 	rgb = PureMagenta privateRGB ifTrue: [^ 9].
- 
- 	bIndex := (self luminance * 8.0) rounded.  "bIndex in [0..8]"
- 	^ #(
- 		1	"black"
- 		10	"1/8 gray"
- 		11	"2/8 gray"
- 		12	"3/8 gray"
- 		3	"4/8 gray"
- 		13	"5/8 gray"
- 		14	"6/8 gray"
- 		15	"7/8 gray"
- 		2	"opaque white"
- 	) at: bIndex + 1.
- !

Item was removed:
- ----- Method: Color>>closestPixelValue8 (in category 'conversions') -----
- closestPixelValue8
- 	"Return the nearest approximation to this color for an 8-bit deep Form."
- 
- 	"fast special cases"
- 	rgb = 0 ifTrue: [^ 1].  "black"
- 	rgb = 16r3FFFFFFF ifTrue: [^ 255].  "white"
- 
- 	self saturation < 0.2 ifTrue: [
- 		^ GrayToIndexMap at: (self privateGreen >> 2) + 1.  "nearest gray"
- 	] ifFalse: [
- 		"compute nearest entry in the color cube"
- 		^ 40 +
- 		  ((((self privateRed * 5) + HalfComponentMask) // ComponentMask) * 36) +
- 		  ((((self privateBlue * 5) + HalfComponentMask) // ComponentMask) * 6) +
- 		  (((self privateGreen * 5) + HalfComponentMask) // ComponentMask)].
- !

Item was removed:
- ----- Method: Color>>colorForInsets (in category 'other') -----
- colorForInsets
- 	^ self!

Item was removed:
- ----- Method: Color>>dansDarker (in category 'transformations') -----
- dansDarker
- 	"Return a darker shade of the same color.
- 	An attempt to do better than the current darker method.
- 	(now obsolete, since darker has been changed to do this. -dew)"
- 	^ Color h: self hue s: self saturation
- 		v: (self brightness - 0.16 max: 0.0)!

Item was removed:
- ----- Method: Color>>darkShades: (in category 'groups of shades') -----
- darkShades: thisMany
- 	"An array of thisMany colors from black to the receiver.  Array is of length num. Very useful for displaying color based on a variable in your program.  "
- 	"Color showColors: (Color red darkShades: 12)"
- 
- 	^ self class black mix: self shades: thisMany
- !

Item was removed:
- ----- Method: Color>>darker (in category 'transformations') -----
- darker
- 	"Answer a darker shade of this color."
- 
- 	^ self adjustBrightness: -0.08!

Item was removed:
- ----- Method: Color>>diff: (in category 'comparing') -----
- diff: theOther
- 	"Returns a number between 0.0 and 1.0"
- 
- 	^ ((self privateRed - theOther privateRed) abs
- 		+ (self privateGreen - theOther privateGreen) abs
- 		+ (self privateBlue - theOther privateBlue) abs)
- 		/ 3.0 / ComponentMax!

Item was removed:
- ----- Method: Color>>display (in category 'other') -----
- display
- 	"Show a swatch of this color tracking the cursor until the next mouseClick. "
- 	"Color red display"
- 	| f |
- 	f := Form extent: 40 at 20 depth: Display depth.
- 	f fillColor: self.
- 	Cursor blank showWhile:
- 		[f follow: [Sensor cursorPoint] while: [Sensor noButtonPressed]]!

Item was removed:
- ----- Method: Color>>dominantColor (in category 'conversions') -----
- dominantColor
- 	^ self!

Item was removed:
- ----- Method: Color>>duller (in category 'transformations') -----
- duller
- 	"Answer a darker, desaturated color.  If the original color isn't very saturated, desaturate it by less (otherwise will just end up with grey). If the original color is a grey, don't try to be smart."
- 	| sat adjust |
- 	(sat := self saturation) > 0.3
- 		ifTrue: [adjust := -0.1]
- 		ifFalse: [adjust := 0.1 - sat max: 0.0].
- 	^ sat isZero 
- 		ifTrue: [self adjustBrightness: -0.1]
- 		ifFalse: [self adjustSaturation: adjust brightness: -0.1]!

Item was removed:
- ----- Method: Color>>flushCache (in category 'private') -----
- flushCache
- 	"Flush my cached bit pattern."
- 
- 	cachedDepth := nil.
- 	cachedBitPattern := nil.
- !

Item was removed:
- ----- Method: Color>>green (in category 'accessing') -----
- green
- 	"Return the green component of this color, a float in the range [0.0..1.0]."
- 
- 	^ self privateGreen asFloat / ComponentMax!

Item was removed:
- ----- Method: Color>>halfTonePattern1 (in category 'conversions') -----
- halfTonePattern1
- 	"Return a halftone-pattern to approximate luminance levels on 1-bit deep Forms."
- 
- 	| lum |
- 	lum := self luminance.
- 	lum < 0.1 ifTrue: [^ Bitmap with: 16rFFFFFFFF]. "black"
- 	lum < 0.4 ifTrue: [^ Bitmap with: 16rBBBBBBBB with: 16rEEEEEEEE]. "dark gray"
- 	lum < 0.6 ifTrue: [^ Bitmap with: 16r55555555 with: 16rAAAAAAAA]. "medium gray"
- 	lum < 0.9 ifTrue: [^ Bitmap with: 16r44444444 with: 16r11111111]. "light gray"
- 	^ Bitmap with: 0  "1-bit white"
- !

Item was removed:
- ----- Method: Color>>halfTonePattern2 (in category 'conversions') -----
- halfTonePattern2
- 	"Return a halftone-pattern to approximate luminance levels on 2-bit deep Forms."
- 
- 	| lum |
- 	lum := self luminance.
- 	lum < 0.125 ifTrue: [^ Bitmap with: 16r55555555].  "black"
- 	lum < 0.25 ifTrue: [^ Bitmap with: 16r55555555 with: 16rDDDDDDDD].  "1/8 gray"
- 	lum < 0.375 ifTrue: [^ Bitmap with: 16rDDDDDDDD with: 16r77777777].  "2/8 gray"
- 	lum < 0.5 ifTrue: [^ Bitmap with: 16rFFFFFFFF with: 16r77777777].  "3/8 gray"
- 	lum < 0.625 ifTrue: [^ Bitmap with: 16rFFFFFFFF].  "4/8 gray"
- 	lum < 0.75 ifTrue: [^ Bitmap with: 16rFFFFFFFF with: 16rBBBBBBBB].  "5/8 gray"
- 	lum < 0.875 ifTrue: [^ Bitmap with: 16rEEEEEEEE with: 16rBBBBBBBB].  "6/8 gray"
- 	lum < 1.0 ifTrue: [^ Bitmap with: 16rAAAAAAAA with: 16rBBBBBBBB].  "7/8 gray"
- 	^ Bitmap with: 16rAAAAAAAA  "opaque white"
- 
- "handy expression for computing patterns for 2x2 tiles;
-  set p to a string of 4 letters (e.g., 'wggw' for a gray-and-
-  white checkerboard) and print the result of evaluating:
- | p d w1 w2 |
- p := 'wggw'.
- d := Dictionary new.
- d at: $b put: '01'.
- d at: $w put: '10'.
- d at: $g put: '11'.
- w1 := (d at: (p at: 1)), (d at: (p at: 2)).
- w1 := '2r', w1, w1, w1, w1, w1, w1, w1, w1, ' hex'.
- w2 := (d at: (p at: 3)), (d at: (p at: 4)).
- w2 := '2r', w2, w2, w2, w2, w2, w2, w2, w2, ' hex'.
- Array with: (Compiler evaluate: w1) with: (Compiler evaluate: w2) 
- "!

Item was removed:
- ----- Method: Color>>hash (in category 'comparing') -----
- hash
- 
- 	^ rgb!

Item was removed:
- ----- Method: Color>>hue (in category 'accessing') -----
- hue
- 	"Return the hue of this color, an angle in the range [0.0..360.0]."
- 
- 	| r g b max min span h |
- 	r := self privateRed.
- 	g := self privateGreen.
- 	b := self privateBlue. 
- 
- 	max := ((r max: g) max: b).
- 	min := ((r min: g) min: b).
- 	span := (max - min) asFloat.
- 	span = 0.0 ifTrue: [ ^ 0.0 ].
- 
- 	r = max ifTrue: [
- 		h := ((g - b) asFloat / span) * 60.0.
- 	] ifFalse: [
- 		g = max
- 			ifTrue: [ h := 120.0 + (((b - r) asFloat / span) * 60.0). ]
- 			ifFalse: [ h := 240.0 + (((r - g) asFloat / span) * 60.0). ].
- 	].
- 
- 	h < 0.0 ifTrue: [ h := 360.0 + h ].
- 	^ h!

Item was removed:
- ----- Method: Color>>indexInMap: (in category 'conversions') -----
- indexInMap: aColorMap
- 	"Return the index corresponding to this color in the given color map. RGB colors are truncated to 3-, 4-, or 5-bits per color component when indexing into such a colorMap.  "
- 
- 	aColorMap size = 2 ifTrue: [^ (self pixelValueForDepth: 1) + 1].
- 	aColorMap size = 4 ifTrue: [^ (self pixelValueForDepth: 2) + 1].
- 	aColorMap size = 16 ifTrue: [^ (self pixelValueForDepth: 4) + 1].
- 	aColorMap size = 256 ifTrue: [^ (self pixelValueForDepth: 8) + 1].
- 	aColorMap size = 512 ifTrue: [^ (self pixelValueForDepth: 9) + 1].
- 	aColorMap size = 4096 ifTrue: [^ (self pixelValueForDepth: 12) + 1].
- 	aColorMap size = 32768 ifTrue: [^ (self pixelValueForDepth: 16) + 1].
- 	self error: 'unknown pixel depth'.
- !

Item was removed:
- ----- Method: Color>>isBitmapFill (in category 'testing') -----
- isBitmapFill
- 	^false!

Item was removed:
- ----- Method: Color>>isBlack (in category 'testing') -----
- isBlack
- 	"Return true if the receiver represents black"
- 	^rgb = 0!

Item was removed:
- ----- Method: Color>>isColor (in category 'testing') -----
- isColor
- 
- 	^ true
- !

Item was removed:
- ----- Method: Color>>isGradientFill (in category 'testing') -----
- isGradientFill
- 	^false!

Item was removed:
- ----- Method: Color>>isGray (in category 'testing') -----
- isGray
- 	"Return true if the receiver represents a shade of gray"
- 	^(self privateRed = self privateGreen) and:[self privateRed = self privateBlue]!

Item was removed:
- ----- Method: Color>>isOpaque (in category 'testing') -----
- isOpaque
- 	^true!

Item was removed:
- ----- Method: Color>>isOrientedFill (in category 'testing') -----
- isOrientedFill
- 	"Return true if the receiver keeps an orientation (e.g., origin, direction, and normal)"
- 	^false!

Item was removed:
- ----- Method: Color>>isSolidFill (in category 'testing') -----
- isSolidFill
- 	^true!

Item was removed:
- ----- Method: Color>>isTranslucent (in category 'testing') -----
- isTranslucent
- 
- 	^ false
- !

Item was removed:
- ----- Method: Color>>isTranslucentColor (in category 'testing') -----
- isTranslucentColor
- 	"This means: self isTranslucent, but isTransparent not"
- 	^ false!

Item was removed:
- ----- Method: Color>>isTransparent (in category 'testing') -----
- isTransparent
- 
- 	^ false
- !

Item was removed:
- ----- Method: Color>>lightShades: (in category 'groups of shades') -----
- lightShades: thisMany
- 	"An array of thisMany colors from white to self. Very useful for displaying color based on a variable in your program.  "
- 	"Color showColors: (Color red lightShades: 12)"
- 
- 	^ self class white mix: self shades: thisMany
- !

Item was removed:
- ----- Method: Color>>lighter (in category 'transformations') -----
- lighter
- 	"Answer a lighter shade of this color."
- 
- 	^ self adjustSaturation: -0.03 brightness: 0.08!

Item was removed:
- ----- Method: Color>>luminance (in category 'accessing') -----
- luminance
- 	"Return the luminance of this color, a brightness value weighted by the human eye's color sensitivity."
- 
- 	^ ((299 * self privateRed) +
- 	   (587 * self privateGreen) +
- 	   (114 * self privateBlue)) / (1000 * ComponentMax)
- !

Item was removed:
- ----- Method: Color>>makeForegroundColor (in category 'conversions') -----
- makeForegroundColor
-         "Make a foreground color contrasting with me"
-         ^self luminance >= 0.5
-                 ifTrue: [Color black]
-                 ifFalse: [Color white]!

Item was removed:
- ----- Method: Color>>mix:shades: (in category 'groups of shades') -----
- mix: color2 shades: thisMany
- 	"Return an array of thisMany colors from self to color2. Very useful for displaying color based on a variable in your program.  "
- 	"Color showColors: (Color red mix: Color green shades: 12)"
- 
- 	| redInc greenInc blueInc out rr gg bb |
- 	thisMany = 1 ifTrue: [^ Array with: color2].
- 	redInc := color2 red - self red / (thisMany-1).
- 	greenInc := color2 green - self green / (thisMany-1).
- 	blueInc := color2 blue - self blue / (thisMany-1).
- 	rr := self red.  gg := self green.  bb := self blue.
- 	out := (1 to: thisMany) collect: [:num | | c |
- 		c := Color r: rr g: gg b: bb.
- 		rr := rr + redInc.
- 		gg := gg + greenInc.
- 		bb := bb + blueInc.
- 		c].
- 	out at: out size put: color2.	"hide roundoff errors"
- 	^ out
- !

Item was removed:
- ----- Method: Color>>mixed:with: (in category 'transformations') -----
- mixed: proportion with: aColor 
- 	"Mix with another color and do not preserve transpareny.  Only use this for extracting the RGB value and mixing it.  All other callers should use instead: 
- 	aColor alphaMixed: proportion with: anotherColor
- 	"
- 
- 	| frac1 frac2 |
- 	frac1 := proportion asFloat min: 1.0 max: 0.0.
- 	frac2 := 1.0 - frac1.
- 	^ Color
- 		r: self red * frac1 + (aColor red * frac2)
- 		g: self green * frac1 + (aColor green * frac2)
- 		b: self blue * frac1 + (aColor blue * frac2)!

Item was removed:
- ----- Method: Color>>muchDarker (in category 'transformations') -----
- muchDarker
- 
- 	^ self alphaMixed: 0.5 with: Color black
- !

Item was removed:
- ----- Method: Color>>muchLighter (in category 'transformations') -----
- muchLighter
- 
- 	^ self alphaMixed: 0.233 with: Color white
- !

Item was removed:
- ----- Method: Color>>name (in category 'other') -----
- name
- 	"Return this color's name, or nil if it has no name."
- 
- 	^ (RGBToNames at: rgb ifAbsent: [nil]) ifNotNil: [:names | names at: 1 ifAbsent: [nil]]!

Item was removed:
- ----- Method: Color>>names (in category 'other') -----
- names
- 	"Return a collection of all known names for this color.
- 	These are Symbol that can be used as message send to Color."
- 
- 	^ RGBToNames at: rgb ifAbsent: [Array new]!

Item was removed:
- ----- Method: Color>>negated (in category 'transformations') -----
- negated
- 	"Return an RGB inverted color"
- 	^Color
- 		r: 1.0 - self red
- 		g: 1.0 - self green
- 		b: 1.0 - self blue
- 		alpha: self alpha!

Item was removed:
- ----- Method: Color>>orColorUnlike: (in category 'transformations') -----
- orColorUnlike: theOther
- 	"If this color is a lot like theOther, then return its complement, otherwide, return self"
- 
- 	(self diff: theOther) < 0.3
- 		ifTrue: [^ theOther negated]
- 		ifFalse: [^ self]!

Item was removed:
- ----- Method: Color>>paler (in category 'transformations') -----
- paler
- 	"Answer a paler shade of this color."
- 
- 	^ self adjustSaturation: -0.09 brightness: 0.09
- !

Item was removed:
- ----- Method: Color>>pixelValue32 (in category 'conversions') -----
- pixelValue32
- 	"Note: pixelWord not pixelValue so we include translucency"
- 	^self pixelWordForDepth: 32!

Item was removed:
- ----- Method: Color>>pixelValueForDepth: (in category 'conversions') -----
- pixelValueForDepth: d
- 	"Answers an integer representing the bits that appear in a single pixel of this color in a Form of the given depth.
- 	 The depth must be one of 1, 2, 4, 8, 16, or 32. Contrast with pixelWordForDepth: and bitPatternForDepth:, which
- 	 answer either a 32-bit word packed with the given pixel value or a multiple-word Bitmap containing a pattern.
- 	 The inverse is the class message colorFromPixelValue:depth:"
- 	"Details:
- 		For depths of 8 or less, the result is a colorMap index.
- 		For depths of 16 and 32, it is a direct color value with 5 or 8 bits per color component."
- 	"Transparency:
- 		The pixel value zero is reserved for transparent.
- 		For depths greater than 8, black maps to the darkest possible blue."
- 
- 	| val |
- 	d > 8 ifTrue: "most common case"
- 		[d = 32 ifTrue: "eight bits per component; top 8 bits set to all ones (opaque alpha)"
- 			["this subexpression is a SmallInteger in both 32- and 64-bits."
- 			 val :=	((rgb bitShift: -6) bitAnd: 16rFF0000) bitOr:
- 					(((rgb bitShift: -4) bitAnd: 16rFF00) bitOr:
- 					((rgb bitShift: -2) bitAnd: 16rFF)).
- 			"16rFF000000 & 16rFF000001 are LargeIntegers in 32-bits, SmallIntegers in 64-bits."
- 			^val = 0 ifTrue: [16rFF000001] ifFalse: [16rFF000000 + val]].
- 			
- 		d = 16 ifTrue: "five bits per component; top bits ignored"
- 			[val := (((rgb bitShift: -15) bitAnd: 16r7C00) bitOr:
- 					 ((rgb bitShift: -10) bitAnd: 16r03E0)) bitOr:
- 					 ((rgb bitShift: -5) bitAnd: 16r001F).
- 			^val = 0 ifTrue: [1] ifFalse: [val]].
- 
- 		d = 12 ifTrue: "for indexing a color map with 4 bits per color component"
- 			[val := (((rgb bitShift: -18) bitAnd: 16r0F00) bitOr:
- 					 ((rgb bitShift: -12) bitAnd: 16r00F0)) bitOr:
- 					 ((rgb bitShift: -6) bitAnd: 16r000F).
- 			^val = 0 ifTrue: [1] ifFalse: [val]].
- 
- 		d = 9 ifTrue: "for indexing a color map with 3 bits per color component"
- 			[val := (((rgb bitShift: -21) bitAnd: 16r01C0) bitOr:
- 				 ((rgb bitShift: -14) bitAnd: 16r0038)) bitOr:
- 				 ((rgb bitShift: -7) bitAnd: 16r0007).
- 			^val = 0 ifTrue: [1] ifFalse: [val]]].
- 	d = 8 ifTrue: [^ self closestPixelValue8].
- 	d = 4 ifTrue: [^ self closestPixelValue4].
- 	d = 2 ifTrue: [^ self closestPixelValue2]..
- 	d = 1 ifTrue: [^ self closestPixelValue1].
- 
- 	self error: 'unknown pixel depth: ', d printString
- !

Item was removed:
- ----- Method: Color>>pixelWordFor:filledWith: (in category 'conversions') -----
- pixelWordFor: depth filledWith: pixelValue
- 	"Return to a 32-bit word that concatenates enough copies of the given pixel value to fill the word (i.e., 32/depth copies). Depth should be one of 1, 2, 4, 8, 16, or 32. The pixel value should be an integer in 0..2^depth-1."
- 	| halfword |
- 	depth = 32 ifTrue: [^ pixelValue].
- 	depth = 16
- 		ifTrue: [halfword := pixelValue]
- 		ifFalse: [halfword := pixelValue * 
- 					(#(16rFFFF				"replicates at every bit"
- 						16r5555 -			"replicates every 2 bits"
- 						16r1111 - - -			"replicates every 4 bits"
- 						16r0101) at: depth)	"replicates every 8 bits"].
- 	^ halfword bitOr: (halfword bitShift: 16)!

Item was removed:
- ----- Method: Color>>pixelWordForDepth: (in category 'conversions') -----
- pixelWordForDepth: depth
- 	"Return to a 32-bit word that concatenates enough copies of the receiver's pixel value to fill the word (i.e., 32/depth copies). Depth should be one of 1, 2, 4, 8, 16, or 32. The pixel value should be an integer in 0..2^depth-1."
- 
- 	| pixelValue |
- 	pixelValue := self pixelValueForDepth: depth.
- 	^ self pixelWordFor: depth filledWith: pixelValue
- !

Item was removed:
- ----- Method: Color>>printHtmlString (in category 'html') -----
- printHtmlString
- 	"answer a string whose characters are the html representation  
- 	of the receiver"
- 	^ ((self red * 255) rounded printStringBase: 16 length: 2 padded: true)
- 		, ((self green * 255) rounded printStringBase: 16 length: 2 padded: true)
- 		, ((self blue * 255) rounded printStringBase: 16 length: 2 padded: true)!

Item was removed:
- ----- Method: Color>>printOn: (in category 'printing') -----
- printOn: aStream
- 	| name |
- 	(name := self name) ifNotNil:
- 		[^ aStream
- 			nextPutAll: 'Color ';
- 			nextPutAll: name].
- 	self storeOn: aStream.
- !

Item was removed:
- ----- Method: Color>>privateAlpha (in category 'private') -----
- privateAlpha
- 	"Private!! Return the raw alpha value for opaque. Used only for equality testing."
- 
- 	^ 255!

Item was removed:
- ----- Method: Color>>privateBlue (in category 'private') -----
- privateBlue
- 	"Private!! Return the internal representation of my blue component."
- 
- 	^ rgb bitAnd: ComponentMask!

Item was removed:
- ----- Method: Color>>privateGreen (in category 'private') -----
- privateGreen
- 	"Private!! Return the internal representation of my green component.
- 	Replaced >> by bitShift: 0 -. SqR!! 2/25/1999 23:08"
- 
- 	^ (rgb bitShift: 0 - GreenShift) bitAnd: ComponentMask!

Item was removed:
- ----- Method: Color>>privateRGB (in category 'private') -----
- privateRGB
- 	"Private!! Return the internal representation of my RGB components."
- 
- 	^ rgb
- !

Item was removed:
- ----- Method: Color>>privateRed (in category 'private') -----
- privateRed
- 	"Private!! Return the internal representation of my red component."
- 
- 	^ (rgb bitShift: 0 - RedShift) bitAnd: ComponentMask!

Item was removed:
- ----- Method: Color>>raisedColor (in category 'other') -----
- raisedColor
- 	^ self!

Item was removed:
- ----- Method: Color>>red (in category 'accessing') -----
- red
- 	"Return the red component of this color, a float in the range [0.0..1.0]."
- 
- 	^ self privateRed asFloat / ComponentMax!

Item was removed:
- ----- Method: Color>>rgbTriplet (in category 'other') -----
- rgbTriplet
- 	"Color fromUser rgbTriplet"
- 
- 	^ Array
- 		with: (self red roundTo: 0.01)
- 		with: (self green roundTo: 0.01)
- 		with: (self blue roundTo: 0.01)
- !

Item was removed:
- ----- Method: Color>>saturation (in category 'accessing') -----
- saturation
- 	"Return the saturation of this color, a value between 0.0 and 1.0."
- 
- 	| r g b max min |
- 	r := self privateRed.
- 	g := self privateGreen.
- 	b := self privateBlue. 
- 
- 	max := min := r.
- 	g > max ifTrue: [max := g].
- 	b > max ifTrue: [max := b].
- 	g < min ifTrue: [min := g].
- 	b < min ifTrue: [min := b].
- 
- 	max = 0
- 		ifTrue: [ ^ 0.0 ]
- 		ifFalse: [ ^ (max - min) asFloat / max asFloat ].
- !

Item was removed:
- ----- Method: Color>>scaledPixelValue32 (in category 'conversions') -----
- scaledPixelValue32
- 	"Return the alpha scaled pixel value for depth 32"
- 	^self pixelWordForDepth: 32!

Item was removed:
- ----- Method: Color>>setHue:saturation:brightness: (in category 'private') -----
- setHue: hue saturation: saturation brightness: brightness
- 	"Initialize this color to the given hue, saturation, and brightness. See the comment in the instance creation method for details."
- 
- 	| s v hf i f p q t | 
- 	s := (saturation asFloat max: 0.0) min: 1.0.
- 	v := (brightness asFloat max: 0.0) min: 1.0.
- 
- 	"zero saturation yields gray with the given brightness"
- 	s = 0.0 ifTrue: [ ^ self setRed: v green: v blue: v ].
- 
- 	hf := hue asFloat.
- 	(hf < 0.0 or: [hf >= 360.0])
- 		ifTrue: [hf := hf \\ 360].
- 	hf := hf / 60.0.
- 	i := hf asInteger.  "integer part of hue"
- 	f := hf fractionPart.         "fractional part of hue"
- 	p := (1.0 - s) * v.
- 	q := (1.0 - (s * f)) * v.
- 	t := (1.0 - (s * (1.0 - f))) * v.
- 
- 	0 = i ifTrue: [ ^ self setRed: v green: t blue: p ].
- 	1 = i ifTrue: [ ^ self setRed: q green: v blue: p ].
- 	2 = i ifTrue: [ ^ self setRed: p green: v blue: t ].
- 	3 = i ifTrue: [ ^ self setRed: p green: q blue: v ].
- 	4 = i ifTrue: [ ^ self setRed: t green: p blue: v ].
- 	5 = i ifTrue: [ ^ self setRed: v green: p blue: q ].
- 
- 	self error: 'implementation error'.
- !

Item was removed:
- ----- Method: Color>>setPrivateRed:green:blue: (in category 'private') -----
- setPrivateRed: r green: g blue: b
- 	"Initialize this color's r, g, and b components to the given values in the range [0..ComponentMax].  Encoded in a single variable as 3 integers in [0..1023]."
- 
- 	rgb == nil ifFalse: [self attemptToMutateError].
- 	rgb := ((r min: ComponentMask max: 0) bitShift: RedShift) +
- 		((g min: ComponentMask max: 0) bitShift: GreenShift) +
- 		 (b min: ComponentMask max: 0).
- 	cachedDepth := nil.
- 	cachedBitPattern := nil.
- !

Item was removed:
- ----- Method: Color>>setRGB: (in category 'private') -----
- setRGB: rgb0
- 	rgb == nil ifFalse: [self attemptToMutateError].
- 	rgb := rgb0!

Item was removed:
- ----- Method: Color>>setRed:green:blue: (in category 'private') -----
- setRed: r green: g blue: b
- 	"Initialize this color's r, g, and b components to the given values in the range [0.0..1.0].  Encoded in a single variable as 3 integers in [0..1023]."
- 
- 	rgb == nil ifFalse: [self attemptToMutateError].
- 	rgb :=
- 		(((r * ComponentMax) rounded bitAnd: ComponentMask) bitShift: RedShift) +
- 		(((g * ComponentMax) rounded bitAnd: ComponentMask) bitShift: GreenShift) +
- 		 ((b * ComponentMax) rounded bitAnd: ComponentMask).
- 	cachedDepth := nil.
- 	cachedBitPattern := nil.
- !

Item was removed:
- ----- Method: Color>>setRed:green:blue:range: (in category 'private') -----
- setRed: r green: g blue: b range: range
- 	"Initialize this color's r, g, and b components to the given values in the range [0..r]."
- 
- 	^ self setRed: r / range green: g / range blue: b / range!

Item was removed:
- ----- Method: Color>>shortPrintString (in category 'printing') -----
- shortPrintString
- 	"Return a short (but less precise) print string for use where space is tight."
- 
- 	^String streamContents: [:s | s
- 		nextPutAll: '(';
- 		print: self class;
- 		nextPutAll: ' r: '; print: self red maxDecimalPlaces: 2;
- 		nextPutAll: ' g: '; print: self green maxDecimalPlaces: 2;
- 		nextPutAll: ' b: '; print: self blue maxDecimalPlaces: 2;
- 		nextPutAll: ')']!

Item was removed:
- ----- Method: Color>>slightlyDarker (in category 'transformations') -----
- slightlyDarker
- 
- 	^ self adjustBrightness: -0.03
- !

Item was removed:
- ----- Method: Color>>slightlyLighter (in category 'transformations') -----
- slightlyLighter
- 
- 	^ self adjustSaturation: -0.01 brightness: 0.03!

Item was removed:
- ----- Method: Color>>slightlyWhiter (in category 'transformations') -----
- slightlyWhiter
- 
- 	^ self alphaMixed: 0.85 with: Color white
- !

Item was removed:
- ----- Method: Color>>storeArrayOn: (in category 'printing') -----
- storeArrayOn: aStream
- 
- 	aStream nextPutAll: '#('.
- 	self storeArrayValuesOn: aStream.
- 	aStream nextPutAll: ') '
- !

Item was removed:
- ----- Method: Color>>storeArrayValuesOn: (in category 'printing') -----
- storeArrayValuesOn: aStream
- 
- 	aStream
- 		print: self red maxDecimalPlaces: 3;
- 		space;
- 		print: self green maxDecimalPlaces: 3;
- 		space;
- 		print: self blue maxDecimalPlaces: 3.
- !

Item was removed:
- ----- Method: Color>>storeOn: (in category 'printing') -----
- storeOn: aStream
- 
- 	aStream
- 		nextPutAll: '(' , self species name;
- 		nextPutAll: ' r: '; print: self red maxDecimalPlaces: 3;
- 		nextPutAll: ' g: '; print: self green maxDecimalPlaces: 3;
- 		nextPutAll: ' b: '; print: self blue maxDecimalPlaces: 3;
- 		nextPutAll: ')'.
- !

Item was removed:
- ----- Method: Color>>thriceDarker (in category 'transformations') -----
- thriceDarker
- 	"Answer a significantly darker shade of this color."
- 
- 	^ self adjustSaturation: 0.09 brightness: -0.22!

Item was removed:
- ----- Method: Color>>thriceLighter (in category 'transformations') -----
- thriceLighter
- 	"Answer a significantly lighter shade of this color."
- 
- 	^ self adjustSaturation: -0.09 brightness: 0.22!

Item was removed:
- ----- Method: Color>>twiceDarker (in category 'transformations') -----
- twiceDarker
- 	"Answer a significantly darker shade of this color."
- 
- 	^ self adjustSaturation: 0.075 brightness: -0.15!

Item was removed:
- ----- Method: Color>>twiceLighter (in category 'transformations') -----
- twiceLighter
- 	"Answer a significantly lighter shade of this color."
- 
- 	^ self adjustSaturation: -0.06 brightness: 0.15!

Item was removed:
- ----- Method: Color>>veryDeepCopyWith: (in category 'copying') -----
- veryDeepCopyWith: deepCopier
- 	"I am immutable in the Morphic world. Do not record me."
- 	^ self!

Item was removed:
- ----- Method: Color>>veryMuchDarker (in category 'transformations') -----
- veryMuchDarker
- 
- 	^ self alphaMixed: 0.25 with: Color black
- !

Item was removed:
- ----- Method: Color>>veryMuchLighter (in category 'transformations') -----
- veryMuchLighter
- 
- 	^ self alphaMixed: 0.1165 with: Color white
- !

Item was removed:
- ----- Method: Color>>wheel: (in category 'groups of shades') -----
- wheel: thisMany
- 	"An array of thisMany colors around the color wheel starting at self and ending all the way around the hue space just before self.  Array is of length thisMany.  Very useful for displaying color based on a variable in your program.  "
- 
- 	| sat bri step hue |
- 	sat := self saturation.
- 	bri := self brightness.
- 	hue := self hue.
- 	step := 360.0 / (thisMany max: 1).
- 	^ (1 to: thisMany) collect: [:num | | c |
- 		c := Color h: hue s: sat v: bri.  "hue is taken mod 360"
- 		hue := hue + step.
- 		c].
- "
- (Color wheel: 8) withIndexDo: [:c :i | Display fill: (i*10 at 20 extent: 10 at 20) fillColor: c]
- "!

Item was removed:
- ----- Method: Color>>whiter (in category 'transformations') -----
- whiter
- 
- 	^ self alphaMixed: 0.8333 with: Color white
- !

Item was removed:
- Form subclass: #ColorForm
- 	instanceVariableNames: 'colors cachedDepth cachedColormap'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Display Objects'!
- ColorForm class
- 	instanceVariableNames: 'grayScalePalette'!
- 
- !ColorForm commentStamp: '<historical>' prior: 0!
- ColorForm is a normal Form plus a color map of up to 2^depth Colors. Typically, one reserves one entry in the color map for transparent. This allows 1, 3, 15, or 255 non-transparent colors in ColorForms of depths 1, 2, 4, and 8 bits per pixel. ColorForms don't support depths greater than 8 bits because that would require excessively large color maps with little real benefit, since 16-bit and 32-bit depths already support thousands and millions of colors.
- 
- ColorForms have several uses:
-   1) Precise colors. You can have up to 256 true colors, instead being limited to the 8-bit color palette.
-   2) Easy transparency. Just store (Color transparent) at the desired position in the color map.
-   3) Cheap color remapping by changing the color map.
- 
- A color map is an Array of up to 2^depth Color objects. A Bitmap colorMap is automatically computed and cached for rapid display. Note that if you change the color map, you must resubmit it via the colors: method to flush this cache.
- 
- ColorForms can be a bit tricky. Note that:
-   a) When you BitBlt from one ColorForm to another, you must remember to copy the color map of the source ColorForm to the destination ColorForm.
-   b) A ColorForm's color map is an array of depth-independent Color objects. BitBlt requires a BitMap of actual pixel values, adjusted to the destination depth. These are different things!! ColorForms automatically maintain a cache of the BitBlt-style color map corresponding to the colors array for the last depth on which the ColorForm was displayed, so there should be little need for clients to work with BitBlt-style color maps.
-   c) The default map for 8 bit depth has black in the first entry, not transparent.  Say (cform colors at: 1 put: Color transparent).
- !
- ColorForm class
- 	instanceVariableNames: 'grayScalePalette'!

Item was removed:
- ----- Method: ColorForm class>>grayScalePalette (in category 'constants') -----
- grayScalePalette
- 	grayScalePalette ifNil: [
- 		grayScalePalette := (0 to: 255) collect: [:brightness | Color gray: brightness asFloat / 255.0].
- 		grayScalePalette at: 1 put: Color transparent].
- 	^ grayScalePalette!

Item was removed:
- ----- Method: ColorForm class>>mappingWhiteToTransparentFrom: (in category 'as yet unclassified') -----
- mappingWhiteToTransparentFrom: aFormOrCursor
- 	"Return a ColorForm copied from the given Form or Cursor with white mapped to transparent."
- 
- 	| f map |
- 	aFormOrCursor depth <= 8 ifFalse: [
- 		^ self error: 'argument depth must be 8-bits per pixel or less'].
- 	(aFormOrCursor isColorForm) ifTrue: [
- 		f := aFormOrCursor deepCopy.
- 		map := aFormOrCursor colors.
- 	] ifFalse: [
- 		f := ColorForm extent: aFormOrCursor extent depth: aFormOrCursor depth.
- 		f copyBits: aFormOrCursor boundingBox
- 			from: aFormOrCursor
- 			at: 0 at 0
- 			clippingBox: aFormOrCursor boundingBox
- 			rule: Form over
- 			fillColor: nil.
- 		map := Color indexedColors copyFrom: 1 to: (1 bitShift: aFormOrCursor depth)].
- 	map := map collect: [:c |
- 		c = Color white ifTrue: [Color transparent] ifFalse: [c]].
- 	f colors: map.
- 	^ f
- !

Item was removed:
- ----- Method: ColorForm class>>twoToneFromDisplay:using:backgroundColor: (in category 'as yet unclassified') -----
- twoToneFromDisplay: aRectangle using: oldForm backgroundColor: bgColor
- 	"Return a 1-bit deep ColorForm copied from the given rectangle of the display. All colors except the background color will be mapped to black."
- 
- 	| f |
- 	((oldForm ~~ nil) and: [oldForm extent = aRectangle extent]) ifTrue: [
- 		f := oldForm fromDisplay: aRectangle.
- 	] ifFalse: [
- 		f := ColorForm extent: aRectangle extent depth: 1.
- 		f twoToneFromDisplay: aRectangle backgroundColor: bgColor.
- 		f colors: (Array
- 			with: bgColor
- 			with: Color black)].
- 	^ f
- !

Item was removed:
- ----- Method: ColorForm>>asCursorForm (in category 'copying') -----
- asCursorForm
- 
- 	^ (self asFormOfDepth: 32) offset: offset; as: StaticForm!

Item was removed:
- ----- Method: ColorForm>>asFormWithSingleTransparentColors (in category 'postscript generation') -----
- asFormWithSingleTransparentColors
- 	| transparentIndexes |
- 	transparentIndexes := self transparentColorIndexes.
- 	transparentIndexes size <= 1 ifTrue:[^self]
- 		ifFalse:[^self mapTransparencies:transparentIndexes].!

Item was removed:
- ----- Method: ColorForm>>asGrayScale (in category 'color manipulation') -----
- asGrayScale
- 	"Return a grayscale ColorForm computed by mapping each color into its grayscale equivalent"
- 	^ self copy colors:
- 		(colors collect:
- 			[:c | c isTransparent ifTrue: [c]
- 						ifFalse: [Color gray: c luminance]])!

Item was removed:
- ----- Method: ColorForm>>blankCopyOf:scaledBy: (in category 'copying') -----
- blankCopyOf: aRectangle scaledBy: scale
- 	^Form extent: (aRectangle extent * scale) truncated depth: 32!

Item was removed:
- ----- Method: ColorForm>>clearColormapCache (in category 'private') -----
- clearColormapCache
- 
- 	cachedDepth := nil.
- 	cachedColormap := nil.
- !

Item was removed:
- ----- Method: ColorForm>>collectColors: (in category 'converting') -----
- collectColors: aBlock
- 
- 	^ (ColorForm extent: self extent depth: self depth bits: self bits)
- 		colors: (self colors collect: aBlock);
- 		yourself!

Item was removed:
- ----- Method: ColorForm>>colorAt: (in category 'pixel accessing') -----
- colorAt: aPoint
- 	"Return the color of the pixel at aPoint."
- 
- 	^ self colors at: (self pixelValueAt: aPoint) + 1
- !

Item was removed:
- ----- Method: ColorForm>>colorAt:put: (in category 'pixel accessing') -----
- colorAt: aPoint put: aColor
- 	"Store the given color into the pixel at aPoint. The given color must match one of the colors in the receiver's colormap."
- 
- 	| i |
- 	i := self colors indexOf: aColor
- 		ifAbsent: [^ self error: 'trying to use a color that is not in my colormap'].
- 	self pixelValueAt: aPoint put: i - 1.
- !

Item was removed:
- ----- Method: ColorForm>>colormapIfNeededFor: (in category 'color mapping') -----
- colormapIfNeededFor: destForm
- 	| newMap color pv |
- 	(self hasNonStandardPalette or:[destForm hasNonStandardPalette]) ifFalse:[
- 		^self colormapIfNeededForDepth: destForm depth.
- 	].
- 	colors == nil ifTrue: [
- 		"use the standard colormap"
- 		^ super colormapIfNeededFor: destForm].
- 
- 	(destForm depth = cachedDepth and:[cachedColormap isColormap]) 
- 		ifTrue: [^ cachedColormap].
- 	newMap := WordArray new: (1 bitShift: self depth).
- 	1 to: colors size do: [:i |
- 		color := colors at: i.
- 		pv := destForm pixelValueFor: color.
- 		(pv = 0 and:[color isTransparent not]) ifTrue:[pv := 1].
- 		newMap at: i put: pv].
- 
- 	cachedDepth := destForm depth.
- 	^cachedColormap := ColorMap shifts: nil masks: nil colors: newMap.!

Item was removed:
- ----- Method: ColorForm>>colormapIfNeededForDepth: (in category 'color manipulation') -----
- colormapIfNeededForDepth: destDepth
- 	"Return a colormap for displaying the receiver at the given depth, or nil if no colormap is needed."
- 
- 	| newMap |
- 	colors == nil ifTrue: [
- 		"use the standard colormap"
- 		^ Color colorMapIfNeededFrom: self depth to: destDepth].
- 
- 	(destDepth = cachedDepth and:[cachedColormap isColormap not]) 
- 		ifTrue: [^ cachedColormap].
- 	newMap := Bitmap new: colors size.
- 	1 to: colors size do: [:i |
- 		newMap
- 			at: i
- 			put: ((colors at: i) pixelValueForDepth: destDepth)].
- 
- 	cachedDepth := destDepth.
- 	^ cachedColormap := newMap.
- !

Item was removed:
- ----- Method: ColorForm>>colors (in category 'accessing') -----
- colors
- 	"Return my color palette."
- 
- 	self ensureColorArrayExists.
- 	^ colors
- !

Item was removed:
- ----- Method: ColorForm>>colors: (in category 'accessing') -----
- colors: colorList
- 	"Set my color palette to the given collection."
- 
- 	| colorArray colorCount newColors |
- 	colorList ifNil: [
- 		colors := cachedDepth := cachedColormap := nil.
- 		^ self].
- 
- 	colorArray := colorList asArray.
- 	colorCount := colorArray size.
- 	newColors := Array new: (1 bitShift: self depth).
- 	1 to: newColors size do: [:i |
- 		i <= colorCount
- 			ifTrue: [newColors at: i put: (colorArray at: i)]
- 			ifFalse: [newColors at: i put: Color transparent]].
- 
- 	colors := newColors.
- 	cachedDepth := nil.
- 	cachedColormap := nil.
- !

Item was removed:
- ----- Method: ColorForm>>colorsFromArray: (in category 'accessing') -----
- colorsFromArray: colorArray
- 	| colorList |
- 	colorList := colorArray collect: [:colorDef |
- 		Color fromArray: colorDef].
- 	self colors: colorList!

Item was removed:
- ----- Method: ColorForm>>colorsUsed (in category 'color manipulation') -----
- colorsUsed
- 	"Return a list of the colors actually used by this ColorForm."
- 
- 	| myColor list |
- 	myColor := self colors.
- 	list := OrderedCollection new.
- 	self tallyPixelValues withIndexDo: [:count :i |
- 		count > 0 ifTrue: [list add: (myColor at: i)]].
- 	^ list asArray
- !

Item was removed:
- ----- Method: ColorForm>>copy: (in category 'copying') -----
- copy: aRect
-  	"Return a new ColorForm containing the portion of the receiver delineated by aRect."
- 
- 	| newForm |
- 	newForm := self species extent: aRect extent depth: depth.
- 	((BitBlt
- 		destForm: newForm
- 		sourceForm: self
- 		fillColor: nil
- 		combinationRule: Form over
- 		destOrigin: 0 at 0
- 		sourceOrigin: aRect origin
- 		extent: aRect extent
- 		clipRect: newForm boundingBox)
- 		colorMap: nil) copyBits.
- 	colors ifNotNil: [newForm colors: colors copy].
- 	^ newForm
- !

Item was removed:
- ----- Method: ColorForm>>decodeArray (in category 'postscript generation') -----
- decodeArray
- 	^self depth = 1 ifTrue:['[1 0]'] ifFalse:['[0 255]'].!

Item was removed:
- ----- Method: ColorForm>>depth: (in category 'private') -----
- depth: bitsPerPixel
- 
- 	bitsPerPixel > 8 ifTrue: [self error: 'ColorForms only support depths up to 8 bits'].
- 	super depth: bitsPerPixel.
- !

Item was removed:
- ----- Method: ColorForm>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: rule fillColor: aForm
- 
- 	aDisplayMedium copyBits: self boundingBox
- 		from: self
- 		at: aDisplayPoint + self offset
- 		clippingBox: clipRectangle
- 		rule: rule
- 		fillColor: aForm
- 		map: (self colormapIfNeededFor: aDisplayMedium).
- !

Item was removed:
- ----- Method: ColorForm>>displayOnPort:at: (in category 'displaying') -----
- displayOnPort: port at: location
- 
- 	port copyForm: self to: location rule: Form paint!

Item was removed:
- ----- Method: ColorForm>>dominantColor (in category 'analyzing') -----
- dominantColor
- 	"Overridden to consider color table"
- 	
- 	| tally max maxi |
- 	tally := self tallyPixelValues.
- 	max := maxi := 0.
- 	tally withIndexDo: [:n :i | n > max ifTrue: [max := n. maxi := i]].
- 	^ self colors at: maxi!

Item was removed:
- ----- Method: ColorForm>>ensureColorArrayExists (in category 'private') -----
- ensureColorArrayExists
- 	"Return my color palette."
- 
- 	colors ifNil: [
- 		self depth > 8 ifTrue: [^ self error: 'ColorForms only support depths up to 8 bits'].
- 		self colors: (Color indexedColors copyFrom: 1 to: (1 bitShift: self depth))].
- !

Item was removed:
- ----- Method: ColorForm>>ensureTransparentColor (in category 'color manipulation') -----
- ensureTransparentColor
- 	"Ensure that the receiver (a) includes Color transparent in its color map and (b) that the entry for Color transparent is the first entry in its color map."
- 
- 	| i |
- self error: 'not yet implemented'.
- 	(colors includes: Color transparent)
- 		ifTrue: [
- 			(colors indexOf: Color transparent) = 1 ifTrue: [^ self].
- 			"shift the entry for color transparent"]
- 		ifFalse: [
- 			i := self unusedColormapEntry.
- 			i = 0 ifTrue: [self error: 'no color map entry is available'].
- 			colors at: i put: Color transparent.
- 			"shift the entry for color transparent"].
- !

Item was removed:
- ----- Method: ColorForm>>flipBy:centerAt: (in category 'scaling, rotation') -----
- flipBy: direction centerAt: aPoint
- 	| oldColors newForm |
- 	oldColors := colors.
- 	self colors: nil.
- 	newForm := super flipBy: direction centerAt: aPoint.
- 	self colors: oldColors.
- 	newForm colors: oldColors.
- 	^newForm !

Item was removed:
- ----- Method: ColorForm>>getTransparencyUnificationLUT (in category 'postscript generation') -----
- getTransparencyUnificationLUT
- 	| lut transparentIndex |
- 	lut := Array new:colors size.
- 	transparentIndex := self indexOfColor:Color transparent.
- 	1 to: colors size do:
- 		[ :i | lut at:i put:(((colors at:i) = Color transparent) ifTrue:[transparentIndex] ifFalse:[i])].
-  !

Item was removed:
- ----- Method: ColorForm>>hibernate (in category 'fileIn/Out') -----
- hibernate
- 	"Make myself take up less space. See comment in Form>hibernate."
- 
- 	super hibernate.
- 	self clearColormapCache.
- 	colors ifNotNil:[colors := colors asColorArray].!

Item was removed:
- ----- Method: ColorForm>>indexOfColor: (in category 'color manipulation') -----
- indexOfColor: aColor
- 	"Return the index of aColor in my color array"
- 
- 	self ensureColorArrayExists.
- 	^ colors indexOf: aColor!

Item was removed:
- ----- Method: ColorForm>>isColorForm (in category 'testing') -----
- isColorForm
- 	^true!

Item was removed:
- ----- Method: ColorForm>>isGrayScale (in category 'testing') -----
- isGrayScale
- 	^ self colors = ColorForm grayScalePalette.!

Item was removed:
- ----- Method: ColorForm>>isTranslucent (in category 'testing') -----
- isTranslucent
- 	"Answer whether this form may be translucent"
- 	^true!

Item was removed:
- ----- Method: ColorForm>>isTransparentAt: (in category 'pixel accessing') -----
- isTransparentAt: aPoint 
- 	"Return true if the receiver is transparent at the given point."
- 
- 	^ (self colorAt: aPoint) isTransparent
- !

Item was removed:
- ----- Method: ColorForm>>mapColor:to: (in category 'color manipulation') -----
- mapColor: oldColor to: newColor
- 	"Replace all occurances of the given color with the given new color in my color map."
- 
- 	self ensureColorArrayExists.
- 	1 to: colors size do: [:i | 
- 		(colors at: i) = oldColor ifTrue: [colors at: i put: newColor]].
- 	self clearColormapCache.
- !

Item was removed:
- ----- Method: ColorForm>>mapTransparencies: (in category 'postscript generation') -----
- mapTransparencies:transparentIndexes
- 	^self deepCopy mapColors:transparentIndexes to:(transparentIndexes at:1).!

Item was removed:
- ----- Method: ColorForm>>maskingMap (in category 'displaying') -----
- maskingMap
- 	"Return a color map that maps all colors except transparent to words of all ones. Used to create a mask for a Form whose transparent pixel value is zero."
- 	| maskingMap |
- 	maskingMap := Bitmap new: (1 bitShift: depth) withAll: 16rFFFFFFFF.
- 	1 to: colors size do:[:i|
- 		(colors at: i) isTransparent ifTrue:[maskingMap at: i put: 0].
- 	].
- 	colors size+1 to: maskingMap size do:[:i| maskingMap at: i put: 0].
- 	^maskingMap!

Item was removed:
- ----- Method: ColorForm>>postCopy (in category 'copying') -----
- postCopy
- 	super postCopy.
- 	colors := colors copy.
- !

Item was removed:
- ----- Method: ColorForm>>readAttributesFrom: (in category 'fileIn/Out') -----
- readAttributesFrom: aBinaryStream
- 	super readAttributesFrom: aBinaryStream.
- 	colors := ColorArray new: (2 raisedTo: depth).
- 	1 to: colors size do: [:idx | 
- 		colors basicAt: idx put: (aBinaryStream nextLittleEndianNumber: 4).
- 	]. 
- 	!

Item was removed:
- ----- Method: ColorForm>>replaceColor:with: (in category 'color manipulation') -----
- replaceColor: oldColor with: newColor
- 	"Replace all occurances of the given color with the given new color in my color map."
- 
- 	self ensureColorArrayExists.
- 	1 to: colors size do: [:i | 
- 		(colors at: i) = oldColor ifTrue: [colors at: i put: newColor]].
- 	self clearColormapCache.
- !

Item was removed:
- ----- Method: ColorForm>>replaceColorAt:with: (in category 'color manipulation') -----
- replaceColorAt: aPoint with: newColor
- 	"Replace a color map entry with newColor.  The entry replaced is the one used by aPoint.  If there are are two entries in the colorMap for the oldColor, just replace ONE!!!!  There are often two whites or two blacks, and this is what you want, when replacing one."
- 
- 	| oldIndex |
- 	self ensureColorArrayExists.
- 	oldIndex := self pixelValueAt: aPoint.
- 	colors at: oldIndex+1 put: newColor.
- 	self clearColormapCache.
- !

Item was removed:
- ----- Method: ColorForm>>replaceColorAtIndex:with: (in category 'color manipulation') -----
- replaceColorAtIndex: index with: newColor
- 	"Replace a color map entry with newColor."
- 
- 	self ensureColorArrayExists.
- 	colors at: index put: newColor.
- 	cachedColormap == nil ifFalse:
- 		[cachedColormap at: index put: (newColor pixelValueForDepth: cachedDepth)]!

Item was removed:
- ----- Method: ColorForm>>scaledIntoFormOfSize:smoothing: (in category 'scaling, rotation') -----
- scaledIntoFormOfSize: aNumberOrPoint smoothing: factor
- 
- 	^ (self asFormOfDepth: 32) scaledIntoFormOfSize: aNumberOrPoint smoothing: factor!

Item was removed:
- ----- Method: ColorForm>>scaledToSize:smoothing: (in category 'scaling, rotation') -----
- scaledToSize: newExtent smoothing: factor
- 	"super method did not seem to work so well on ColorForms"
- 
- 	^(self asFormOfDepth: 32) scaledToSize: newExtent smoothing: factor!

Item was removed:
- ----- Method: ColorForm>>setColors:cachedColormap:depth: (in category 'private') -----
- setColors: colorArray cachedColormap: aBitmap depth: anInteger
- 	"Semi-private. Set the color array, cached colormap, and cached colormap depth to avoid having to recompute the colormap when switching color palettes in animations."
- 
- 	colors := colorArray.
- 	cachedDepth := anInteger.
- 	cachedColormap := aBitmap.
- !

Item was removed:
- ----- Method: ColorForm>>setColorspaceOn: (in category 'postscript generation') -----
- setColorspaceOn:aStream
- 	self depth = 1 ifTrue:[
- 		aStream print:'/DeviceRGB setcolorspace 0 setgray'; cr.
- 	]
- 	ifFalse:[
- 	aStream print:'[ /Indexed /DeviceRGB ';
- 	write:self colors size-1;
- 	print:' <'.
- 	(self colormapIfNeededForDepth: 32 ) storeBits:20 to:0 on:aStream.
- 	aStream print:'> ] setcolorspace'; cr.].
- !

Item was removed:
- ----- Method: ColorForm>>setExtent:depth: (in category 'private') -----
- setExtent: extent depth: bitsPerPixel
- 	"Create a virtual bit map with the given extent and bitsPerPixel."
- 
- 	bitsPerPixel > 8 ifTrue: [self error: 'ColorForms only support depths up to 8 bits'].
- 	super setExtent: extent depth: bitsPerPixel.
- !

Item was removed:
- ----- Method: ColorForm>>storeOn: (in category 'fileIn/Out') -----
- storeOn: aStream
- 	aStream nextPut: $(.
- 	super storeOn: aStream.
- 	aStream
- 		cr; tab;
- 		nextPutAll: 'colorsFromArray: #('.
- 	self colors do: [:color |
- 		color storeArrayOn: aStream].
- 	aStream nextPutAll: ' ))'.!

Item was removed:
- ----- Method: ColorForm>>transparentAllPixelsLike: (in category 'color manipulation') -----
- transparentAllPixelsLike: aPoint
- 	"Make all occurances of the given pixel value transparent.  Very useful when two entries in the colorMap have the same value.  This only changes ONE."
- 
- 	self replaceColorAt: aPoint with: Color transparent.
- !

Item was removed:
- ----- Method: ColorForm>>transparentColor: (in category 'color manipulation') -----
- transparentColor: aColor
- 	"Make all occurances of the given color transparent.  Note: for colors like black and white, which have two entries in the colorMap, this changes BOTH of them.  Not always what you want."
- 
- 	self replaceColor: aColor with: Color transparent.
- !

Item was removed:
- ----- Method: ColorForm>>transparentColorIndexes (in category 'postscript generation') -----
- transparentColorIndexes
- 	^(1 to: colors size) select: [ :index | (colors at:index) isTransparent ].
- !

Item was removed:
- ----- Method: ColorForm>>twoToneFromDisplay:backgroundColor: (in category 'color manipulation') -----
- twoToneFromDisplay: aRectangle backgroundColor: bgColor
- 	"Copy one-bit deep ColorForm from the Display using a color map that maps all colors except the background color to black. Used for caching the contents of inactive MVC windows."
- 
- 	| map |
- 	(width = aRectangle width and: [height = aRectangle height])
- 		ifFalse: [self setExtent: aRectangle extent depth: depth].
- 
- 	"make a color map mapping the background color
- 	 to zero and all other colors to one"
- 	map := Bitmap new: (1 bitShift: (Display depth min: 9)).
- 	1 to: map size do: [:i | map at: i put: 16rFFFFFFFF].
- 	map at: (bgColor indexInMap: map) put: 0.
- 
- 	(BitBlt toForm: self)
- 		destOrigin: 0 at 0;
- 		sourceForm: Display;
- 		sourceRect: aRectangle;
- 		combinationRule: Form over;
- 		colorMap: map;
- 		copyBits.
- !

Item was removed:
- ----- Method: ColorForm>>unhibernate (in category 'fileIn/Out') -----
- unhibernate
- 	colors ifNotNil:[colors := colors asArray].
- 	^super unhibernate.
- !

Item was removed:
- ----- Method: ColorForm>>unusedColormapEntry (in category 'private') -----
- unusedColormapEntry
- 	"Return the index of an unused color map entry, or zero if there isn't one."
- 
- 	| tallies |
- 	tallies := self tallyPixelValues.
- 	1 to: tallies size do: [:i |
- 		(tallies at: i) = 0 ifTrue: [^ i]].
- 	^ 0
- !

Item was removed:
- ----- Method: ColorForm>>writeAttributesOn: (in category 'fileIn/Out') -----
- writeAttributesOn: file
- 	| colorArray |
- 	super writeAttributesOn: file.
- 	colorArray := self colors asColorArray.
- 	1 to: (2 raisedTo: depth) do: [:idx |
- 		file nextLittleEndianNumber: 4 put: (colorArray basicAt: idx).
- 	] !

Item was removed:
- Object subclass: #ColorMap
- 	instanceVariableNames: 'shifts masks colors'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Primitives'!

Item was removed:
- ----- Method: ColorMap class>>colors: (in category 'instance creation') -----
- colors: colorArray
- 	^self new setShifts: nil masks: nil colors: colorArray!

Item was removed:
- ----- Method: ColorMap class>>mapBitsFrom:to: (in category 'instance creation') -----
- mapBitsFrom: srcBitMask to: dstBitMask
- 	"Return an array consisting of the shift and the mask for
- 	mapping component values out of srcBitMask and into dstBitMask.
- 	While this computation is somewhat complicated it eases the batch
- 	conversion of all the pixels in BitBlt."
- 	| srcBits dstBits srcLow srcHigh dstLow dstHigh bits mask shift |
- 	(srcBitMask = 0 or:[dstBitMask = 0]) ifTrue:[^#(0 0)]. "Zero mask and shift"
- 	"Compute low and high bit position for source and dest bit mask"
- 	srcLow := srcBitMask lowBit - 1.	srcHigh := srcBitMask highBit.
- 	dstLow := dstBitMask lowBit - 1.	dstHigh := dstBitMask highBit.
- 	"Compute the number of bits in source and dest bit mask"
- 	srcBits := srcHigh - srcLow.		dstBits := dstHigh - dstLow.
- 	"Compute the maximum number of bits we can transfer inbetween"
- 	bits := srcBits min: dstBits.
- 	"Compute the (unshifted) transfer mask"
- 	mask := (1 bitShift: bits) - 1.
- 	"Shift the transfer mask to the mask the highest n bits of srcBitMask"
- 	mask := mask bitShift: (srcHigh - bits).
- 	"Compute the delta shift so that the most significant bit of the
- 	source bit mask falls on the most significant bit of the dest bit mask.
- 	Note that delta is used for #bitShift: so
- 		shift > 0 : shift right
- 		shift < 0 : shift left
- 	e.g., if dstHigh > srcHigh we need to shift left and if dstHigh < srcHigh
- 	we need to shift right. This leads to:"
- 	shift := dstHigh - srcHigh.
- 	"And that's all we need"
- 	^Array with: shift with: mask!

Item was removed:
- ----- Method: ColorMap class>>mappingFrom:to: (in category 'instance creation') -----
- mappingFrom: srcBitMasks to: dstBitMasks
- 	"Return a color map mapping from the array of source bit masks
- 	to the array of dest bit masks."
- 	| shifts masks shiftAndMask |
- 	shifts := IntegerArray new: 4.
- 	masks := WordArray new: 4.
- 	1 to: 4 do:[:i|
- 		shiftAndMask := self mapBitsFrom: (srcBitMasks at: i) to: (dstBitMasks at: i).
- 		shifts at: i put: (shiftAndMask at: 1).
- 		masks at: i put: (shiftAndMask at: 2).
- 	].
- 	^self shifts: shifts masks: masks!

Item was removed:
- ----- Method: ColorMap class>>mappingFromARGB: (in category 'instance creation') -----
- mappingFromARGB: dstBitMasks
- 	"Return a ColorMap mapping from canonical ARGB space into dstBitMasks"
- 	^self mappingFrom: #(16rFF0000 16rFF00 16rFF 16rFF000000) to: dstBitMasks!

Item was removed:
- ----- Method: ColorMap class>>mappingToARGB: (in category 'instance creation') -----
- mappingToARGB: srcBitMasks
- 	"Return a ColorMap mapping from srcBitMasks into canonical ARGB space"
- 	^self mappingFrom: srcBitMasks to: #(16rFF0000 16rFF00 16rFF 16rFF000000)!

Item was removed:
- ----- Method: ColorMap class>>masks:shifts: (in category 'instance creation') -----
- masks: maskArray shifts: shiftArray
- 	^self shifts: shiftArray masks: maskArray colors: nil.!

Item was removed:
- ----- Method: ColorMap class>>shifts:masks: (in category 'instance creation') -----
- shifts: shiftArray masks: maskArray
- 	^self shifts: shiftArray masks: maskArray colors: nil.!

Item was removed:
- ----- Method: ColorMap class>>shifts:masks:colors: (in category 'instance creation') -----
- shifts: shiftArray masks: maskArray colors: colorArray
- 	^self new setShifts: shiftArray masks: maskArray colors: colorArray!

Item was removed:
- ----- Method: ColorMap>>= (in category 'comparing') -----
- = aColorMap
- 	"Return true if the receiver is equal to aColorMap"
- 	self species == aColorMap species ifFalse:[^false].
- 	self isIndexed == aColorMap isIndexed ifFalse:[^false].
- 	^self colors = aColorMap colors and:[
- 		self shifts = aColorMap shifts and:[
- 			self masks = aColorMap masks]]!

Item was removed:
- ----- Method: ColorMap>>alphaMask (in category 'accessing') -----
- alphaMask
- 	^masks at: 4!

Item was removed:
- ----- Method: ColorMap>>alphaMask: (in category 'accessing') -----
- alphaMask: value
- 	masks at: 4 put: value!

Item was removed:
- ----- Method: ColorMap>>alphaShift (in category 'accessing') -----
- alphaShift
- 	^shifts at: 4!

Item was removed:
- ----- Method: ColorMap>>alphaShift: (in category 'accessing') -----
- alphaShift: value
- 	shifts at: 4 put: value!

Item was removed:
- ----- Method: ColorMap>>at: (in category 'accessing') -----
- at: index
- 	^colors at: index!

Item was removed:
- ----- Method: ColorMap>>at:put: (in category 'accessing') -----
- at: index put: value
- 	^colors at: index put: value!

Item was removed:
- ----- Method: ColorMap>>blueMask (in category 'accessing') -----
- blueMask
- 	^masks at: 3!

Item was removed:
- ----- Method: ColorMap>>blueMask: (in category 'accessing') -----
- blueMask: value
- 	masks at: 3 put: value!

Item was removed:
- ----- Method: ColorMap>>blueShift (in category 'accessing') -----
- blueShift
- 	^shifts at: 3!

Item was removed:
- ----- Method: ColorMap>>blueShift: (in category 'accessing') -----
- blueShift: value
- 	shifts at: 3 put: value!

Item was removed:
- ----- Method: ColorMap>>colors (in category 'accessing') -----
- colors
- 	^colors!

Item was removed:
- ----- Method: ColorMap>>greenMask (in category 'accessing') -----
- greenMask
- 	^masks at: 2!

Item was removed:
- ----- Method: ColorMap>>greenMask: (in category 'accessing') -----
- greenMask: value
- 	masks at: 2 put: value!

Item was removed:
- ----- Method: ColorMap>>greenShift (in category 'accessing') -----
- greenShift
- 	^shifts at: 2!

Item was removed:
- ----- Method: ColorMap>>greenShift: (in category 'accessing') -----
- greenShift: value
- 	shifts at: 2 put: value.!

Item was removed:
- ----- Method: ColorMap>>hash (in category 'comparing') -----
- hash
- 	"Hash is re-implemented because #= is re-implemented"
- 	^colors hash bitXor: (shifts hash bitXor: masks hash)!

Item was removed:
- ----- Method: ColorMap>>inverseMap (in category 'accessing') -----
- inverseMap
- 	"Return the inverse map of the receiver"
- 	| newMasks newShifts |
- 	colors ifNotNil:[^self error:'Not yet implemented'].
- 	newMasks := WriteStream on: (Array new: 4).
- 	newShifts := WriteStream on: (Array new: 4).
- 	masks with: shifts do:[:mask :shift|
- 		newMasks nextPut: (mask bitShift: shift).
- 		newShifts nextPut: shift negated].
- 	^ColorMap
- 		shifts: newShifts contents
- 		masks: newMasks contents!

Item was removed:
- ----- Method: ColorMap>>isColormap (in category 'testing') -----
- isColormap
- 	^true!

Item was removed:
- ----- Method: ColorMap>>isFixed (in category 'testing') -----
- isFixed
- 	"Return true if the receiver does not use a lookup mechanism for pixel mapping"
- 	^self isIndexed not!

Item was removed:
- ----- Method: ColorMap>>isIndexed (in category 'testing') -----
- isIndexed
- 	"Return true if the receiver uses a lookup mechanism for pixel mapping"
- 	^colors notNil!

Item was removed:
- ----- Method: ColorMap>>mapPixel: (in category 'pixel mapping') -----
- mapPixel: pixelValue
- 	"Perform a forward pixel mapping operation"
- 	| pv |
- 	(shifts == nil and:[masks == nil]) ifFalse:[
- 		pv := (((pixelValue bitAnd: self redMask) bitShift: self redShift) bitOr:
- 			((pixelValue bitAnd: self greenMask) bitShift: self greenShift)) bitOr:
- 			(((pixelValue bitAnd: self blueMask) bitShift: self blueShift) bitOr:
- 			((pixelValue bitAnd: self alphaMask) bitShift: self alphaShift)).
- 	] ifTrue:[pv := pixelValue].
- 	colors ifNotNil:[pv := colors at: pv].
- 	"Need to check for translucency else Form>>paint goes gaga"
- 	pv = 0 ifTrue:[pixelValue = 0 ifFalse:[pv := 1]].
- 	^pv!

Item was removed:
- ----- Method: ColorMap>>mappingTo: (in category 'pixel mapping') -----
- mappingTo: aColorMap
- 	"Compute a new color map through the receiver and aColorMap.
- 	Both maps are assumed to be mappings into canonical ARGB space"
- 	| fixedMap |
- 	self = aColorMap ifTrue:[^nil]. "No mapping needed"
- 	aColorMap isIndexed ifTrue:[^nil]. "We can't compute mappings to an indexed map yet"
- 	fixedMap := self species mappingFrom: self rgbaBitMasks to: aColorMap rgbaBitMasks.
- 	self isIndexed ifFalse:[^fixedMap].
- 	"If the receiver is indexed then we need to map the colors as well"
- 	self flag: #untested.
- 	^ColorMap
- 		shifts: fixedMap shifts
- 		masks: fixedMap masks
- 		colors: (colors collect:[:pv| aColorMap pixelMap: pv]).
- !

Item was removed:
- ----- Method: ColorMap>>masks (in category 'accessing') -----
- masks
- 	^masks!

Item was removed:
- ----- Method: ColorMap>>pixelMap: (in category 'pixel mapping') -----
- pixelMap: pixelValue
- 	"Perform a reverse pixel mapping operation"
- 	| pv |
- 	colors == nil
- 		ifTrue:[pv := pixelValue]
- 		ifFalse:[pv := colors at: pixelValue].
- 	(shifts == nil and:[masks == nil]) 
- 		ifFalse:[pv := (((pv bitAnd: self redMask) bitShift: self redShift) bitOr: 
- 				((pv bitAnd: self greenMask) bitShift: self greenShift)) bitOr:
- 					(((pv bitAnd: self blueMask) bitShift: self blueShift) bitOr: 
- 						((pv bitAnd: self alphaMask) bitShift: self alphaShift))].
- 	"Need to check for translucency else Form>>paint goes gaga"
- 	pv = 0 ifTrue:[pixelValue = 0 ifFalse:[pv := 1]].
- 	^pv!

Item was removed:
- ----- Method: ColorMap>>redMask (in category 'accessing') -----
- redMask
- 	^masks at: 1!

Item was removed:
- ----- Method: ColorMap>>redMask: (in category 'accessing') -----
- redMask: value
- 	masks at: 1 put: value!

Item was removed:
- ----- Method: ColorMap>>redShift (in category 'accessing') -----
- redShift
- 	^shifts at: 1!

Item was removed:
- ----- Method: ColorMap>>redShift: (in category 'accessing') -----
- redShift: value
- 	shifts at: 1 put: value!

Item was removed:
- ----- Method: ColorMap>>rgbaBitMasks (in category 'accessing') -----
- rgbaBitMasks
- 	"Return the rgba bit masks for the receiver"
- 	^masks asArray with: shifts collect:[:m :s| m bitShift: s]!

Item was removed:
- ----- Method: ColorMap>>setShifts:masks:colors: (in category 'private') -----
- setShifts: shiftArray masks: maskArray colors: colorArray
- 	shiftArray ifNotNil:[shifts := shiftArray asIntegerArray].
- 	maskArray ifNotNil:[masks := maskArray asWordArray].
- 	colorArray ifNotNil:[colors := colorArray asWordArray].!

Item was removed:
- ----- Method: ColorMap>>shifts (in category 'accessing') -----
- shifts
- 	^shifts!

Item was removed:
- DisplayTransform subclass: #CompositeTransform
- 	instanceVariableNames: 'globalTransform localTransform'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Transformations'!
- 
- !CompositeTransform commentStamp: '<historical>' prior: 0!
- A composite transform provides the effect of several levels of coordinate transformations.!

Item was removed:
- ----- Method: CompositeTransform class>>globalTransform:localTransform: (in category 'instance creation') -----
- globalTransform: gt localTransform: lt
- 	^self new globalTransform: gt localTransform: lt!

Item was removed:
- ----- Method: CompositeTransform>>angle (in category 'accessing') -----
- angle
- 	^ localTransform angle + globalTransform angle!

Item was removed:
- ----- Method: CompositeTransform>>asCompositeTransform (in category 'converting') -----
- asCompositeTransform
- 	^self!

Item was removed:
- ----- Method: CompositeTransform>>asMatrixTransform2x3 (in category 'converting') -----
- asMatrixTransform2x3
- 	^globalTransform asMatrixTransform2x3
- 		composedWithLocal: localTransform asMatrixTransform2x3!

Item was removed:
- ----- Method: CompositeTransform>>asMorphicTransform (in category 'converting') -----
- asMorphicTransform
- 	"Squash a composite transform down to a simple one"
- 	^ MorphicTransform
- 		offset: (self localPointToGlobal: 0 at 0) negated
- 		angle: self angle
- 		scale: self scale!

Item was removed:
- ----- Method: CompositeTransform>>composedWith: (in category 'initialization') -----
- composedWith: aTransform
- 	"Return a new transform that has the effect of transforming points first by the receiver and then by the argument."
- 
- 	self isIdentity ifTrue: [^ aTransform].
- 	aTransform isIdentity ifTrue: [^ self].
- 	^ CompositeTransform new globalTransform: self
- 							localTransform: aTransform!

Item was removed:
- ----- Method: CompositeTransform>>globalPointToLocal: (in category 'transforming points') -----
- globalPointToLocal: aPoint
- 	"Transform aPoint from global coordinates into local coordinates"
- 	^localTransform globalPointToLocal:
- 		(globalTransform globalPointToLocal: aPoint)!

Item was removed:
- ----- Method: CompositeTransform>>globalTransform:localTransform: (in category 'initialization') -----
- globalTransform: gt localTransform: lt
- 	globalTransform := gt.
- 	localTransform := lt!

Item was removed:
- ----- Method: CompositeTransform>>inverseTransformation (in category 'accessing') -----
- inverseTransformation
- 	"Return the inverse transformation of the receiver"
- 	^self species new
- 		globalTransform: localTransform inverseTransformation
- 		localTransform: globalTransform inverseTransformation!

Item was removed:
- ----- Method: CompositeTransform>>invert: (in category 'transformations') -----
- invert: aPoint
- 	^ globalTransform invert: (localTransform invert: aPoint)!

Item was removed:
- ----- Method: CompositeTransform>>isCompositeTransform (in category 'testing') -----
- isCompositeTransform
- 	^true!

Item was removed:
- ----- Method: CompositeTransform>>isIdentity (in category 'testing') -----
- isIdentity
- 	^ globalTransform isIdentity and: [localTransform isIdentity]!

Item was removed:
- ----- Method: CompositeTransform>>isPureTranslation (in category 'testing') -----
- isPureTranslation
- 	^ globalTransform isPureTranslation and: [localTransform isPureTranslation]!

Item was removed:
- ----- Method: CompositeTransform>>localPointToGlobal: (in category 'transforming points') -----
- localPointToGlobal: aPoint
- 	"Transform aPoint from global coordinates into local coordinates"
- 	^globalTransform localPointToGlobal:
- 		(localTransform localPointToGlobal: aPoint)!

Item was removed:
- ----- Method: CompositeTransform>>scale (in category 'accessing') -----
- scale
- 	^ localTransform scale * globalTransform scale!

Item was removed:
- ----- Method: CompositeTransform>>transform: (in category 'transformations') -----
- transform: aPoint
- 	^ localTransform transform: (globalTransform transform: aPoint)!

Item was removed:
- CharacterScanner subclass: #CompositionScanner
- 	instanceVariableNames: 'spaceX spaceIndex lineHeight baseline lineGap lineGapSlice topMargin bottomMargin lineHeightAtSpace baselineAtSpace lastBreakIsNotASpace nextIndexAfterLineBreak'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Text'!
- 
- !CompositionScanner commentStamp: 'nice 10/6/2013 23:24' prior: 0!
- A CompositionScanner measures text and determines where line breaks.
- Given a rectangular zone on input, it is used to split text in horizontal lines, and produce information about those lines on output (at which index a line starts/stops, which vertical space does the line require, which horizontal space if left for adjusting inter-word spacing, etc...)
- 
- Instance Variables
- 	baseline:		<Number>
- 	baselineAtSpace:		<Number>
- 	lastBreakIsNotASpace:		<Boolean>
- 	lineHeight:		<Number>
- 	lineHeightAtSpace:		<Number>
- 	nextIndexAfterLineBreak:		<Integer>
- 	spaceIndex:		<Integer>
- 	spaceX:		<Number>
- 
- baseline
- 	- the distance between top of line and the base line (that is the bottom of latin characters abcdehiklmnorstuvwx in most fonts)
- 
- baselineAtSpace
- 	- memorize the baseline at last encountered space or other breakable character.
- 	This is necessary because the CompositionScanner wants to break line at a breakable character.
- 	If a word layout overflows the right margin, the scanner has to roll back and restore the line state to last encountered breakable character.
- 
- lastBreakIsNotASpace
- 	- indicates that the last breakable character was not a space.
- 	This is necessary because handling a line break at a space differs from non space.
- 	If line break occurs on space, the space won't be displayed in next line.
- 	If it's another breakable character, it has to be displayed on next line.
- 
- lineHeight
- 	- the total line height from top to bottom, including inter-line spacing.
- 
- lineHeightAtSpace
- 	- the line height at last encountered space or other breakable character.
- 	See baselineAtSpace for explanation.
- 
- nextIndexAfterLineBreak
- 	- the index of character after the last line break that was encountered.
- 
- spaceIndex
- 	- the index of last space or other breakable character that was encountered
- 
- spaceX
- 	- the distance from left of composition zone to left of last encountered space or other breakable character 
- 	See baselineAtSpace for explanation.
- 
- Note: if a line breaks on a space, a linefeed or a carriage return, then the space, linefeed or carriage return is integrated in the line.
- If there is a carriage return - linefeed pair, the pair is integrated to the line as if it were a single line break for compatibility with legacy software.!

Item was removed:
- ----- Method: CompositionScanner>>alignmentMorphOffsetFor:of: (in category 'private') -----
- alignmentMorphOffsetFor: textAnchorProperties of: aMorphOrForm
- 
- 	^ textAnchorProperties verticalAlignmentMorph caseOf: {
- 				[#top] -> [textAnchorProperties padding top].
- 				[#center] -> [(aMorphOrForm height / 2) floor].
- 				[#baseline] -> [textAnchorProperties morphBaselineGetter
- 					ifNil: [0]
- 					ifNotNil: [:s | aMorphOrForm perform: s]].
- 				[#bottom] -> [aMorphOrForm height + textAnchorProperties padding bottom]}!

Item was removed:
- ----- Method: CompositionScanner>>atEnd (in category 'testing') -----
- atEnd
- 
- 	^ lastIndex = text size!

Item was removed:
- ----- Method: CompositionScanner>>baselineAdjustmentFor: (in category 'private') -----
- baselineAdjustmentFor: textAnchorProperties
- 
- 	^ textAnchorProperties verticalAlignmentLine caseOf: {
- 				[#top] -> [font ascent].
- 				[#center] -> [(font ascent / 2) floor].
- 				[#baseline] -> [0].
- 				[#bottom] -> [font descent negated]}.
- 			
- 	!

Item was removed:
- ----- Method: CompositionScanner>>canComputeDefaultLineHeight (in category 'testing') -----
- canComputeDefaultLineHeight
- 	^ rightMargin notNil!

Item was removed:
- ----- Method: CompositionScanner>>columnBreak (in category 'stop conditions') -----
- columnBreak
- 
- 	"Answer true. Set up values for the text line interval currently being 
- 	composed."
- 
- 	pendingKernX := 0.
- 	line stop: lastIndex.
- 	spaceX := destX.
- 	lastBreakIsNotASpace := false.
- 	line paddingWidth: rightMargin - spaceX.
- 	^true!

Item was removed:
- ----- Method: CompositionScanner>>composeFrom:inRectangle:firstLine:leftSide:rightSide: (in category 'scanning') -----
- composeFrom: startIndex inRectangle: lineRectangle
- 	firstLine: firstLine leftSide: leftSide rightSide: rightSide
- 	"Answer an instance of TextLineInterval that represents the next line in the paragraph."
- 	| runLength stopCondition lineSpacing |
- 	"Set up margins"
- 	leftMargin := lineRectangle left.
- 	leftSide ifTrue: [leftMargin := leftMargin +
- 						(firstLine ifTrue: [textStyle firstIndent]
- 								ifFalse: [textStyle restIndent])].
- 	destX := spaceX := leftMargin.
- 	rightMargin := lineRectangle right.
- 	rightSide ifTrue: [rightMargin := rightMargin - textStyle rightIndent].
- 	lastIndex := startIndex.	"scanning sets last index"
- 	destY := lineRectangle top.
- 	lineHeight := baseline := 0. "Will be increased by setFont"
- 	lineGap := lineGapSlice := -9999. "Will be increased by setFont; allow negative to show all effects of a custom #extraGap value. See TTFontDescription."
- 	topMargin := bottomMargin := 0.
- 	line := (TextLine start: lastIndex stop: 0 internalSpaces: 0 paddingWidth: 0)
- 				rectangle: lineRectangle.
- 	self setStopConditions.	"also sets font"
- 	runLength := text runLengthFor: startIndex.
- 	runStopIndex := (lastIndex := startIndex) + (runLength - 1).
- 	nextIndexAfterLineBreak := spaceCount := 0.
- 	lastBreakIsNotASpace := false.
- 	self handleIndentation.
- 	leftMargin := destX.
- 	line leftMargin: leftMargin.
- 
- 	[stopCondition := self scanCharactersFrom: lastIndex to: runStopIndex
- 		in: text string rightX: rightMargin.
- 	"See setStopConditions for stopping conditions for composing."
- 	self perform: stopCondition] whileFalse.
- 
- 	lineHeight := lineHeight + lineGap.
- 	baseline := baseline + lineGapSlice.
- 	
- 	(lineSpacing := textStyle lineSpacing) = 0.0 ifFalse: [
- 		"Modify lineHeight to realize lineSpacing instead of bottomMargin to avoid
- 		rendering glitches for lineSpacing values < 0.0."
- 		lineHeight := lineHeight + (lineSpacing * lineHeight) truncated.
- 		"ALT: bottomMargin := bottomMargin + (lineSpacing * lineHeight) truncated"].
- 
- 	line lineHeight: lineHeight baseline: baseline.
- 	"TODO: Allow special characters or text attributes to accumulate extra top or bottom margin."
- 	line topMargin: topMargin bottomMargin: bottomMargin.
- 	^ line!

Item was removed:
- ----- Method: CompositionScanner>>computeDefaultLineHeight (in category 'scanning') -----
- computeDefaultLineHeight
- 	"Compute the default line height for a potentially empty text"
- 	rightMargin notNil
- 		ifTrue: [lastIndex := 1.
- 			self setFont.
- 			^ lineHeight + lineGap]
- 		ifFalse: [^textStyle lineGrid]!

Item was removed:
- ----- Method: CompositionScanner>>cr (in category 'stop conditions') -----
- cr
- 	"Answer true. Set up values for the text line interval currently being 
- 	composed."
- 
- 	pendingKernX := 0.
- 	(lastIndex < text size and: [(text at: lastIndex) = CR and: [(text at: lastIndex+1) = Character lf]]) ifTrue: [lastIndex := lastIndex + 1].
- 	line stop: lastIndex.
- 	nextIndexAfterLineBreak := lastIndex + 1.
- 	spaceX := destX.
- 	lastBreakIsNotASpace := false.
- 	line paddingWidth: rightMargin - spaceX.
- 	^true!

Item was removed:
- ----- Method: CompositionScanner>>crossedX (in category 'stop conditions') -----
- crossedX
- 	"There is a word that has fallen across the right edge of the composition 
- 	rectangle. This signals the need for wrapping which is done to the last 
- 	space that was encountered, as recorded by the space stop condition,
- 	or any other breakable character if the language permits so."
- 
- 	pendingKernX := 0.
- 	
- 	lastBreakIsNotASpace ifTrue:
- 		["In some languages line break is possible before a non space."
- 		^self wrapAtLastBreakable].
- 	 
- 	spaceCount >= 1 ifTrue:
- 		["The common case. there is a space on the line."
- 		^self wrapAtLastSpace].
- 	
- 	"Neither internal nor trailing spaces -- almost never happens."
- 	self advanceIfFirstCharOfLine.
- 	^self wrapHere!

Item was removed:
- ----- Method: CompositionScanner>>doesTheLineBreakAfterLastChar (in category 'testing') -----
- doesTheLineBreakAfterLastChar
- 
- 	^nextIndexAfterLineBreak > text size!

Item was removed:
- ----- Method: CompositionScanner>>endOfRun (in category 'stop conditions') -----
- endOfRun
- 	"Answer true if scanning has reached the end of the paragraph. 
- 	Otherwise step conditions (mostly install potential new font) and answer 
- 	false."
- 
- 	| runLength |
- 	lastIndex = text size
- 	ifTrue:	[line stop: lastIndex.
- 			spaceX := destX.
- 			line paddingWidth: rightMargin - destX.
- 			^true]
- 	ifFalse:	[runLength := (text runLengthFor: (lastIndex := lastIndex + 1)).
- 			runStopIndex := lastIndex + (runLength - 1).
- 			self setStopConditions.
- 			^false]
- !

Item was removed:
- ----- Method: CompositionScanner>>initialize (in category 'initialize') -----
- initialize
- 	wantsColumnBreaks := false.
- 	super initialize!

Item was removed:
- ----- Method: CompositionScanner>>lineHeightForMorphOfHeight:aligned:to: (in category 'private') -----
- lineHeightForMorphOfHeight: aMorphHeight aligned: morphPosition to: linePosition 
- 	
- 	^ self
- 		lineHeightForMorphOfHeight: aMorphHeight
- 		aligned: morphPosition 
- 		to: linePosition
- 		paddedWith: 0
- 		andOptionalMorphBaseline: 0!

Item was removed:
- ----- Method: CompositionScanner>>lineHeightForMorphOfHeight:aligned:to:paddedWith:andOptionalMorphBaseline: (in category 'private') -----
- lineHeightForMorphOfHeight: aMorphHeight aligned: morphPosition to: linePosition paddedWith: verticalPadding andOptionalMorphBaseline: morphBaseline
- 	"The idea here is to first compute the total height and then subtract the overlapping area."
- 
- 	| adjustedLineHeight morphHeight total |
- 	morphHeight := aMorphHeight + verticalPadding.
- 	total := font height + morphHeight.
- 	adjustedLineHeight := 0.
- 	
- 	morphPosition = #top 		ifTrue: [
- 			linePosition = #top			ifTrue: [adjustedLineHeight := total - font height].
- 			linePosition = #center 		ifTrue: [adjustedLineHeight := total - (font descent + (font ascent / 2))].
- 			linePosition = #baseline 	ifTrue: [adjustedLineHeight := total - font descent].
- 			linePosition = #bottom 		ifTrue: [adjustedLineHeight := total].].
- 	morphPosition = #center 	ifTrue: [ | upperMorphHalf lowerMorphHalf |
- 			"The overlapping area of a morph aligned at the center position can be determined by splitting 
- 			the morph into a top half which is aligned at the bottom and a lower half aligned at the top."
- 			upperMorphHalf := self 
- 				lineHeightForMorphOfHeight: aMorphHeight // 2 
- 				aligned: #bottom to: linePosition. 
- 			lowerMorphHalf := self 
- 				lineHeightForMorphOfHeight: aMorphHeight // 2
- 				aligned: #top to: linePosition.
- 			adjustedLineHeight := upperMorphHalf + lowerMorphHalf - font height].
- 	morphPosition = #baseline ifTrue: [ | upperMorphHalf lowerMorphHalf |
- 			"We use the same trick as we used with the center position but with different proportions of the morph."
- 			upperMorphHalf := self 
- 				lineHeightForMorphOfHeight: morphBaseline 
- 				aligned: #bottom to: linePosition. 
- 			lowerMorphHalf := self 
- 				lineHeightForMorphOfHeight: aMorphHeight - morphBaseline 
- 				aligned: #top to: linePosition.
- 			adjustedLineHeight := upperMorphHalf + lowerMorphHalf - font height].
- 	morphPosition = #bottom 	ifTrue: [
- 			linePosition = #top			ifTrue: [adjustedLineHeight := total].
- 			linePosition = #center 		ifTrue: [adjustedLineHeight := total - (font ascent / 2)].
- 			linePosition = #baseline 	ifTrue: [adjustedLineHeight := total - font ascent].
- 			linePosition = #bottom 		ifTrue: [adjustedLineHeight := total - font height].].
- 
- 	^ adjustedLineHeight!

Item was removed:
- ----- Method: CompositionScanner>>placeEmbeddedObjectFrom: (in category 'private') -----
- placeEmbeddedObjectFrom: aTextAttribute
- 
- 	| width anchoredMorphOrForm textAnchorProperties |
- 	anchoredMorphOrForm := aTextAttribute anchoredMorph.
- 	textAnchorProperties := self textAnchorPropertiesFor: anchoredMorphOrForm.
- 	
- 	textAnchorProperties anchorLayout == #document ifTrue: [^ true].
- 	"If it is not anchored at the document, we assume that it is inline."
- 	width := anchoredMorphOrForm width + textAnchorProperties horizontalPadding.
- 	(textAnchorProperties consumesHorizontalSpace and: [destX + width > rightMargin and: [(leftMargin + width) <= rightMargin or: [lastIndex > line first]]])
- 		ifTrue: ["Won't fit, but would on next line"
- 				^ false].
- 	
- 	"The width had to be set beforehand to determine line wrapping. 
- 	We can now re-use and reset it as it might not be necessary anymore. --pre"
- 	width := textAnchorProperties consumesHorizontalSpace 
- 		ifTrue: [anchoredMorphOrForm width + textAnchorProperties horizontalPadding]
- 		ifFalse: [0].
- 	destX := destX + width + kern.
- 	
- 	baseline := baseline max: 
- 		(self alignmentMorphOffsetFor: textAnchorProperties of: anchoredMorphOrForm) 
- 			+ (self baselineAdjustmentFor: textAnchorProperties).
- 	lineHeight := lineHeight max: (self 
- 		lineHeightForMorphOfHeight: anchoredMorphOrForm height
- 		aligned: textAnchorProperties verticalAlignmentMorph 
- 		to: textAnchorProperties verticalAlignmentLine
- 		paddedWith: textAnchorProperties verticalPadding
- 		andOptionalMorphBaseline: (textAnchorProperties morphBaselineGetter 
- 			ifNotNil: [:getter | anchoredMorphOrForm perform: getter] ifNil: [0])).
- 	^ true!

Item was removed:
- ----- Method: CompositionScanner>>rightX (in category 'accessing') -----
- rightX
- 	"Meaningful only when a line has just been composed -- refers to the 
- 	line most recently composed. This is a subtrefuge to allow for easy 
- 	resizing of a composition rectangle to the width of the maximum line. 
- 	Useful only when there is only one line in the form or when each line 
- 	is terminated by a carriage return. Handy for sizing menus and lists."
- 
- 	^spaceX!

Item was removed:
- ----- Method: CompositionScanner>>setActualFont: (in category 'text attributes') -----
- setActualFont: aFont
- 	"Keep track of max height and ascent for auto lineheight"
- 	| descent |
- 	super setActualFont: aFont.
- 	lineHeight == nil
- 		ifTrue: [descent := font descent.
- 				baseline := font ascent.
- 				lineHeight := baseline + descent.
- 				lineGap := aFont lineGap.
- 				lineGapSlice := aFont lineGapSlice]
- 		ifFalse: [descent := lineHeight - baseline max: font descent.
- 				baseline := baseline max: font ascent.
- 				lineHeight := lineHeight max: baseline + descent.
- 				lineGap := lineGap max: aFont lineGap.
- 				lineGapSlice := lineGapSlice max: aFont lineGapSlice]!

Item was removed:
- ----- Method: CompositionScanner>>setStopConditions (in category 'private') -----
- setStopConditions
- 	"Set the font and the stop conditions for the current run."
- 	
- 	self setFont.
- 	stopConditions := wantsColumnBreaks == true
- 		ifTrue: [ColumnBreakStopConditions]
- 		ifFalse: [CompositionStopConditions]!

Item was removed:
- ----- Method: CompositionScanner>>space (in category 'stop conditions') -----
- space
- 	"Record left x and character index of the space character just encountered. 
- 	Used for wrap-around. Answer whether the character has crossed the 
- 	right edge of the composition rectangle of the paragraph."
- 
- 	spaceX := destX.
- 	spaceIndex := lastIndex.
- 	lineHeightAtSpace := lineHeight.
- 	baselineAtSpace := baseline.
- 	spaceCount := spaceCount + 1.
- 	lastBreakIsNotASpace := false.
- 	destX + spaceWidth > rightMargin ifTrue:[^self crossedX].
- 	destX := spaceX + spaceWidth + kern.
- 	lastIndex := lastIndex + 1.
- 	^false
- !

Item was removed:
- ----- Method: CompositionScanner>>tab (in category 'stop conditions') -----
- tab
- 	"Advance destination x according to tab settings in the paragraph's 
- 	textStyle. Answer whether the character has crossed the right edge of 
- 	the composition rectangle of the paragraph."
- 
- 	pendingKernX := 0.
- 	destX := textStyle
- 				nextTabXFrom: destX leftMargin: leftMargin rightMargin: rightMargin.
- 	destX > rightMargin ifTrue:	[^self crossedX].
- 	lastIndex := lastIndex + 1.
- 	^false
- !

Item was removed:
- ----- Method: CompositionScanner>>wantsColumnBreaks: (in category 'initialize') -----
- wantsColumnBreaks: aBoolean
- 
- 	wantsColumnBreaks := aBoolean!

Item was removed:
- ----- Method: CompositionScanner>>wrapAtLastBreakable (in category 'stop conditions') -----
- wrapAtLastBreakable
- 	"Wrap the line before last encountered breakable character."
- 	pendingKernX := 0.
- 	nextIndexAfterLineBreak := spaceIndex.
- 	line stop: spaceIndex - 1.
- 	lineHeight := lineHeightAtSpace.
- 	baseline := baselineAtSpace.
- 	line paddingWidth: rightMargin - spaceX.
- 	line internalSpaces: spaceCount.
- 	^true!

Item was removed:
- ----- Method: CompositionScanner>>wrapAtLastSpace (in category 'stop conditions') -----
- wrapAtLastSpace
- 	"Wrap the line before last encountered space"
- 	
- 	pendingKernX := 0.
- 	nextIndexAfterLineBreak := spaceIndex + 1.
- 	alignment = Justified ifTrue: [
- 		"gobble all subsequent spaces"
- 		[nextIndexAfterLineBreak <= text size and: [(text at: nextIndexAfterLineBreak) == Space]]
- 			whileTrue: [nextIndexAfterLineBreak := nextIndexAfterLineBreak + 1]].
- 	
- 	line stop: nextIndexAfterLineBreak - 1.
- 	lineHeight := lineHeightAtSpace.
- 	baseline := baselineAtSpace.
- 
- 	["remove the space at which we break..."
- 	spaceCount := spaceCount - 1.
- 	spaceIndex := spaceIndex - 1.
- 
- 	"...and every other spaces preceding the one at which we wrap.
- 		Double space after punctuation, most likely."
- 	spaceCount >= 1 and: [(text at: spaceIndex) = Space]]
- 		whileTrue:
- 			["Account for backing over a run which might
- 				change width of space."
- 			font := text fontAt: spaceIndex withStyle: textStyle.
- 			spaceX := spaceX - (font widthOf: Space)].
- 	line paddingWidth: rightMargin - spaceX.
- 	line internalSpaces: spaceCount.
- 	^true!

Item was removed:
- ----- Method: CompositionScanner>>wrapHere (in category 'stop conditions') -----
- wrapHere
- 	"Wrap the line before current character."
- 	pendingKernX := 0.
- 	nextIndexAfterLineBreak := lastIndex.
- 	lastIndex := lastIndex - 1.
- 	spaceX := destX.
- 	line paddingWidth: rightMargin - destX.
- 	line stop: (lastIndex max: line first).
- 	^true!

Item was removed:
- Form subclass: #Cursor
- 	instanceVariableNames: ''
- 	classVariableNames: 'BlankCursor BottomLeftCursor BottomRightCursor CornerCursor CrossHairCursor CurrentCursor DownCursor MarkerCursor MenuCursor MoveCursor NormalCursor OriginCursor ReadCursor ResizeLeftCursor ResizeTopCursor ResizeTopLeftCursor ResizeTopRightCursor RightArrowCursor SquareCursor TargetCursor TextCursor TopLeftCursor TopRightCursor UpCursor UseBiggerCursors WaitCursor WebLinkCursor WriteCursor XeqCursor'
- 	poolDictionaries: ''
- 	category: 'Graphics-Display Objects'!
- 
- !Cursor commentStamp: '<historical>' prior: 0!
- I am a Form that is a possible appearance for a mouse cursor.  My size is always 16x16, ever since the original implementation on the Alto.
- 
- There are many examples available in the "current cursor" category of class methods.  For example, "Cursor normal" and "Cursor wait".  For example:
- 
- 	Cursor wait show
- 
- !

Item was removed:
- ----- Method: Cursor class>>blank (in category 'constants') -----
- blank
- 	"Answer the instance of me that is all white."
- 
- 	^BlankCursor!

Item was removed:
- ----- Method: Cursor class>>bottomLeft (in category 'constants') -----
- bottomLeft
- 	"Cursor bottomLeft showWhile: [Sensor waitButton]"
- 	^BottomLeftCursor
- !

Item was removed:
- ----- Method: Cursor class>>bottomRight (in category 'constants') -----
- bottomRight
- 	"Cursor bottomRight showWhile: [Sensor waitButton]"
- 	^BottomRightCursor
- !

Item was removed:
- ----- Method: Cursor class>>corner (in category 'constants') -----
- corner
- 	"Answer the instance of me that is the shape of the bottom right corner 
- 	of a rectangle."
- 
- 	^CornerCursor!

Item was removed:
- ----- Method: Cursor class>>crossHair (in category 'constants') -----
- crossHair
- 	"Answer the instance of me that is the shape of a cross."
- 
- 	^CrossHairCursor!

Item was removed:
- ----- Method: Cursor class>>currentCursor (in category 'current cursor') -----
- currentCursor
- 	"Answer the instance of Cursor that is the one currently displayed."
- 
- 	^CurrentCursor!

Item was removed:
- ----- Method: Cursor class>>currentCursor: (in category 'current cursor') -----
- currentCursor: aCursor 
- 	"Make the instance of cursor, aCursor, be the current cursor. Display it. 
- 	Create an error if the argument is not a Cursor."
- 
- 	(aCursor isKindOf: self)
- 		ifTrue: [ | platformCursor |
- 			CurrentCursor := aCursor. "unscaled"
- 			self flag: #todo. "mt: The current OSVM platform code for macOS has an issue with *not* scaling up hardware cursors for Retina displays. So we avoid scaling it here and let the OS do it. Note that this is not good because we could never provide a high-resolution cursor from within Squeak since the OS would scale it up anyway."
- 			Smalltalk platformName = 'Mac OS'
- 				ifTrue: [platformCursor := aCursor]
- 				ifFalse: [platformCursor := aCursor scaleIconToDisplay].
- 			self useBiggerCursors
- 				ifTrue: [platformCursor := platformCursor enlargedBy: 2].
- 			platformCursor beCursor]
- 		ifFalse: [self error: 'The new cursor must be an instance of class Cursor']!

Item was removed:
- ----- Method: Cursor class>>down (in category 'constants') -----
- down
- 	"Answer the instance of me that is the shape of an arrow facing 
- 	downward."
- 
- 	^DownCursor!

Item was removed:
- ----- Method: Cursor class>>execute (in category 'constants') -----
- execute
- 	"Answer the instance of me that is the shape of an arrow slanted left 
- 	with a star next to it."
- 
- 	^XeqCursor!

Item was removed:
- ----- Method: Cursor class>>extent:fromArray:offset: (in category 'instance creation') -----
- extent: extentPoint fromArray: anArray offset: offsetPoint 
- 	"Answer a new instance of me with width and height specified by
- 	extentPoint, offset by offsetPoint, and bits from anArray.
- 	NOTE: This has been kluged to take an array of 16-bit constants,
- 	and shift them over so they are left-justified in a 32-bit bitmap"
- 
- 	extentPoint = (16 @ 16)
- 		ifTrue: 
- 			[^ super
- 				extent: extentPoint
- 				fromArray: (anArray collect: [:bits | bits bitShift: 16])
- 				offset: offsetPoint]
- 		ifFalse: [self error: 'cursors must be 16 at 16']!

Item was removed:
- ----- Method: Cursor class>>initBottomLeft (in category 'class initialization') -----
- initBottomLeft
- 
- 	BottomLeftCursor := 
- 		(Cursor extent: 16 @ 16
- 			fromArray: #(
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1111111111111111
- 		2r1111111111111111)
- 			offset: 0 @ -16).
- !

Item was removed:
- ----- Method: Cursor class>>initBottomRight (in category 'class initialization') -----
- initBottomRight
- 
- 	BottomRightCursor := 
- 		(Cursor extent: 16 @ 16
- 			fromArray: #(
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r1111111111111111
- 		2r1111111111111111)
- 			offset: -16 @ -16).
- !

Item was removed:
- ----- Method: Cursor class>>initCorner (in category 'class initialization') -----
- initCorner
- 
- 	CornerCursor := 
- 		(Cursor 
- 			extent: 16 @ 16
- 			fromArray: #(
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r1111111111111111
- 		2r1111111111111111)
- 			offset: -16 @ -16).
- !

Item was removed:
- ----- Method: Cursor class>>initCrossHair (in category 'class initialization') -----
- initCrossHair
- 
- 	CrossHairCursor :=   
- 		(Cursor
- 			extent: 16 @ 16
- 			fromArray: #(
- 		2r0000000000000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0111111111111100
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000000000000
- 		2r0)
- 			offset: -7 @ -7).
- 	
- 	!

Item was removed:
- ----- Method: Cursor class>>initDown (in category 'class initialization') -----
- initDown
- 
- 	DownCursor  :=
- 		     (Cursor
- 	extent: 16 @ 16
- 	fromArray: #(
- 		2r11000000000000
- 		2r11000000000000
- 		2r11000000000000
- 		2r11000000000000
- 		2r11000000000000
- 		2r11000000000000
- 		2r11000000000000
- 		2r1111110000000000
- 		2r111100000000000
- 		2r11000000000000
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0)
- 	offset: 0 @ 0).
- !

Item was removed:
- ----- Method: Cursor class>>initMarker (in category 'class initialization') -----
- initMarker
- 
- 	MarkerCursor := 
- 		Cursor
- 			extent: 16 @ 16
- 			fromArray: #(
- 		2r0111000000000000
- 		2r1111100000000000
- 		2r1111100000000000
- 		2r0111000000000000
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0)
- 			offset: 0 @ 0.
- !

Item was removed:
- ----- Method: Cursor class>>initMenu (in category 'class initialization') -----
- initMenu 
- 
- 	MenuCursor  :=
- 		        (Cursor
- 	extent: 16 @ 16
- 	fromArray: #(
- 		2r1111111111100000
- 		2r1000000000100000
- 		2r1010011000100000
- 		2r1000000000100000
- 		2r1101001101100000
- 		2r1111111111100000
- 		2r1000000000100000
- 		2r1011001010100000
- 		2r1000000000100000
- 		2r1010110010100000
- 		2r1000000000100000
- 		2r1010010100100000
- 		2r1000000000100000
- 		2r1111111111100000
- 		0)
- 	offset: 0 @ 0).
- !

Item was removed:
- ----- Method: Cursor class>>initMove (in category 'class initialization') -----
- initMove
- 
- 	MoveCursor := 
- 		Cursor 
- 			extent: 16 @ 16
- 			fromArray: #(
- 		2r1111111111111100
- 		2r1111111111111100
- 		2r1100001100001100
- 		2r1100001100001100
- 		2r1100001100001100
- 		2r1100001100001100
- 		2r1111111111111100
- 		2r1111111111111100
- 		2r1100001100001100
- 		2r1100001100001100
- 		2r1100001100001100
- 		2r1100001100001100
- 		2r1111111111111100
- 		2r1111111111111100
-           0)
- 			offset: 0 @ 0.
- !

Item was removed:
- ----- Method: Cursor class>>initNormal (in category 'class initialization') -----
- initNormal
- 
- 	NormalCursor :=   
- 		(Cursor
- 			extent: 16 @ 16
- 			fromArray: #(
- 		2r1000000000000000
- 		2r1100000000000000
- 		2r1110000000000000
- 		2r1111000000000000
- 		2r1111100000000000
- 		2r1111110000000000
- 		2r1111111000000000
- 		2r1111100000000000
- 		2r1111100000000000
- 		2r1001100000000000
- 		2r0000110000000000
- 		2r0000110000000000
- 		2r0000011000000000
- 		2r0000011000000000
- 		2r0000001100000000
- 		2r0000001100000000)
- 	offset: 0 @ 0).
- 
- 	
- 	!

Item was removed:
- ----- Method: Cursor class>>initNormalWithMask (in category 'class initialization') -----
- initNormalWithMask    "Cursor initNormalWithMask.  Cursor normal show"
- 	"Next two lines work simply for any cursor..."
- 	self initNormal.
- 	NormalCursor := CursorWithMask derivedFrom: NormalCursor.
- 
- 	"But for a good looking cursor, you have to tweak things..."
- 	NormalCursor := (CursorWithMask extent: 16 @ 16 depth: 1
- 			fromArray: #( 0 1073741824 1610612736 1879048192
- 				2013265920 2080374784 2113929216 2130706432
- 				2080374784 2080374784 1275068416 100663296
- 				100663296 50331648 50331648 0)
- 			offset: -1 @ -1)
- 		setMaskForm: (Form extent: 16 @ 16 depth: 1
- 			fromArray: #( 3221225472 3758096384 4026531840 4160749568
- 				4227858432 4261412864 4278190080 4286578688
- 				4278190080 4261412864 4261412864 3472883712
- 				251658240 125829120 125829120 50331648)
- 			offset: 0 @ 0).!

Item was removed:
- ----- Method: Cursor class>>initOrigin (in category 'class initialization') -----
- initOrigin
- 
- 	OriginCursor :=   
- 		(Cursor
- 			extent: 16 @ 16
- 			fromArray: #(
- 		2r1111111111111111
- 		2r1111111111111111
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000)
- 			offset: 0 @ 0).
- !

Item was removed:
- ----- Method: Cursor class>>initRead (in category 'class initialization') -----
- initRead
- 
- 	ReadCursor :=  
- 		(Cursor
- 			extent: 16 @ 16
- 			fromArray: #(
- 		2r0000000000000000
- 		2r0000000000000000
- 		2r0001000000001000
- 		2r0010100000010100
- 		2r0100000000100000
- 		2r1111101111100000
- 		2r1000010000100000
- 		2r1000010000100000
- 		2r1011010110100000
- 		2r0111101111000000
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0)
- 	offset: 0 @ 0).
- !

Item was removed:
- ----- Method: Cursor class>>initResizeLeft (in category 'class initialization') -----
- initResizeLeft
- 
-        ResizeLeftCursor :=
-                (Cursor extent: 16 @ 16 fromArray: #(
-                2r0000000000000000
-                2r0000000000000000
-                2r0000000000000000
-                2r0000000000000000
-                2r0000100000010000
-                2r0001100000011000
-                2r0011100000011100
-                2r0111111111111110
-                2r0011100000011100
-                2r0001100000011000
-                2r0000100000010000
-                2r0000000000000000
-                2r0000000000000000
-                2r0000000000000000
-                2r0000000000000000
-                2r0000000000000000 )
-        offset: -7 @ -7 ) withMask!

Item was removed:
- ----- Method: Cursor class>>initResizeTop (in category 'class initialization') -----
- initResizeTop
-     "Cursor initResizeTop"
-        ResizeTopCursor :=
-                (Cursor extent: 16 @ 16 fromArray: #(
-                2r000000100000000
-                2r000001110000000
-                2r000011111000000
-                2r000111111100000
-                2r000000100000000
-                2r000000100000000
-                2r000000100000000
-                2r000000100000000
-                2r000000100000000
-                2r000000100000000
-                2r000111111100000
-                2r000011111000000
-                2r000001110000000
-                2r000000100000000
-                2r000000000000000)
-        offset: -7 @ -7) withMask!

Item was removed:
- ----- Method: Cursor class>>initResizeTopLeft (in category 'class initialization') -----
- initResizeTopLeft
- 
-        ResizeTopLeftCursor :=
-                (Cursor extent: 16 @ 16 fromArray: #(
-                2r0000000000000000
-                2r0111110000000000
-                2r0111100000000000
-                2r0111000000000000
-                2r0110100000000000
-                2r0100010000000000
-                2r0000001000000000
-                2r0000000100000000
-                2r0000000010000000
-                2r0000000001000100
-                2r0000000000101100
-                2r0000000000011100
-                2r0000000000111100
-                2r0000000001111100
-                2r0000000000000000
-                2r0000000000000000)
-        offset: -7 @ -7) withMask!

Item was removed:
- ----- Method: Cursor class>>initResizeTopRight (in category 'class initialization') -----
- initResizeTopRight
- 
-        ResizeTopRightCursor :=
-                (Cursor extent: 16 @ 16 fromArray: #(
-                2r0000000000000000
-                2r0000000001111100
-                2r0000000000111100
-                2r0000000000011100
-                2r0000000000101100
-                2r0000000001000100
-                2r0000000010000000
-                2r0000000100000000
-                2r0000001000000000
-                2r0100010000000000
-                2r0110100000000000
-                2r0111000000000000
-                2r0111100000000000
-                2r0111110000000000
-                2r0000000000000000
-                2r0000000000000000)
-        offset: -7 @ -7) withMask!

Item was removed:
- ----- Method: Cursor class>>initRightArrow (in category 'class initialization') -----
- initRightArrow 
- 
- 	RightArrowCursor  :=
- 		      (Cursor
- 	extent: 16 @ 16
- 	fromArray: #(
- 		2r100000000000
- 		2r111000000000
- 		2r1111111110000000
- 		2r111000000000
- 		2r100000000000
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0)
- 	offset: 0 @ 0).
- 	
- 	"Cursor initRightArrow"!

Item was removed:
- ----- Method: Cursor class>>initSquare (in category 'class initialization') -----
- initSquare
- 
- 	SquareCursor := 
- 		(Cursor
- 			extent: 16 @ 16
- 			fromArray: #(
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0000001111000000
- 		2r0000001111000000
- 		2r0000001111000000
- 		2r0000001111000000
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0)
- 	offset: -8 @ -8).
- 
- 	!

Item was removed:
- ----- Method: Cursor class>>initTarget (in category 'class initialization') -----
- initTarget
- 	^TargetCursor := Cursor
- 				extent: 16 @ 16
- 				fromArray:  #(1984 6448 8456 16644 17284 33026 35106 65278 35106 33026 17284 16644 8456 6448 1984 0)
- 				offset: -7 @ -7!

Item was removed:
- ----- Method: Cursor class>>initText (in category 'class initialization') -----
- initText
- 
- 	TextCursor :=   
- 		(Cursor
- 			extent: 16 @ 16
- 			fromArray: #(
- 		2r0000000000000000
- 		2r0000111011100000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000000100000000
- 		2r0000111011100000
- 		2r0000000000000000
- 		2r0)
- 			offset: -7 @ -7).
- 	
- 	!

Item was removed:
- ----- Method: Cursor class>>initTopLeft (in category 'class initialization') -----
- initTopLeft
- 	TopLeftCursor := 
- 		(Cursor extent: 16 @ 16
- 			fromArray: #(
- 		2r1111111111111111
- 		2r1111111111111111
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000
- 		2r1100000000000000)
- 			offset: 0 @ 0).
- !

Item was removed:
- ----- Method: Cursor class>>initTopRight (in category 'class initialization') -----
- initTopRight
- 	TopRightCursor := 
- 		(Cursor extent: 16 @ 16
- 			fromArray: #(
- 		2r1111111111111111
- 		2r1111111111111111
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011
- 		2r0000000000000011)
- 			offset: -16 @ 0).
- !

Item was removed:
- ----- Method: Cursor class>>initUp (in category 'class initialization') -----
- initUp
- 
- 	UpCursor := 
- 		    (Cursor
- 	extent: 16 @ 16
- 	fromArray: #(
- 		2r11000000000000
- 		2r111100000000000
- 		2r1111110000000000
- 		2r11000000000000
- 		2r11000000000000
- 		2r11000000000000
- 		2r11000000000000
- 		2r11000000000000
- 		2r11000000000000
- 		2r11000000000000
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0
- 		2r0)
- 	offset: 0 @ 0).
- !

Item was removed:
- ----- Method: Cursor class>>initWait (in category 'class initialization') -----
- initWait
- 
- 	WaitCursor := 
- 		  (Cursor
- 			extent: 16 @ 16
- 			fromArray: #(
- 		2r1111111111111100
- 		2r1000000000000100
- 		2r0100000000001000
- 		2r0010000000010000
- 		2r0001110011100000
- 		2r0000111111000000
- 		2r0000011110000000
- 		2r0000011110000000
- 		2r0000100101000000
- 		2r0001000100100000
- 		2r0010000110010000
- 		2r0100001111001000
- 		2r1000111111110100
- 		2r1111111111111100
- 		0)
- 			offset: 0 @ 0).
- !

Item was removed:
- ----- Method: Cursor class>>initWrite (in category 'class initialization') -----
- initWrite
- 
- 	WriteCursor := (Cursor
- 	extent: 16 @ 16
- 	fromArray: #(
- 		2r0000000000011000
- 		2r0000000000111100
- 		2r0000000001001000
- 		2r0000000010010000
- 		2r0000000100100000
- 		2r0000001001000100
- 		2r0000010010000100
- 		2r0000100100001100
- 		2r0001001000010000
- 		2r0010010000010000
- 		2r0111100000001000
- 		2r0101000011111000
- 		2r1110000110000000
- 		2r0111111100000000
- 		2r0
- 		2r0)
- 	offset: 0 @ 0).
- !

Item was removed:
- ----- Method: Cursor class>>initXeq (in category 'class initialization') -----
- initXeq
- 
- 	XeqCursor := 
- 		(Cursor
- 			extent: 16 @ 16
- 			fromArray: #(
- 		2r1000000000010000
- 		2r1100000000010000
- 		2r1110000000111000
- 		2r1111000111111111
- 		2r1111100011000110
- 		2r1111110001000100
- 		2r1111111001111100
- 		2r1111000001101100
- 		2r1101100011000110
- 		2r1001100010000010
- 		2r0000110000000000
- 		2r0000110000000000
- 		2r0000011000000000
- 		2r0000011000000000
- 		2r0000001100000000
- 		2r0000001100000000)
- 	offset: 0 @ 0).
- !

Item was removed:
- ----- Method: Cursor class>>initialize (in category 'class initialization') -----
- initialize
- 	"Create all the standard cursors..."
- 		self initOrigin.
- 		self initRightArrow.
- 		self initMenu.
- 		self initCorner.
- 		self initRead.
- 		self initWrite.
- 		self initWait.
- 		BlankCursor := Cursor new.
- 		self initXeq.
- 		self initSquare.
- 		self initNormalWithMask.
- 		self initCrossHair.
- 		self initMarker.
- 		self initUp.
- 		self initDown.
- 		self initMove.
- 		self initBottomLeft.
- 		self initBottomRight.
- 		self initResizeLeft.
- 		self initResizeTop.
- 		self initResizeTopLeft.
- 		self initResizeTopRight.
- 		self initText.
- 		self initTopLeft.
- 		self initTopRight.
- 		self makeCursorsWithMask.
- 
- 		"Cursor initialize"
- !

Item was removed:
- ----- Method: Cursor class>>makeCursorsWithMask (in category 'class initialization') -----
- makeCursorsWithMask
- 	"Cursor initialize;makeCursorsWithMask"
- 
- 	self classPool associationsDo: [:var |
- 		((var value isKindOf: Cursor) and:[var value hasMask not])
- 			ifTrue: [var value: var value withMask]]!

Item was removed:
- ----- Method: Cursor class>>marker (in category 'constants') -----
- marker
- 	"Answer the instance of me that is the shape of a small ball."
- 
- 	^MarkerCursor!

Item was removed:
- ----- Method: Cursor class>>menu (in category 'constants') -----
- menu 
- 	"Answer the instance of me that is the shape of a menu."
- 
- 	^MenuCursor!

Item was removed:
- ----- Method: Cursor class>>move (in category 'constants') -----
- move
- 	"Answer the instance of me that is the shape of a cross inside a square."
- 
- 	^MoveCursor!

Item was removed:
- ----- Method: Cursor class>>new (in category 'instance creation') -----
- new
- 
- 	^ self extent: 16 @ 16
- 		fromArray: (Array new: 16 withAll: 0)
- 		offset: 0 @ 0
- 
- 	"Cursor new bitEdit show"!

Item was removed:
- ----- Method: Cursor class>>normal (in category 'constants') -----
- normal
- 	"Answer the instance of me that is the shape of an arrow slanted left."
- 
- 	^NormalCursor!

Item was removed:
- ----- Method: Cursor class>>origin (in category 'constants') -----
- origin
- 	"Answer the instance of me that is the shape of the top left corner of a 
- 	rectangle."
- 
- 	^OriginCursor!

Item was removed:
- ----- Method: Cursor class>>read (in category 'constants') -----
- read
- 	"Answer the instance of me that is the shape of eyeglasses."
- 
- 	^ReadCursor!

Item was removed:
- ----- Method: Cursor class>>resizeBottom (in category 'constants') -----
- resizeBottom
- 	"Cursor resizeBottom showWhile: [Sensor waitButton]"
- 	^self resizeTop!

Item was removed:
- ----- Method: Cursor class>>resizeBottomLeft (in category 'constants') -----
- resizeBottomLeft
- 	"Cursor resizeBottomLeft showWhile: [Sensor waitButton]"
- 	^self resizeTopRight!

Item was removed:
- ----- Method: Cursor class>>resizeBottomRight (in category 'constants') -----
- resizeBottomRight
- 	"Cursor resizeBottomRight showWhile: [Sensor waitButton]"
- 	^self resizeTopLeft!

Item was removed:
- ----- Method: Cursor class>>resizeForEdge: (in category 'instance creation') -----
- resizeForEdge: aSymbol
- 	"Cursor resizeForEdge: #top"
- 	"Cursor resizeForEdge: #bottomLeft"
- 	^self perform: ('resize', aSymbol first asString asUppercase, (aSymbol copyFrom: 2 to: aSymbol size)) asSymbol.!

Item was removed:
- ----- Method: Cursor class>>resizeLeft (in category 'constants') -----
- resizeLeft
- 	"Cursor resizeLeft showWhile: [Sensor waitButton]"
- 	^ResizeLeftCursor!

Item was removed:
- ----- Method: Cursor class>>resizeRight (in category 'constants') -----
- resizeRight
- 	"Cursor resizeRight showWhile: [Sensor waitButton]"
- 	^self resizeLeft!

Item was removed:
- ----- Method: Cursor class>>resizeTop (in category 'constants') -----
- resizeTop
- 	"Cursor resizeTop showWhile: [Sensor waitButton]"
- 	^ResizeTopCursor!

Item was removed:
- ----- Method: Cursor class>>resizeTopLeft (in category 'constants') -----
- resizeTopLeft
- 	"Cursor resizeTopLeft showWhile: [Sensor waitButton]"
- 	^ ResizeTopLeftCursor!

Item was removed:
- ----- Method: Cursor class>>resizeTopRight (in category 'constants') -----
- resizeTopRight
- 	"Cursor resizeTopRight showWhile: [Sensor waitButton]"
- 	^ResizeTopRightCursor!

Item was removed:
- ----- Method: Cursor class>>rightArrow (in category 'constants') -----
- rightArrow 
- 	"Answer the instance of me that is the shape of an arrow pointing to the right."
- 
- 	^RightArrowCursor!

Item was removed:
- ----- Method: Cursor class>>square (in category 'constants') -----
- square
- 	"Answer the instance of me that is the shape of a square."
- 
- 	^SquareCursor!

Item was removed:
- ----- Method: Cursor class>>startUp (in category 'class initialization') -----
- startUp
- 	self currentCursor: self currentCursor!

Item was removed:
- ----- Method: Cursor class>>target (in category 'constants') -----
- target
- 	"Answer the instance of me that is the shape of a gunsight."
- 	"Cursor target show"
- 	^TargetCursor ifNil:[self initTarget]!

Item was removed:
- ----- Method: Cursor class>>text (in category 'constants') -----
- text
- 	^ TextCursor!

Item was removed:
- ----- Method: Cursor class>>topLeft (in category 'constants') -----
- topLeft
- 	"Cursor topLeft showWhile: [Sensor waitButton]"
- 	^ TopLeftCursor!

Item was removed:
- ----- Method: Cursor class>>topRight (in category 'constants') -----
- topRight
- 	"Cursor topRight showWhile: [Sensor waitButton]"
- 	^ TopRightCursor!

Item was removed:
- ----- Method: Cursor class>>up (in category 'constants') -----
- up
- 	"Answer the instance of me that is the shape of an arrow facing upward."
- 
- 	^UpCursor!

Item was removed:
- ----- Method: Cursor class>>useBiggerCursors (in category 'preferences') -----
- useBiggerCursors
- 
- 	<preference: 'Use bigger mouse cursors'
- 		categoryList: #(mouse Accessibility)
- 		description: 'If true, mouse cursors are scaled up'
- 		type: #Boolean>
- 	^ UseBiggerCursors ifNil: [false]!

Item was removed:
- ----- Method: Cursor class>>useBiggerCursors: (in category 'preferences') -----
- useBiggerCursors: aBool
- 
- 	UseBiggerCursors := aBool.
- 	Cursor currentCursor: Cursor currentCursor.!

Item was removed:
- ----- Method: Cursor class>>wait (in category 'constants') -----
- wait
- 	"Answer the instance of me that is the shape of an Hourglass (was in the 
- 	shape of three small balls)."
- 
- 	^WaitCursor!

Item was removed:
- ----- Method: Cursor class>>webLink (in category 'constants') -----
- webLink
- 	"Return a cursor that can be used for emphasizing web links"
- 	"Cursor webLink showWhile: [Sensor waitButton]"
- 	^WebLinkCursor ifNil:[
- 		WebLinkCursor :=  (CursorWithMask extent: 16 at 16
- 			fromArray: #(3072 4608 4608 4608 4608 5046 4681 29257 37449 37449 32769 32769 49155 16386 24582 16380 )
- 			offset: -5 at 0) setMaskForm:
- 		(Form extent: 16 at 16 
- 			fromArray: (#(3072 7680 7680 7680 7680 8118 8191 32767 65535 65535 65535 65535 65535 32766 32766 16380 )  collect: [:bits | bits bitShift: 16])
- 			offset: 0 at 0)].!

Item was removed:
- ----- Method: Cursor class>>write (in category 'constants') -----
- write
- 	"Answer the instance of me that is the shape of a pen writing."
- 
- 	^WriteCursor!

Item was removed:
- ----- Method: Cursor>>asBigCursor (in category 'converting') -----
- asBigCursor
- 	"Big cursors are 32 bits deep (ARGB premultiplied)"
- 	depth = 32
- 		ifFalse: [^self enlargedBy: 2].
- 	^self!

Item was removed:
- ----- Method: Cursor>>asCursorForm (in category 'converting') -----
- asCursorForm
- 	| form |
- 	form := StaticForm extent: self extent depth: 8.
- 	form fillShape: self fillColor: Color black at: offset negated.
- 	^ form offset: offset!

Item was removed:
- ----- Method: Cursor>>beCursor (in category 'primitives') -----
- beCursor
- 	"Primitive. Tell the interpreter to use the receiver as the current cursor 
- 	image. Fail if the receiver does not match the size expected by the 
- 	hardware. Essential. See Object documentation whatIsAPrimitive."
- 
- 	<primitive: 101>
- 	self primitiveFailed!

Item was removed:
- ----- Method: Cursor>>beCursorWithMask: (in category 'primitives') -----
- beCursorWithMask: maskForm
- 	"Primitive. Tell the interpreter to use the receiver as the current cursor image with the given mask Form. Both the receiver and the mask should have extent 16 at 16 and a depth of one. The mask and cursor bits are combined as follow:
- 			mask	cursor	effect
- 			 0		  0		transparent (underlying pixel shows through)
- 			 1		  1		opaque black
- 			 1		  0		opaque white
- 			 0		  1		invert the underlying pixel"
- "Essential. See Object documentation whatIsAPrimitive."
- 
- 	<primitive: 101>
- 	self primitiveFailed
- !

Item was removed:
- ----- Method: Cursor>>changed: (in category 'updating') -----
- changed: aParameter
- 	"overriden to reinstall the cursor if it is the active cursor, in case the appearance has changed.  (Is this used anywhere?  Do cursors really change in place these days?)"
- 	self == CurrentCursor ifTrue: [self beCursor].
- 	super changed: aParameter!

Item was removed:
- ----- Method: Cursor>>enlargedBy: (in category 'converting') -----
- enlargedBy: scale
- 	"Big cursors are 32 bits deep (ARGB premultiplied)"
- 	| big |
- 	scale = 1 ifTrue: [^self].
- 	big := CursorWithAlpha extent: self extent * scale depth: 32.
- 	(self asCursorForm magnifyBy: scale) displayOn: big.
- 	big offset: (self offset - 0.5 * scale min: 0 at 0 max: big extent negated) asIntegerPoint.
- 	big fallback: self.
- 	^big!

Item was removed:
- ----- Method: Cursor>>hasMask (in category 'testing') -----
- hasMask
- 	^false!

Item was removed:
- ----- Method: Cursor>>printOn: (in category 'printing') -----
- printOn: aStream
- 
- 	self storeOn: aStream base: 2!

Item was removed:
- ----- Method: Cursor>>scaleIconToDisplay (in category 'converting') -----
- scaleIconToDisplay
- 	"Overwritten to use the custom #enlargedBy: method to scale up the receiver."
- 	
- 	^ self enlargedBy: (RealEstateAgent scaleFactor max: 1)!

Item was removed:
- ----- Method: Cursor>>show (in category 'displaying') -----
- show
- 	"Make the hardware's mouse cursor look like the receiver"
- 
- 	Cursor currentCursor: self!

Item was removed:
- ----- Method: Cursor>>showGridded: (in category 'displaying') -----
- showGridded: gridPoint 
- 	"Make the current cursor shape be the receiver, forcing the location of the cursor to the point nearest gridPoint."
- 	
- 	Sensor cursorPoint: (Sensor cursorPoint grid: gridPoint).
- 	Cursor currentCursor: self!

Item was removed:
- ----- Method: Cursor>>showWhile: (in category 'displaying') -----
- showWhile: aBlock 
- 	"While evaluating the argument, aBlock, make the receiver be the cursor shape."
- 	"ar 2/2/2006: Only allow this if active process is ui process"
- 	| oldcursor |
- 	Processor activeProcess == Project uiProcess ifFalse:[^aBlock value].
- 	oldcursor := Cursor currentCursor.
- 	self show.
- 	^aBlock ensure: [oldcursor show]
- !

Item was removed:
- ----- Method: Cursor>>withMask (in category 'converting') -----
- withMask
- 	^CursorWithMask derivedFrom: self!

Item was removed:
- Cursor subclass: #CursorWithAlpha
- 	instanceVariableNames: 'fallback'
- 	classVariableNames: 'Constants'
- 	poolDictionaries: ''
- 	category: 'Graphics-Display Objects'!
- 
- !CursorWithAlpha commentStamp: '<historical>' prior: 0!
- A 32-bit ARGB Cursor of arbitrary extent (some platforms may limit the size). Compositing assumes alpha is pre-multiplied.!

Item was removed:
- ----- Method: CursorWithAlpha class>>biggerNormal (in category 'constants') -----
- biggerNormal
- 	"self biggerNormal showWhile:[Sensor waitButton]"
- 	"(Base64MimeConverter mimeEncode: ((FileStream readOnlyFileNamed: 'EtoysCursor.png') binary)) upToEnd"
- 
- 	^self constants at: #biggerNormal ifAbsentPut: [
- 		| form cursor |
- 		form := (PNGReadWriter on: (Base64MimeConverter mimeDecodeToBytes:
- 			'iVBORw0KGgoAAAANSUhEUgAAABsAAAArCAYAAACJrvP4AAAACXBIWXMAAAsTAAALEwEAmpwY
- 			AAAEF0lEQVRYCb2XS0hcVxjHj2/G8ZWMQQbSGO2iRhERwRALBmJNoOOqwUXtYtxOTQJxI8SN
- 			CyXJqggVEghusrAuBB8IddUWF64CvnCj+AJrsYKio6JJOPn/j+dc5s6MztyZMR/857v3PL7f
- 			/c4595w7QmiTUvrN9ZV7wGhfB3jOunpgOoYtPQQm19fXn6DsulY2PJUSi4ARvLm5+SuiE5hS
- 			mAsBXSYzv99vLuXExMRL1H2jlRKoDYbAMhS4uLj4PJUwN4K5TTqEhQPHxsZeayCzTCrDqLC0
- 			tLQryTAqjNmFA1OR4YWwaMBk5/BSWDRgMhnGhEUDJpphXDACqdDXIpEMHcHCF43TDB3Bks0w
- 			IVj4kMabYcKwcGA8c+gIlp2drRaKGc5wYKwMHcFycnIiYOHACzLkhi9SAgsHRsnQOSzaMBJk
- 			FPoejo6OvkJ5iZY67R1lZoJe5kOBKysrzxzBCgoKrCcnpKysTO7v75sjMKafmZl5gX6uNPww
- 			M4EeQXrsEAJDJc7Ozngr8vPzRVVVldjZ2RGrq6uqrLi4WPT394u2tjZxeHj4P8C7qiLkJzMz
- 			8zNvc3NzT+jR/yl9xDBmZWWpTAoLC2V9fb3c29uTXV1dtuwaGxtVRgcHBzuI0QY91vLBUw+0
- 			voOnXPyyijBEUWWVlZViampKFBUVCcyDKC8vt9pitYnp6WlmfqO7u/uOVRHjIiKzjIwM2dDQ
- 			oDIKnZCWlhZbdoFAQFUvLCz8Bcb3WrfgqWItFR/XKrEIWG1trQWam5v7Z3Bw8C2jjoyMyNLS
- 			UgvIYeYQ05A5h5HA+GE1NTVWgPn5+b/RubWiosJ/enoaZNDq6moLhjrZ19fHYjk7O/sO9/eg
- 			G1oZ8JTNbJmZJ9Wgn9GyleJQMWhPT48NhnllsTw+Pv4X7WLCuI1YX8TsuLy8/CfKmrXuwt9t
- 			b2//iXX4LJder9cCut1uOT4+zio5PDz8G9pWaqm4uLaZDaZBXLY2GO4bdnd3PzAowDZYc3Mz
- 			i+X29vY82l0K4ypR/2JOTk7e49qsIuMLUEbdXFpaes6gk5OT0uPxWECeBGtra6ySvb29v6Bt
- 			ve7DfjZTsKOjo99RyvkzEOMtGOpuBoPBbQblQsK9Ejfnzs5OFsuNjY0JlF8IQ11clodWeVgo
- 			bxh0YGDABmOmNGxzh2j3EPJqRV2VqLvUFKyjo+NHBuWqxb4nS0pKVFZmGFG+gihJw8wTerHx
- 			/kEgXng6y7a2thYxnAHAHkHfavEcoxyZBcOh+AOHixS+7HwnfT4f/6nynSQoaZh5MjWcTU1N
- 			94aGhtrr6up8qLgPcVFQd7SuwVPmIdN5njk1wmi31a8QHu3VuYVrLhDaf+dOHGgvE4Gp3RsB
- 			cnUQMx+f9P1H7c9PXyHUIcoy01HXX637AibwgHAnFRPGAAAAAElFTkSuQmCC' 
- 				readStream) readStream) nextImage.
- 	cursor := CursorWithAlpha extent: form extent depth: 32.
- 	form displayOn: cursor.
- 	cursor offset: -2 @ -1.
- 	cursor preMultiplyAlpha.
- 	cursor]!

Item was removed:
- ----- Method: CursorWithAlpha class>>constants (in category 'constants') -----
- constants
- 	^Constants ifNil: [Constants := Dictionary new]!

Item was removed:
- ----- Method: CursorWithAlpha class>>fromDisplay: (in category 'instance creation') -----
- fromDisplay: aRectangle 
- 	"Answer an ARGB cursor with bitmap initialized from the area of the 
- 	display screen defined by aRectangle."
- 
- 	^ (self extent: aRectangle extent depth: 32)
- 		offset: aRectangle extent // -2;
- 		fromDisplay: aRectangle;
- 		fixAlpha!

Item was removed:
- ----- Method: CursorWithAlpha class>>resetConstants (in category 'constants') -----
- resetConstants
- 	Constants := nil.
- !

Item was removed:
- ----- Method: CursorWithAlpha>>asCursorForm (in category 'converting') -----
- asCursorForm
- 
- 	^ self as: StaticForm!

Item was removed:
- ----- Method: CursorWithAlpha>>beCursor (in category 'primitives') -----
- beCursor
- 	<primitive: 101>
- 	self fallback beCursor!

Item was removed:
- ----- Method: CursorWithAlpha>>fallback (in category 'accessing') -----
- fallback
- 	^fallback ifNil: [NormalCursor]!

Item was removed:
- ----- Method: CursorWithAlpha>>fallback: (in category 'accessing') -----
- fallback: aCursor
- 	fallback := aCursor!

Item was removed:
- Cursor subclass: #CursorWithMask
- 	instanceVariableNames: 'maskForm'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Display Objects'!
- 
- !CursorWithMask commentStamp: '<historical>' prior: 0!
- A Cursor which additionally has a 16x16 transparency bitmap called a "mask".  See the comment of beCursorWithMask: for details on how the mask is treated.!

Item was removed:
- ----- Method: CursorWithMask class>>derivedFrom: (in category 'as yet unclassified') -----
- derivedFrom: aForm      "Cursor initNormalWithMask.  Cursor normal show"
- 	"aForm is presumably a cursor"
- 	| cursor mask ext |
- 	ext := aForm extent.
- 	cursor := self extent: ext.
- 	cursor copy: (1 at 1 extent: ext) from: 0 at 0 in: aForm rule: Form over.
- 	mask := Form extent: ext.
- 	(1 at 1) eightNeighbors do:
- 		[:p | mask copy: (p extent: ext) from: 0 at 0 in: aForm rule: Form under].
- 	cursor setMaskForm: mask.
- 	cursor offset: ((aForm offset - (1 at 1)) max: ext negated).
- 	^ cursor!

Item was removed:
- ----- Method: CursorWithMask>>asCursorForm (in category 'converting') -----
- asCursorForm
- 	| form |
- 	form := StaticForm extent: self extent depth: 8.
- 	form fillShape: maskForm fillColor: Color white.
- 	form fillShape: self fillColor: Color black at: offset negated.
- 	^ form offset: offset!

Item was removed:
- ----- Method: CursorWithMask>>beCursor (in category 'primitives') -----
- beCursor
- 	maskForm unhibernate.
- 	^ self beCursorWithMask: maskForm!

Item was removed:
- ----- Method: CursorWithMask>>hasMask (in category 'mask') -----
- hasMask
- 	^true!

Item was removed:
- ----- Method: CursorWithMask>>maskForm (in category 'mask') -----
- maskForm
- 	^ maskForm!

Item was removed:
- ----- Method: CursorWithMask>>postCopy (in category 'copying') -----
- postCopy
- 	super postCopy.
- 	maskForm := maskForm copy!

Item was removed:
- ----- Method: CursorWithMask>>setMaskForm: (in category 'mask') -----
- setMaskForm: aForm
- 	maskForm := aForm!

Item was removed:
- ----- Method: CursorWithMask>>storeOn:base: (in category 'mask') -----
- storeOn: aStream base: anInteger
- 
- 	aStream nextPut: $(.
- 	super storeOn: aStream base: anInteger.
- 	aStream nextPutAll: ' setMaskForm: '.
- 	maskForm storeOn: aStream base: anInteger.
- 	aStream nextPut: $)!

Item was removed:
- ----- Method: CursorWithMask>>withMask (in category 'mask') -----
- withMask
- 	^self!

Item was removed:
- DisplayScreen subclass: #DisplayHostWindow
- 	instanceVariableNames: 'windowProxy title windowType eventQueue'
- 	classVariableNames: ''
- 	poolDictionaries: 'EventSensorConstants'
- 	category: 'Graphics-External-Ffenestri'!
- 
- !DisplayHostWindow commentStamp: '<historical>' prior: 0!
- A subclass of DisplayScreen that uses a (platform appropriate) HostWindowProxy
- to do its displaying in a separate host OS window. This is just one example of a
- client for HostWindowProxy.
- See #test #test2 and HostWindowTests for example usage.!

Item was removed:
- ----- Method: DisplayHostWindow class>>examplePaint (in category 'examples') -----
- examplePaint
- 	"DisplayHostWindow examplePaint inspect"
- 	"Should
- 		a) open a window
- 		b) fork a process to allow painting with mouse
- 		c) survive saving and re-opening the image
- 		d) close and terminate the process when clicking close box or pressing ESC or garbage collect
- 	This relies on the Morphic main loop repeatedly fetching events from Sensor.
- 	"
- 	| win evt pen |
- 	win := DisplayHostWindow extent: 400 at 400 depth: 32.
- 	win offset: 50 at 50; open; windowTitle: 'Paint Test'.
- 	pen := nil.
- 	[
- 		[win isOpen] whileTrue: [
- 			evt := win nextEvent.
- 			"check for ESC event"
- 			((evt at: 1) = EventTypeKeyboard and: [(evt at: 4) = EventKeyChar and: [(evt at: 3) = 27]])
- 				ifTrue: [win close].
- 			"process for mouse events"
- 			(evt at: 1) = EventTypeMouse ifTrue: [
- 				(evt at: 5) > 0	"button pressed"
- 					ifTrue: [
- 						pen ifNil: [
- 							pen := Pen newOnForm: win.
- 							pen roundNib: 5; color: Color random.
- 							pen place: (evt at: 3)@(evt at: 4)].
- 						pen goto: (evt at: 3)@(evt at: 4)]
- 					ifFalse: [pen := nil]].
- 			win forceToScreen.
- 		].
- 	] forkNamed: thisContext asString.
- 	^win!

Item was removed:
- ----- Method: DisplayHostWindow>>actualScreenSize (in category 'snapshots') -----
- actualScreenSize
- "return the host window size as if it were 'the' screen"
- 	^self windowSize!

Item was removed:
- ----- Method: DisplayHostWindow>>close (in category 'initialize-release') -----
- close
- 	"close this window"
- 	windowProxy ifNil: [ ^ self error: 'cannot close never opened window' ].
- 	"We don't use 'self windowProxy close' here because if we've never setup the window why do it now only to close it immediately?"
- 	windowProxy close.
- 	windowProxy := nil!

Item was removed:
- ----- Method: DisplayHostWindow>>eventQueue (in category 'accessing') -----
- eventQueue
- 	^eventQueue ifNil: [eventQueue := SharedQueue new]
- !

Item was removed:
- ----- Method: DisplayHostWindow>>forceToScreen (in category 'basic api') -----
- forceToScreen
- 	"update the area defined by my bounds"
- 	self forceToScreen: self boundingBox!

Item was removed:
- ----- Method: DisplayHostWindow>>forceToScreen: (in category 'basic api') -----
- forceToScreen: damageRectangle 
- 	"update the area defined by damageRectangle"
- 	windowProxy ifNotNil:[ windowProxy forceToScreen: damageRectangle]!

Item was removed:
- ----- Method: DisplayHostWindow>>handleActivated (in category 'private-events') -----
- handleActivated
- 	"window made active - some platforms only - do not rely upon this"!

Item was removed:
- ----- Method: DisplayHostWindow>>handleClose (in category 'private-events') -----
- handleClose
- 	"window close icon pressed"
- 
- 	self close.
- !

Item was removed:
- ----- Method: DisplayHostWindow>>handleIconise (in category 'private-events') -----
- handleIconise
- 	"window iconised or hidden etc"!

Item was removed:
- ----- Method: DisplayHostWindow>>handleMetricChange: (in category 'private-events') -----
- handleMetricChange: aRectangle
- 	"size or position of window changed"
- 
- 	offset := aRectangle origin.
- 
- 	(width = aRectangle width and: [height = aRectangle height])
- 		ifFalse: [self setExtent: aRectangle extent depth: depth].
- !

Item was removed:
- ----- Method: DisplayHostWindow>>handlePaint: (in category 'private-events') -----
- handlePaint: aRectangle
- 	"window area needs updating. Some platforms do not need to send this, do not rely on it in image"
- 
- 	self forceToScreen: aRectangle.
- !

Item was removed:
- ----- Method: DisplayHostWindow>>isOpen (in category 'accessing') -----
- isOpen
- 	^windowProxy notNil!

Item was removed:
- ----- Method: DisplayHostWindow>>nextEvent (in category 'accessing') -----
- nextEvent
- 	^self eventQueue next!

Item was removed:
- ----- Method: DisplayHostWindow>>nextEventOrNil (in category 'accessing') -----
- nextEventOrNil
- 	^self eventQueue nextOrNil!

Item was removed:
- ----- Method: DisplayHostWindow>>open (in category 'initialize-release') -----
- open
- 	"open the host window"
- 	windowProxy ifNil: [ windowProxy := HostWindowProxy on: self ].
- 	windowType ifNil: [ windowType := #defaultWindowType ].
- 	windowProxy perform: windowType.
- 	windowProxy open.
- 	title ifNotNil: [ windowProxy windowTitle: title ].
- !

Item was removed:
- ----- Method: DisplayHostWindow>>processEvent: (in category 'private-events') -----
- processEvent: evt
- 	"evt is a raw event buffer from VM. Check for window events (close etc.). Queue events if queue exists"
- 	(evt at: 1) = EventTypeWindow
- 		ifTrue: [self processWindowEvent: evt].
- 	self queueEvent: evt.
- !

Item was removed:
- ----- Method: DisplayHostWindow>>processWindowEvent: (in category 'private-events') -----
- processWindowEvent: evt
- 	(evt at: 3) caseOf: {
- 		[WindowEventMetricChange] -> [self handleMetricChange: ((evt at: 4)@(evt at: 5) corner: (evt at: 6)@(evt at: 7)) ].
- 		[WindowEventClose] ->	 [self handleClose].
- 		[WindowEventIconise] -> [self handleIconise]. 
- 		[WindowEventActivated] -> [self handleActivated]. 
- 		[WindowEventPaint] -> [self handlePaint: ((evt at: 4)@(evt at: 5) corner: (evt at: 6)@(evt at: 7))].
- 	} otherwise: ["unknown"]
- !

Item was removed:
- ----- Method: DisplayHostWindow>>queueEvent: (in category 'private-events') -----
- queueEvent: evt
- 	"Queue the given event in the event queue (if any).
- 	Note that the event buffer must be copied since it
- 	will be reused later on."
- 	eventQueue ifNil: [^self].	"queue gets created by client"
- 	eventQueue nextPut: evt shallowCopy.
- !

Item was removed:
- ----- Method: DisplayHostWindow>>resetProxy (in category 'snapshots') -----
- resetProxy
- 	"private - for use when resuming a snapshot file only. If the windowProxy had previously been created, nil it and reopen cleanly. IF you try to use this in a 'live' system it will NOT close the windows since startup conditions assume that proxies are invalid so we don't attempt to close them - since that could cause other problems"
- 	windowProxy ifNotNil: 
- 		[ windowProxy := nil.
- 		self open ]!

Item was removed:
- ----- Method: DisplayHostWindow>>test (in category 'testing') -----
- test
- 	"((DisplayHostWindow extent: 400 at 400 depth: 16 ) translateBy: 210 at 450) test"
- 	"Should
- 		a) open a window with the upper left portion of the current Display
- 		b) find the window size
- 		f) close the window"
- 	| size |
- 	self open.
- 	Display displayOn: self.
- 	self forceToScreen: self boundingBox.
- 	size := self windowSize.
- 	self close.
- 	^ size!

Item was removed:
- ----- Method: DisplayHostWindow>>test2 (in category 'testing') -----
- test2
- 	"((DisplayHostWindow extent: 400 @ 400 depth: 16 ) translateBy: 210 @ 450) test2"
- 	"Should
- 		a) open a window with the upper left portion of the current Display
- 		b) update the middle area with part of Display
- 		c) move the window from 210 @ 450 to 300 @ 300
- 		d) change the window title
- 		e) change the window size from 400 @ 400 to 600 @ 400
- 		f) wait 4 seconds so you can see the result
- 		g) close the window via the garbage collecttor finalizing it"
- 	self open.
- 	Display displayOn: self.
- 	self forceToScreen.
- 	Display displayOn: self at: -100 @ -200.
- 	self forceToScreen: (100 @ 100 extent: 200 @ 200).
- 	self windowPosition: 300 @ 300.
- 	self windowTitle: 'YooHoo!! New title'.
- 	self windowSize: 600 @ 400.
- 	(Delay forSeconds: 4) wait.!

Item was removed:
- ----- Method: DisplayHostWindow>>windowPosition (in category 'basic api') -----
- windowPosition
- 	"return the current position of the window"
- 		
- 	^windowProxy ifNotNil:[ windowProxy windowPosition]!

Item was removed:
- ----- Method: DisplayHostWindow>>windowPosition: (in category 'basic api') -----
- windowPosition: aPoint
- 	"set the position of the window and then return the new position"
- 	^windowProxy ifNotNil:[ windowProxy windowPosition: aPoint]!

Item was removed:
- ----- Method: DisplayHostWindow>>windowSize (in category 'basic api') -----
- windowSize
- 	"return the current size of the window - not neccessarily the same as my bitmap"
- 
- 	^windowProxy ifNotNil:[ windowProxy windowSize]!

Item was removed:
- ----- Method: DisplayHostWindow>>windowSize: (in category 'basic api') -----
- windowSize: aPoint
- 	"Set the size of the window and then return the current size of the window -
- not neccessarily the same "
- 		
- 	^windowProxy ifNotNil:[ windowProxy windowSize: aPoint]!

Item was removed:
- ----- Method: DisplayHostWindow>>windowTitle: (in category 'basic api') -----
- windowTitle: titleString 
- 	"set the label in the window titlebar to titleString"
- 	title := titleString.
- 	windowProxy ifNotNil: [ windowProxy windowTitle: title ]!

Item was removed:
- DisplayObject subclass: #DisplayMedium
- 	instanceVariableNames: ''
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Display Objects'!
- 
- !DisplayMedium commentStamp: '<historical>' prior: 0!
- I am a display object which can both paint myself on a medium (displayOn: messages), and can act as a medium myself. My chief subclass is Form.!

Item was removed:
- ----- Method: DisplayMedium>>border:width: (in category 'bordering') -----
- border: aRectangle width: borderWidth 
- 	"Paint a border whose rectangular area is defined by aRectangle. The 
- 	width of the border of each side is borderWidth. Uses black for 
- 	drawing the border."
- 
- 	self border: aRectangle width: borderWidth fillColor: Color black.
- !

Item was removed:
- ----- Method: DisplayMedium>>border:width:fillColor: (in category 'bordering') -----
- border: aRectangle width: borderWidth fillColor: aHalfTone 
- 	"Paint a border whose rectangular area is defined by aRectangle. The 
- 	width of the border of each side is borderWidth. Uses aHalfTone for 
- 	drawing the border."
- 
- 	self border: aRectangle
- 		widthRectangle: 
- 			(Rectangle
- 				left: borderWidth
- 				right: borderWidth
- 				top: borderWidth
- 				bottom: borderWidth)
- 		rule: Form over
- 		fillColor: aHalfTone!

Item was removed:
- ----- Method: DisplayMedium>>border:width:rule:fillColor: (in category 'bordering') -----
- border: aRectangle width: borderWidth rule: combinationRule fillColor: aHalfTone 
- 	"Paint a border whose rectangular area is defined by aRectangle. The 
- 	width of the border of each side is borderWidth. Uses aHalfTone for 
- 	drawing the border."
- 
- 	self border: aRectangle
- 		widthRectangle: 
- 			(Rectangle
- 				left: borderWidth
- 				right: borderWidth
- 				top: borderWidth
- 				bottom: borderWidth)
- 		rule: combinationRule
- 		fillColor: aHalfTone!

Item was removed:
- ----- Method: DisplayMedium>>border:widthRectangle:rule:fillColor: (in category 'bordering') -----
- border: aRectangle widthRectangle: insets rule: combinationRule fillColor: aHalfTone
- 	"Paint a border whose rectangular area is defined by aRectangle. The 
- 	width of each edge of the border is determined by the four coordinates 
- 	of insets. Uses aHalfTone and combinationRule for drawing the border."
- 
- 	(aRectangle areasOutside: (aRectangle insetBy: insets)) do:
- 		[:edgeStrip | self fill: edgeStrip rule: combinationRule fillColor: aHalfTone]!

Item was removed:
- ----- Method: DisplayMedium>>copyBits:from:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- copyBits: sourceRect from: sourceForm at: destOrigin clippingBox: clipRect rule: rule fillColor: aForm 
- 	"Make up a BitBlt table and copy the bits."
- 
- 	self subclassResponsibility!

Item was removed:
- ----- Method: DisplayMedium>>deferUpdatesIn:while: (in category 'displaying') -----
- deferUpdatesIn: aRectangle while: aBlock
- 	"DisplayScreen overrides with something more involved..."
- 	^aBlock value!

Item was removed:
- ----- Method: DisplayMedium>>drawLine:from:to:clippingBox:rule:fillColor: (in category 'displaying') -----
- drawLine: sourceForm from: beginPoint to: endPoint clippingBox: clipRect rule: anInteger fillColor: aForm 
- 	"Draw line by copying the argument, sourceForm, starting at location 
- 	beginPoint and ending at endPoint, clipped by the rectangle, clipRect. 
- 	The rule and mask for copying are the arguments anInteger and aForm."
- 
- 	self subclassResponsibility!

Item was removed:
- ----- Method: DisplayMedium>>fill:fillColor: (in category 'coloring') -----
- fill: aRectangle fillColor: aForm 
- 	"Replace a rectangular area of the receiver with the pattern described by 
- 	aForm according to the rule over."
- 
- 	self fill: aRectangle rule: Form over fillColor: aForm!

Item was removed:
- ----- Method: DisplayMedium>>fill:rule:fillColor: (in category 'coloring') -----
- fill: aRectangle rule: anInteger fillColor: aForm 
- 	"Replace a rectangular area of the receiver with the pattern described by 
- 	aForm according to the rule anInteger."
- 
- 	self subclassResponsibility!

Item was removed:
- ----- Method: DisplayMedium>>fillBlack (in category 'coloring') -----
- fillBlack
- 	"Set all bits in the receiver to black (ones)."
- 
- 	self fill: self boundingBox fillColor: Color black!

Item was removed:
- ----- Method: DisplayMedium>>fillBlack: (in category 'coloring') -----
- fillBlack: aRectangle 
- 	"Set all bits in the receiver's area defined by aRectangle to black (ones)."
- 
- 	self fill: aRectangle rule: Form over fillColor: Color black!

Item was removed:
- ----- Method: DisplayMedium>>fillColor: (in category 'coloring') -----
- fillColor: aColor
- 	"Set all pixels in the receiver to the color.  Must be a correct color for this depth of medium.  TK 1 Jun 96"
- 
- 	self fill: self boundingBox fillColor: aColor!

Item was removed:
- ----- Method: DisplayMedium>>fillGray (in category 'coloring') -----
- fillGray
- 	"Set all bits in the receiver to gray."
- 
- 	self fill: self boundingBox fillColor: Color gray!

Item was removed:
- ----- Method: DisplayMedium>>fillGray: (in category 'coloring') -----
- fillGray: aRectangle
- 	"Set all bits in the receiver's area defined by aRectangle to the gray mask."
- 
- 	self fill: aRectangle rule: Form over fillColor: Color gray!

Item was removed:
- ----- Method: DisplayMedium>>fillShape:fillColor: (in category 'coloring') -----
- fillShape: aShapeForm fillColor: aColor
- 	"Fill a region corresponding to 1 bits in aShapeForm with aColor"
- 
- 	^ self fillShape: aShapeForm fillColor: aColor at: 0 at 0!

Item was removed:
- ----- Method: DisplayMedium>>fillShape:fillColor:at: (in category 'coloring') -----
- fillShape: aShapeForm fillColor: aColor at: location
- 	"Fill a region corresponding to 1 bits in aShapeForm with aColor"
- 
- 	((BitBlt destForm: self sourceForm: aShapeForm fillColor: aColor
- 		combinationRule: Form paint
- 		destOrigin: location + aShapeForm offset sourceOrigin: 0 at 0
- 		extent: self extent clipRect: self boundingBox)
- 		colorMap: (Bitmap with: 0 with: 16rFFFFFFFF))
- 		copyBits!

Item was removed:
- ----- Method: DisplayMedium>>fillWhite (in category 'coloring') -----
- fillWhite
- 	"Set all bits in the form to white."
- 
- 	self fill: self boundingBox fillColor: Color white.
- !

Item was removed:
- ----- Method: DisplayMedium>>fillWhite: (in category 'coloring') -----
- fillWhite: aRectangle
- 	"Set all bits in the receiver's area defined by aRectangle to white."
- 
- 	self fill: aRectangle rule: Form over fillColor: Color white.
- !

Item was removed:
- ----- Method: DisplayMedium>>fillWithColor: (in category 'coloring') -----
- fillWithColor: aColor
- 	"Fill the receiver's bounding box with the given color."
- 
- 	self fill: self boundingBox fillColor: aColor.
- !

Item was removed:
- ----- Method: DisplayMedium>>reverse (in category 'coloring') -----
- reverse
- 	"Change all the bits in the receiver that are white to black, and the ones 
- 	that are black to white."
- 
- 	self fill: self boundingBox rule: Form reverse fillColor: (Color quickHighLight: self depth)!

Item was removed:
- ----- Method: DisplayMedium>>reverse: (in category 'coloring') -----
- reverse: aRectangle
- 	"Change all the bits in the receiver's area that intersects with aRectangle 
- 	that are white to black, and the ones that are black to white."
- 
- 	self fill: aRectangle rule: Form reverse fillColor: (Color quickHighLight: self depth)!

Item was removed:
- ----- Method: DisplayMedium>>reverse:fillColor: (in category 'coloring') -----
- reverse: aRectangle fillColor: aMask	
- 	"Change all the bits in the receiver's area that intersects with aRectangle 
- 	according to the mask. Black does not necessarily turn to white, rather it 
- 	changes with respect to the rule and the bit in a corresponding mask 
- 	location. Bound to give a surprise."
- 
- 	self fill: aRectangle rule: Form reverse fillColor: aMask!

Item was removed:
- Object subclass: #DisplayObject
- 	instanceVariableNames: ''
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Display Objects'!
- 
- !DisplayObject commentStamp: '<historical>' prior: 0!
- The abstract protocol for most display primitives that are used by Views for presenting information on the screen.!

Item was removed:
- ----- Method: DisplayObject class>>collectionFromFileNamed: (in category 'fileIn/Out') -----
- collectionFromFileNamed: fileName 
- 	"Answer a collection of Forms read from the external file 
- 	named fileName. The file format is: fileCode, {depth, extent, offset, bits}."
- 
- 	| formList f fileCode |
- 	formList := OrderedCollection new.
- 	f := (FileStream readOnlyFileNamed: fileName) binary.
- 	fileCode := f next.
- 	fileCode = 1
- 		ifTrue: [
- 			[f atEnd] whileFalse: [formList add: (self new readFromOldFormat: f)]]
- 		ifFalse: [
- 			fileCode = 2 ifFalse: [self error: 'unknown Form file format'. ^ formList].
- 			[f atEnd] whileFalse: [formList add: (self new readFrom: f)]].
- 	f close.
- 	^ formList
- !

Item was removed:
- ----- Method: DisplayObject class>>writeCollection:onFileNamed: (in category 'fileIn/Out') -----
- writeCollection: coll onFileNamed: fileName 
- 	"Saves a collection of Forms on the file fileName in the format:
- 		fileCode, {depth, extent, offset, bits}."
- 	| file |
- 	file := FileStream newFileNamed: fileName.
- 	file binary.
- 	file nextPut: 2.  "file code = 2"
- 	coll do: [:f | f writeOn: file].
- 	file close
- "
-  | f c | c := OrderedCollection new.
- [(f := Form fromUser) boundingBox area>25] whileTrue: [c add: f].
- Form writeCollection: c onFileNamed: 'test.forms'.
- c := Form collectionFromFileNamed: 'test.forms'.
- 1 to: c size do: [:i | (c at: i) displayAt: 0@(i*100)].
- "!

Item was removed:
- ----- Method: DisplayObject>>align:with: (in category 'transforming') -----
- align: alignmentPoint with: relativePoint 
- 	"Translate the receiver's offset such that alignmentPoint aligns with 
- 	relativePoint."
- 
- 	self offset: (self offset translateBy: relativePoint - alignmentPoint)!

Item was removed:
- ----- Method: DisplayObject>>boundingBox (in category 'display box access') -----
- boundingBox
- 	"Answer the rectangular area that represents the boundaries of the 
- 	receiver's space of information."
- 
- 	^self computeBoundingBox!

Item was removed:
- ----- Method: DisplayObject>>center (in category 'display box access') -----
- center
- 
- 	^ self boundingBox center!

Item was removed:
- ----- Method: DisplayObject>>computeBoundingBox (in category 'display box access') -----
- computeBoundingBox
- 	"Answer the rectangular area that represents the boundaries of the 
- 	receiver's area for displaying information. This is the primitive for 
- 	computing the area if it is not already known."
- 
- 	self subclassResponsibility!

Item was removed:
- ----- Method: DisplayObject>>display (in category 'displaying-Display') -----
- display 
- 	"Display the receiver on the Display at location 0,0."
- 
- 	self displayOn: Display!

Item was removed:
- ----- Method: DisplayObject>>displayAt: (in category 'displaying-generic') -----
- displayAt: aDisplayPoint 
- 	"Display the receiver located at aDisplayPoint with default settings for 
- 	the displayMedium, rule and halftone."
- 
- 	self displayOn: Display
- 		at: aDisplayPoint
- 		clippingBox: Display boundingBox
- 		rule: Form over
- 		fillColor: nil!

Item was removed:
- ----- Method: DisplayObject>>displayOn: (in category 'displaying-generic') -----
- displayOn: aDisplayMedium
- 	"Simple default display in order to see the receiver in the upper left 
- 	corner of screen."
- 
- 	self displayOn: aDisplayMedium at: 0 @ 0!

Item was removed:
- ----- Method: DisplayObject>>displayOn:at: (in category 'displaying-generic') -----
- displayOn: aDisplayMedium at: aDisplayPoint 
- 	"Display the receiver located at aDisplayPoint with default settings for 
- 	rule and halftone."
- 
- 	self displayOn: aDisplayMedium
- 		at: aDisplayPoint
- 		clippingBox: aDisplayMedium boundingBox
- 		rule: Form over
- 		fillColor: nil!

Item was removed:
- ----- Method: DisplayObject>>displayOn:at:clippingBox: (in category 'displaying-generic') -----
- displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle 
- 	"Display the receiver located at aDisplayPoint with default settings for 
- 	rule and halftone. Information to be displayed must be confined to the 
- 	area that intersects with clipRectangle."
- 
- 	self displayOn: aDisplayMedium
- 		at: aDisplayPoint
- 		clippingBox: clipRectangle
- 		rule: Form over
- 		fillColor: nil!

Item was removed:
- ----- Method: DisplayObject>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying-generic') -----
- displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
- 	"This is the basic display primitive for graphic display objects. Display 
- 	the receiver located at aDisplayPoint with rule, ruleInteger, and mask, 
- 	aForm. Information to be displayed must be confined to the area that 
- 	intersects with clipRectangle."
- 
- 	self subclassResponsibility!

Item was removed:
- ----- Method: DisplayObject>>displayOn:at:rule: (in category 'displaying-generic') -----
- displayOn: aDisplayMedium at: aDisplayPoint rule: ruleInteger
- 	"Display the receiver located at aPoint with default setting for the 
- 	halftone and clippingBox."
- 
- 	self displayOn: aDisplayMedium
- 		at: aDisplayPoint
- 		clippingBox: aDisplayMedium boundingBox
- 		rule: ruleInteger
- 		fillColor: nil!

Item was removed:
- ----- Method: DisplayObject>>displayOn:transformation:clippingBox: (in category 'displaying-generic') -----
- displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle 
- 	"Display primitive for the receiver where a DisplayTransformation is 
- 	provided as an argument. Alignment is defaulted to the receiver's 
- 	rectangle. Information to be displayed must be confined to the area that 
- 	intersects with clipRectangle."
- 
- 	self displayOn: aDisplayMedium
- 		transformation: displayTransformation
- 		clippingBox: clipRectangle
- 		align: self relativeRectangle center
- 		with: self relativeRectangle center
- 		rule: Form over
- 		fillColor: nil!

Item was removed:
- ----- Method: DisplayObject>>displayOn:transformation:clippingBox:align:with: (in category 'displaying-generic') -----
- displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint 
- 	"Display primitive where a DisplayTransformation is provided as an 
- 	argument, rule is over and mask is Form black. Information to be 
- 	displayed must be confined to the area that intersects with clipRectangle."
- 
- 	self displayOn: aDisplayMedium
- 		transformation: displayTransformation
- 		clippingBox: clipRectangle
- 		align: alignmentPoint
- 		with: relativePoint
- 		rule: Form over
- 		fillColor: nil!

Item was removed:
- ----- Method: DisplayObject>>displayOn:transformation:clippingBox:align:with:rule:fillColor: (in category 'displaying-generic') -----
- displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm 
- 	"Display the receiver where a DisplayTransformation is provided as an 
- 	argument, rule is ruleInteger and mask is aForm. Translate by 
- 	relativePoint-alignmentPoint. Information to be displayed must be 
- 	confined to the area that intersects with clipRectangle."
- 
- 	| absolutePoint |
- 	absolutePoint := displayTransformation applyTo: relativePoint.
- 	self displayOn: aDisplayMedium
- 		at: (absolutePoint - alignmentPoint) 
- 		clippingBox: clipRectangle 
- 		rule: ruleInteger 
- 		fillColor: aForm !

Item was removed:
- ----- Method: DisplayObject>>displayOn:transformation:clippingBox:fixedPoint: (in category 'displaying-generic') -----
- displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle fixedPoint: aPoint 
- 	"Display the receiver where a DisplayTransformation is provided as an 
- 	argument, rule is over and mask is Form black. No translation. 
- 	Information to be displayed must be confined to the area that intersects 
- 	with clipRectangle."
- 
- 	self displayOn: aDisplayMedium
- 		transformation: displayTransformation
- 		clippingBox: clipRectangle
- 		align: aPoint
- 		with: aPoint
- 		rule: Form over
- 		fillColor: nil!

Item was removed:
- ----- Method: DisplayObject>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying-generic') -----
- displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle rule: ruleInteger fillColor: aForm 
- 	"Display the receiver where a DisplayTransformation is provided as an 
- 	argument, rule is ruleInteger and mask is aForm. No translation. 
- 	Information to be displayed must be confined to the area that intersects 
- 	with clipRectangle."
- 
- 	self displayOn: aDisplayMedium
- 		transformation: displayTransformation
- 		clippingBox: clipRectangle
- 		align: self relativeRectangle origin
- 		with: self relativeRectangle origin
- 		rule: ruleInteger
- 		fillColor: aForm!

Item was removed:
- ----- Method: DisplayObject>>displayOnPort: (in category 'displaying-generic') -----
- displayOnPort: aPort 
- 	self displayOnPort: aPort at: 0 at 0!

Item was removed:
- ----- Method: DisplayObject>>displayOnPort:at:rule: (in category 'displaying-generic') -----
- displayOnPort: port at: location rule: rule
- 
- 	port copyForm: self to: location rule: rule.
- !

Item was removed:
- ----- Method: DisplayObject>>extent (in category 'accessing') -----
- extent
- 	"Answer the point that represents the width and height of the receiver's 
- 	bounding box."
- 
- 	^self boundingBox extent!

Item was removed:
- ----- Method: DisplayObject>>follow:while: (in category 'displaying-Display') -----
- follow: locationBlock while: durationBlock
-    "Move an image around on the Display. Restore the background
-    continuously without causing flashing. The argument, locationBlock,
-    supplies each new location, and the argument, durationBlock, supplies
-    true to continue, and then false to stop.
-    8/20/96 sw: call follow:while:bitsBehind: to do the real work.  Note that th
- method
-    now returns the final bits behind as method value."
-  
-    | bitsBehind loc |
-    bitsBehind := Form fromDisplay: ((loc := locationBlock value) extent: self extent).
-    ^ self follow: locationBlock while: durationBlock bitsBehind: bitsBehind startingLoc: loc!

Item was removed:
- ----- Method: DisplayObject>>follow:while:bitsBehind:startingLoc: (in category 'displaying-Display') -----
- follow: locationBlock while: durationBlock bitsBehind: initialBitsBehind startingLoc: loc
-    "Move an image around on the Display. Restore the background continuously without causing flashing. The argument, locationBlock, supplies each new location, and the argument, durationBlock, supplies true to continue or false to stop. This variant takes the bitsBehind as an input argument, and returns the final saved saved bits as method value."
- 
-    | location rect1 save1 save1Blt buffer bufferBlt newLoc rect2 bothRects |
-    location := loc.
-    rect1 := location extent: self extent.
-    save1 := initialBitsBehind.
-    save1Blt := BitBlt toForm: save1.
-    buffer := Form extent: self extent*2 depth: Display depth.  "Holds overlapping region"
-    bufferBlt := BitBlt toForm: buffer.
-    Display deferUpdates: true.
-    self displayOn: Display at: location rule: Form paint.
-    Display deferUpdates: false; forceToScreen: (location extent: self extent).
-    [durationBlock value] whileTrue: [
- 		newLoc := locationBlock value.
- 		newLoc ~= location ifTrue: [
- 			rect2 := newLoc extent: self extent.
- 			bothRects := rect1 merge: rect2.
- 			(rect1 intersects: rect2)
- 				ifTrue: [  "when overlap, buffer background for both rectangles"
- 					bufferBlt copyFrom: bothRects in: Display to: 0 at 0.
- 					bufferBlt copyFrom: save1 boundingBox in: save1 to: rect1 origin - bothRects origin.
- 					"now buffer is clean background; get new bits for save1"
- 					save1Blt copy: (0 at 0 extent: self extent) from: rect2 origin - bothRects origin in: buffer.
- 					self displayOnPort: bufferBlt at: rect2 origin - bothRects origin rule: Form paint.
- 					Display deferUpdates: true.
- 					Display copy: bothRects from: 0 at 0 in: buffer rule: Form over.
- 					Display deferUpdates: false; forceToScreen: bothRects]
- 				ifFalse: [  "when no overlap, do the simple thing (both rects might be too big)"
- 					Display deferUpdates: true.
- 					Display copy: (location extent: save1 extent) from: 0 at 0 in: save1 rule: Form over.
- 					save1Blt copyFrom: rect2 in: Display to: 0 at 0.
- 					self displayOn: Display at: newLoc rule: Form paint.
- 					Display deferUpdates: false; 
- 						forceToScreen: (location extent: save1 extent); 
- 						forceToScreen: (newLoc extent: self extent)].
- 			location := newLoc.
- 			rect1 := rect2]].
- 
- 	^ save1 displayOn: Display at: location
- !

Item was removed:
- ----- Method: DisplayObject>>followCursor (in category 'displaying-generic') -----
- followCursor
- 	"Just show the Form following the mouse. 6/21/96 tk"
- 	Cursor blank showWhile:
- 		[self follow: [Sensor cursorPoint] while: [Sensor noButtonPressed]]
- !

Item was removed:
- ----- Method: DisplayObject>>height (in category 'accessing') -----
- height
- 	"Answer the number that represents the height of the receiver's 
- 	bounding box."
- 
- 	^self boundingBox height!

Item was removed:
- ----- Method: DisplayObject>>initialExtent (in category 'display box access') -----
- initialExtent
- 	"Included here for when a FormView is being opened
- 	as a window.  (4 at 4) covers border widths."
- 
- 	^ self extent + (4 at 4) !

Item was removed:
- ----- Method: DisplayObject>>isTransparent (in category 'testing') -----
- isTransparent
- 	^ false!

Item was removed:
- ----- Method: DisplayObject>>offset (in category 'accessing') -----
- offset
- 	"Answer the amount by which the receiver should be offset when it is 
- 	displayed or its position is tested."
- 
- 	self subclassResponsibility!

Item was removed:
- ----- Method: DisplayObject>>offset: (in category 'accessing') -----
- offset: aPoint 
- 	"Set the amount by which the receiver's position is offset."
- 
- 	^self!

Item was removed:
- ----- Method: DisplayObject>>relativeRectangle (in category 'accessing') -----
- relativeRectangle
- 	"Answer a Rectangle whose top left corner is the receiver's offset position 
- 	and whose width and height are the same as the receiver."
- 
- 	^Rectangle origin: self offset extent: self extent!

Item was removed:
- ----- Method: DisplayObject>>rounded (in category 'truncation and round off') -----
- rounded
- 	"Convert the offset of the receiver to integer coordinates."
- 
- 	self offset: self offset rounded!

Item was removed:
- ----- Method: DisplayObject>>scaleBy: (in category 'transforming') -----
- scaleBy: aPoint 
- 	"Scale the receiver's offset by aPoint."
- 
- 	self offset: (self offset scaleBy: aPoint)!

Item was removed:
- ----- Method: DisplayObject>>slideFrom:to:nSteps: (in category 'displaying-Display') -----
- slideFrom: startPoint to: stopPoint nSteps: nSteps 
- 	"does not display at the first point, but does at the last"
- 	| i p delta |
- 	i := 0.
- 	p := startPoint.
- 	delta := stopPoint - startPoint // nSteps.
- 	^ self
- 		follow: [(p := p + delta) truncated]
- 		while: [(i := i + 1) < nSteps]!

Item was removed:
- ----- Method: DisplayObject>>slideFrom:to:nSteps:delay: (in category 'displaying-Display') -----
- slideFrom: startPoint to: stopPoint nSteps: nSteps delay: milliSecs
- 	"Slide this object across the display over the given number of steps, pausing for the given number of milliseconds after each step."
- 	"Note: Does not display at the first point, but does at the last."
- 
- 	| i p delta |
- 	i := 0.
- 	p := startPoint.
- 	delta := (stopPoint - startPoint) / nSteps asFloat.
- 	^ self
- 		follow: [(p := p + delta) truncated]
- 		while: [
- 			(Delay forMilliseconds: milliSecs) wait.
- 			(i := i + 1) < nSteps]
- !

Item was removed:
- ----- Method: DisplayObject>>slideFrom:to:nSteps:delay:andStay: (in category 'displaying-Display') -----
- slideFrom: startPoint to: stopPoint nSteps: nSteps delay: milliSecs andStay: stayAtEnd
- 	"Does not display at the first point, but does at the last.
- 	Moreover, if stayAtEnd is true, it leaves the dragged image at the stopPoint"
- 	| i |
- 	i := 0.
- 	^ self follow: [startPoint + ((stopPoint-startPoint) * i // nSteps)]
- 		while: [ | done |
- 				milliSecs ifNotNil: [(Delay forMilliseconds: milliSecs) wait].
- 				((done := (i := i+1) > nSteps) and: [stayAtEnd])
- 					ifTrue: [^ self "Return without clearing the image"].
- 				done not]!

Item was removed:
- ----- Method: DisplayObject>>slideWithFirstFrom:to:nSteps:delay: (in category 'displaying-Display') -----
- slideWithFirstFrom: startPoint to: stopPoint nSteps: nSteps delay: milliSecs 
- 	"Slide this object across the display over the given number of steps, 
- 	pausing for the given number of milliseconds after each step."
- 	"Note: Does display at the first point and at the last."
- 	| i p delta |
- 	i := 0.
- 	delta := stopPoint - startPoint / nSteps asFloat.
- 	p := startPoint - delta.
- 	^ self follow: [(p := p + delta) truncated]
- 		while: 
- 			[(Delay forMilliseconds: milliSecs) wait.
- 			(i := i + 1) <= nSteps]!

Item was removed:
- ----- Method: DisplayObject>>translateBy: (in category 'transforming') -----
- translateBy: aPoint 
- 	"Translate the receiver's offset."
- 
- 	self offset: (self offset translateBy: aPoint)!

Item was removed:
- ----- Method: DisplayObject>>width (in category 'accessing') -----
- width
- 	"Answer the number that represents the width of the receiver's bounding 
- 	box."
- 
- 	^self boundingBox width!

Item was removed:
- ----- Method: DisplayObject>>writeOnFileNamed: (in category 'fileIn/Out') -----
- writeOnFileNamed: fileName 
- 	"Saves the receiver on the file fileName in the format:
- 		fileCode, depth, extent, offset, bits."
- 	| file |
- 	file := FileStream newFileNamed: fileName.
- 	file binary.
- 	file nextPut: 2.  "file code = 2"
- 	self writeOn: file.
- 	file close
- "
-  | f |
- [(f := Form fromUser) boundingBox area>25] whileTrue:
- 	[f writeOnFileNamed: 'test.form'.
- 	(Form newFromFileNamed: 'test.form') display].
- "!

Item was removed:
- ----- Method: DisplayObject>>writeUncompressedOnFileNamed: (in category 'fileIn/Out') -----
- writeUncompressedOnFileNamed: fileName 
- 	"Saves the receiver on the file fileName in the format:
- 		fileCode, depth, extent, offset, bits."
- 	| file |
- 	file := FileStream newFileNamed: fileName.
- 	file binary.
- 	file nextPut: 2.  "file code = 2"
- 	self writeUncompressedOn: file.
- 	file close
- "
-  | f |
- [(f := Form fromUser) boundingBox area>25] whileTrue:
- 	[f writeUncompressedOnFileNamed: 'test.form'.
- 	(Form fromBinaryStream: (FileStream oldFileNamed: 'test.form')) display].
- "!

Item was removed:
- CharacterScanner subclass: #DisplayScanner
- 	instanceVariableNames: 'lineY foregroundColor backgroundColor defaultTextColor paragraphColor morphicOffset ignoreColorChanges lastDisplayableIndex stopConditionsMustBeReset'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Text'!
- 
- !DisplayScanner commentStamp: 'pre 10/8/2019 16:16' prior: 0!
- A DisplayScanner is an abstract class for displaying characters.
- It is splitting text into elementary chunks of displayable String/Font pairs (see scanning protocol).
- Subclasses responsibility is to handle the effective rendering of these chunks on various backends.
- 
- Instance Variables
- 	backgroundColor:		<Color>
- 	defaultTextColor:		<Color>
- 	foregroundColor:		<Color>
- 	ignoreColorChanges:		<Boolean>
- 	lastDisplayableIndex:		<Integer>
- 	lineY:		<Number>
- 	morphicOffset:		<Point>
- 	stopConditionsMustBeReset:		<Boolean>
- 
- backgroundColor
- 	- the background color for displaying next chunk of text.
- 	Note that this can be set to Color transparent, in which case no background is displayed.
- 
- defaultTextColor
- 	- the default foreground color for displaying text in absence of other text attributes specification 
- 
- foregroundColor
- 	- the foreground color for displaying next chunk of text
- 
- ignoreColorChanges
- 	- indicates that any change of color specified in text attributes shall be ignored.
- 	This is used for displaying text in a shadow mode, when dragging text for example.
- 
- lastDisplayableIndex
- 	- the index of last character to be displayed.
- 	A different index than lastIndex is required in order to avoid display of control characters.
- 	This variable must be updated by the stop condition at each inner scan loop.
- 
- lineY
- 	- the distance between destination form top and current line top
- 
- morphicOffset
- 	- an offset for displaying the lines passed from morphic to the scanner (via NewParagraph>>#displayOn:using:at:)
- 
- stopConditionsMustBeReset
- 	- indicates that it's necessary to call setStopConditions in next scan loop.
- 
- Notes:
- In order to correctly set the lastDisplayableIndex, the display scanner performs the stopCondition BEFORE displaying the string being scanned.
- This explains why the stopCondition must not reset the font immediately, but differ this reset AFTER the display, thanks to stopConditionsMustBeReset.
- !

Item was removed:
- ----- Method: DisplayScanner class>>defaultFont (in category 'queries') -----
- defaultFont
- 	^ TextStyle defaultFont!

Item was removed:
- ----- Method: DisplayScanner class>>new (in category 'instance creation') -----
- new
- 	"Use default concrete class"
- 	^(self == DisplayScanner
- 		ifTrue: [BitBltDisplayScanner]
- 		ifFalse: [self]) basicNew initialize!

Item was removed:
- ----- Method: DisplayScanner>>cr (in category 'stop conditions') -----
- cr
- 	"When a carriage return is encountered, simply increment the pointer 
- 	into the paragraph."
- 
- 	pendingKernX := 0.
- 	lastDisplayableIndex := lastIndex - 1.
- 	(lastIndex < text size and: [(text at: lastIndex) = CR and: [(text at: lastIndex+1) = Character lf]])
- 		ifTrue: [lastIndex := lastIndex + 2]
- 		ifFalse: [lastIndex := lastIndex + 1].
- 	^false!

Item was removed:
- ----- Method: DisplayScanner>>crossedX (in category 'stop conditions') -----
- crossedX
- 	"This condition will sometimes be reached 'legally' during display, when, 
- 	for instance the space that caused the line to wrap actually extends over 
- 	the right boundary. This character is allowed to display, even though it 
- 	is technically outside or straddling the clipping rectangle since it is in 
- 	the normal case not visible and is in any case appropriately clipped by 
- 	the scanner."
- 
- 	self advanceIfFirstCharOfLine.
- 	lastDisplayableIndex := lastIndex - 1.
- 	^ true !

Item was removed:
- ----- Method: DisplayScanner>>defaultTextColor (in category 'private') -----
- defaultTextColor
- 	defaultTextColor ifNil:[defaultTextColor := Color black].
- 	^defaultTextColor!

Item was removed:
- ----- Method: DisplayScanner>>defaultTextColor: (in category 'private') -----
- defaultTextColor: color
- 	defaultTextColor := color.!

Item was removed:
- ----- Method: DisplayScanner>>displayEmbeddedForm:at: (in category 'displaying') -----
- displayEmbeddedForm: aForm at: aPoint
- 	self subclassResponsibility!

Item was removed:
- ----- Method: DisplayScanner>>displayLine:offset:leftInRun: (in category 'scanning') -----
- displayLine: textLine offset: offset leftInRun: leftInRun
- 	"The call on the primitive (scanCharactersFrom:to:in:rightX:) will be interrupted according to an array of stop conditions passed to the scanner at which time the code to handle the stop condition is run and the call on the primitive continued until a stop condition returns true (which means the line has terminated).  leftInRun is the # of characters left to scan in the current run; when 0, it is time to call setStopConditions."
- 	| stopCondition nowLeftInRun startIndex string lastPos lineHeight stop |
- 	line := textLine.
- 	morphicOffset := offset.
- 	lineY := line top + offset y.
- 	lineHeight := line lineHeight.
- 	rightMargin := line rightMargin + offset x.
- 	lastIndex := line first.
- 	leftInRun <= 0 ifTrue: [self setStopConditions].
- 	leftMargin := (line leftMarginForAlignment: alignment) + offset x.
- 	destX := leftMargin.
- 	self fillTextBackground.
- 	lastDisplayableIndex := lastIndex := line first.
- 	leftInRun <= 0
- 		ifTrue: [nowLeftInRun := text runLengthFor: lastIndex]
- 		ifFalse: [nowLeftInRun := leftInRun].
- 	destY := lineY + line baseline - font ascent.
- 	runStopIndex := lastIndex + (nowLeftInRun - 1) min: line last.
- 	spaceCount := 0.
- 	string := text string.
- 	[
- 		"reset the stopping conditions of this displaying loop, and also the font."
- 		stopConditionsMustBeReset
- 			ifTrue:[self setStopConditions].
- 		
- 		"remember where this portion of the line starts"
- 		startIndex := lastIndex.
- 		lastPos := destX at destY.
- 		
- 		"find the end of this portion of the line"
- 		stopCondition := self scanCharactersFrom: lastIndex to: runStopIndex
- 						in: string rightX: rightMargin.
- 		"handle the stop condition - this will also set lastDisplayableIndex"
- 		stop := self perform: stopCondition.
- 		
- 		"display that portion of the line"
- 		lastDisplayableIndex >= startIndex ifTrue:[
- 			self displayString: string
- 				from: startIndex 
- 				to: lastDisplayableIndex 
- 				at: lastPos].
- 		
- 		"if the stop condition were true, stop the loop"
- 		stop
- 	] whileFalse.
- 	^ runStopIndex - lastIndex   "Number of characters remaining in the current run"!

Item was removed:
- ----- Method: DisplayScanner>>displayString:from:to:at: (in category 'displaying') -----
- displayString: string from: startIndex  to: stopIndex at: aPoint
- 	self subclassResponsibility!

Item was removed:
- ----- Method: DisplayScanner>>embeddedObject (in category 'stop conditions') -----
- embeddedObject
- 
- 	"We have to set the last displayed index to a value smaller than last index
- 	in order to prevent the text anchor placeholder character to be printed. For
- 	details see end of DisplayScanner>>#displayLine:offset:leftInRun:"
- 	lastDisplayableIndex := lastIndex - 1.
- 	^ super embeddedObject!

Item was removed:
- ----- Method: DisplayScanner>>embeddedObject:shouldBePlacedInDocumentGiven: (in category 'private') -----
- embeddedObject: anchoredMorphOrForm shouldBePlacedInDocumentGiven: textAnchorProperties
- 	
- 	^ textAnchorProperties hasPositionInDocument 
- 		and: [textAnchorProperties anchorLayout == #document] 
- 		and: [anchoredMorphOrForm isMorph]!

Item was removed:
- ----- Method: DisplayScanner>>endOfRun (in category 'stop conditions') -----
- endOfRun
- 	"The end of a run in the display case either means that there is actually 
- 	a change in the style (run code) to be associated with the string or the 
- 	end of this line has been reached."
- 	| runLength |
- 	lastDisplayableIndex := lastIndex.
- 	lastIndex = line last ifTrue: [^true].
- 	runLength := text runLengthFor: (lastIndex := lastIndex + 1).
- 	runStopIndex := lastIndex + (runLength - 1) min: line last.
- 	"differ reset of stopConditions and font AFTER the dispaly of last scanned string"
- 	stopConditionsMustBeReset := true.
- 	^ false!

Item was removed:
- ----- Method: DisplayScanner>>fillTextBackground (in category 'displaying') -----
- fillTextBackground
- 	self subclassResponsibility!

Item was removed:
- ----- Method: DisplayScanner>>initialize (in category 'displaying') -----
- initialize
- 	super initialize.
- 	ignoreColorChanges := false.!

Item was removed:
- ----- Method: DisplayScanner>>paddedSpace (in category 'stop conditions') -----
- paddedSpace
- 	"Each space is a stop condition when the alignment is right justified. 
- 	Padding must be added to the base width of the space according to 
- 	which space in the line this space is and according to the amount of 
- 	space that remained at the end of the line when it was composed."
- 
- 	lastDisplayableIndex := lastIndex - 1.
- 	spaceCount := spaceCount + 1.
- 	destX := destX + spaceWidth + kern + (line justifiedPadFor: spaceCount font: font).
- 	lastIndex := lastIndex + 1.
- 	pendingKernX := 0.
- 	^ false!

Item was removed:
- ----- Method: DisplayScanner>>placeEmbeddedObject:inlineGiven: (in category 'private') -----
- placeEmbeddedObject: anchoredMorphOrForm inlineGiven: textAnchorProperties
- 	
- 	| alignedPositionY position |
- 	alignedPositionY := self verticallyAlignEmbeddedObject: anchoredMorphOrForm given: textAnchorProperties.
- 	position := (destX + textAnchorProperties padding left) @ alignedPositionY.
- 	anchoredMorphOrForm isMorph
- 		ifTrue: [
- 			"We have to remove the offset passed to us from morphic as this embedded morph
- 			will only be rendered later on. We now only set the position. --pre"
- 			self flag: #fishy. "Setting the position of the morph during drawing can be problematic --pre"
- 			anchoredMorphOrForm setPositionFromLayout: position - morphicOffset]
- 		ifFalse: ["we assume this to be a form"
- 			self displayEmbeddedForm: anchoredMorphOrForm at: position].!

Item was removed:
- ----- Method: DisplayScanner>>placeEmbeddedObjectFrom: (in category 'private') -----
- placeEmbeddedObjectFrom: aTextAttribute
- 	
- 	| width anchoredMorphOrForm textAnchorProperties |
- 	anchoredMorphOrForm := aTextAttribute anchoredMorph.
- 	textAnchorProperties := self textAnchorPropertiesFor: anchoredMorphOrForm.
- 	
- 	(self embeddedObject: anchoredMorphOrForm shouldBePlacedInDocumentGiven: textAnchorProperties) 
- 			ifTrue: [^ self placeEmbeddedObjectInDocument: anchoredMorphOrForm].
- 	self placeEmbeddedObject: anchoredMorphOrForm inlineGiven: textAnchorProperties.
- 	
- 	width := textAnchorProperties consumesHorizontalSpace 
- 				ifTrue: [anchoredMorphOrForm width + textAnchorProperties horizontalPadding]
- 				ifFalse: [0].
- 	destX := destX + width + kern.
- 	
- 	^ true!

Item was removed:
- ----- Method: DisplayScanner>>placeEmbeddedObjectInDocument: (in category 'private') -----
- placeEmbeddedObjectInDocument: anchoredMorphOrForm
- 	
- 	anchoredMorphOrForm position: 
- 			anchoredMorphOrForm textAnchorProperties positionInDocument +
- 			(anchoredMorphOrForm owner textBounds origin x @ (lineY - morphicOffset y)).
- 	^ true!

Item was removed:
- ----- Method: DisplayScanner>>setFont (in category 'private') -----
- setFont 
- 	foregroundColor := self defaultTextColor.
- 	super setFont.  "Sets font and emphasis bits, and maybe foregroundColor"
- 	text ifNotNil:[destY := lineY + line baseline - font ascent]!

Item was removed:
- ----- Method: DisplayScanner>>setStopConditions (in category 'private') -----
- setStopConditions
- 	super setStopConditions.
- 	stopConditionsMustBeReset := false!

Item was removed:
- ----- Method: DisplayScanner>>tab (in category 'stop conditions') -----
- tab
- 	lastDisplayableIndex := lastIndex - 1.
- 	destX := self plainTab.
- 	lastIndex := lastIndex + 1.
- 	^ false!

Item was removed:
- ----- Method: DisplayScanner>>text:textStyle:foreground:background:fillBlt:ignoreColorChanges: (in category 'private') -----
- text: t textStyle: ts foreground: foreColor background: backColor fillBlt: blt ignoreColorChanges: shadowMode
- 	text := t.
- 	textStyle := ts. 
- 	foregroundColor := defaultTextColor := foreColor.
- 	backgroundColor := backColor.
- 	ignoreColorChanges := shadowMode!

Item was removed:
- ----- Method: DisplayScanner>>textColor: (in category 'text attributes') -----
- textColor: textColor
- 	ignoreColorChanges ifTrue: [^ self].
- 	foregroundColor := textColor!

Item was removed:
- ----- Method: DisplayScanner>>verticallyAlignEmbeddedObject:given: (in category 'private') -----
- verticallyAlignEmbeddedObject: aMorphOrForm given: textAnchorProperties
- 
- 	| alignedPositionY positionInLine morphPosition padding morphBaselineGetter |
- 	alignedPositionY := lineY + line baseline.
- 	positionInLine := textAnchorProperties verticalAlignmentLine.
- 	positionInLine = #top 		ifTrue: 	[alignedPositionY := alignedPositionY - font ascent].
- 	positionInLine = #center 	ifTrue: 	[alignedPositionY := (alignedPositionY - (font ascent / 2)) floor].
- 	positionInLine = #bottom	ifTrue: 	[alignedPositionY := alignedPositionY + font descent].
- 	"#baseline does not require adjustments"
- 	
- 	padding := textAnchorProperties padding.
- 	morphBaselineGetter := textAnchorProperties morphBaselineGetter.
- 	morphPosition := textAnchorProperties verticalAlignmentMorph.
- 	morphPosition = #top		ifTrue: [alignedPositionY := alignedPositionY + padding top].
- 	morphPosition = #center 	ifTrue: [alignedPositionY := (alignedPositionY - (aMorphOrForm height / 2)) floor].
- 	morphPosition = #baseline	ifTrue: [
- 			alignedPositionY := alignedPositionY - (morphBaselineGetter ifNotNil: [:getter | 
- 				aMorphOrForm perform: getter] ifNil: [0])].
- 	morphPosition = #bottom 	ifTrue: [alignedPositionY := (alignedPositionY - aMorphOrForm height) - padding bottom].
- 	"We only apply padding to the position the morph is aligned to."	
- 	
- 	^ alignedPositionY!

Item was removed:
- Form subclass: #DisplayScreen
- 	instanceVariableNames: 'clippingBox extraRegions'
- 	classVariableNames: 'DeferringUpdates DisplayChangeSignature DisplayIsFullScreen PlatformScaleFactor RelativeScaleFactorEnabled'
- 	poolDictionaries: ''
- 	category: 'Graphics-Display Objects'!
- 
- !DisplayScreen commentStamp: '<historical>' prior: 0!
- There is only one instance of me, Display. It is a global and is used to handle general user requests to deal with the whole display screen. 
- 	Although I offer no protocol, my name provides a way to distinguish this special instance from all other Forms. This is useful, for example, in dealing with saving and restoring the system.
- 	To change the depth of your Display...
- 		Display newDepth: 16.
- 		Display newDepth: 8.
- 		Display newDepth: 1.
- Valid display depths are 1, 2, 4, 8, 16 and 32.  It is suggested that you run with your monitors setting the same, for better speed and color fidelity.  Note that this can add up to 4Mb for the Display form.  Finally, note that newDepth: ends by executing a 'ControlManager restore' which currently terminates the active process, so nothing that follows in the doit will get executed.
- 
- Depths 1, 2, 4 and 8 bits go through a color map to put color on the screen, but 16 and 32-bit color use the pixel values directly for RGB color (5 and 8 bits per, respectivlely).  The color choice an be observed by executing Color fromUser in whatever depth you are using.
- !

Item was removed:
- ----- Method: DisplayScreen class>>actualScreenDepth (in category 'snapshots') -----
- actualScreenDepth
- 	<primitive: 'primitiveScreenDepth'>
- 	^ Display depth!

Item was removed:
- ----- Method: DisplayScreen class>>actualScreenScaleFactor (in category 'snapshots') -----
- actualScreenScaleFactor
- 	<primitive: #primitiveScreenScaleFactor>
- 
- 	^ Float nan "Unknown scale factor"!

Item was removed:
- ----- Method: DisplayScreen class>>actualScreenSize (in category 'snapshots') -----
- actualScreenSize
- 	<primitive: 106>
- 	^ 640 at 480!

Item was removed:
- ----- Method: DisplayScreen class>>boundingBox (in category 'display box access') -----
- boundingBox
- 	"Answer the bounding box for the form representing the current display 
- 	screen."
- 
- 	^Display boundingBox!

Item was removed:
- ----- Method: DisplayScreen class>>checkForNewScreenScaleFactor (in category 'display box access') -----
- checkForNewScreenScaleFactor
- 	"Check whether the platform's scale factor has changed and if so take appropriate actions"
- 
- 	Display platformScaleFactor: DisplayScreen actualScreenScaleFactor.!

Item was removed:
- ----- Method: DisplayScreen class>>checkForNewScreenSize (in category 'display box access') -----
- checkForNewScreenSize
- 	"Check whether the screen size has changed and if so take appropriate actions"
- 
- 	Display isVirtualScreen ifTrue: [^Display checkForNewScreenSize].
- 
- 	Display extent = DisplayScreen actualScreenSize
- 		ifFalse: [Display restore].!

Item was removed:
- ----- Method: DisplayScreen class>>depth:width:height:fullscreen: (in category 'display box access') -----
- depth: depthInteger width: widthInteger height: heightInteger fullscreen: aBoolean
- 	"Force Squeak's window (if there's one) into a new size and depth."
- 	"DisplayScreen depth: 8 width: 1024 height: 768 fullscreen: false"
- 
- 	"August 2019: This method will be deprecated in the future!! Use the HostWindowPlugin instead if possible.
- 	
- 	This method is still the only way to change the size of the display, when the image is started with the -vm-display-none flag, because
- (1) you still have a Display, hurray!!, and (2) HostWindowPlugin will refuse to notice that, because you don't have any windows."
- 
- 	<primitive: 92>
- 	self primitiveFailed!

Item was removed:
- ----- Method: DisplayScreen class>>displayIsFullScreen (in category 'screen modes') -----
- displayIsFullScreen
- 
- 	^ DisplayIsFullScreen ifNil: [DisplayIsFullScreen := false]!

Item was removed:
- ----- Method: DisplayScreen class>>fullScreenOff (in category 'screen modes') -----
- fullScreenOff
- 
- 	Display fullScreenMode: (DisplayIsFullScreen := false).
- 	self checkForNewScreenSize.
- !

Item was removed:
- ----- Method: DisplayScreen class>>fullScreenOn (in category 'screen modes') -----
- fullScreenOn
- 
- 	Display fullScreenMode: (DisplayIsFullScreen := true).
- 	self checkForNewScreenSize.!

Item was removed:
- ----- Method: DisplayScreen class>>hostWindowExtent: (in category 'host window access') -----
- hostWindowExtent: aPoint
- 	
- 	[self
- 		primitiveWindow: self hostWindowIndex
- 		width: aPoint x
- 		height: aPoint y]
- 			on: Error "primitive failed such as in headless mode"
- 			do: [:ex | "ignore" ].
- 			
- 	Smalltalk windowSystemName = 'X11'
- 		ifTrue: [100 milliSeconds wait].
- 		
- 	^ self actualScreenSize!

Item was removed:
- ----- Method: DisplayScreen class>>hostWindowIndex (in category 'host window access') -----
- hostWindowIndex
- 	"By convention, the reference to the primary Squeak display window is 1.
- 	The host window plugin may use different conventions for references to
- 	windows. In general, the handles for references to host windows should be
- 	considered as meaningful only to the VM plugin, with host window index 1
- 	being a special case of a well known handle value."
- 
- 	^ 1!

Item was removed:
- ----- Method: DisplayScreen class>>hostWindowTitle: (in category 'host window access') -----
- hostWindowTitle: aString
- 
- 	[self
- 		primitiveWindow: self hostWindowIndex
- 		title: aString squeakToUtf8]
- 			on: Error "primitive failed such as in headless mode"
- 			do: [:ex | "ignore"].!

Item was removed:
- ----- Method: DisplayScreen class>>isDeferringUpdates (in category 'testing') -----
- isDeferringUpdates
- 
- 	^ DeferringUpdates == true!

Item was removed:
- ----- Method: DisplayScreen class>>primitiveWindow:title: (in category 'primitives - host window access') -----
- primitiveWindow: id title: titleString
- 
- 	<primitive: 'primitiveHostWindowTitle' module: 'HostWindowPlugin'>
- 	^self primitiveFailed!

Item was removed:
- ----- Method: DisplayScreen class>>primitiveWindow:width:height: (in category 'primitives - host window access') -----
- primitiveWindow: id width: width height: height
- 
- 	<primitive: 'primitiveHostWindowSizeSet' module: 'HostWindowPlugin'>
- 	^self primitiveFailed!

Item was removed:
- ----- Method: DisplayScreen class>>relativeScaleFactor (in category 'preferences') -----
- relativeScaleFactor
- 	<preference: 'Scale Factor'
- 		categoryList: #(Morphic Tools visuals Accessibility)
- 		description: 'Set the size of fonts and tools according to the pixels-per-inch of your display. Can be used to zoom in even further.'
- 		type: #String>
- 
- 	^ Display relativeUiScaleFactor!

Item was removed:
- ----- Method: DisplayScreen class>>relativeScaleFactor: (in category 'preferences') -----
- relativeScaleFactor: aFloatString
- 
- 	Display relativeUiScaleFactor: (aFloatString ifNotNil: [:s | s asNumber] ifNil: [1.0]).!

Item was removed:
- ----- Method: DisplayScreen class>>relativeScaleFactorEnabled (in category 'preferences') -----
- relativeScaleFactorEnabled
- 	<preference: 'Show Relative Scale Factor'
- 		categoryList: #(Morphic Tools visuals)
- 		description: 'When true, 100% means as-the-platform/monitor-demands, which is typical for macOS. When false, 100% means pixel-perfect, which is typical for Windows. Only works if #platformScaleFactorKnown.'
- 		type: #Boolean>
- 
- 	"Note that we set the default to 'false' because pixels are very prominent in the Morphic programming model. So it makes sense to communcate this kind of pixel scaling openly and thus not hide the #platformScaleFactor from the user."
- 	^ RelativeScaleFactorEnabled ifNil: [false].!

Item was removed:
- ----- Method: DisplayScreen class>>relativeScaleFactorEnabled: (in category 'preferences') -----
- relativeScaleFactorEnabled: aBoolean
- 
- 	RelativeScaleFactorEnabled := Display platformScaleFactorKnown and: [aBoolean ifNil: [false]].!

Item was removed:
- ----- Method: DisplayScreen class>>setNewScreenSize: (in category 'display box access') -----
- setNewScreenSize: aPoint
- 	"Ensure that the Display is set to the given extent."
- 	
- 	self hostWindowExtent: aPoint.
- 	self checkForNewScreenSize.
- 	
- 	"In the Windows version of the host window plugin, the extent currently includes window decorations. Therefore, we need two attempts to ensure that the Display extent is aPoint. Note that this is a bug in the plugin."
- 	(Display extent x < aPoint x or: [Display extent y < aPoint y]) ifTrue: [
- 		self hostWindowExtent: 2*aPoint - Display extent.
- 		self checkForNewScreenSize].!

Item was removed:
- ----- Method: DisplayScreen class>>toggleFullScreen (in category 'screen modes') -----
- toggleFullScreen
- 	"Toggle between full screen and windowed mode."
- 	
- 	self displayIsFullScreen
- 		ifTrue: [self fullScreenOff]
- 		ifFalse: [self fullScreenOn].!

Item was removed:
- ----- Method: DisplayScreen>>addExtraRegion:for: (in category 'displaying') -----
- addExtraRegion: aRectangle for: regionDrawer
- 	"Register the given rectangle as a region which is drawn by the specified region drawer. The region will be excluded from any updates when #forceDamageToScreen: is called. Note that the rectangle is only valid for a single update cycle; once #forceDamageToScreen: has been called, the region drawer and its region are being removed from the list"
- 	extraRegions ifNil:[extraRegions := #()].
- 	extraRegions := extraRegions copyWith: (Array with: regionDrawer with: aRectangle).
- !

Item was removed:
- ----- Method: DisplayScreen>>beDisplay (in category 'private') -----
- beDisplay
- 	"Primitive. Tell the interpreter to use the receiver as the current display 
- 	image. Fail if the form is too wide to fit on the physical display. 
- 	Essential. See Object documentation whatIsAPrimitive."
- 
- 	<primitive: 102>
- 	self primitiveFailed!

Item was removed:
- ----- Method: DisplayScreen>>boundingBox (in category 'other') -----
- boundingBox
- 	clippingBox == nil
- 		ifTrue: [clippingBox := super boundingBox].
- 	^ clippingBox!

Item was removed:
- ----- Method: DisplayScreen>>clippingTo:do: (in category 'other') -----
- clippingTo: aRect do: aBlock
- 	"Display clippingTo: Rectangle fromUser do:
- 	[ScheduledControllers restore: Display fullBoundingBox]"
- 	| saveClip |
- 	saveClip := clippingBox.
- 	clippingBox := aRect.
- 	aBlock value.
- 	clippingBox := saveClip!

Item was removed:
- ----- Method: DisplayScreen>>copyBits:from:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- copyBits: rect from: sf at: destOrigin clippingBox: clipRect rule: cr fillColor: hf 
- 	(BitBlt
- 		destForm: self
- 		sourceForm: sf
- 		fillColor: hf
- 		combinationRule: cr
- 		destOrigin: destOrigin
- 		sourceOrigin: rect origin
- 		extent: rect extent
- 		clipRect: (clipRect intersect: clippingBox)) copyBits!

Item was removed:
- ----- Method: DisplayScreen>>copyBits:from:at:clippingBox:rule:fillColor:map: (in category 'displaying') -----
- copyBits: rect from: sf at: destOrigin clippingBox: clipRect rule: cr fillColor: hf map: map
- 	((BitBlt
- 		destForm: self
- 		sourceForm: sf
- 		fillColor: hf
- 		combinationRule: cr
- 		destOrigin: destOrigin
- 		sourceOrigin: rect origin
- 		extent: rect extent
- 		clipRect: (clipRect intersect: clippingBox)) colorMap: map) copyBits!

Item was removed:
- ----- Method: DisplayScreen>>copyFrom: (in category 'private') -----
- copyFrom: aForm
- 	"Take on all state of aForm, with complete sharing"
- 
- 	super copyFrom: aForm.
- 	clippingBox := super boundingBox!

Item was removed:
- ----- Method: DisplayScreen>>currentScaleError (in category 'scale factor') -----
- currentScaleError
- 	"Documentation and debugging only. The scale error originates in rounding errors while rendering the standard TTCFont font into pixels or using a pre-rendered StrikeFont in the first place.
- 	
- 	Display currentScaleError
- 	"
- 	
- 	^ RealEstateAgent scaleFactor - self uiScaleFactor
- 	
- "
- | errors current |
- errors := OrderedDictionary new.
- current := Display uiScaleFactor.
- 1.0 to: 3.0 by: 0.25 do: [:s |
- 	Display uiScaleFactor: s.
- 	errors at: s put: Display currentScaleError].
- Display uiScaleFactor: current.
- errors explore.
- "!

Item was removed:
- ----- Method: DisplayScreen>>defaultBitBltClass (in category 'blitter defaults') -----
- defaultBitBltClass
- 	"Return the BitBlt version to use when I am active"
- 	^BitBlt!

Item was removed:
- ----- Method: DisplayScreen>>defaultWarpBltClass (in category 'blitter defaults') -----
- defaultWarpBltClass
- 	"Return the WarpBlt version to use when I am active"
- 	^WarpBlt!

Item was removed:
- ----- Method: DisplayScreen>>deferUpdates: (in category 'other') -----
- deferUpdates: aBoolean
- 	"Set the deferUpdates flag in the virtual machine. When this flag is true, BitBlt operations on the Display are not automatically propagated to the screen. If this underlying platform does not support deferred updates, this primitive will fail. Answer whether updates were deferred before if the primitive succeeds, nil if it fails.
- 	
- 	Note that when disabling deferred upates again after modifying the receiver, it is advisable to call #forceDisplayUpdate so that the deferred updates can actually be displayed on the screen."
- 
- 	| wasDeferred |
- 	wasDeferred := DeferringUpdates == true.
- 	DeferringUpdates := aBoolean.
- 	^(self primitiveDeferUpdates: aBoolean) ifNotNil: [wasDeferred]!

Item was removed:
- ----- Method: DisplayScreen>>deferUpdatesIn:while: (in category 'other') -----
- deferUpdatesIn: aRectangle while: aBlock
- 	| result |
- 	((self deferUpdates: true) ifNil: [true]) ifTrue: [
- 		"Outer call did set this already. Ignore here."
- 		^ aBlock value].
- 	result := aBlock value.
- 	self deferUpdates: false.
- 	self forceToScreen: aRectangle.
- 	^result!

Item was removed:
- ----- Method: DisplayScreen>>displayChangeSignature (in category 'other') -----
- displayChangeSignature
- 
- 	^DisplayChangeSignature!

Item was removed:
- ----- Method: DisplayScreen>>findAnyDisplayDepth (in category 'private') -----
- findAnyDisplayDepth
- 	"Return any display depth that is supported on this system."
- 	^self findAnyDisplayDepthIfNone:[
- 		"Ugh .... now this is a biggie - a system that does not support
- 		any of the Squeak display depths at all."
- 		Smalltalk
- 			logSqueakError:'Fatal error: This system has no support for any display depth at all.'
- 			inContext: thisContext .
- 		Smalltalk quitPrimitive. "There is no way to continue from here"
- 	].!

Item was removed:
- ----- Method: DisplayScreen>>findAnyDisplayDepthIfNone: (in category 'private') -----
- findAnyDisplayDepthIfNone: aBlock
- 	"Return any display depth that is supported on this system.
- 	If there is none, evaluate aBlock."
- 	#(1 2 4 8 16 32 -1 -2 -4 -8 -16 -32) do:[:bpp|
- 		(self supportsDisplayDepth: bpp) ifTrue:[^bpp].
- 	].
- 	^aBlock value!

Item was removed:
- ----- Method: DisplayScreen>>flash: (in category 'displaying') -----
- flash: aRectangle 
- 	"Flash the area of the screen defined by the given rectangle."
- 
- 	self reverse: aRectangle.
- 	self forceDisplayUpdate.
- 	(Delay forMilliseconds: 50) wait.
- 	self reverse: aRectangle.
- 	self forceDisplayUpdate.
- !

Item was removed:
- ----- Method: DisplayScreen>>flash:andWait: (in category 'displaying') -----
- flash: aRectangle andWait: msecs
- 	"Flash the area of the screen defined by the given rectangle."
- 
- 	self reverse: aRectangle.
- 	self forceDisplayUpdate.
- 	(Delay forMilliseconds: msecs) wait.
- 	self reverse: aRectangle.
- 	self forceDisplayUpdate.
- 	(Delay forMilliseconds: msecs) wait.
- !

Item was removed:
- ----- Method: DisplayScreen>>flashAll:andWait: (in category 'displaying') -----
- flashAll: rectangleList andWait: msecs
- 	"Flash the areas of the screen defined by the given rectangles."
- 
- 	rectangleList do: [:aRectangle | self reverse: aRectangle].
- 	self forceDisplayUpdate.
- 	(Delay forMilliseconds: msecs) wait.
- 	rectangleList do: [:aRectangle | self reverse: aRectangle].
- 	self forceDisplayUpdate.
- 	(Delay forMilliseconds: msecs) wait.
- !

Item was removed:
- ----- Method: DisplayScreen>>forceDamageToScreen: (in category 'displaying') -----
- forceDamageToScreen: allDamage
- 	"Force all the damage rects to the screen."
- 	| regions rectList |
- 	rectList := allDamage.
- 	"Note: Reset extra regions at the beginning to prevent repeated errors"
- 	regions := extraRegions.
- 	extraRegions := nil.
- 	regions ifNotNil:[
- 		"exclude extra regions"
- 		regions do:[:drawerAndRect| | excluded remaining |
- 			excluded := drawerAndRect at: 2.
- 			remaining := WriteStream on: #().
- 			rectList do:[:r|
- 				remaining nextPutAll:(r areasOutside: excluded)].
- 			rectList := remaining contents].
- 	].
- 	rectList do:[:r| self forceToScreen: r].
- 	regions ifNotNil:[
- 		"Have the drawers paint what is needed"
- 		regions do:[:drawerAndRect| (drawerAndRect at: 1) forceToScreen].
- 	].!

Item was removed:
- ----- Method: DisplayScreen>>forceDisplayUpdate (in category 'other') -----
- forceDisplayUpdate
- 	"On platforms that buffer screen updates, force the screen to be updated immediately. On other platforms, or if the primitive is not implemented, do nothing."
- 
- 	<primitive: 231>
- 	"do nothing if primitive fails"!

Item was removed:
- ----- Method: DisplayScreen>>forceToScreen (in category 'other') -----
- forceToScreen
- 	"Force the entire display area to the screen"
- 	^self forceToScreen: self boundingBox!

Item was removed:
- ----- Method: DisplayScreen>>forceToScreen: (in category 'other') -----
- forceToScreen: aRectangle
- 	"Force the given rectangular section of the Display to be copied to the screen. The primitive call does nothing if the primitive is not implemented. Typically used when the deferUpdates flag in the virtual machine is on; see deferUpdates:."
- 
- 	self primShowRectLeft: aRectangle left
- 		right: aRectangle right
- 		top: aRectangle top
- 		bottom: aRectangle bottom.
- !

Item was removed:
- ----- Method: DisplayScreen>>fullBoundingBox (in category 'other') -----
- fullBoundingBox
- 	^ super boundingBox!

Item was removed:
- ----- Method: DisplayScreen>>fullScreenMode: (in category 'other') -----
- fullScreenMode: aBoolean
- 	"On platforms that support it, set full-screen mode to the value of the argument. (Note: you'll need to restore the Display after calling this primitive."
- 	"Display fullScreenMode: true. Display newDepth: Display depth"
- 
- 	<primitive: 233>
- 	self primitiveFailed
- !

Item was removed:
- ----- Method: DisplayScreen>>height (in category 'other') -----
- height
- 	^ self boundingBox height!

Item was removed:
- ----- Method: DisplayScreen>>isDisplayScreen (in category 'testing') -----
- isDisplayScreen
- 	^true!

Item was removed:
- ----- Method: DisplayScreen>>newDepth: (in category 'other') -----
- newDepth: pixelSize
- "
- 	Display newDepth: 8.
- 	Display newDepth: 1.
- "
- 	| area need |
- 	
- 	(self supportsDisplayDepth: pixelSize)
- 		ifFalse:[^self inform:'Display depth ', pixelSize printString, ' is not supported on this system'].
- 
- 	pixelSize = self nativeDepth ifTrue: [^ self  "no change"].
- 	pixelSize abs < self depth ifFalse:
- 		["Make sure there is enough space"
- 		area := self boundingBox area. "pixels"
- 
- 		need := (area * (pixelSize abs - self depth) // 8)  "new bytes needed"
- 				+ Smalltalk lowSpaceThreshold.
- 		(Smalltalk garbageCollectMost <= need
- 			and: [Smalltalk garbageCollect <= need])
- 			ifTrue: [self error: 'Insufficient free space']].
- 
- 	Display setExtent: Display extent depth: pixelSize.
- 	Display beDisplay.
- 
- 	Project current ifNotNil: [:p |
- 		p
- 			displayDepthChanged;
- 			displaySizeChanged].!

Item was removed:
- ----- Method: DisplayScreen>>objectForDataStream: (in category 'disk I/O') -----
- objectForDataStream: refStrm
- 	| dp |
- 	"I am about to be written on an object file.  Write a reference to the Display in the other system instead.  "
- 
- 	"A path to me"
- 	dp := DiskProxy global: #Display selector: #yourself args: #().
- 	refStrm replace: self with: dp.
- 	^ dp
- !

Item was removed:
- ----- Method: DisplayScreen>>platformScaleFactor (in category 'scale factor') -----
- platformScaleFactor
- 	"Answers the platform's (and thus monitor's) current scale factor as last reported via VM primitive. See #checkForNewScreenScaleFactor. For robustness, always report a sensible value. However, you should check via #platformScaleFactorKnown whether this value is reliable."
- 
- 	^ PlatformScaleFactor ifNil: [1.0 "Primitive not ready."]!

Item was removed:
- ----- Method: DisplayScreen>>platformScaleFactor: (in category 'scale factor') -----
- platformScaleFactor: aFloatOrNil
- 	"Report a new scale factor from the platform to the image. This can happen if you move Squeak's window between monitors with different pixels-per-inch. On some platforms, you can also set a scale factor independent of monitor PPI. Note that the user might have scaled the image regardless of the previous platform scale factor."
- 
- 	| old new |
- 	(aFloatOrNil isNil or: [aFloatOrNil isNaN]) ifTrue: [
- 		"Ignore. Primitive not ready (anymore)."
- 		PlatformScaleFactor := nil.
- 		^ self].
- 	PlatformScaleFactor ifNil: [
- 		"First time. Ignore. Assume that the user scaled manually until now."
- 		"self assert: [aFloatOrNil notNil]."
- 		"self assert: [aFloatOrNil isNaN not]."
- 		PlatformScaleFactor := aFloatOrNil.
- 		^ self].
- 	
- 	(old := self platformScaleFactor) = (new := aFloatOrNil) ifTrue: [^ self].
- 	PlatformScaleFactor := new.
- 	self uiScaleFactor: self uiScaleFactor * (new/old).!

Item was removed:
- ----- Method: DisplayScreen>>platformScaleFactorKnown (in category 'scale factor') -----
- platformScaleFactorKnown
- 	"Tools can help users understand whether Squeak will adjust the scale factor automatically or whether they have to scale manually. See class-side's #actualScreenScaleFactor and also #relativeUiScaleFactor."
- 
- 	^ PlatformScaleFactor notNil!

Item was removed:
- ----- Method: DisplayScreen>>primRetryShowRectLeft:right:top:bottom: (in category 'private') -----
- primRetryShowRectLeft: l right: r top: t bottom: b
- 	"Copy the given rectangular section of the Display to to the screen. This primitive is not implemented on all platforms. Do nothing if it fails. "
- 
- 	<primitive: 127>
- 	"do nothing if primitive fails"
- !

Item was removed:
- ----- Method: DisplayScreen>>primShowRectLeft:right:top:bottom: (in category 'private') -----
- primShowRectLeft: l right: r top: t bottom: b
- 	"Copy the given rectangular section of the Display to to the screen. This primitive is not implemented on all platforms. If this fails, retry integer coordinates."
- 
- 	<primitive: 127>
- 	"if this fails, coerce coordinates to integers and try again"
- 	self primRetryShowRectLeft: l truncated
- 		right: r rounded
- 		top: t truncated
- 		bottom: b rounded.
- !

Item was removed:
- ----- Method: DisplayScreen>>primSupportsDisplayDepth: (in category 'other') -----
- primSupportsDisplayDepth: pixelDepth
- 	"Return true if this pixel depth is supported on the current host platform.
- 	Primitive. Optional."
- 	<primitive: 91>
- 	^#(1 2 4 8 16 32) includes: pixelDepth!

Item was removed:
- ----- Method: DisplayScreen>>primitiveDeferUpdates: (in category 'other') -----
- primitiveDeferUpdates: aBoolean
- 	"Set the deferUpdates flag in the virtual machine. When this flag is true, BitBlt operations on the Display are not automatically propagated to the screen. If this underlying platform does not support deferred updates, this primitive will fail. Answer the receiver if the primitive succeeds, nil if it fails."
- 
- 	<primitive: 126>
- 	^ nil  "answer nil if primitive fails"
- !

Item was removed:
- ----- Method: DisplayScreen>>relativeUiScaleFactor (in category 'scale factor') -----
- relativeUiScaleFactor
- 	"Answers the scale factor as perceived by the user. Note that this concept might be platform-dependent. On Windows, for example, 100% means pixel-perfect while on macOS 100% means as-the-monitor-demands. So, Retina displays are effectively scaled even if the user sees 100% in a Choose-Your-Scale dialog."
- 	
- 	^ self class relativeScaleFactorEnabled
- 		ifTrue: [ "macOS" self uiScaleFactor / self platformScaleFactor ]
- 		ifFalse: [ "Windows" self uiScaleFactor ]!

Item was removed:
- ----- Method: DisplayScreen>>relativeUiScaleFactor: (in category 'scale factor') -----
- relativeUiScaleFactor: aFloat
- 	
- 	^ self class relativeScaleFactorEnabled
- 		ifTrue: [ "macOS" self uiScaleFactor: aFloat * self platformScaleFactor ]
- 		ifFalse: [ "Windows" self uiScaleFactor: aFloat ]!

Item was removed:
- ----- Method: DisplayScreen>>release (in category 'initialize-release') -----
- release
- 	"I am no longer Display. Release any resources if necessary"!

Item was removed:
- ----- Method: DisplayScreen>>restore (in category 'other') -----
- restore
- 
- 	| priorBits |
- 	priorBits := bits. "Must avoid to be GC'ed!!"
- 		self setExtent: self class actualScreenSize depth: self nativeDepth.
- 		self beDisplay.
- 	priorBits := nil. "Documentation only."
- 	
- 	Project current ifNotNil: [:p| p displaySizeChanged].!

Item was removed:
- ----- Method: DisplayScreen>>restoreAfter: (in category 'other') -----
- restoreAfter: aBlock
- 	"Evaluate the block, wait for a mouse click, and then restore the screen."
- 
- 	aBlock ensure: [
- 		Sensor waitButton.
- 		self restore].!

Item was removed:
- ----- Method: DisplayScreen>>setExtent:depth: (in category 'private') -----
- setExtent: aPoint depth: bitsPerPixel  "DisplayScreen startUp"
- 	"This method is critical.  If the setExtent fails, there will be no
- 	proper display on which to show the error condition..."
- 	"ar 5/1/1999: ... and that is exactly why we check for the available display depths first."
- 
- 	"RAA 27 Nov 99 - if depth and extent are the same and acceptable, why go through this.
- 	also - record when we change so worlds can tell if it is time to repaint"
- 
- 	(depth == bitsPerPixel and: [aPoint = self extent and: 
- 					[self supportsDisplayDepth: bitsPerPixel]]) ifFalse: [
- 		bits := nil.  "Free up old bitmap in case space is low"
- 		DisplayChangeSignature := (DisplayChangeSignature ifNil: [0]) + 1.
- 		(self supportsDisplayDepth: bitsPerPixel)
- 			ifTrue:[super setExtent: aPoint depth: bitsPerPixel]
- 			ifFalse:[(self supportsDisplayDepth: bitsPerPixel negated)
- 				ifTrue:[super setExtent: aPoint depth: bitsPerPixel negated]
- 				ifFalse:["Search for a suitable depth"
- 					super setExtent: aPoint depth: self findAnyDisplayDepth]].
- 	].
- 	clippingBox := super boundingBox!

Item was removed:
- ----- Method: DisplayScreen>>shrink (in category 'initialize-release') -----
- shrink 
- 	"Reduce the memory footprint of this display object before being stored into the .image file."
- 	
- 	self setExtent: 240 at 120 depth: self depth.!

Item was removed:
- ----- Method: DisplayScreen>>supportedDisplayDepths (in category 'other') -----
- supportedDisplayDepths
- 	"Return all pixel depths supported on the current host platform."
- 	^#(1 2 4 8 16 32 -1 -2 -4 -8 -16 -32) select: [:d | self supportsDisplayDepth: d]!

Item was removed:
- ----- Method: DisplayScreen>>supportsDisplayDepth: (in category 'other') -----
- supportsDisplayDepth: pixelDepth
- 	"Return true if this pixel depth is supported on the current host platform."
- 	Smalltalk platformName = 'Mac OS' ifTrue: [^pixelDepth abs = 32]. "Work around VM bug"
- 	^self primSupportsDisplayDepth: pixelDepth!

Item was removed:
- ----- Method: DisplayScreen>>uiScaleFactor (in category 'scale factor') -----
- uiScaleFactor
- 	"Answers the current scale factor used to configure all widgets, tools, or windows to be prepared for the current rendering system, i.e., BitBlt. Note that 1.0 is usually the design space for pixel-based metrics such as #borderWidth or #layoutInset (if not based on font metrics)."
- 	
- 	^ UserInterfaceTheme current isTTCBased
- 		ifTrue: [TextStyle pixelsPerInch / 96.0 "Hide rounding errors in TTCFont >> #height."]
- 		ifFalse: [RealEstateAgent scaleFactor roundTo: 0.25 "Force 25% steps. See, e.g., #doScale150."].!

Item was removed:
- ----- Method: DisplayScreen>>uiScaleFactor: (in category 'scale factor') -----
- uiScaleFactor: aFloat
- 	"Sets the effective scale factor for the user interface, i.e., all widgets, tools, and windows. Note that the user can override the #platformScaleFactor, which is just a hint recommended by the platform."
- 
- 	| oldPixelFactor newPixelFactor newScaleFactor |
- 	newScaleFactor := aFloat max: 0.75.
- 	
- 	(UserInterfaceTheme current canFakeScaleFactor: newScaleFactor) ifTrue: [
- 		self flag: #isTTCBased.
- 		^ UserInterfaceTheme current applyScaled: newScaleFactor].
- 	
- 	newScaleFactor = 0.75 ifTrue: [(Project uiManager
- 		confirm: ('You are currently using <b>TrueType fonts</b>. Your requested scale factor of <b>{1}%</b> looks better using pre-rendered <b>pixel fonts</b>.<br><br>Do you want to switch to pixel fonts now?' translated format: {(newScaleFactor * 100) rounded}) asTextFromHtml
- 		title: 'Blurry Fonts Detected' translated) == true
- 			ifTrue: [UserInterfaceTheme cleanUpAndReset. ^ self uiScaleFactor: newScaleFactor]].
- 	
- 	"Do nothing if the factor is unchanged. For comparison, use actual pixel-based scale factor to account for rounding errors, instead of #uiScaleFactor."
- 	oldPixelFactor := RealEstateAgent scaleFactor. 
- 	newScaleFactor = oldPixelFactor ifTrue: [^ self].
- 		
- 	"Update system's PPI to then compute the new pixel-based scale factor."
- 	TextStyle pixelsPerInch: 96.0 * newScaleFactor.
- 	newPixelFactor := RealEstateAgent resetScaleFactor; scaleFactor.
- 	
- 	"Let the current project (kind) decide how to update the system."
- 	Project current ifNotNil: [:p | p displayScaleChangedFrom: oldPixelFactor to: newPixelFactor].!

Item was removed:
- ----- Method: DisplayScreen>>usableArea (in category 'other') -----
- usableArea
- 	"Answer the usable area of the receiver.  5/22/96 sw."
- 
- 	^ self boundingBox deepCopy!

Item was removed:
- ----- Method: DisplayScreen>>width (in category 'other') -----
- width
- 	^ self boundingBox width!

Item was removed:
- DisplayObject subclass: #DisplayText
- 	instanceVariableNames: 'text textStyle offset form foreColor backColor'
- 	classVariableNames: ''
- 	poolDictionaries: 'TextConstants'
- 	category: 'Graphics-Display Objects'!
- 
- !DisplayText commentStamp: '<historical>' prior: 0!
- I represent Text whose emphasis changes are mapped to a set of fonts. My instances have an offset used in determining screen placement for displaying. They get used two different ways in the system. In the user interface, they mainly hold onto some text which is viewed by some form of ParagraphEditor. However, as a DisplayObject, they may need to display efficiently, so my instances have a cache for the bits.!

Item was removed:
- ----- Method: DisplayText class>>example (in category 'examples') -----
- example
- 	"Continually prints two lines of text wherever you point with the cursor.  Terminate by pressing any button on the
- 	mouse."
- 	| tx |
- 	tx := 'this is a line of characters and
- this is the second line.' asDisplayText.
- 	tx foregroundColor: Color black backgroundColor: Color transparent.
- 	tx := tx alignedTo: #center.
- 	[Sensor anyButtonPressed]
- 		whileFalse:
- 			[tx displayOn: Display at: Sensor cursorPoint]
- 
- 	"DisplayText example."!

Item was removed:
- ----- Method: DisplayText class>>text: (in category 'instance creation') -----
- text: aText 
- 	"Answer an instance of me such that the text displayed is aText 
- 	according to the system's default text style."
- 
- 	^self new
- 		setText: aText
- 		textStyle: DefaultTextStyle copy
- 		offset: 0 @ 0!

Item was removed:
- ----- Method: DisplayText class>>text:textStyle: (in category 'instance creation') -----
- text: aText textStyle: aTextStyle 
- 	"Answer an instance of me such that the text displayed is aText 
- 	according to the style specified by aTextStyle."
- 
- 	^self new
- 		setText: aText
- 		textStyle: aTextStyle
- 		offset: 0 @ 0!

Item was removed:
- ----- Method: DisplayText class>>text:textStyle:offset: (in category 'instance creation') -----
- text: aText textStyle: aTextStyle offset: aPoint 
- 	"Answer an instance of me such that the text displayed is aText 
- 	according to the style specified by aTextStyle. The display of the 
- 	information should be offset by the amount given as the argument, 
- 	aPoint."
- 
- 	^self new
- 		setText: aText
- 		textStyle: aTextStyle
- 		offset: aPoint!

Item was removed:
- ----- Method: DisplayText>>alignedTo: (in category 'accessing') -----
- alignedTo: alignPointSelector
- 	"Return a copy with offset according to alignPointSelector which is one of...
- 	#(topLeft, topCenter, topRight, leftCenter, center, etc)"
- 	| boundingBox |
- 	boundingBox := 0 at 0 corner: self form extent.
- 	^ self shallowCopy offset: (0 at 0) - (boundingBox perform: alignPointSelector)!

Item was removed:
- ----- Method: DisplayText>>asString (in category 'converting') -----
- asString
- 	"See String >> #asDisplayText."
- 	
- 	^ self string!

Item was removed:
- ----- Method: DisplayText>>asText (in category 'converting') -----
- asText
- 	"See Text >> #asDisplayText."
- 
- 	^ self text!

Item was removed:
- ----- Method: DisplayText>>backgroundColor (in category 'color') -----
- backgroundColor
- 	backColor == nil ifTrue: [^ Color transparent].
- 	^ backColor!

Item was removed:
- ----- Method: DisplayText>>boundingBox (in category 'display box access') -----
- boundingBox 
- 	"Refer to the comment in DisplayObject|boundingBox."
- 
- 	^self form boundingBox!

Item was removed:
- ----- Method: DisplayText>>composeForm (in category 'private') -----
- composeForm
- 
- 	form := Project current composeDisplayTextIntoForm: self.!

Item was removed:
- ----- Method: DisplayText>>computeBoundingBox (in category 'display box access') -----
- computeBoundingBox 
- 	"Compute minimum enclosing rectangle around characters."
- 
- 	| character font width carriageReturn lineWidth lineHeight |
- 	carriageReturn := Character cr.
- 	width := lineWidth := 0.
- 	font := textStyle defaultFont.
- 	lineHeight := textStyle lineGrid.
- 	1 to: text size do: 
- 		[:i | 
- 		character := text at: i.
- 		character = carriageReturn
- 		  ifTrue: 
- 			[lineWidth := lineWidth max: width.
- 			lineHeight := lineHeight + textStyle lineGrid.
- 			width := 0]
- 		  ifFalse: [width := width + (font widthOf: character)]].
- 	lineWidth := lineWidth max: width.
- 	^offset extent: lineWidth @ lineHeight!

Item was removed:
- ----- Method: DisplayText>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
- 	"For TT font, rule 34 is used if possible."
- 	"Refer to the comment in 
- 	DisplayObject|displayOn:at:clippingBox:rule:mask:."
- 
- 	| form1 rule |
- 	form1 := self form.
- 	rule := (ruleInteger = Form over and: [backColor isTransparent])
- 				ifTrue: [form1 depth = 32 ifTrue: [rule := 34] ifFalse: [Form paint]]
- 				ifFalse: [ruleInteger].
- 	form1 depth = 32 ifTrue: [rule := 34].
- 	form1
- 		displayOn: aDisplayMedium
- 		at: aDisplayPoint + offset
- 		clippingBox: clipRectangle
- 		rule: rule
- 		fillColor: aForm!

Item was removed:
- ----- Method: DisplayText>>displayOn:transformation:clippingBox:align:with:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm 
- 	"Refer to the comment in 
- 	DisplayObject|displayOn:transformation:clippingBox:align:with:rule:mask:."
- 
- 	| absolutePoint |
- 	absolutePoint := displayTransformation applyTo: relativePoint.
- 	absolutePoint := absolutePoint x asInteger @ absolutePoint y asInteger.
- 	self displayOn: aDisplayMedium
- 		at: absolutePoint - alignmentPoint
- 		clippingBox: clipRectangle
- 		rule: ruleInteger
- 		fillColor: aForm!

Item was removed:
- ----- Method: DisplayText>>displayOnPort:at: (in category 'displaying') -----
- displayOnPort: aPort at: location
- 	self form displayOnPort: aPort at: location + offset!

Item was removed:
- ----- Method: DisplayText>>fontsUsed (in category 'accessing') -----
- fontsUsed
- 	"Return a list of all fonts used currently in this text.  8/19/96 tk"
- 
- 	^ text runs values asSet collect: [:each | textStyle fontAt: each]!

Item was removed:
- ----- Method: DisplayText>>foregroundColor (in category 'color') -----
- foregroundColor
- 	foreColor == nil ifTrue: [^ Color black].
- 	^ foreColor!

Item was removed:
- ----- Method: DisplayText>>foregroundColor:backgroundColor: (in category 'color') -----
- foregroundColor: cf backgroundColor: cb
- 	foreColor := cf.
- 	backColor := cb!

Item was removed:
- ----- Method: DisplayText>>form (in category 'accessing') -----
- form 
- 	"Answer the form into which the receiver's display bits are cached."
- 
- 	form == nil ifTrue: [self composeForm].
- 	^form!

Item was removed:
- ----- Method: DisplayText>>lineGrid (in category 'accessing') -----
- lineGrid
- 	"Answer the relative space between lines of the receiver's text."
- 
- 	^textStyle lineGrid!

Item was removed:
- ----- Method: DisplayText>>numberOfLines (in category 'accessing') -----
- numberOfLines 
- 	"Answer the number of lines of text in the receiver."
- 
- 	^self height // text lineGrid!

Item was removed:
- ----- Method: DisplayText>>offset (in category 'accessing') -----
- offset 
- 	"Refer to the comment in DisplayObject|offset."
- 
- 	^offset!

Item was removed:
- ----- Method: DisplayText>>offset: (in category 'accessing') -----
- offset: aPoint 
- 	"Refer to the comment in DisplayObject|offset:."
- 
- 	offset := aPoint!

Item was removed:
- ----- Method: DisplayText>>setText:textStyle:offset: (in category 'private') -----
- setText: aText textStyle: aTextStyle offset: aPoint
- 
- 	text := aText.
- 	textStyle := aTextStyle.
- 	offset := aPoint.
- 	form := nil!

Item was removed:
- ----- Method: DisplayText>>string (in category 'accessing') -----
- string
- 	"Answer the string of the characters displayed by the receiver."
- 
- 	^text string!

Item was removed:
- ----- Method: DisplayText>>text (in category 'accessing') -----
- text 
- 	"Answer the text displayed by the receiver."
- 
- 	^text!

Item was removed:
- ----- Method: DisplayText>>text: (in category 'accessing') -----
- text: aText 
- 	"Set the receiver to display the argument, aText."
- 	
- 	text := aText.
- 	form := nil.
- 	self changed.
- 	!

Item was removed:
- ----- Method: DisplayText>>textStyle (in category 'accessing') -----
- textStyle 
- 	"Answer the style by which the receiver displays its text."
- 
- 	^textStyle!

Item was removed:
- ----- Method: DisplayText>>textStyle: (in category 'accessing') -----
- textStyle: aTextStyle 
- 	"Set the style by which the receiver should display its text."
- 
- 	textStyle := aTextStyle.
- 	form := nil.
- 	self changed.
- 	!

Item was removed:
- Object subclass: #DisplayTransform
- 	instanceVariableNames: ''
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Transformations'!
- 
- !DisplayTransform commentStamp: '<historical>' prior: 0!
- This class represents a base for generic transformations of 2D points between different coordinate systems (including scaling and rotation). The transformations map objects between one coordinate system and another where it is assumed that a nested hierarchy of transformations can be defined.
- 
- It is assumed that transformations deal with Integer points. All transformations should return Integer coordinates (even though float points may be passed in as argument).
- 
- Compositions of transformations MUST work in the following order. A 'global' transformation (the argument in #composedWithGlobal:) is defined as a transformation that takes place between the receiver (the 'local') transformation and any 'global' point computations, whereas a 'local' transformation (e.g., the argument in #composedWithLocal:) takes place between the receiver ('global') and any 'local' points. For the transformation methods this means that combining a global and a local transformation will result in the following order:
- 
- 		globalPointToLocal: globalPoint
- 			"globalPoint -> globalTransform -> localTransform -> locaPoint"
- 			^localTransform globalPointToLocal:
- 				(globalTransform globalPointToLocal: globalPoint)
- 
- 		localPointToGlobal: localPoint
- 			"localPoint -> localTransform -> globalTransform -> globalPoint"
- 			^globalTransform localPointToGlobal:
- 				(localTransform localPointToGlobal: localPoint)
- 
- !

Item was removed:
- ----- Method: DisplayTransform class>>identity (in category 'instance creation') -----
- identity
- 	^self new setIdentity!

Item was removed:
- ----- Method: DisplayTransform>>asCompositeTransform (in category 'converting') -----
- asCompositeTransform
- 	"Represent the receiver as a composite transformation"
- 	^CompositeTransform new
- 		globalTransform: self
- 		localTransform: self species identity!

Item was removed:
- ----- Method: DisplayTransform>>asMatrixTransform2x3 (in category 'converting') -----
- asMatrixTransform2x3
- 	"Represent the receiver as a 2x3 matrix transformation"
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: DisplayTransform>>composedWithGlobal: (in category 'composing') -----
- composedWithGlobal: aTransformation
- 	"Return the composition of the receiver and the global transformation passed in.
- 	A 'global' transformation is defined as a transformation that takes place
- 	between the receiver (the 'local') transformation and any 'global' point
- 	computations, e.g., for the methods
- 
- 		globalPointToLocal: globalPoint
- 			globalPoint -> globalTransform -> localTransform -> locaPoint
- 
- 		localPointToGlobal: localPoint
- 			localPoint -> localTransform -> globalTransform -> globalPoint
- 
- 		"
- 	^aTransformation composedWithLocal: self!

Item was removed:
- ----- Method: DisplayTransform>>composedWithLocal: (in category 'composing') -----
- composedWithLocal: aTransformation
- 	"Return the composition of the receiver and the local transformation passed in.
- 	A 'local' transformation is defined as a transformation that takes place
- 	between the receiver (the 'global') transformation and any 'local' point
- 	computations, e.g., for the methods
- 
- 		globalPointToLocal: globalPoint
- 			globalPoint -> globalTransform -> localTransform -> locaPoint
- 
- 		localPointToGlobal: localPoint
- 			localPoint -> localTransform -> globalTransform -> globalPoint
- 
- 		"
- 	self isIdentity ifTrue:[^ aTransformation].
- 	aTransformation isIdentity ifTrue:[^ self].
- 	^ CompositeTransform new globalTransform: self
- 							localTransform: aTransformation!

Item was removed:
- ----- Method: DisplayTransform>>globalBoundsToLocal: (in category 'transforming rects') -----
- globalBoundsToLocal: aRectangle
- 	"Transform aRectangle from global coordinates into local coordinates"
- 	^Rectangle encompassing: (self globalPointsToLocal: aRectangle corners)!

Item was removed:
- ----- Method: DisplayTransform>>globalPointToLocal: (in category 'transforming points') -----
- globalPointToLocal: aPoint
- 	"Transform aPoint from global coordinates into local coordinates"
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: DisplayTransform>>globalPointsToLocal: (in category 'transforming points') -----
- globalPointsToLocal: inArray
- 	"Transform all the points of inArray from global into local coordinates"
- 	^inArray collect:[:pt| self globalPointToLocal: pt]!

Item was removed:
- ----- Method: DisplayTransform>>inverseTransformation (in category 'accessing') -----
- inverseTransformation
- 	"Return the inverse transformation of the receiver"
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: DisplayTransform>>invertBoundsRect: (in category 'transforming points') -----
- invertBoundsRect: aRectangle
- 	"Return a rectangle whose coordinates have been transformed
- 	from local back to global coordinates."
- 
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: DisplayTransform>>invertPoint: (in category 'transforming points') -----
- invertPoint: aPoint
- 	^self globalPointToLocal: aPoint!

Item was removed:
- ----- Method: DisplayTransform>>invertRect: (in category 'transforming rects') -----
- invertRect: aRectangle
- 	^self globalBoundsToLocal: aRectangle!

Item was removed:
- ----- Method: DisplayTransform>>isCompositeTransform (in category 'testing') -----
- isCompositeTransform
- 	"Return true if the receiver is a composite transformation.
- 	Composite transformations may have impact on the accuracy."
- 	^false!

Item was removed:
- ----- Method: DisplayTransform>>isIdentity (in category 'testing') -----
- isIdentity
- 	"Return true if the receiver is the identity transform; that is, if applying to a point returns the point itself."
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: DisplayTransform>>isMatrixTransform2x3 (in category 'testing') -----
- isMatrixTransform2x3
- 	"Return true if the receiver is 2x3 matrix transformation"
- 	^false!

Item was removed:
- ----- Method: DisplayTransform>>isMorphicTransform (in category 'testing') -----
- isMorphicTransform
- 	"Return true if the receiver is a MorphicTransform, that is specifies the transformation values explicitly."
- 	^false!

Item was removed:
- ----- Method: DisplayTransform>>isPureTranslation (in category 'testing') -----
- isPureTranslation
- 	"Return true if the receiver specifies no rotation or scaling."
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: DisplayTransform>>localBoundsToGlobal: (in category 'transforming rects') -----
- localBoundsToGlobal: aRectangle
- 	"Transform aRectangle from local coordinates into global coordinates"
- 	^Rectangle encompassing: (self localPointsToGlobal: aRectangle corners)!

Item was removed:
- ----- Method: DisplayTransform>>localPointToGlobal: (in category 'transforming points') -----
- localPointToGlobal: aPoint
- 	"Transform aPoint from local coordinates into global coordinates"
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: DisplayTransform>>localPointsToGlobal: (in category 'transforming points') -----
- localPointsToGlobal: inArray
- 	"Transform all the points of inArray from local into global coordinates"
- 	^inArray collect:[:pt| self localPointToGlobal: pt]!

Item was removed:
- ----- Method: DisplayTransform>>setIdentity (in category 'initialize') -----
- setIdentity
- 	"Initialize the receiver to the identity transformation (e.g., not affecting points)"
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: DisplayTransform>>sourceQuadFor: (in category 'transforming rects') -----
- sourceQuadFor: aRectangle
- 	^ aRectangle innerCorners collect: 
- 		[:p | self globalPointToLocal: p]!

Item was removed:
- ----- Method: DisplayTransform>>transformPoint: (in category 'transforming points') -----
- transformPoint: aPoint
- 	"Point transform double dispatch"
- 	^self localPointToGlobal: aPoint!

Item was removed:
- ----- Method: DisplayTransform>>transformRect: (in category 'transforming rects') -----
- transformRect: aRectangle
- 	^self localBoundsToGlobal: aRectangle!

Item was removed:
- ----- Method: DisplayTransform>>transformedBy: (in category 'converting') -----
- transformedBy: aTransform
- 	^self composedWithGlobal: aTransform!

Item was removed:
- ----- Method: EventSensor>>testJoystick: (in category '*Graphics-KernelExtensions') -----
- testJoystick: index
- 	"Sensor testJoystick: 3"
- 
- 	| f pt buttons status |
- 	f := Form extent: 110 at 50.
- 	[Sensor anyButtonPressed] whileFalse: [
- 		pt := Sensor joystickXY: index.
- 		buttons := Sensor joystickButtons: index.
- 		status :=
- 'xy: ', pt printString, '
- buttons: ', buttons printStringHex.
- 		f fillWhite.
- 		status displayOn: f at: 10 at 10.
- 		f displayOn: Display at: 10 at 10.
- 	].
- !

Item was removed:
- AbstractFont subclass: #FixedFaceFont
- 	instanceVariableNames: 'baseFont substitutionCharacter displaySelector'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Fonts'!
- 
- !FixedFaceFont commentStamp: 'tak 12/22/2004 01:45' prior: 0!
- I am a font for special purpose like password or fallback.
- I can show same form whenever someone requests any character.
- 
- Variable displaySelector is future use to show a form dynamically.
- (Although it would be unnecessary...)!

Item was removed:
- ----- Method: FixedFaceFont>>ascent (in category 'accessing') -----
- ascent
- 	^baseFont ascent!

Item was removed:
- ----- Method: FixedFaceFont>>ascentOf: (in category 'accessing') -----
- ascentOf: aCharacter
- 	^ self ascent!

Item was removed:
- ----- Method: FixedFaceFont>>baseFont (in category 'accessing') -----
- baseFont
- 	^baseFont!

Item was removed:
- ----- Method: FixedFaceFont>>baseFont: (in category 'accessing') -----
- baseFont: aFont
- 	baseFont := aFont.
- 	self fixSubstitutionCharacter.!

Item was removed:
- ----- Method: FixedFaceFont>>baseKern (in category 'accessing') -----
- baseKern
- 	^baseFont baseKern!

Item was removed:
- ----- Method: FixedFaceFont>>basicHasGlyphOf: (in category 'private') -----
- basicHasGlyphOf: aCharacter
- 
- 	" We present the same for any character, so, yes"
- 	^ true!

Item was removed:
- ----- Method: FixedFaceFont>>characterFormAt: (in category 'character shapes') -----
- characterFormAt: character 
- 	^ baseFont characterFormAt: substitutionCharacter!

Item was removed:
- ----- Method: FixedFaceFont>>depth (in category 'accessing') -----
- depth
- 
- 	^ self baseFont depth!

Item was removed:
- ----- Method: FixedFaceFont>>descent (in category 'accessing') -----
- descent
- 	^baseFont descent!

Item was removed:
- ----- Method: FixedFaceFont>>descentKern (in category 'accessing') -----
- descentKern
- 	^baseFont descentKern!

Item was removed:
- ----- Method: FixedFaceFont>>descentOf: (in category 'accessing') -----
- descentOf: aCharacter
- 	^ self descent!

Item was removed:
- ----- Method: FixedFaceFont>>displayErrorOn:length:at:kern: (in category 'displaying') -----
- displayErrorOn: aCanvas length: length at: aPoint kern: kernDelta 
- 	| maskedString |
- 	maskedString := String new: length.
- 	maskedString atAllPut: substitutionCharacter.
- 	^ baseFont
- 		displayString: maskedString
- 		on: aCanvas
- 		from: 1
- 		to: length
- 		at: aPoint
- 		kern: kernDelta!

Item was removed:
- ----- Method: FixedFaceFont>>displayErrorOn:length:at:kern:baselineY: (in category 'displaying') -----
- displayErrorOn: aCanvas length: length at: aPoint kern: kernDelta baselineY: baselineY
- 	| maskedString |
- 	maskedString := String new: length.
- 	maskedString atAllPut: substitutionCharacter.
- 	^ baseFont
- 		displayString: maskedString
- 		on: aCanvas
- 		from: 1
- 		to: length
- 		at: aPoint
- 		kern: kernDelta
- 		baselineY: baselineY!

Item was removed:
- ----- Method: FixedFaceFont>>displayPasswordOn:length:at:kern: (in category 'displaying') -----
- displayPasswordOn: aCanvas length: length at: aPoint kern: kernDelta 
- 	| maskedString |
- 	maskedString := String new: length.
- 	maskedString atAllPut: substitutionCharacter.
- 	^ baseFont
- 		displayString: maskedString
- 		on: aCanvas
- 		from: 1
- 		to: length
- 		at: aPoint
- 		kern: kernDelta!

Item was removed:
- ----- Method: FixedFaceFont>>displayPasswordOn:length:at:kern:baselineY: (in category 'displaying') -----
- displayPasswordOn: aCanvas length: length at: aPoint kern: kernDelta baselineY: baselineY
- 	| maskedString |
- 	maskedString := String new: length.
- 	maskedString atAllPut: substitutionCharacter.
- 	^ baseFont
- 		displayString: maskedString
- 		on: aCanvas
- 		from: 1
- 		to: length
- 		at: aPoint
- 		kern: kernDelta
- 		baselineY: baselineY!

Item was removed:
- ----- Method: FixedFaceFont>>displayString:on:from:to:at:kern: (in category 'displaying') -----
- displayString: aString on: aDisplayContext from: startIndex to: stopIndex at: aPoint kern: kernDelta 
- 	| size |
- 	size := stopIndex - startIndex + 1.
- 	^ self perform: displaySelector withArguments: (Array with: aDisplayContext with: size with: aPoint with: kernDelta with: aPoint y + self ascent).!

Item was removed:
- ----- Method: FixedFaceFont>>displayString:on:from:to:at:kern:baselineY: (in category 'displaying') -----
- displayString: aString on: aDisplayContext from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY
- 	| size |
- 	size := stopIndex - startIndex + 1.
- 	^ self perform: displaySelector withArguments: (Array with: aDisplayContext with: size with: aPoint with: kernDelta with: baselineY).!

Item was removed:
- ----- Method: FixedFaceFont>>displayString:on:from:to:at:kern:from: (in category 'displaying') -----
- displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta from: fromFont 
- 	| destPoint |
- 	destPoint := self
- 				displayString: aString
- 				on: aBitBlt
- 				from: startIndex
- 				to: stopIndex
- 				at: aPoint
- 				kern: kernDelta.
- 	^ Array with: stopIndex + 1 with: destPoint!

Item was removed:
- ----- Method: FixedFaceFont>>displayString:on:from:to:at:kern:from:baselineY: (in category 'displaying') -----
- displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta from: fromFont baselineY: baselineY
- 	| destPoint |
- 	destPoint := self
- 				displayString: aString
- 				on: aBitBlt
- 				from: startIndex
- 				to: stopIndex
- 				at: aPoint
- 				kern: kernDelta
- 				baselineY: baselineY.
- 	^destPoint!

Item was removed:
- ----- Method: FixedFaceFont>>emphasized: (in category 'accessing') -----
- emphasized: emph
- 	^self class new baseFont: (baseFont emphasized: emph)!

Item was removed:
- ----- Method: FixedFaceFont>>errorCharacter (in category 'accessing') -----
- errorCharacter
- 	^$?!

Item was removed:
- ----- Method: FixedFaceFont>>errorFont (in category 'initialize-release') -----
- errorFont
- 	displaySelector := #displayErrorOn:length:at:kern:baselineY:.
- 	substitutionCharacter := self errorCharacter.
- 	self fixSubstitutionCharacter.!

Item was removed:
- ----- Method: FixedFaceFont>>familyName (in category 'accessing') -----
- familyName
- 	^baseFont familyName, '-pw'!

Item was removed:
- ----- Method: FixedFaceFont>>fixSubstitutionCharacter (in category 'private') -----
- fixSubstitutionCharacter
- 	
- 	substitutionCharacter ifNil: [^ self].
- 	baseFont ifNil: [^ self].
- 	(baseFont hasGlyphOf: substitutionCharacter) ifTrue: [^ self].
- 
- 	((baseFont minCodePoint max: 33) to: baseFont maxCodePoint)
- 		detect: [:codePoint | baseFont hasGlyphOf: (Character value: codePoint)]
- 		ifFound: [:codePoint | substitutionCharacter := Character value: codePoint]
- 		ifNone: [
- 			baseFont := TextStyle defaultFont.
- 			substitutionCharacter := $?].	
- 	self
- 		assert: [baseFont hasGlyphOf: substitutionCharacter]
- 		description: 'Could not find a possible substitution character and font!!'.!

Item was removed:
- ----- Method: FixedFaceFont>>fontPointSize: (in category 'accessing') -----
- fontPointSize: aNumber 
- 	self baseFont: (StrikeFont familyName: baseFont familyName pointSize: aNumber) copy!

Item was removed:
- ----- Method: FixedFaceFont>>fontSize: (in category 'accessing') -----
- fontSize: aNumber 
- 	self baseFont: (StrikeFont familyName: baseFont familyName size: aNumber) copy!

Item was removed:
- ----- Method: FixedFaceFont>>foregroundColor (in category 'displaying') -----
- foregroundColor
- 
- 	^ baseFont foregroundColor!

Item was removed:
- ----- Method: FixedFaceFont>>foregroundColor: (in category 'displaying') -----
- foregroundColor: fgColor
- 
- 	baseFont foregroundColor: fgColor.!

Item was removed:
- ----- Method: FixedFaceFont>>formOf: (in category 'private') -----
- formOf: aCharacter
- 	"No need to check #hasGlyphOf:."
- 
- 	^ self characterFormAt: aCharacter!

Item was removed:
- ----- Method: FixedFaceFont>>glyphInfoOf:into: (in category 'private') -----
- glyphInfoOf: aCharacter into: glyphInfoArray
- "since we replace every character with substitutionCharacter, get my baseFont's glyphInfo for that"
- 	^ baseFont glyphInfoOf: substitutionCharacter into: glyphInfoArray.
- !

Item was removed:
- ----- Method: FixedFaceFont>>height (in category 'accessing') -----
- height
- 	^baseFont height!

Item was removed:
- ----- Method: FixedFaceFont>>initialize (in category 'initialize-release') -----
- initialize
- 
- 	baseFont := TextStyle defaultFont.
- 	self passwordFont.!

Item was removed:
- ----- Method: FixedFaceFont>>installOn:foregroundColor:backgroundColor: (in category 'displaying') -----
- installOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor
- 	^baseFont installOn: aDisplayContext foregroundColor: foregroundColor backgroundColor: backgroundColor!

Item was removed:
- ----- Method: FixedFaceFont>>isTTCFont (in category 'testing') -----
- isTTCFont
- 
- 	^ baseFont isTTCFont!

Item was removed:
- ----- Method: FixedFaceFont>>lineGrid (in category 'accessing') -----
- lineGrid
- 	^baseFont lineGrid!

Item was removed:
- ----- Method: FixedFaceFont>>maxCodePoint (in category 'accessing') -----
- maxCodePoint
- 	"Overwritten for robustness. The receiver MUST BE a reliable source of glyphs if all else fails. Font rendering must never stop."
- 	
- 	^ SmallInteger maxVal!

Item was removed:
- ----- Method: FixedFaceFont>>minSubstitutionCharacter (in category 'private') -----
- minSubstitutionCharacter
- 
- 	^ Character value: (baseFont ifNil: [0] ifNotNil: [baseFont minCodePoint])!

Item was removed:
- ----- Method: FixedFaceFont>>passwordCharacter (in category 'accessing') -----
- passwordCharacter
- 	^$*!

Item was removed:
- ----- Method: FixedFaceFont>>passwordFont (in category 'initialize-release') -----
- passwordFont
- 	displaySelector := #displayPasswordOn:length:at:kern:baselineY:.
- 	substitutionCharacter := self passwordCharacter.
- 	self fixSubstitutionCharacter.!

Item was removed:
- ----- Method: FixedFaceFont>>pointSize (in category 'accessing') -----
- pointSize
- 	^baseFont pointSize!

Item was removed:
- ----- Method: FixedFaceFont>>releaseCachedState (in category 'caching') -----
- releaseCachedState
- 	baseFont releaseCachedState.!

Item was removed:
- ----- Method: FixedFaceFont>>widthOf: (in category 'measuring') -----
- widthOf: aCharacter
- 	^ (baseFont hasGlyphOf: substitutionCharacter)
- 		ifTrue: [baseFont widthOf: substitutionCharacter]
- 		ifFalse: [1]!

Item was removed:
- Object subclass: #FontSet
- 	instanceVariableNames: ''
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Fonts'!
- 
- !FontSet commentStamp: '<historical>' prior: 0!
- FontSet provides a mechanism for storing a set of fonts as a class that can be conveniently filedOut, filedIn, and installed as a TextStyle.
- 
- The most common use is...
- 	Find a font you like.
- 	Use BitFont to convert a bunch of sizes to data files named, eg, LovelyNN.BF
- 	Use FontSet convertFontsNamed: 'Lovely' to produce a FontSet named Lovely.
- 	FileOut that FontSet for later use.
- 	Use Lovely installAsTextStyle to make all sizes available in a TextStyle
- 		named #Lovely in the TextConstants dictionary.
- 	Use ctrl-k in any text pane to select the new Lovely style for that paragraph.
- 	Then use cmd-1 through 5 or cmd-k to set the point-size for any selection.
- !

Item was removed:
- ----- Method: FontSet class>>acceptsLoggingOfCompilation (in category 'compiling') -----
- acceptsLoggingOfCompilation
- 	"Dont log sources for my subclasses, so as not to waste time
- 	and space storing printString versions of the string literals."
- 
- 	^super acceptsLoggingOfCompilation
- 		and:
- 			[self == FontSet]!

Item was removed:
- ----- Method: FontSet class>>compileFont: (in category 'compiling') -----
- compileFont: strikeFont 
- 	| tempName literalString header sizeStr familyName |
- 	tempName := 'FontTemp.sf2'.
- 	strikeFont writeAsStrike2named: tempName.
- 	literalString := (Base64MimeConverter mimeEncode: (FileStream readOnlyFileNamed: tempName) binary) contents fullPrintString.
- 	sizeStr := strikeFont pointSize asString.
- 	familyName := strikeFont name first: (strikeFont name findLast: [:x | x isDigit not]).
- 
- 	header := 'size' , sizeStr , '
- 	^ self fontNamed: ''' , familyName , sizeStr , ''' fromMimeLiteral:
- ' .
- 	self class
- 		compile: header , literalString
- 		classified: 'fonts'
- 		notifying: nil.
- 	FileDirectory default deleteFileNamed: tempName
- !

Item was removed:
- ----- Method: FontSet class>>convertFontsNamed: (in category 'as yet unclassified') -----
- convertFontsNamed: familyName  "FontSet convertFontsNamed: 'Palatino' "
- 	^ self convertFontsNamed: familyName inDirectoryNamed: ''!

Item was removed:
- ----- Method: FontSet class>>convertFontsNamed:inDirectoryNamed: (in category 'converting') -----
- convertFontsNamed: familyName inDirectoryNamed: dirName
- 		"FontSet convertFontsNamed: 'Tekton' inDirectoryNamed: 'Tekton Fonts' "
- 	"This utility is for use after you have used BitFont to produce data files 
- 	for the fonts you wish to use.  It will read the BitFont files and build
- 	a fontset class from them.  If one already exists, the sizes that can be
- 	found will be overwritten."
- 	"For this utility to work as is, the BitFont data files must be named 'familyNN.BF',
- 	and must reside in the directory named by dirName (use '' for the current directory)."
- 
- 	| allFontNames fontSet dir |
- 	"Check first for matching file names and usable FontSet class name."
- 	dir := dirName isEmpty
- 		ifTrue: [FileDirectory default]
- 		ifFalse: [FileDirectory default directoryNamed: dirName].
- 	allFontNames := dir fileNamesMatching: familyName , '##.BF'.
- 	allFontNames isEmpty ifTrue: [^ self error: 'No files found like ' , familyName , 'NN.BF'].
- 	fontSet := self fontSetClass: familyName.
- 	allFontNames do:
- 		[:each |
- 		Transcript cr; show: each.
- 		fontSet compileFont: (StrikeFont new readFromBitFont: (dir fullNameFor: each))]!

Item was removed:
- ----- Method: FontSet class>>convertTextStyleNamed: (in category 'converting') -----
- convertTextStyleNamed: aString
- 	| style fontSet |
- 	(style := TextStyle named: aString) ifNil: [^ self error: 'unknown text style ' , aString].
- 	fontSet := self fontSetClass: aString.
- 	style fontArray do: [:each | fontSet compileFont: each]!

Item was removed:
- ----- Method: FontSet class>>fileOut (in category 'filein/out') -----
- fileOut
- 	"FileOut and then change the properties of the file so that it won't be
- 	treated as text by, eg, email attachment facilities"
- 
- 	super fileOut.
- 	(FileStream oldFileNamed: self name , '.st') setFileTypeToObject; close!

Item was removed:
- ----- Method: FontSet class>>fontCategory (in category 'private') -----
- fontCategory
- 	^ #'Graphics-Fonts'!

Item was removed:
- ----- Method: FontSet class>>fontName (in category 'private') -----
- fontName
- 
- 	self flag: #bob.		"temporary hack until I figure out what's happening here"
- 	(self name beginsWith: superclass name) ifFalse: [^self name].
- 	^ (self name copyFrom: superclass name size + 1 to: self name size) asSymbol!

Item was removed:
- ----- Method: FontSet class>>fontNamed:fromLiteral: (in category 'installing') -----
- fontNamed: fontName fromLiteral: aString
- 	"NOTE -- THIS IS AN OBSOLETE METHOD THAT MAY CAUSE ERRORS.
- 
- The old form of fileOut for FontSets produced binary literal strings which may not be accurately read in systems with support for international character sets.  If possible, file the FontSet out again from a system that produces the newer MIME encoding (current def of compileFont:), and uses the corresponding altered version of this method.  If this is not easy, then
- 	file the fontSet into an older system (3.7 or earlier),
- 	assume it is called FontSetZork...
- 	execute FontSetZork installAsTextStyle.
- 	copy the compileFont: method from this system into that older one.
- 	remove the class FontSetZork.
- 	Execute:  FontSet convertTextStyleNamed: 'Zork', and see that it creates a new FontSetZork.
- 	FileOut the new class FontSetZork.
- 	The resulting file should be able to be read into this system.
- "
- 
- 	^ StrikeFont new 
- 		name: fontName;
- 		readFromStrike2Stream: (ReadStream on: aString asByteArray)!

Item was removed:
- ----- Method: FontSet class>>fontNamed:fromMimeLiteral: (in category 'installing') -----
- fontNamed: fontName fromMimeLiteral: aString
- 	"This method allows a font set to be captured as sourcecode in a subclass.
- 	The string literals will presumably be created by printing, eg,
- 		(FileStream readOnlyFileNamed: 'Palatino24.sf2') contentsOfEntireFile,
- 		and following the logic in compileFont: to encode and add a heading.
- 
- 	See the method installAsTextStyle to see how this can be used."
- 
- 	^ StrikeFont new 
- 		name: fontName;
- 		readFromStrike2Stream: (Base64MimeConverter mimeDecodeToBytes: aString readStream)!

Item was removed:
- ----- Method: FontSet class>>fontSetClass: (in category 'private') -----
- fontSetClass: aString
- 	| className fontSet |
- 	className := (self name , (aString select: [:c | c isAlphaNumeric]) capitalized) asSymbol.
- 	fontSet := Smalltalk
- 		at: className
- 		ifAbsentPut: [self
- 			subclass: className
- 			instanceVariableNames: ''
- 			classVariableNames: ''
- 			poolDictionaries: ''
- 			category: self fontCategory].
- 	(fontSet inheritsFrom: self) ifFalse: [^ self error: 'The name ' , className , ' is already in use'].
- 	^ fontSet!

Item was removed:
- ----- Method: FontSet class>>installAsDefault (in category 'installing') -----
- installAsDefault  "FontSetNewYork installAsDefault"
- 	(UIManager default confirm: 'Do you want to install
- ''' , self fontName , ''' as default font?')
- 		ifFalse: [^ self].
- 	self installAsTextStyle.
- 	"TextConstants at: #OldDefaultTextStyle put: TextStyle default."
- 	TextConstants at: #DefaultTextStyle put: (TextStyle named: self fontName).
- 	#(ListParagraph PopUpMenu StandardSystemView) do:[:className|
- 		Smalltalk at: className ifPresent:[:aClass| aClass initialize].
- 	].!

Item was removed:
- ----- Method: FontSet class>>installAsTextStyle (in category 'installing') -----
- installAsTextStyle  "FontSetNewYork installAsTextStyle"
- 	| selectors |
- 	(TextConstants includesKey: self fontName) ifTrue:
- 		[(self confirm: 
- self fontName , ' is already defined in TextConstants.
- Do you want to replace that definition?')
- 			ifFalse: [^ self]].
- 	selectors := (self class selectors select: [:s | s beginsWith: 'size']) sort
- 		 replace: [:each | self perform: each].
- 	TextConstants
- 		at: self fontName
- 		put: (TextStyle fontArray: selectors)!

Item was removed:
- ----- Method: FontSet class>>size:fromLiteral: (in category 'installing') -----
- size: pointSize fromLiteral: aString 
- 	"This method allows a font set to be captured as sourcecode in a subclass.
- 	The string literals will presumably be created by printing, eg,
- 		(FileStream readOnlyFileNamed: 'Palatino24.sf2') contentsOfEntireFile,
- 		and then pasting into a browser after a heading like, eg,
- size24
- 	^ self size: 24 fromLiteral:
- 	'--unreadable binary data--'
- 
- 	See the method installAsTextStyle to see how this can be used."
- 
- 	"This method is old and for backward compatibility only.
- 	please use fontNamed:fromLiteral: instead."
- 
- 	self flag: #bob.	"used in Alan's projects"
- 	^(StrikeFont new)
- 		name: self fontName , (pointSize < 10 
- 							ifTrue: ['0' , pointSize printString]
- 							ifFalse: [pointSize printString]);
- 		readFromStrike2Stream: ((RWBinaryOrTextStream with: aString)
- 					reset;
- 					binary);
- 		yourself!

Item was removed:
- DisplayMedium subclass: #Form
- 	instanceVariableNames: 'bits width height depth offset'
- 	classVariableNames: 'CompressOnSnapshot'
- 	poolDictionaries: ''
- 	category: 'Graphics-Display Objects'!
- 
- !Form commentStamp: 'cbc 5/5/2017 10:07' prior: 0!
- A rectangular array of pixels, used for holding images.  All pictures, including character images are Forms.  The depth of a Form is how many bits are used to specify the color at each pixel.  The actual bits are held in a Bitmap, whose internal structure is different at each depth.  Class Color allows you to deal with colors without knowing how they are actually encoded inside a Bitmap.
- 	  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.
- 	Forms are indexed starting at 0 instead of 1; thus, the top-left pixel of a Form has coordinates 0 at 0.
- 	Forms are combined using BitBlt.  See the comment in class BitBlt.  Forms that repeat many times to fill a large destination are InfiniteForms.
- 
- 	colorAt: x at y		Returns the abstract Color at this location
- 	displayAt: x at y		shows this form on the screen
- 	displayOn: aMedium at: x at y	shows this form in a Window, a Form, or other DisplayMedium
- 	fillColor: aColor		Set all the pixels to the color.
- 	edit		launch an editor to change the bits of this form.
- 	pixelValueAt: x at y	The encoded color.  The encoding depends on the depth.
- 
- Note: If you want to hook up other external forms/displayScreens, please look at the (successful) Graphics-External package in http://www.squeaksource.com/Balloon3D.!

Item was removed:
- ----- Method: Form class>>allTypicalFileExtensions (in category 'file list services') -----
- allTypicalFileExtensions
- 
- 	^ImageReadWriter allTypicalFileExtensions add: 'form'; yourself!

Item was removed:
- ----- Method: Form class>>alphaScale (in category 'mode constants') -----
- alphaScale
- 	"Answer the integer denoting BitBlt's pre-multiply rgb components by alpha (alphaScale) rule."
- 
- 	^ 42!

Item was removed:
- ----- Method: Form class>>alphaUnscale (in category 'mode constants') -----
- alphaUnscale
- 	"Answer the integer denoting BitBlt's post-multiply rgb components by alpha (alphaUnscale) rule."
- 
- 	^ 43!

Item was removed:
- ----- Method: Form class>>and (in category 'mode constants') -----
- and
- 	"Answer the integer denoting the logical 'and' combination rule."
- 
- 	^1!

Item was removed:
- ----- Method: Form class>>blend (in category 'mode constants') -----
- blend
- 	"Answer the integer denoting BitBlt's alpha blend combination rule."
- 	^24!

Item was removed:
- ----- Method: Form class>>blendAlpha (in category 'mode constants') -----
- blendAlpha
- 	"Answer the integer denoting BitBlt's blend-with-constant-alpha rule."
- 
- 	^ 30!

Item was removed:
- ----- Method: Form class>>blendAlphaScaled (in category 'mode constants') -----
- blendAlphaScaled
- 	"Answer the integer denoting BitBlt's blend-with-alpha-scaled rule."
- 
- 	^ 34!

Item was removed:
- ----- Method: Form class>>blendAlphaUnscaled (in category 'mode constants') -----
- blendAlphaUnscaled
- 	"Answer the integer denoting BitBlt's blend-with-alpha-unscaled rule."
- 
- 	^ 44!

Item was removed:
- ----- Method: Form class>>compareMatchColor (in category 'mode constants') -----
- compareMatchColor
- 	"The primCompare test id values are
- 	compareMatchColors -> 0
- 	compareNotColorANotColorB -> 1
- 	compareNotColorAMatchColorB -> 2"
- 	^0!

Item was removed:
- ----- Method: Form class>>compareNotColorAMatchColorB (in category 'mode constants') -----
- compareNotColorAMatchColorB
- 	"The primCompare test id values are
- 	compareMatchColors -> 0
- 	compareNotColorANotColorB -> 1
- 	compareNotColorAMatchColorB -> 2"
- 	^2!

Item was removed:
- ----- Method: Form class>>compareNotColorANotColorB (in category 'mode constants') -----
- compareNotColorANotColorB
- 	"The primCompare test id values are
- 	compareMatchColors -> 0
- 	compareNotColorANotColorB -> 1
- 	compareNotColorAMatchColorB -> 2"
- 	^1!

Item was removed:
- ----- Method: Form class>>compareTallyFlag (in category 'mode constants') -----
- compareTallyFlag
- 	"The primCompare test id values are ORR'd with 8 to indicate tallying rather than simply reporting the first hit"
- 	^8!

Item was removed:
- ----- Method: Form class>>compressOnSnapshot (in category 'preferences') -----
- compressOnSnapshot
- 	<preference: 'Always compress graphics data on snapshot'
- 		categoryList: #(performance Graphics)
- 		description: 'When enabled, graphics data such as all instances of Form are compressed during image snapshots -- even when the image will not quit after the snapshot. This includes cache clean-up such as the TrueType glyph cache. Disable to avoid render lags after snapshots at the cost of a bigger footprint of your .image file. Note that snapshot-and-quit always compresses graphics data.'
- 		type: #Boolean>
- 
- 	^ CompressOnSnapshot ifNil: [true]!

Item was removed:
- ----- Method: Form class>>compressOnSnapshot: (in category 'preferences') -----
- compressOnSnapshot: aBoolean
- 
- 	CompressOnSnapshot := aBoolean.!

Item was removed:
- ----- Method: Form class>>dotOfSize: (in category 'instance creation') -----
- dotOfSize: diameter
- 	"Create a form which contains a round black dot."
- 	| radius form bb rect centerX centerY centerYBias centerXBias radiusSquared xOverY maxy dx |
- 	radius := diameter//2.
- 	form := self extent: diameter at diameter offset: (0 at 0) - (radius at radius).	
- 	bb := (BitBlt toForm: form)
- 		sourceX: 0; sourceY: 0;
- 		combinationRule: Form over;
- 		fillColor: Color black.
- 	rect := form boundingBox.
- 	centerX := rect center x.
- 	centerY := rect center y.
- 	centerYBias := rect height odd ifTrue: [0] ifFalse: [1].
- 	centerXBias := rect width odd ifTrue: [0] ifFalse: [1].
- 	radiusSquared := (rect height asFloat / 2.0) squared - 0.01.
- 	xOverY := rect width asFloat / rect height asFloat.
- 	maxy := rect height - 1 // 2.
- 
- 	"First do the inner fill, and collect x values"
- 	0 to: maxy do:
- 		[:dy |
- 		dx := ((radiusSquared - (dy * dy) asFloat) sqrt * xOverY) truncated.
- 		bb	destX: centerX - centerXBias - dx
- 			destY: centerY - centerYBias - dy
- 			width: dx + dx + centerXBias + 1
- 			height: 1;
- 			copyBits.
- 		bb	destY: centerY + dy;
- 			copyBits].
- 	^ form
- "
- Time millisecondsToRun:
- 	[1 to: 20 do: [:i | (Form dotOfSize: i) displayAt: (i*20)@(i*20)]]
- "!

Item was removed:
- ----- Method: Form class>>dotOfSize:color: (in category 'examples') -----
- dotOfSize: diameter color: color
- 
- 	| form |
- 	form := self extent: diameter asPoint depth: Display depth.
- 	form getCanvas fillOval: form boundingBox color: color.
- 	^form!

Item was removed:
- ----- Method: Form class>>erase (in category 'mode constants') -----
- erase
- 	"Answer the integer denoting mode erase."
- 
- 	^4!

Item was removed:
- ----- Method: Form class>>erase1bitShape (in category 'mode constants') -----
- erase1bitShape
- 	"Answer the integer denoting mode erase."
- 
- 	^ 26!

Item was removed:
- ----- Method: Form class>>exampleBorder (in category 'examples') -----
- exampleBorder    "Form exampleBorder"
- 	"This example demonstrates the border finding algorithm. Start
- 	by having the user sketch on the screen (end with option-click) and then select a rectangular
- 	area of the screen which includes all of the area to be filled. Finally,
- 	(with crosshair cursor), the user points at the interior of the region to be
- 	outlined, and the region begins with that place as its seed."
- 	| f r interiorPoint |
- 	Form exampleSketch.		"sketch a little area with an enclosed region"
- 	r := Rectangle fromUser.
- 	f := Form fromDisplay: r.
- 	interiorPoint := Cursor crossHair showWhile:
- 		[Sensor waitButton - r origin].
- 	Cursor execute showWhile:
- 		[f shapeBorder: Color blue width: 2 interiorPoint: interiorPoint
- 			sharpCorners: false internal: false].
- 	f displayOn: Display at: r origin	!

Item was removed:
- ----- Method: Form class>>exampleEdits (in category 'examples') -----
- exampleEdits
- 	"In Form category editing are messages edit and bitEdit that make it possible to 
- 	create editors on instances of Form. 
- 	 
- 	This is the general form editor:
- 	| f | 
- 	f := Form fromUser. 
- 	f edit. 
- 	 
- 	This is the general bit editor:
- 	| f | 
- 	f := Form fromUser. 
- 	f bitEdit."!

Item was removed:
- ----- Method: Form class>>exampleMagnify (in category 'examples') -----
- exampleMagnify
- 
- 	| f m |
- 	f := Form fromUser.
- 	m := f magnify: f boundingBox by: 5 @ 5.
- 	m displayOn: Display at: Sensor waitButton
- 
- 	"Form exampleMagnify."!

Item was removed:
- ----- Method: Form class>>exampleShrink (in category 'examples') -----
- exampleShrink
- 
- 	| f s |
- 	f := Form fromUser.
- 	s := f shrink: f boundingBox by: 2 @ 5.
- 	s displayOn: Display at: Sensor waitButton	
- 
- 	"Form exampleShrink."!

Item was removed:
- ----- Method: Form class>>exampleSketch (in category 'examples') -----
- exampleSketch
- 	"This is a simple drawing algorithm to get a sketch on the display screen.
- 	Draws whenever mouse button down.  Ends with option-click."
- 	| aPen color |
- 	aPen := Pen new.
- 	color := 0.
- 	[Sensor yellowButtonPressed]
- 		whileFalse:
- 		[aPen place: Sensor cursorPoint; color: (color := color + 1).
- 		[Sensor redButtonPressed]
- 			whileTrue: [aPen goto: Sensor cursorPoint]].
- 	Sensor waitNoButton.
- 
- 	"Form exampleSketch"!

Item was removed:
- ----- Method: Form class>>exampleSpaceFill (in category 'examples') -----
- exampleSpaceFill    "Form exampleSpaceFill"
- 	"This example demonstrates the area filling algorithm. Starts by having
- 	the user sketch on the screen (ended by option-click) and then select a rectangular
- 	area of the screen which includes all of the area to be filled. Finally,
- 	(with crosshair cursor), the user points at the interior of some region to be
- 	filled, and the filling begins with that place as its seed."
- 	| f r interiorPoint |
- 	Form exampleSketch.		"sketch a little area with an enclosed region"
- 	r := Rectangle fromUser.
- 	f := Form fromDisplay: r.
- 	interiorPoint := Cursor crossHair showWhile:
- 		[Sensor waitButton - r origin].
- 	Cursor execute showWhile:
- 		[f shapeFill: Color gray interiorPoint: interiorPoint].
- 	f displayOn: Display at: r origin	!

Item was removed:
- ----- Method: Form class>>extent: (in category 'instance creation') -----
- extent: extentPoint
- 	"Answer an instance of me with a blank bitmap of depth 1."
- 
- 	^ self extent: extentPoint depth: 1
- !

Item was removed:
- ----- Method: Form class>>extent:depth: (in category 'instance creation') -----
- extent: extentPoint depth: bitsPerPixel
- 	"Answer an instance of me with blank bitmap of the given dimensions and depth."
- 
- 	^ self basicNew setExtent: extentPoint depth: bitsPerPixel
- !

Item was removed:
- ----- Method: Form class>>extent:depth:bits: (in category 'instance creation') -----
- extent: extentPoint depth: bitsPerPixel bits: aBitmap
- 	"Answer an instance of me with blank bitmap of the given dimensions and depth."
- 
- 	^ self basicNew setExtent: extentPoint depth: bitsPerPixel bits: aBitmap!

Item was removed:
- ----- Method: Form class>>extent:depth:fromArray:offset: (in category 'instance creation') -----
- extent: extentPoint depth: bitsPerPixel fromArray: anArray offset: offsetPoint 
- 	"Answer an instance of me with a pixmap of the given depth initialized from anArray."
- 
- 	^ (self extent: extentPoint depth: bitsPerPixel)
- 		offset: offsetPoint;
- 		initFromArray: anArray
- !

Item was removed:
- ----- Method: Form class>>extent:fromArray:offset: (in category 'instance creation') -----
- extent: extentPoint fromArray: anArray offset: offsetPoint 
- 	"Answer an instance of me of depth 1 with bitmap initialized from anArray."
- 
- 	^ (self extent: extentPoint depth: 1)
- 		offset: offsetPoint;
- 		initFromArray: anArray
- !

Item was removed:
- ----- Method: Form class>>extent:fromStipple: (in category 'instance creation') -----
- extent: extentPoint fromStipple: fourNibbles
- 	"Answer an instance of me with bitmap initialized from
- 	a repeating 4x4 bit stipple encoded in a 16-bit constant."
- 	
- 	^ (self extent: extentPoint depth: 1)
- 		initFromArray: ((1 to: 4) collect:
- 				[:i | | nibble |
- 				nibble := (fourNibbles bitShift: -4*(4-i)) bitAnd: 16rF.
- 				16r11111111 * nibble])  "fill 32 bits with each 4-bit nibble"
- !

Item was removed:
- ----- Method: Form class>>extent:offset: (in category 'instance creation') -----
- extent: extentPoint offset: offsetPoint 
- 	"Answer an instance of me with a blank bitmap of depth 1."
- 
- 	^ (self extent: extentPoint depth: 1) offset: offsetPoint
- !

Item was removed:
- ----- Method: Form class>>fileReaderServicesForDirectory: (in category 'file list services') -----
- fileReaderServicesForDirectory: aFileDirectory
- 	^{
- 		self serviceImageImportDirectory.
- 		self serviceImageImportDirectoryWithSubdirectories.
- 	}!

Item was removed:
- ----- Method: Form class>>fileReaderServicesForFile:suffix: (in category 'file list services') -----
- fileReaderServicesForFile: fullName suffix: suffix
- 
- 	^(self  allTypicalFileExtensions 
- 		includes: suffix)
- 		ifTrue: [ self services ]
- 		ifFalse: [#()]
- !

Item was removed:
- ----- Method: Form class>>fromBMPFile: (in category 'BMP file reading') -----
- fromBMPFile: aBinaryStream
- 	"Obsolete"
- 	^self fromBinaryStream: aBinaryStream.!

Item was removed:
- ----- Method: Form class>>fromBMPFileNamed: (in category 'BMP file reading') -----
- fromBMPFileNamed: fileName
- 	"Obsolete"
- 	^self fromFileNamed: fileName
- !

Item was removed:
- ----- Method: Form class>>fromBinaryStream: (in category 'instance creation') -----
- fromBinaryStream: aBinaryStream
- 	"Read a Form or ColorForm from given file, using the first byte of the file to guess its format. Currently handles: GIF, uncompressed BMP, and both old and new DisplayObject writeOn: formats, JPEG, and PCX. Return nil if the file could not be read or was of an unrecognized format."
- 
- 	| firstByte |
- 	aBinaryStream binary.
- 	firstByte := aBinaryStream next.
- 	firstByte = 1 ifTrue: [
- 		"old Squeakform format"
- 		^ self new readFromOldFormat: aBinaryStream].
- 	firstByte = 2 ifTrue: [
- 		"new Squeak form format"
- 		^ self new readFrom: aBinaryStream].
- 
- 	"Try for JPG, GIF, or PCX..."
- 	"Note: The following call closes the stream."
- 	^ ImageReadWriter formFromStream: aBinaryStream
- !

Item was removed:
- ----- Method: Form class>>fromDisplay: (in category 'instance creation') -----
- fromDisplay: aRectangle 
- 	"Answer an instance of me with bitmap initialized from the area of the 
- 	display screen defined by aRectangle."
- 
- 	^ (self extent: aRectangle extent depth: Display depth)
- 		fromDisplay: aRectangle!

Item was removed:
- ----- Method: Form class>>fromDisplay:using: (in category 'instance creation') -----
- fromDisplay: aRectangle using: oldForm
- 	"Like fromDisplay: only if oldForm is the right size, copy into it and answer it instead."
- 
- 	((oldForm ~~ nil) and: [oldForm extent = aRectangle extent])
- 		ifTrue:
- 			[oldForm fromDisplay: aRectangle.
- 			 ^ oldForm]
- 		ifFalse:
- 			[^ self fromDisplay: aRectangle]!

Item was removed:
- ----- Method: Form class>>fromFileNamed: (in category 'instance creation') -----
- fromFileNamed: fileName
- 	"Read a Form or ColorForm from the given file."
- 
- 	| file form |
- 	file := (FileStream readOnlyFileNamed: fileName) binary.
- 	form := self fromBinaryStream: file.
- 	Smalltalk isMorphic ifTrue:[
- 		Project current resourceManager
- 			addResource: form
- 			url: (FileDirectory urlForFileNamed: file name) asString].
- 	file close.
- 	^ form
- !

Item was removed:
- ----- Method: Form class>>fromUser (in category 'instance creation') -----
- fromUser
- 	"Answer an instance of me with bitmap initialized from the area of the 
- 	display screen designated by the user. The grid for selecting an area is 
- 	1 at 1."
- 
- 	^self fromUser: 1 @ 1!

Item was removed:
- ----- Method: Form class>>fromUser: (in category 'instance creation') -----
- fromUser: gridPoint
- 	"Answer an instance of me with bitmap initialized from the area of the 
- 	display screen designated by the user. The grid for selecting an area is 
- 	aPoint. Ensures that the returned form has positive extent."
- 	| rect |
- 	rect := Rectangle fromUser: gridPoint.
- 	^ self fromDisplay: (rect origin extent: (rect extent max: gridPoint))!

Item was removed:
- ----- Method: Form class>>fromUserWithExtent: (in category 'instance creation') -----
- fromUserWithExtent: anExtent
- 	"Answer an instance of me with bitmap initialized from the area of the 
- 	display screen whose origin is designated by the user and whose size is anExtent"
- 
- 	^ self fromDisplay: (Rectangle originFromUser: anExtent)
- 
- "(Form fromUserWithExtent: 50 at 50) displayAt: 10 at 10"!

Item was removed:
- ----- Method: Form class>>importImage: (in category 'fileIn/Out') -----
- importImage: fullName
- 	"Import the given image file and store the resulting Form in the default Imports.
- 	The image is named with the short filename up to the first period, possibly with additions from the directory path to make it unique."
- 
- 	Imports default importImageFromFileNamed: fullName.
- !

Item was removed:
- ----- Method: Form class>>importImageAndShowImports: (in category 'file list services') -----
- importImageAndShowImports: fullName
- 
- 	self importImage: fullName.
- 	Imports default explore.!

Item was removed:
- ----- Method: Form class>>importImageDirectory: (in category 'fileIn/Out') -----
- importImageDirectory: dir
- 	"Import the given image file and store the resulting Form in the default Imports.
- 	The image is named with the short filename up to the first period, possibly with additions from the directory path to make it unique."
- 
- 	Imports default importImageDirectory: dir
- !

Item was removed:
- ----- Method: Form class>>importImageDirectoryWithSubdirectories: (in category 'fileIn/Out') -----
- importImageDirectoryWithSubdirectories: dir
- 	"Import the given image file and store the resulting Form in the default Imports.
- 	The image is named with the short filename up to the first period, possibly with additions from the directory path to make it unique."
- 
- 	Imports default importImageDirectoryWithSubdirectories: dir
- !

Item was removed:
- ----- Method: Form class>>initialize (in category 'initialize-release') -----
- initialize
- 
- 	FileServices registerFileReader: self!

Item was removed:
- ----- Method: Form class>>makeStar (in category 'examples') -----
- makeStar  "See the similar example in OpaqueForm"
- 	| sampleForm pen |
- 	sampleForm := Form extent: 50 at 50.  "Make a form"
- 	pen := Pen newOnForm: sampleForm.
- 	pen place: 24 at 50; turn: 18.		"Draw a 5-pointed star on it."
- 	1 to: 5 do: [:i | pen go: 19; turn: 72; go: 19; turn: -144].
- 	^ sampleForm
- "
- Form makeStar follow: [Sensor cursorPoint]
- 				while: [Sensor noButtonPressed]
- "!

Item was removed:
- ----- Method: Form class>>oldErase1bitShape (in category 'mode constants') -----
- oldErase1bitShape
- 	"Answer the integer denoting mode erase."
- 
- 	^ 17!

Item was removed:
- ----- Method: Form class>>oldPaint (in category 'mode constants') -----
- oldPaint
- 	"Answer the integer denoting the 'paint' combination rule."
- 
- 	^16!

Item was removed:
- ----- Method: Form class>>openAsBackground: (in category 'file list services') -----
- openAsBackground: fullName
- 	"Set an image as a background image.  Support Squeak's common file format 
- 	(GIF, JPG, PNG, 'Form stoteOn: (run coded)' and BMP)"
- 
- 	(self fromFileNamed: fullName) setAsBackground!

Item was removed:
- ----- Method: Form class>>openImageInWindow: (in category 'file list services') -----
- openImageInWindow: fullName
- 	"Handle five file formats: GIF, JPG, PNG, Form storeOn: (run coded), and BMP.
- 	Fail if file format is not recognized."
- 
- 	| image myStream |
- 
- 	myStream := (FileStream readOnlyFileNamed: fullName) binary.
- 	[image := self fromBinaryStream: myStream.
- 	Project current openImage: image name: fullName saveResource: true]
- 		ensure: [myStream close]!

Item was removed:
- ----- Method: Form class>>over (in category 'mode constants') -----
- over
- 	"Answer the integer denoting mode over."
- 
- 	^3!

Item was removed:
- ----- Method: Form class>>paint (in category 'mode constants') -----
- paint
- 	"Answer the integer denoting the 'paint' combination rule."
- 
- 	^25!

Item was removed:
- ----- Method: Form class>>paintAlpha (in category 'mode constants') -----
- paintAlpha
- 	"Answer the integer denoting BitBlt's paint-with-constant-alpha rule."
- 
- 	^ 31!

Item was removed:
- ----- Method: Form class>>reverse (in category 'mode constants') -----
- reverse
- 	"Answer the integer denoting mode reverse."
- 
- 	^6!

Item was removed:
- ----- Method: Form class>>rgbMul (in category 'mode constants') -----
- rgbMul
- 	"Answer the integer denoting 'Multiply each color component, 
- 	 their values regarded as fractions of 1' rule."
- 
- 	^ 37!

Item was removed:
- ----- Method: Form class>>serviceImageAsBackground (in category 'file list services') -----
- serviceImageAsBackground
- 	"Answer a service for setting the desktop background from a given graphical file's contents"
- 
- 	^ SimpleServiceEntry 
- 		provider: self 
- 		label: 'use graphic as background' translatedNoop
- 		selector: #openAsBackground:
- 		description: 'use the graphic as the background for the desktop' translatedNoop
- 		buttonLabel: 'background' translatedNoop!

Item was removed:
- ----- Method: Form class>>serviceImageImportAndShowImports (in category 'file list services') -----
- serviceImageImportAndShowImports
- 	"Answer a service for reading a graphic into ImageImports"
- 
- 	^	SimpleServiceEntry
- 			provider: self 
- 			label: 'read graphic into and show ImageImports'
- 			selector: #importImageAndShowImports:
- 			description: 'Load a graphic, placing it in the ImageImports repository and browse that repository.'
- 			buttonLabel: 'import'!

Item was removed:
- ----- Method: Form class>>serviceImageImportDirectory (in category 'file list services') -----
- serviceImageImportDirectory
- 	"Answer a service for reading a graphic into ImageImports"
- 
- 	^(SimpleServiceEntry
- 			provider: self 
- 			label: 'import all images from this directory' translatedNoop
- 			selector: #importImageDirectory:
- 			description: 'Load all graphics found in this directory, adding them to the ImageImports repository.' translatedNoop
- 			buttonLabel: 'import dir' translatedNoop)
- 			argumentGetter: [ :fileList | fileList directory ];
- 			yourself
- !

Item was removed:
- ----- Method: Form class>>serviceImageImportDirectoryWithSubdirectories (in category 'file list services') -----
- serviceImageImportDirectoryWithSubdirectories
- 	"Answer a service for reading all graphics from a directory and its subdirectories into ImageImports"
- 
- 	^(SimpleServiceEntry
- 			provider: self 
- 			label: 'import all images from here and subdirectories' translatedNoop
- 			selector: #importImageDirectoryWithSubdirectories:
- 			description: 'Load all graphics found in this directory and its subdirectories, adding them to the ImageImports repository.' translatedNoop
- 			buttonLabel: 'import subdirs' translatedNoop)
- 			argumentGetter: [ :fileList | fileList directory ];
- 			yourself
- !

Item was removed:
- ----- Method: Form class>>serviceImageImports (in category 'file list services') -----
- serviceImageImports
- 	"Answer a service for reading a graphic into ImageImports"
- 
- 	^	SimpleServiceEntry
- 			provider: self 
- 			label: 'read graphic into ImageImports'
- 			selector: #importImage:
- 			description: 'Load a graphic, placing it in the ImageImports repository.'
- 			buttonLabel: 'import'!

Item was removed:
- ----- Method: Form class>>serviceOpenImageInWindow (in category 'file list services') -----
- serviceOpenImageInWindow
- 	"Answer a service for opening a graphic in a window"
- 
- 	^ SimpleServiceEntry 
- 		provider: self 
- 		label: 'open graphic in a window' translatedNoop
- 		selector: #openImageInWindow:
- 		description: 'open a graphic file in a window' translatedNoop
- 		buttonLabel: 'open' translatedNoop!

Item was removed:
- ----- Method: Form class>>services (in category 'file list services') -----
- services
- 
- 	^ Array 
- 		with: self serviceImageImports
- 		with: self serviceImageImportAndShowImports
- 		with: self serviceOpenImageInWindow
- 		with: self serviceImageAsBackground !

Item was removed:
- ----- Method: Form class>>shutDown: (in category 'shut down') -----
- shutDown: quitting
- 	"When quitting, compress all instances in the system.  Will decompress on demand after start-up. Note that #compressOnShapshot can avoid hibernating forms during no-quit snapshotting to keep the system as responsive as possible directly after."
- 
- 	"Form shutDown: true"
- 	(quitting or: [self compressOnSnapshot]) ifTrue: [
- 		Form allInstancesDo: [:f | f hibernate].
- 		ColorForm allInstancesDo: [:f | f hibernate]].!

Item was removed:
- ----- Method: Form class>>toothpaste: (in category 'examples') -----
- toothpaste: diam		"Display restoreAfter: [Form toothpaste: 30]"
- 	"Draws wormlike lines by laying down images of spheres.
- 	See Ken Knowlton, Computer Graphics, vol. 15 no. 4 p352.
- 	Draw with mouse button down; terminate by option-click."
- 	| facade ball filter point queue port color q colors colr colr2 |
- 	colors := Display depth = 1
- 		ifTrue: [Array with: Color black]
- 		ifFalse: [Color red wheel: 12].
- 	facade := Form extent: diam at diam offset: (diam // -2) asPoint.
- 	(Form dotOfSize: diam) displayOn: facade
- 			at: (diam // 2) asPoint clippingBox: facade boundingBox
- 			rule: Form under fillColor: Color white.
- 	#(1 2 3) do:
- 		[:x |  "simulate facade by circles of gray"
- 		(Form dotOfSize: x * diam // 5) displayOn: facade
- 			at: (diam * 2 // 5) asPoint clippingBox: facade boundingBox
- 			rule: Form under
- 			fillColor: (Color perform: 
- 					(#(black gray lightGray) at: x)).
- 		"facade displayAt: 50*x at 50"].
- 	ball := Form dotOfSize: diam.
- 	color := 8.
- 	[port := BitBlt toForm: Display.
- 	"Expand 1-bit forms to any pixel depth"
- 	port colorMap: (Bitmap with: 0 with: 16rFFFFFFFF).
- 	queue := OrderedCollection new: 32.
- 	16 timesRepeat: [queue addLast: -20 @ -20].
- 	Sensor waitButton.
- 	Sensor yellowButtonPressed ifTrue: [^ self].
- 	filter := Sensor cursorPoint.
- 	colr := colors atWrap: (color := color + 5).  "choose increment relatively prime to colors size"
- 	colr2 := colr alphaMixed: 0.3 with: Color white.
- 	[Sensor redButtonPressed or: [queue size > 0]] whileTrue:
- 		[filter := filter * 4 + Sensor cursorPoint  //  5.
- 		point := Sensor redButtonPressed
- 			ifTrue: [filter] ifFalse: [-20 @ -20].
- 		port copyForm: ball to: point rule: Form paint fillColor: colr.
- 		(q := queue removeFirst) == nil ifTrue: [^ self].	"exit"
- 		Display depth = 1
- 			ifTrue: [port copyForm: facade to: q rule: Form erase]
- 			ifFalse: [port copyForm: facade to: q rule: Form paint fillColor: colr2].
- 		Sensor redButtonPressed ifTrue: [queue addLast: point]]] repeat.
- !

Item was removed:
- ----- Method: Form class>>under (in category 'mode constants') -----
- under
- 	"Answer the integer denoting mode under."
- 
- 	^7!

Item was removed:
- ----- Method: Form class>>unload (in category 'class initialization') -----
- unload
- 
- 	FileServices unregisterFileReader: self !

Item was removed:
- ----- Method: Form class>>xorHack: (in category 'examples') -----
- xorHack: size  "Display restoreAfter: [Form xorHack: 256]"
- 	"Draw a smiley face or stick figure, and end with option-click.
- 	Thereafter image gets 'processed' as long as you have button down.
- 	If you stop at just the right time, you'll see you figure upside down,
- 	and at the end of a full cycle, you'll see it perfectly restored.
- 	Dude -- this works in color too!!"
- 	| rect form i bb |
- 	rect := 5 @ 5 extent: size @ size.
- 	Display fillWhite: rect; border: (rect expandBy: 2) width: 2.
- 	Display border: (rect topRight - (0 @ 2) extent: rect extent * 2 + 4) width: 2.
- 	Form exampleSketch.
- 	form := Form fromDisplay: rect.
- 	bb := form boundingBox.
- 	i := 0.
- 	[Sensor yellowButtonPressed] whileFalse:
- 		[[Sensor redButtonPressed] whileTrue:
- 			[i := i + 1.
- 			(Array with: 0 @ 1 with: 0 @ -1 with: 1 @ 0 with: -1 @ 0) do:
- 				[:d | form copyBits: bb from: form at: d
- 					clippingBox: bb rule: Form reverse fillColor: nil].
- 			form displayAt: rect topLeft.
- 			i+2\\size < 4 ifTrue: [(Delay forMilliseconds: 300) wait]].
- 		(form magnify: form boundingBox by: 2 @ 2) displayAt: rect topRight + (2 @ 0).
- 		Sensor waitButton].!

Item was removed:
- ----- Method: Form>>adjustBrightness: (in category 'converting') -----
- adjustBrightness: brightness
- 
- 	^ self collectColors: [:color | color adjustSaturation: 0 brightness: brightness]!

Item was removed:
- ----- Method: Form>>adjustSaturation: (in category 'converting') -----
- adjustSaturation: saturation
- 
- 	^ self collectColors: [:color | color adjustSaturation: saturation brightness: 0]!

Item was removed:
- ----- Method: Form>>allocateForm: (in category 'initialize-release') -----
- allocateForm: extentPoint
- 	"Allocate a new form which is similar to the receiver and can be used for accelerated blts"
- 	^Form extent: extentPoint depth: self nativeDepth!

Item was removed:
- ----- Method: Form>>anyShapeFill (in category 'filling') -----
- anyShapeFill
- 	"Fill the interior of the outermost outlined region in the receiver, a 1-bit deep form.  Typically the resulting form is used with fillShape:fillColor: to paint a solid color.  See also convexShapeFill:"
- 
- 	| shape |
- 	"Draw a seed line around the edge and fill inward from the outside."
- 	shape := self findShapeAroundSeedBlock: [:f | f borderWidth: 1].
- 	"Reverse so that this becomes solid in the middle"
- 	shape := shape reverse.
- 	"Finally erase any bits from the original so the fill is only elsewhere"
- 	shape copy: shape boundingBox from: self to: 0 at 0 rule: Form erase.
- 	^ shape!

Item was removed:
- ----- Method: Form>>approxGaussianBlur (in category 'processing') -----
- approxGaussianBlur
- 
- 	^ self processUsingKernel: (Matrix rows: 3 columns: 3 contents: #(
- 		 1 2 1
- 		 2 4 2
- 		 1 2 1
- 	) *  0.0625)!

Item was removed:
- ----- Method: Form>>as8BitColorForm (in category 'converting') -----
- as8BitColorForm
- 	"Simple conversion of zero pixels to transparent.  Force it to 8 bits."
- 
- 	| f map |
- 	f := ColorForm extent: self extent depth: 8.
- 	self displayOn: f at: self offset negated.
- 	map := Color indexedColors copy.
- 	map at: 1 put: Color transparent.
- 	f colors: map.
- 	f offset: self offset.
- 	^ f
- !

Item was removed:
- ----- Method: Form>>asCursorForm (in category 'converting') -----
- asCursorForm
- 
- 	^ self as: StaticForm!

Item was removed:
- ----- Method: Form>>asFormOfDepth: (in category 'converting') -----
- asFormOfDepth: d
- 	"Create a copy of me with depth 'd'. Includes a correction for some bitmaps that when imported have poorly set up transparency"
- 	| newForm |
- 	d = self depth ifTrue:[^self].
- 	newForm := Form extent: self extent depth: d.
- 	(BitBlt toForm: newForm)
- 		colorMap: (self colormapIfNeededFor: newForm);
- 		copy: (self boundingBox)
- 		from: 0 at 0 in: self
- 		fillColor: nil rule: Form over.
- 	"Special case: For a 16 -> 32 bit conversion fill the alpha channel because it gets lost in translation."
- 	d = 32 ifTrue:[newForm fixAlpha].
- 	^newForm!

Item was removed:
- ----- Method: Form>>asGrayScale (in category 'converting') -----
- asGrayScale
- 	"Assume the receiver is a grayscale image. Return a grayscale ColorForm computed by extracting the brightness levels of one color component. This technique allows a 32-bit Form to be converted to an 8-bit ColorForm to save space while retaining a full 255 levels of gray. (The usual colormapping technique quantizes to 8, 16, or 32 levels, which loses information.)"
- 	| f32 srcForm result map bb |
- 	self depth = 32 ifFalse: [
- 		f32 := Form extent: width at height depth: 32.
- 		self displayOn: f32.
- 		^ f32 asGrayScale].
- 	self unhibernate.
- 	srcForm := Form extent: (width * 4)@height depth: 8.
- 	srcForm bits: bits.
- 	result := ColorForm extent: width at height depth: 8.
- 	map := Bitmap new: 256.
- 	2 to: 256 do: [:i | map at: i put: i - 1].
- 	map at: 1 put: 1.  "map zero pixel values to near-black"
- 	bb := (BitBlt toForm: result)
- 		sourceForm: srcForm;
- 		combinationRule: Form over;
- 		colorMap: map.
- 	0 to: width - 1 do: [:dstX |
- 		bb  sourceRect: (((dstX * 4) + 2)@0 extent: 1 at height);
- 			destOrigin: dstX at 0;
- 			copyBits].
- 
- 	"final BitBlt to zero-out pixels that were truely transparent in the original"
- 	map := Bitmap new: 512.
- 	map at: 1 put: 16rFF.
- 	(BitBlt toForm: result)
- 		sourceForm: self;
- 		sourceRect: self boundingBox;
- 		destOrigin: 0 at 0;
- 		combinationRule: Form erase;
- 		colorMap: map;
- 		copyBits.
- 	
- 	
- 	result colors: ColorForm grayScalePalette.
- 	^ result
- !

Item was removed:
- ----- Method: Form>>asSourceForm (in category 'converting') -----
- asSourceForm
- 	^self!

Item was removed:
- ----- Method: Form>>asTextAnchor (in category 'converting') -----
- asTextAnchor
- 	"Convert the receiver to be embedded in text."
- 
- 	self flag: #refactor. "mt: Text anchors should work outside of Morphic, too. Any instance of Form could be embedded in Text."
- 	^ (Smalltalk classNamed: 'TextAnchor')
- 		ifNil: [TextColor black "Fall back"]
- 		ifNotNil: [:cls | cls new anchoredMorph: self]!

Item was removed:
- ----- Method: Form>>balancedPatternFor: (in category 'color mapping') -----
- balancedPatternFor: aColor
- 	"Return the pixel word for representing the given color on the receiver"
- 	^aColor balancedPatternForDepth: self depth!

Item was removed:
- ----- Method: Form>>bitEdit (in category 'editing') -----
- bitEdit
- 	"Create and schedule a view located in an area designated by the user 
- 	that contains a view of the receiver magnified by 8 at 8 that can be 
- 	modified using the Bit Editor. It also contains a view of the original 
- 	form."
- 
- 	Project current bitEdit: self
- !

Item was removed:
- ----- Method: Form>>bitEditAt:scale: (in category 'editing') -----
- bitEditAt: magnifiedFormLocation scale: scaleFactor 
- 	"Create and schedule a view whose top left corner is magnifiedLocation 
- 	and that contains a view of the receiver magnified by scaleFactor that 
- 	can be modified using the Bit Editor. It also contains a view of the 
- 	original form."
- 
- 	Project current bitEdit: self at: magnifiedFormLocation scale: scaleFactor 
- !

Item was removed:
- ----- Method: Form>>bitPatternFor: (in category 'color mapping') -----
- bitPatternFor: aColor
- 	"Return the pixel word for representing the given color on the receiver"
- 	^aColor bitPatternForDepth: self depth!

Item was removed:
- ----- Method: Form>>bitPatternForDepth: (in category 'filling') -----
- bitPatternForDepth: suspectedDepth
- 	"Only called when a Form is being used as a fillColor.  Use a Pattern or InfiniteForm instead for this purpose.
- 	Interpret me as an array of (32/depth) Color pixelValues.  BitBlt aligns the first element of this array with the top scanline of the destinationForm, the second with the second, and so on, cycling through the color array as necessary. 6/18/96 tk"
- 
- 	^ self!

Item was removed:
- ----- Method: Form>>bits (in category 'accessing') -----
- bits
- 	"Answer the receiver's Bitmap containing its bits."
- 
- 	^ bits!

Item was removed:
- ----- Method: Form>>bits: (in category 'accessing') -----
- bits: aBitmap 
- 	"Reset the Bitmap containing the receiver's bits."
- 
- 	bits := aBitmap!

Item was removed:
- ----- Method: Form>>bitsPerComponent (in category 'postscript generation') -----
- bitsPerComponent
- 	^self depth <= 8 ifTrue:[self depth] ifFalse:[8].
- !

Item was removed:
- ----- Method: Form>>bitsSize (in category 'accessing') -----
- bitsSize
- 	| pixelsPerWord |
- 	depth ifNil: [depth := 1].
- 	pixelsPerWord := 32 // self depth.
- 	^width + pixelsPerWord - 1 // pixelsPerWord * height!

Item was removed:
- ----- Method: Form>>blankCopyOf:scaledBy: (in category 'copying') -----
- blankCopyOf: aRectangle scaledBy: scale 
- 	^ self species
- 		extent: (aRectangle extent * scale) truncated
- 		depth: depth!

Item was removed:
- ----- Method: Form>>border:width:rule:fillColor: (in category 'bordering') -----
- border: rect width: borderWidth rule: rule fillColor: fillColor
-         "Paint a border whose rectangular area is defined by rect. The
- width of the border of each side is borderWidth. Uses fillColor for drawing
- the border."
-         | blt |
-         blt := (BitBlt toForm: self) combinationRule: rule; fillColor: fillColor.
-         blt sourceOrigin: 0 at 0.
-         blt destOrigin: rect origin.
-         blt width: rect width; height: borderWidth; copyBits.
-         blt destY: rect corner y - borderWidth; copyBits.
-         blt destY: rect origin y + borderWidth.
-         blt height: rect height - borderWidth - borderWidth; width:
- borderWidth; copyBits.
-         blt destX: rect corner x - borderWidth; copyBits!

Item was removed:
- ----- Method: Form>>borderFormOfWidth:sharpCorners: (in category 'bordering') -----
- borderFormOfWidth: borderWidth sharpCorners: sharpen
- 	"Smear this form around and then subtract the original to produce
- 	an outline.  If sharpen is true, then cause right angles to be outlined
- 	by right angles (takes an additional diagonal smears ANDed with both
- 	horizontal and vertical smears)."
- 	| smearForm bigForm smearPort all cornerForm cornerPort nbrs |
- 	self depth > 1 ifTrue: [self halt]. "Only meaningful for B/W forms."
- 	bigForm := self deepCopy.
- 	all := bigForm boundingBox.
- 	smearForm := Form extent: self extent.
- 	smearPort := BitBlt toForm: smearForm.
- 	sharpen ifTrue:
- 		[cornerForm := Form extent: self extent.
- 		cornerPort := BitBlt toForm: cornerForm].
- 	nbrs := (0 at 0) fourNeighbors.
- 	1 to: borderWidth do:
- 		[:i |  "Iterate to get several layers of 'skin'"
- 		nbrs do:
- 			[:d |  "Smear the self in 4 directions to grow each layer of skin"
- 			smearPort copyForm: bigForm to: d rule: Form under].
- 		sharpen ifTrue:
- 			["Special treatment to smear sharp corners"
- 			nbrs with: ((2 to: 5) collect: [:i2 | nbrs atWrap: i2]) do:
- 				[:d1 :d2 |
- 				"Copy corner points diagonally"
- 				cornerPort copyForm: bigForm to: d1+d2 rule: Form over.
- 				"But only preserve if there were dots on either side"
- 				cornerPort copyForm: bigForm to: d1+d1+d2 rule: Form and.
- 				cornerPort copyForm: bigForm to: d1+d2+d2 rule: Form and.
- 				smearPort copyForm: cornerForm to: 0 at 0 rule: Form under].
- 			].
- 		bigForm copy: all from: 0 at 0 in: smearForm rule: Form over.
- 		].
- 	"Now erase the original shape to obtain the outline"
- 	bigForm copy: all from: 0 at 0 in: self rule: Form erase.
- 	^ bigForm!

Item was removed:
- ----- Method: Form>>borderWidth: (in category 'bordering') -----
- borderWidth: anInteger 
- 	"Set the width of the border for the receiver to be anInteger and paint it 
- 	using black as the border color."
- 
- 	self border: self boundingBox width: anInteger fillColor: Color black!

Item was removed:
- ----- Method: Form>>borderWidth:color: (in category 'bordering') -----
- borderWidth: anInteger color: aMask
- 	"Set the width of the border for the receiver to be anInteger and paint it 
- 	using aMask as the border color."
- 
- 	self border: self boundingBox width: anInteger fillColor: aMask!

Item was removed:
- ----- Method: Form>>borderWidth:fillColor: (in category 'bordering') -----
- borderWidth: anInteger fillColor: aMask
- 	"Set the width of the border for the receiver to be anInteger and paint it 
- 	using aMask as the border color."
- 
- 	self border: self boundingBox width: anInteger fillColor: aMask!

Item was removed:
- ----- Method: Form>>boundingBox (in category 'display box access') -----
- boundingBox
- 	^ Rectangle origin: 0 @ 0
- 			corner: width @ height!

Item was removed:
- ----- Method: Form>>bytesPerRow (in category 'postscript generation') -----
- bytesPerRow
- 	^ self numComponents * self paddedWidth * self bitsPerComponent / 8.!

Item was removed:
- ----- Method: Form>>center (in category 'display box access') -----
- center
- 	"Note that offset is ignored here.  Are we really going to embrace offset?  "
- 	^ (width @ height) // 2!

Item was removed:
- ----- Method: Form>>cgForPixelValue:orNot: (in category 'analyzing') -----
- cgForPixelValue: pv orNot: not
- 	"Return the center of gravity for all pixels of value pv.
- 	Note:  If orNot is true, then produce the center of gravity for all pixels
- 	that are DIFFERENT from the supplied (background) value"
- 	| xAndY |
- 	xAndY := (Array with: (self xTallyPixelValue: pv orNot: not)
- 					with: (self yTallyPixelValue: pv orNot: not)) collect:
- 		[:profile | | pixCount weighted |	"For both x and y profiles..."
- 		pixCount := 0.  weighted := 0.
- 		profile withIndexDo:
- 			[:t :i | pixCount := pixCount + t.
- 			weighted := weighted + (t*i)].
- 		pixCount = 0  "Produce average of nPixels weighted by coordinate"
- 			ifTrue: [0.0]
- 			ifFalse: [weighted asFloat / pixCount asFloat - 1.0]].
- 
- 	^ xAndY first @ xAndY last
- "
- | f cg |
- [Sensor anyButtonPressed] whileFalse:
- 	[f := Form fromDisplay: (Sensor cursorPoint extent: 50 at 50).
- 	cg := f cgForPixelValue: (Color black pixelValueForDepth: f depth) orNot: false.
- 	f displayAt: 0 at 0.
- 	Display fill: (cg extent: 2 at 2) fillColor: Color red].
- 	ScheduledControllers restore
- "!

Item was removed:
- ----- Method: Form>>clippedToSize: (in category 'scaling, rotation') -----
- clippedToSize: aPoint
-  	"Return a copy of this form that is clipped to the given size around the center."
- 	
- 	| newForm |
- 	newForm := self class extent: aPoint depth: depth.
- 	^ newForm copyBits: ((0 at 0 corner: aPoint) translateBy: (self extent - aPoint) // 2) from: self at: 0 at 0
- 		clippingBox: newForm boundingBox rule: Form over fillColor: nil!

Item was removed:
- ----- Method: Form>>collectColors: (in category 'converting') -----
- collectColors: aBlock
- 	"Create a new copy of the receiver with all the colors transformed by aBlock"
- 	^self collectPixels:[:pv|
- 		(aBlock value: (Color colorFromPixelValue: pv depth: self depth)) 
- 			pixelValueForDepth: self depth.
- 	].!

Item was removed:
- ----- Method: Form>>collectPixels: (in category 'converting') -----
- collectPixels: aBlock
- 	"Create a new copy of the receiver with all the pixels transformed by aBlock"
- 	self depth = 32 ifFalse:[
- 		"Perform the operation in 32bpp"
- 		^((self asFormOfDepth: 32) collectPixels: aBlock) asFormOfDepth: self depth].
- 	self unhibernate. "ensure unhibernated before touching bits"
- 	^Form 
- 		extent: self extent 
- 		depth: self depth
- 		bits: (self bits collect: aBlock)!

Item was removed:
- ----- Method: Form>>colorAt: (in category 'pixel access') -----
- colorAt: aPoint
- 	"Return the color in the pixel at the given point.  "
- 
- 	^ Color 
- 		colorFromPixelValue: (self pixelValueAt: aPoint)
- 		depth: self depth
- !

Item was removed:
- ----- Method: Form>>colorAt:put: (in category 'pixel access') -----
- colorAt: aPoint put: aColor
- 	"Store a Color into the pixel at coordinate aPoint.  "
- 
- 	self pixelValueAt: aPoint put: (self pixelValueFor: aColor).
- 
- "[Sensor anyButtonPressed] whileFalse:
- 	[Display colorAt: Sensor cursorPoint put: Color red]"
- !

Item was removed:
- ----- Method: Form>>colorReduced (in category 'converting') -----
- colorReduced
- 	"Return a color-reduced ColorForm version of the receiver, if possible, or the receiver itself if not."
- 
- 	| tally tallyDepth colorCount newForm cm oldPixelValues newFormColors nextColorIndex c |
- 	tally := self tallyPixelValues asArray.
- 	tallyDepth := (tally size log: 2) asInteger.
- 	colorCount := 0.
- 	tally do: [:n | n > 0 ifTrue: [colorCount := colorCount + 1]].
- 	(tally at: 1) = 0 ifTrue: [colorCount := colorCount + 1].  "include transparent"
- 	colorCount > 256 ifTrue: [^ self].  "cannot reduce"
- 	newForm := self formForColorCount: colorCount.
- 
- 	"build an array of just the colors used, and a color map to translate
- 	 old pixel values to their indices into this color array"
- 	cm := Bitmap new: tally size.
- 	oldPixelValues := self colormapIfNeededForDepth: 32.
- 	newFormColors := Array new: colorCount.
- 	newFormColors at: 1 put: Color transparent.
- 	nextColorIndex := 2.
- 	2 to: cm size do: [:i |
- 		(tally at: i) > 0 ifTrue: [
- 			oldPixelValues = nil
- 				ifTrue: [c := Color colorFromPixelValue: i - 1 depth: tallyDepth]
- 				ifFalse: [c := Color colorFromPixelValue: (oldPixelValues at: i) depth: 32].
- 			newFormColors at: nextColorIndex put: c.
- 			cm at: i put: nextColorIndex - 1.  "pixel values are zero-based indices"
- 			nextColorIndex := nextColorIndex + 1]].
- 
- 	"copy pixels into new ColorForm, mapping to new pixel values"
- 	newForm copyBits: self boundingBox
- 		from: self
- 		at: 0 at 0
- 		clippingBox: self boundingBox
- 		rule: Form over
- 		fillColor: nil
- 		map: cm.
- 	newForm colors: newFormColors.
- 	newForm offset: offset.
- 	^ newForm
- !

Item was removed:
- ----- Method: Form>>colormapFromARGB (in category 'color mapping') -----
- colormapFromARGB
- 	"Return a ColorMap mapping from canonical ARGB space into the receiver.
- 	Note: This version is optimized for Squeak forms."
- 	| map nBits |
- 	self depth <= 8 ifTrue:[
- 		map := Color colorMapIfNeededFrom: 32 to: self depth.
- 		map size = 512 ifTrue:[nBits := 3].
- 		map size = 4096 ifTrue:[nBits := 4].
- 		map size = 32768 ifTrue:[nBits := 5].
- 		^ColorMap
- 			shifts: (Array 
- 						with: 3 * nBits - 24
- 						with: 2 * nBits - 16
- 						with: 1 * nBits - 8
- 						with: 0)
- 			masks: (Array
- 						with: (1 << nBits) - 1 << (24 - nBits)
- 						with: (1 << nBits) - 1 << (16 - nBits)
- 						with: (1 << nBits) - 1 << (8 - nBits)
- 						with: 0)
- 			colors: map].
- 	self depth = 16 ifTrue:[
- 		^ColorMap
- 			shifts: #(-9 -6 -3 0)
- 			masks: #(16rF80000 16rF800 16rF8 0)].
- 	self depth = 32 ifTrue:[
- 		^ColorMap
- 			shifts: #(0 0 0 0)
- 			masks: #(16rFF0000 16rFF00 16rFF 16rFF000000)].
- 	self error:'Bad depth'!

Item was removed:
- ----- Method: Form>>colormapIfNeededFor: (in category 'color mapping') -----
- colormapIfNeededFor: destForm
- 	"Return a ColorMap mapping from the receiver to destForm."
- 	(self hasNonStandardPalette or:[destForm hasNonStandardPalette]) 
- 		ifTrue:[^self colormapFromARGB mappingTo: destForm colormapFromARGB]
- 		ifFalse:[^self colormapIfNeededForDepth: destForm depth]!

Item was removed:
- ----- Method: Form>>colormapIfNeededForDepth: (in category 'color mapping') -----
- colormapIfNeededForDepth: destDepth
- 	"Return a colormap for displaying the receiver at the given depth, or nil if no colormap is needed."
- 
- 	self depth = destDepth ifTrue: [^ nil].  "not needed if depths are the same"
- 	^ Color colorMapIfNeededFrom: self depth to: destDepth
- !

Item was removed:
- ----- Method: Form>>colormapToARGB (in category 'color mapping') -----
- colormapToARGB
- 	"Return a ColorMap mapping from the receiver into canonical ARGB space."
- 	self depth <= 8 ifTrue:[
- 		^ColorMap
- 			shifts: #(0 0 0 0)
- 			masks: #(16rFF0000 16rFF00 16rFF 16rFF000000)
- 			colors: (Color colorMapIfNeededFrom: self depth to: 32)].
- 	self depth = 16 ifTrue:[
- 		^ColorMap 
- 			shifts: #( 9 6 3 0) 
- 			masks: #(16r7C00 16r3E0 16r1F 0)].
- 	self depth = 32 ifTrue:[
- 		^ColorMap
- 			shifts: #(0 0 0 0) 
- 			masks: #(16rFF0000 16rFF00 16rFF 16rFF000000)].
- 	self error:'Bad depth'!

Item was removed:
- ----- Method: Form>>colorsUsed (in category 'analyzing') -----
- colorsUsed
- 	"Return a list of the Colors this form uses."
- 
- 	| tallies tallyDepth usedColors |
- 	tallies := self tallyPixelValues.
- 	tallyDepth := (tallies size log: 2) asInteger.
- 	usedColors := OrderedCollection new.
- 	tallies withIndexDo: [:count :i |
- 		count > 0 ifTrue: [
- 			usedColors add: (Color colorFromPixelValue: i - 1 depth: tallyDepth)]].
- 	^ usedColors asArray
- !

Item was removed:
- ----- Method: Form>>comeFullyUpOnReload: (in category 'fileIn/Out') -----
- comeFullyUpOnReload: smartRefStream
- 	bits isForm ifFalse:[^self].
- 	"make sure the resource gets loaded afterwards"
- 	ResourceCollector current ifNil:[^self].
- 	ResourceCollector current noteResource: bits replacing: self.
- !

Item was removed:
- ----- Method: Form>>computeBoundingBox (in category 'display box access') -----
- computeBoundingBox
- 	^ Rectangle origin: 0 @ 0
- 			corner: width @ height!

Item was removed:
- ----- Method: Form>>contentsOfArea: (in category 'copying') -----
- contentsOfArea: aRect
-  	"Return a new form which derives from the portion of the original form delineated by aRect."
- 	^self contentsOfArea: aRect 
- 		into: (self species extent: aRect extent depth: depth).!

Item was removed:
- ----- Method: Form>>contentsOfArea:into: (in category 'copying') -----
- contentsOfArea: aRect into: newForm
-  	"Return a new form which derives from the portion of the original form delineated by aRect."
- 	^ newForm copyBits: aRect from: self at: 0 at 0
- 		clippingBox: newForm boundingBox rule: Form over fillColor: nil!

Item was removed:
- ----- Method: Form>>convexShapeFill: (in category 'filling') -----
- convexShapeFill: aMask 
- 	"Fill the interior of the outtermost outlined region in the receiver.  The outlined region must not be concave by more than 90 degrees.  Typically aMask is Color black, to produce a solid fill. then the resulting form is used with fillShape: to paint a solid color.  See also anyShapeFill"
- 	| destForm tempForm |
- 	destForm := Form extent: self extent.  destForm fillBlack.
- 	tempForm := Form extent: self extent.
- 	(0 at 0) fourNeighbors do:
- 		[:dir |  "Smear self in all 4 directions, and AND the result"
- 		self displayOn: tempForm at: (0 at 0) - self offset.
- 		tempForm smear: dir distance: (dir dotProduct: tempForm extent) abs.
- 		tempForm displayOn: destForm at: 0 at 0
- 			clippingBox: destForm boundingBox
- 			rule: Form and fillColor: nil].
- 	destForm displayOn: self at: 0 at 0
- 		clippingBox: self boundingBox
- 		rule: Form over fillColor: aMask!

Item was removed:
- ----- Method: Form>>copy: (in category 'copying') -----
- copy: aRect
-  	"Return a new form which derives from the portion of the original form delineated by aRect."
- 	| newForm |
- 	newForm := self species extent: aRect extent depth: depth.
- 	^ newForm copyBits: aRect from: self at: 0 at 0
- 		clippingBox: newForm boundingBox rule: Form over fillColor: nil!

Item was removed:
- ----- Method: Form>>copy:from:in:rule: (in category 'copying') -----
- copy: destRectangle from: sourcePt in: sourceForm rule: rule 
- 	"Make up a BitBlt table and copy the bits."
- 	(BitBlt toForm: self)
- 		copy: destRectangle
- 		from: sourcePt in: sourceForm
- 		fillColor: nil rule: rule!

Item was removed:
- ----- Method: Form>>copy:from:to:rule: (in category 'copying') -----
- copy: sourceRectangle from: sourceForm to: destPt rule: rule
- 	^ self copy: (destPt extent: sourceRectangle extent)
- 		from: sourceRectangle topLeft in: sourceForm rule: rule!

Item was removed:
- ----- Method: Form>>copyBits:at:translucent: (in category 'copying') -----
- copyBits: sourceForm at: destOrigin translucent: factor
- 	"Make up a BitBlt table and copy the bits with the given colorMap."
- 	(BitBlt 
- 		destForm: self
- 		sourceForm: sourceForm
- 		halftoneForm: nil
- 		combinationRule: 30
- 		destOrigin: destOrigin
- 		sourceOrigin: 0 at 0
- 		extent: sourceForm extent
- 		clipRect: self boundingBox)
- 		copyBitsTranslucent: ((0 max: (factor*255.0) asInteger) min: 255)
- "
-  | f f2 f3 | f := Form fromUser. f2 := Form fromDisplay: (0 at 0 extent: f extent). f3 := f2 deepCopy.
- 0.0 to: 1.0 by: 1.0/32 do:
- 	[:t | f3 := f2 deepCopy. f3 copyBits: f at: 0 at 0 translucent: t.
- 	f3 displayAt: 0 at 0. (Delay forMilliseconds: 100) wait].
- "!

Item was removed:
- ----- Method: Form>>copyBits:from:at:clippingBox:rule:fillColor: (in category 'copying') -----
- copyBits: sourceRect from: sourceForm at: destOrigin clippingBox: clipRect rule: rule fillColor: aForm 
- 	"Make up a BitBlt table and copy the bits."
- 
- 	(BitBlt 
- 		destForm: self
- 		sourceForm: sourceForm
- 		fillColor: aForm
- 		combinationRule: rule
- 		destOrigin: destOrigin
- 		sourceOrigin: sourceRect origin
- 		extent: sourceRect extent
- 		clipRect: clipRect) copyBits!

Item was removed:
- ----- Method: Form>>copyBits:from:at:clippingBox:rule:fillColor:map: (in category 'copying') -----
- copyBits: sourceRect from: sourceForm at: destOrigin clippingBox: clipRect rule: rule fillColor: aForm map: map
- 	"Make up a BitBlt table and copy the bits.  Use a colorMap."
- 
- 	((BitBlt 
- 		destForm: self
- 		sourceForm: sourceForm
- 		fillColor: aForm
- 		combinationRule: rule
- 		destOrigin: destOrigin
- 		sourceOrigin: sourceRect origin
- 		extent: sourceRect extent
- 		clipRect: clipRect) colorMap: map) copyBits!

Item was removed:
- ----- Method: Form>>copyBits:from:at:colorMap: (in category 'copying') -----
- copyBits: sourceRect from: sourceForm at: destOrigin colorMap: map 
- 	"Make up a BitBlt table and copy the bits with the given colorMap."
- 	((BitBlt 
- 		destForm: self
- 		sourceForm: sourceForm
- 		halftoneForm: nil
- 		combinationRule: Form over
- 		destOrigin: destOrigin
- 		sourceOrigin: sourceRect origin
- 		extent: sourceRect extent
- 		clipRect: self boundingBox) colorMap: map) copyBits!

Item was removed:
- ----- Method: Form>>copyWithColorsReducedTo: (in category 'converting') -----
- copyWithColorsReducedTo: nColors
- 	"Note: this has not been engineered.
- 	There are better solutions in the literature."
- 	| palette colorMap |
- 	self depth > 16 ifTrue:[^(self asFormOfDepth: 16) copyWithColorsReducedTo: nColors]. "First reduce to 16 bit depth"
- 	palette := self reducedPaletteOfSize: nColors.
- 	colorMap := (1 to: (1 bitShift: depth)) collect:
- 		[:i | | pc closest |
- 		pc := Color colorFromPixelValue: i-1 depth: depth.
- 		closest := palette detectMin: [:c | c diff: pc].
- 		closest pixelValueForDepth: depth].
- 	^ self deepCopy copyBits: self boundingBox from: self at: 0 at 0 colorMap: (colorMap as: Bitmap)
- 		!

Item was removed:
- ----- Method: Form>>darker (in category 'converting') -----
- darker
- 	"Answer a darker variant of this form."
- 	^self collectColors:[:color| color darker darker]!

Item was removed:
- ----- Method: Form>>decodeArray (in category 'postscript generation') -----
- decodeArray
- 	^self depth <= 8 ifTrue:['[1 0]'] ifFalse:['[0 1 0 1 0 1 ]'].
- !

Item was removed:
- ----- Method: Form>>deepCopy (in category 'copying') -----
- deepCopy
- 	^self copy!

Item was removed:
- ----- Method: Form>>defaultCanvasClass (in category 'accessing') -----
- defaultCanvasClass
- 	"Return the default canvas used for drawing onto the receiver"
- 	^Display defaultCanvasClass!

Item was removed:
- ----- Method: Form>>depth (in category 'accessing') -----
- depth
- 	^ depth < 0 ifTrue:[0-depth] ifFalse:[depth]!

Item was removed:
- ----- Method: Form>>depth: (in category 'accessing') -----
- depth: bitsPerPixel
- 	(bitsPerPixel > 32 or:
- 		[(bitsPerPixel bitAnd: bitsPerPixel-1) ~= 0])
- 		ifTrue: [self halt: 'bitsPerPixel must be 1, 2, 4, 8, 16 or 32'].
- 	depth := bitsPerPixel!

Item was removed:
- ----- Method: Form>>dimmed (in category 'converting') -----
- dimmed
- 	"Answer a dimmed variant of this form."
- 	^self collectColors:[:color| (color alpha: (color alpha min: 0.2)) ]!

Item was removed:
- ----- Method: Form>>displayInterpolatedIn:on: (in category 'displaying') -----
- displayInterpolatedIn: aRectangle on: aForm
- 	"Display the receiver on aForm, using interpolation if necessary.
- 		Form fromUser displayInterpolatedOn: Display.
- 	Note: When scaling we attempt to use bilinear interpolation based
- 	on the 3D engine. If the engine is not there then we use WarpBlt.
- 	"
- 	| engine adjustedR |
- 	self extent = aRectangle extent ifTrue:[^self displayOn: aForm at: aRectangle origin].
- 	engine := Smalltalk at: #B3DRenderEngine 
- 		ifPresent: [:engineClass | (engineClass defaultForPlatformOn: aForm)].
- 	engine ifNil:[
- 		"We've got no bilinear interpolation. Use WarpBlt instead"
- 		(WarpBlt toForm: aForm)
- 			sourceForm: self destRect: aRectangle;
- 			combinationRule: 3;
- 			cellSize: 2;
- 			warpBits.
- 		^self
- 	].
- 
- 	"Otherwise use the 3D engine for our purposes"
- 
- 	"there seems to be a slight bug in B3D which the following adjusts for"
- 	adjustedR := (aRectangle withRight: aRectangle right + 1) translateBy: 0 at 1.
- 	engine viewport: adjustedR.
- 	engine material: ((Smalltalk at: #B3DMaterial) new emission: Color white).
- 	engine texture: self.
- 	engine render: ((Smalltalk at: #B3DIndexedQuadMesh) new plainTextureRect).
- 	engine finish.!

Item was removed:
- ----- Method: Form>>displayInterpolatedOn: (in category 'displaying') -----
- displayInterpolatedOn: aForm
- 	"Display the receiver on aForm, using interpolation if necessary.
- 		Form fromUser displayInterpolatedOn: Display.
- 	Note: When scaling we attempt to use bilinear interpolation based
- 	on the 3D engine. If the engine is not there then we use WarpBlt.
- 	"
- 	| engine |
- 	self extent = aForm extent ifTrue:[^self displayOn: aForm].
- 	engine := Smalltalk at: #B3DRenderEngine 
- 		ifPresent:[:engineClass| (engineClass defaultForPlatformOn: aForm)].
- 	engine ifNil:[
- 		"We've got no bilinear interpolation. Use WarpBlt instead"
- 		(WarpBlt toForm: aForm)
- 			sourceForm: self destRect: aForm boundingBox;
- 			combinationRule: 3;
- 			cellSize: 2;
- 			warpBits.
- 		^self
- 	].
- 	"Otherwise use the 3D engine for our purposes"
- 	engine viewport: aForm boundingBox.
- 	engine material: ((Smalltalk at: #B3DMaterial) new emission: Color white).
- 	engine texture: self.
- 	engine render: ((Smalltalk at: #B3DIndexedQuadMesh) new plainTextureRect).
- 	engine finish.!

Item was removed:
- ----- Method: Form>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: rule fillColor: aForm
- 
- 	aDisplayMedium copyBits: self boundingBox
- 		from: self
- 		at: aDisplayPoint + self offset
- 		clippingBox: clipRectangle
- 		rule: rule
- 		fillColor: aForm
- 		map: (self colormapIfNeededFor: aDisplayMedium).
- !

Item was removed:
- ----- Method: Form>>displayOn:transformation:clippingBox:align:with:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm 
- 	"Graphically, it means nothing to scale a Form by floating point values.  
- 	Because scales and other display parameters are kept in floating point to 
- 	minimize round off errors, we are forced in this routine to round off to the 
- 	nearest integer."
- 
- 	| absolutePoint scale magnifiedForm |
- 	absolutePoint := displayTransformation applyTo: relativePoint.
- 	absolutePoint := absolutePoint x asInteger @ absolutePoint y asInteger.
- 	displayTransformation noScale
- 		ifTrue: [magnifiedForm := self]
- 		ifFalse: 
- 			[scale := displayTransformation scale.
- 			scale := scale x @ scale y.
- 			(1 at 1 = scale)
- 					ifTrue: [scale := nil. magnifiedForm := self]
- 					ifFalse: [magnifiedForm := self magnify: self boundingBox by: scale]].
- 	magnifiedForm
- 		displayOn: aDisplayMedium
- 		at: absolutePoint - alignmentPoint
- 		clippingBox: clipRectangle
- 		rule: ruleInteger
- 		fillColor: aForm!

Item was removed:
- ----- Method: Form>>displayOnPort:at: (in category 'displaying') -----
- displayOnPort: port at: location
- 	port copyForm: self to: location rule: Form over!

Item was removed:
- ----- Method: Form>>displayResourceFormOn: (in category 'displaying') -----
- displayResourceFormOn: aForm
- 	"a special display method for blowing up resource thumbnails"
- 	| engine tx cmap blitter |
- 	self extent = aForm extent ifTrue:[^self displayOn: aForm].
- 	engine := Smalltalk at: #B3DRenderEngine ifPresent:
- 		[:engineClass | engineClass defaultForPlatformOn: aForm].
- 	engine ifNil:[
- 		"We've got no bilinear interpolation. Use WarpBlt instead"
- 		(WarpBlt toForm: aForm)
- 			sourceForm: self destRect: aForm boundingBox;
- 			combinationRule: 3;
- 			cellSize: 2;
- 			warpBits.
- 		^self
- 	].
- 	tx := self asTexture.
- 	(blitter := BitBlt toForm: tx)
- 		sourceForm: self; destRect: aForm boundingBox;
- 		sourceOrigin: 0 at 0;
- 		combinationRule: Form paint.
- 	"map transparency to current World background color"
- 	(Project current world color respondsTo: #pixelWordForDepth:) ifTrue: [
- 		cmap := Bitmap new: (self depth <= 8 ifTrue: [1 << self depth] ifFalse: [4096]).
- 		cmap at: 1 put: (tx pixelWordFor: Project current world color).
- 		blitter colorMap: cmap.
- 	].
- 	blitter copyBits.
- 	engine viewport: aForm boundingBox.
- 	engine material: ((Smalltalk at: #B3DMaterial) new emission: Color white).
- 	engine texture: tx.
- 	engine render: ((Smalltalk at: #B3DIndexedQuadMesh) new plainTextureRect).
- 	engine finish.
- 	"the above, using bilinear interpolation doesn't leave transparent pixel values intact"
- 	(WarpBlt toForm: aForm)
- 		sourceForm: self destRect: aForm boundingBox;
- 		combinationRule: Form and;
- 		colorMap: (Color maskingMap: self depth);
- 		warpBits.!

Item was removed:
- ----- Method: Form>>displayScaledOn: (in category 'displaying') -----
- displayScaledOn: aForm
- 	"Display the receiver on aForm, scaling if necessary.
- 		Form fromUser displayScaledOn: Display.
- 	"
- 	self extent = aForm extent ifTrue:[^self displayOn: aForm].
- 	(WarpBlt toForm: aForm)
- 		sourceForm: self destRect: aForm boundingBox;
- 		combinationRule: Form paint;
- 		cellSize: 2;
- 		warpBits.!

Item was removed:
- ----- Method: Form>>dominantColor (in category 'analyzing') -----
- dominantColor
- 	| tally max maxi |
- 	self depth > 16 ifTrue:
- 		[^(self asFormOfDepth: 16) dominantColor].
- 	tally := self tallyPixelValues.
- 	max := maxi := 0.
- 	tally withIndexDo: [:n :i | n > max ifTrue: [max := n. maxi := i]].
- 	^ Color colorFromPixelValue: maxi - 1 depth: self depth!

Item was removed:
- ----- Method: Form>>drawLine:from:to:clippingBox:rule:fillColor: (in category 'displaying') -----
- drawLine: sourceForm from: beginPoint to: endPoint clippingBox: clipRect rule: anInteger fillColor: aForm 
- 	"Refer to the comment in 
- 	DisplayMedium|drawLine:from:to:clippingBox:rule:mask:." 
- 	
- 	| dotSetter |
- 	"set up an instance of BitBlt for display"
- 	dotSetter := BitBlt
- 		destForm: self
- 		sourceForm: sourceForm
- 		fillColor: aForm
- 		combinationRule: anInteger
- 		destOrigin: beginPoint
- 		sourceOrigin: 0 @ 0
- 		extent: sourceForm extent
- 		clipRect: clipRect.
- 	dotSetter drawFrom: beginPoint to: endPoint!

Item was removed:
- ----- Method: Form>>dyed: (in category 'converting') -----
- dyed: aColor
- 	"Dye this form with the given color. For now, the alpha channel should be sufficient to preserve the meaning of the form."
- 	
- 	^ self collectColors: [:ea | aColor alpha: ea alpha]!

Item was removed:
- ----- Method: Form>>edgeDetect (in category 'processing') -----
- edgeDetect
- 
- 	^ self processUsingKernel: (Matrix rows: 3 columns: 3 contents: #(
- 		-1 -1 -1
- 		-1  8 -1
- 		-1 -1 -1
- 	))!

Item was removed:
- ----- Method: Form>>edit (in category 'editing') -----
- edit
- 	"Open a form editor on this form. "
-  
- 	Project current formEdit: self!

Item was removed:
- ----- Method: Form>>emboss (in category 'processing') -----
- emboss
- 
- 	^ self processUsingKernel: (Matrix rows: 3 columns: 3 contents: #(
- 		-2 -1  0
- 		-1  1  1
- 		 0  1  2
- 	))!

Item was removed:
- ----- Method: Form>>eraseShape: (in category 'filling') -----
- eraseShape: bwForm
- 	"use bwForm as a mask to clear all pixels where bwForm has 1's"
- 	((BitBlt destForm: self sourceForm: bwForm 
- 		fillColor: nil
- 		combinationRule: Form erase1bitShape	"Cut a hole in the picture with my mask"
- 		destOrigin: bwForm offset 
- 		sourceOrigin: 0 at 0
- 		extent: self extent clipRect: self boundingBox)
- 		colorMap: (Bitmap with: 0 with: 16rFFFFFFFF))
- 		copyBits.
- !

Item was removed:
- ----- Method: Form>>extent (in category 'accessing') -----
- extent
- 	^ width @ height!

Item was removed:
- ----- Method: Form>>fadeImage:at:indexAndMaskDo: (in category 'transitions') -----
- fadeImage: otherImage at: topLeft
- 	indexAndMaskDo: indexAndMaskBlock
- 	
- 	"This fade uses halftones as a blending hack.
- 	Zeros in the halftone produce the original image (self), and 
- 	ones in the halftone produce the 'otherImage'.
- 	IndexAndMaskBlock gets evaluated prior to each cycle,
- 	and the resulting boolean determines whether to continue cycling."
- 	| index imageRect maskForm resultForm pix returnPix|
- 	imageRect := otherImage boundingBox.
- 	resultForm := self copy: (topLeft extent: imageRect extent).
- 	maskForm := Form extent: 32 at 32.
- 	index := 0.
- 
- 	[indexAndMaskBlock value: (index := index+1) value: maskForm]
- 	whileTrue:
- 		[maskForm reverse.
- 		resultForm copyBits: imageRect from: resultForm at: 0 at 0
- 			clippingBox: imageRect rule: Form over fillColor: maskForm.
- 		maskForm reverse.
- 		resultForm copyBits: imageRect from: otherImage at: 0 at 0
- 			clippingBox: imageRect rule: Form under fillColor: maskForm.
- 		self copyBits: imageRect from: resultForm at: topLeft
- 				clippingBox: self boundingBox rule: Form over fillColor: nil.
- 		Display forceDisplayUpdate]!

Item was removed:
- ----- Method: Form>>fadeImageCoarse:at: (in category 'transitions') -----
- fadeImageCoarse: otherImage at: topLeft
- 	"Display fadeImageCoarse: (Form fromDisplay: (40 at 40 extent: 300 at 300)) reverse at: 40 at 40"
- 	| d pix|
- 	d := self depth.
- 	^ self fadeImage: otherImage at: topLeft indexAndMaskDo:
- 		[:i :mask | | j |
- 		i=1 ifTrue: [pix := (1 bitShift: d) - 1.
- 					1 to: 8//d-1 do: [:q | pix := pix bitOr: (pix bitShift: d*4)]]			.
- 		i <= 16 ifTrue:[
- 		j := i-1//4+1.
- 		(0 to: 28 by: 4) do: [:k |
- 			mask bits at: j+k
- 				put: (pix bitOr: (mask bits at: j+k))].
- 		true]
- 		ifFalse: [false]]!

Item was removed:
- ----- Method: Form>>fadeImageFine:at: (in category 'transitions') -----
- fadeImageFine: otherImage at: topLeft
- 	"Display fadeImageFine: (Form fromDisplay: (40 at 40 extent: 300 at 300)) reverse at: 40 at 40"
- 	| d pix|
- 	d := self depth.
- 	^ self fadeImage: otherImage at: topLeft indexAndMaskDo:
- 		[:i :mask | | j ii  |
- 		i=1 ifTrue: [pix := (1 bitShift: d) - 1.
- 					1 to: 8//d-1 do:
- 						[:q | pix := pix bitOr: (pix bitShift: d*4)]].
- 		i <= 16 ifTrue:
- 		[ii := #(0 10 2 8 7 13 5 15 1 11 3 9 6 12 4 14) at: i.
- 		j := ii//4+1.
- 		(0 to: 28 by: 4) do:
- 			[:k | mask bits at: j+k put:
- 				((mask bits at: j+k) bitOr: (pix))].
- 		true]
- 		ifFalse: [false]]!

Item was removed:
- ----- Method: Form>>fadeImageHor:at: (in category 'transitions') -----
- fadeImageHor: otherImage at: topLeft
- 	"Display fadeImageHor: (Form fromDisplay: (10 at 10 extent: 300 at 300)) reverse at: 10 at 10"
- 	^ self fadeImage: otherImage at: topLeft indexAndMaskDo:
- 		[:i :mask |
- 		mask fill: (0@(mask height//2-i) extent: mask width@(i*2)) fillColor: Color black.
- 		(i*2) <= mask width]!

Item was removed:
- ----- Method: Form>>fadeImageHorFine:at: (in category 'transitions') -----
- fadeImageHorFine: otherImage at: topLeft
- 	"Display fadeImageHorFine: (Form fromDisplay: (10 at 10 extent: 300 at 300)) reverse at: 10 at 10"
- 	^ self fadeImage: otherImage at: topLeft indexAndMaskDo:
- 		[:i :mask |
- 		mask fill: (0@(i-1) extent: mask width at 1) fillColor: Color black.
- 		mask fill: (0@(i-1+16) extent: mask width at 1) fillColor: Color black.
- 		(i*2) <= mask width]!

Item was removed:
- ----- Method: Form>>fadeImageSquares:at: (in category 'transitions') -----
- fadeImageSquares: otherImage at: topLeft 
- 	"Display fadeImageSquares: (Form fromDisplay: (40 at 40 extent: 300 at 300)) reverse at: 40 at 40"
- 	^ self fadeImage: otherImage at: topLeft indexAndMaskDo:
- 		[:i :mask |
- 		mask fill: ((16-i) asPoint extent: (i*2) asPoint) fillColor: Color black.
- 		i <= 16]!

Item was removed:
- ----- Method: Form>>fadeImageVert:at: (in category 'transitions') -----
- fadeImageVert: otherImage at: topLeft
- 	"Display fadeImageVert: (Form fromDisplay: (10 at 10 extent: 300 at 300)) reverse at: 10 at 10"
- 	| d |
- 	d := self depth.
- 	^ self fadeImage: otherImage at: topLeft indexAndMaskDo:
- 		[:i :mask |
- 		mask fill: ((mask width//2//d-i*d)@0 extent: i*2*d at mask height) fillColor: Color black.
- 		i <= (mask width//d)]!

Item was removed:
- ----- Method: Form>>fill:rule:fillColor: (in category 'filling') -----
- fill: aRectangle rule: anInteger fillColor: aForm 
- 	"Replace a rectangular area of the receiver with the pattern described by aForm 
- 	according to the rule anInteger."
- 	(BitBlt toForm: self)
- 		copy: aRectangle
- 		from: 0 at 0 in: nil
- 		fillColor: aForm rule: anInteger!

Item was removed:
- ----- Method: Form>>fillAlpha: (in category 'other') -----
- fillAlpha: alphaValue
- 	"Fill a 32bit form with a constant alpha value"
- 	| bb |
- 	self depth = 32 ifFalse:[^self error: 'Only valid for 32 bit forms'].
- 	bb := BitBlt toForm: self.
- 	bb combinationRule: 7. "bitOr:with:".
- 	bb fillColor: (Bitmap with: alphaValue << 24).
- 	bb copyBits.
- !

Item was removed:
- ----- Method: Form>>fillFromXColorBlock: (in category 'filling') -----
- fillFromXColorBlock: colorBlock
- 	"Horizontal Gradient Fill.
- 	Supply relative x in [0.0 ... 1.0] to colorBlock,
- 	and paint each pixel with the color that comes back"
- 	| xRel |
- 	0 to: width-1 do:
- 		[:x |  xRel := x asFloat / (width-1) asFloat.
- 		self fill: (x at 0 extent: 1 at height) 
- 			fillColor: (colorBlock value: xRel)]
- "
- ((Form extent: 100 at 100 depth: Display depth)
- 	fillFromXColorBlock: [:x | Color r: x g: 0.0 b: 0.5]) display
- "!

Item was removed:
- ----- Method: Form>>fillFromXYColorBlock: (in category 'filling') -----
- fillFromXYColorBlock: colorBlock
- 	"General Gradient Fill.
- 	Supply relative x and y in [0.0 ... 1.0] to colorBlock,
- 	and paint each pixel with the color that comes back"
- 	| poker yRel xRel |
- 	poker := BitBlt bitPokerToForm: self.
- 	0 to: height-1 do:
- 		[:y | yRel := y asFloat / (height-1) asFloat.
- 		0 to: width-1 do:
- 			[:x |  xRel := x asFloat / (width-1) asFloat.
- 			poker pixelAt: x at y
- 				put: ((colorBlock value: xRel value: yRel) pixelWordForDepth: self depth)]]
- "
-  | d |
- ((Form extent: 100 at 20 depth: Display depth)
- 	fillFromXYColorBlock:
- 	[:x :y | d := 1.0 - (x - 0.5) abs - (y - 0.5) abs.
- 	Color r: d g: 0 b: 1.0-d]) display
- "!

Item was removed:
- ----- Method: Form>>fillFromYColorBlock: (in category 'filling') -----
- fillFromYColorBlock: colorBlock
- 	"Vertical Gradient Fill.
- 	Supply relative y in [0.0 ... 1.0] to colorBlock,
- 	and paint each pixel with the color that comes back"
- 	| yRel |
- 	0 to: height-1 do:
- 		[:y |  yRel := y asFloat / (height-1) asFloat.
- 		self fill: (0 at y extent: width at 1) 
- 			fillColor: (colorBlock value: yRel)]
- "
- ((Form extent: 100 at 100 depth: Display depth)
- 	fillFromYColorBlock: [:y | Color r: y g: 0.0 b: 0.5]) display
- "!

Item was removed:
- ----- Method: Form>>findShapeAroundSeedBlock: (in category 'filling') -----
- findShapeAroundSeedBlock: seedBlock
- 	"Build a shape that is black in any region marked by seedBlock. 
- 	SeedBlock will be supplied a form, in which to blacken various
- 	pixels as 'seeds'.  Then the seeds are smeared until 
- 	there is no change in the smear when it fills the region, ie,
- 	when smearing hits a black border and thus goes no further."
- 	| smearForm previousSmear all count smearPort |
- 	self depth > 1 ifTrue: [self halt]. "Only meaningful for B/W forms."
- 	all := self boundingBox.
- 	smearForm := Form extent: self extent.
- 	smearPort := BitBlt toForm: smearForm.
- 	seedBlock value: smearForm.		"Blacken seeds to be smeared"
- 	smearPort copyForm: self to: 0 @ 0 rule: Form erase.  "Clear any in black"
- 	previousSmear := smearForm deepCopy.
- 	count := 1.
- 	[count = 10 and:   "check for no change every 10 smears"
- 		[count := 1.
- 		previousSmear copy: all from: 0 @ 0 in: smearForm rule: Form reverse.
- 		previousSmear isAllWhite]]
- 		whileFalse: 
- 			[smearPort copyForm: smearForm to: 1 @ 0 rule: Form under.
- 			smearPort copyForm: smearForm to: -1 @ 0 rule: Form under.
- 			"After horiz smear, trim around the region border"
- 			smearPort copyForm: self to: 0 @ 0 rule: Form erase.
- 			smearPort copyForm: smearForm to: 0 @ 1 rule: Form under.
- 			smearPort copyForm: smearForm to: 0 @ -1 rule: Form under.
- 			"After vert smear, trim around the region border"
- 			smearPort copyForm: self to: 0 @ 0 rule: Form erase.
- 			count := count + 1.
- 			count = 9 ifTrue: "Save penultimate smear for comparison"
- 				[previousSmear copy: all from: 0 @ 0 in: smearForm rule: Form over]].
- 	"Now paint the filled region in me with aHalftone"
- 	^ smearForm!

Item was removed:
- ----- Method: Form>>finish (in category 'initialize-release') -----
- finish
- 	"If there are any pending operations on the receiver complete them. Do not return before all modifications have taken effect."!

Item was removed:
- ----- Method: Form>>fixAlpha (in category 'other') -----
- fixAlpha
- 	"Fix the alpha channel if the receiver is 32bit"
- 	| bb |
- 	self depth = 32 ifFalse:[^self].
- 	bb := BitBlt toForm: self.
- 	bb combinationRule: 40 "fixAlpha:with:".
- 	bb copyBits.!

Item was removed:
- ----- Method: Form>>flipBy:centerAt: (in category 'scaling, rotation') -----
- flipBy: direction centerAt: aPoint
- 	"Return a copy of the receiver flipped either #vertical or #horizontal."
- 	| newForm quad |
- 	newForm := self class extent: self extent depth: depth.
- 	quad := self boundingBox innerCorners.
- 	quad := (direction = #vertical ifTrue: [#(2 1 4 3)] ifFalse: [#(4 3 2 1)])
- 		collect: [:i | quad at: i].
- 	(WarpBlt toForm: newForm)
- 		sourceForm: self;
- 		colorMap: (self colormapIfNeededFor: newForm);
- 		combinationRule: 3;
- 		copyQuad: quad toRect: newForm boundingBox.
- 	newForm offset: (self offset flipBy: direction centerAt: aPoint).
- 	^ newForm
- "
- [Sensor anyButtonPressed] whileFalse:
- 	[((Form fromDisplay: (Sensor cursorPoint extent: 130 at 66))
- 			flipBy: #vertical centerAt: 0 at 0) display]
- "
- "Consistency test...
-  | f f2 p | [Sensor anyButtonPressed] whileFalse:
- 	[f := Form fromDisplay: ((p := Sensor cursorPoint) extent: 31 at 41).
- 	Display fillBlack: (p extent: 31 at 41).
- 	f2 := f flipBy: #vertical centerAt: 0 at 0.
- 	(f2 flipBy: #vertical centerAt: 0 at 0) displayAt: p]
- "
- !

Item was removed:
- ----- Method: Form>>flipVertically (in category 'converting') -----
- flipVertically
- 	"Flip the image along the y axis"
- 	| rowLen row topIndex botIndex |
- 	self unhibernate.
- 	rowLen := bits size // height.
- 	row := Bitmap new: rowLen.
- 	topIndex := 1.
- 	botIndex := bits size - rowLen + 1.
- 	1 to: height // 2 do: [:i |
- 		self assert:[topIndex+rowLen <= botIndex].
- 		row replaceFrom: 1 to: rowLen with: bits startingAt: topIndex.
- 		bits replaceFrom: topIndex to: topIndex+rowLen-1 with: bits startingAt: botIndex.
- 		bits replaceFrom: botIndex to: botIndex+rowLen-1 with: row startingAt: 1.
- 		topIndex := topIndex + rowLen.
- 		botIndex := botIndex - rowLen.
- 	].
- !

Item was removed:
- ----- Method: Form>>floodFill2:at: (in category 'filling') -----
- floodFill2: aColor at: interiorPoint
- 	"Fill the shape (4-connected) at interiorPoint.  The algorithm is based on Paul Heckbert's 'A Seed Fill Algorithm', Graphic Gems I, Academic Press, 1990.
- 	NOTE: This is a less optimized variant for flood filling which is precisely along the lines of Heckbert's algorithm. For almost all cases #floodFill:at: will be faster (see the comment there) but this method is left in both as reference and as a fallback if such a strange case is encountered in reality."
- 	| poker stack old new x y top x1 x2 dy left goRight |
- 	poker := BitBlt bitPokerToForm: self.
- 	stack := OrderedCollection new: 50.
- 	"read old pixel value"
- 	old := self pixelValueAt: interiorPoint.
- 	"compute new value"
- 	new := self pixelValueFor: aColor.
- 	old = new ifTrue:[^self]. "no point, is there?!!"
- 
- 	x := interiorPoint x.
- 	y := interiorPoint y.
- 	(y >= 0 and:[y < height]) ifTrue:[
- 		stack addLast: {y. x. x. 1}. "y, left, right, dy"
- 		stack addLast: {y+1. x. x. -1}].
- 	[stack isEmpty] whileFalse:[
- 		top := stack removeLast.
- 		y := top at: 1. x1 := top at: 2. x2 := top at: 3. dy := top at: 4.
- 		y := y + dy.
- 		"Segment of scanline (y-dy) for x1 <= x <= x2 was previously filled.
- 		Now explore adjacent pixels in scanline y."
- 		x := x1.
- 		[x >= 0 and:[(self pixelValueAt: x at y) = old]] whileTrue:[
- 			poker pixelAt: x at y put: new.
- 			x := x - 1].
- 		goRight := x < x1.
- 		left := x+1.
- 		(left < x1 and:[y-dy >= 0 and:[y-dy < height]]) 
- 			ifTrue:[stack addLast: {y. left. x1-1. 0-dy}].
- 		goRight ifTrue:[x := x1 + 1].
- 		[
- 			goRight ifTrue:[
- 				[x < width and:[(self pixelValueAt: x at y) = old]] whileTrue:[
- 					poker pixelAt: x at y put: new.
- 					x := x + 1].
- 				(y+dy >= 0 and:[y+dy < height]) 
- 					ifTrue:[stack addLast: {y. left. x-1. dy}].
- 				(x > (x2+1) and:[y-dy >= 0 and:[y-dy >= 0]]) 
- 					ifTrue:[stack addLast: {y. x2+1. x-1. 0-dy}]].
- 			[(x := x + 1) <= x2 and:[(self pixelValueAt: x at y) ~= old]] whileTrue.
- 			left := x.
- 			goRight := true.
- 		x <= x2] whileTrue.
- 	].
- !

Item was removed:
- ----- Method: Form>>floodFill:at: (in category 'filling') -----
- floodFill: aColor at: interiorPoint
- 	Preferences areaFillsAreVeryTolerant ifTrue:
- 		[^ self floodFill: aColor at: interiorPoint tolerance: 0.2].
- 	Preferences areaFillsAreTolerant ifTrue:
- 		[^ self floodFill: aColor at: interiorPoint tolerance: 0.1].
- 	^ self floodFill: aColor at: interiorPoint tolerance: 0
- !

Item was removed:
- ----- Method: Form>>floodFill:at:tolerance: (in category 'filling') -----
- floodFill: aColor at: interiorPoint tolerance: tolerance
- 	"Fill the shape (4-connected) at interiorPoint.  The algorithm is based on Paul Heckbert's 'A Seed Fill Algorithm', Graphic Gems I, Academic Press, 1990.
- 	NOTE (ar): This variant has been heavily optimized to prevent the overhead of repeated calls to BitBlt. Usually this is a really big winner but the runtime now depends a bit on the complexity of the shape to be filled. For extremely complex shapes (say, a Hilbert curve) with very few pixels to fill it can be slower than #floodFill2:at: since it needs to repeatedly read the source bits. However, in all practical cases I found this variant to be 15-20 times faster than anything else.
- 	Further note (di):  I have added a feature that allows this routine to fill areas of approximately constant color (such as  photos, scans, and jpegs).  It does this by computing a color map for the peeker that maps all colors close to 'old' into colors identical to old.  This mild colorblindness achieves the desired effect with no further change or degradation of the algorithm.  tolerance should be 0 (exact match), or a value corresponding to those returned by Color>>diff:, with 0.1 being a reasonable starting choice."
- 
- 	| peeker poker stack old new x y top x1 x2 dy left goRight span spanBits w box debug |
- 	debug := false. "set it to true to see the filling process"
- 	box := interiorPoint extent: 1 at 1.
- 	span := Form extent: width at 1 depth: 32.
- 	spanBits := span bits.
- 
- 	peeker := BitBlt toForm: span.
- 	peeker 
- 		sourceForm: self; 
- 		combinationRule: 3; 
- 		width: width; 
- 		height: 1.
- 
- 	"read old pixel value"
- 	peeker sourceOrigin: interiorPoint; destOrigin: interiorPoint x @ 0; width: 1; copyBits.
- 	old := spanBits at: interiorPoint x + 1.
- 
- 	"compute new value (take care since the algorithm will fail if old = new)"
- 	new := self privateFloodFillValue: aColor.
- 	old = new ifTrue: [^ box].
- 	tolerance > 0 ifTrue:
- 		["Set up color map for approximate fills"
- 		peeker colorMap: (self floodFillMapFrom: self to: span mappingColorsWithin: tolerance to: old)].
- 
- 	poker := BitBlt toForm: self.
- 	poker 
- 		fillColor: aColor;
- 		combinationRule: 3;
- 		width: width;
- 		height: 1.
- 
- 	stack := OrderedCollection new: 50.
- 	x := interiorPoint x.
- 	y := interiorPoint y.
- 	(y >= 0 and:[y < height]) ifTrue:[
- 		stack addLast: {y. x. x. 1}. "y, left, right, dy"
- 		stack addLast: {y+1. x. x. -1}].
- 
- 	[stack isEmpty] whileFalse:[
- 		debug ifTrue:[self displayOn: Display].
- 		top := stack removeLast.
- 		y := top at: 1. x1 := top at: 2. x2 := top at: 3. dy := top at: 4.
- 		y := y + dy.
- 		debug ifTrue:[
- 			Display 
- 				drawLine: (Form extent: 1 at 1 depth: 8) fillWhite
- 				from: (x1-1)@y to: (x2+1)@y 
- 				clippingBox: Display boundingBox
- 				rule: Form over fillColor: nil].
- 		"Segment of scanline (y-dy) for x1 <= x <= x2 was previously filled.
- 		Now explore adjacent pixels in scanline y."
- 		peeker sourceOrigin: 0 at y; destOrigin: 0 at 0; width: width; copyBits.
- 			"Note: above is necessary since we don't know where we'll end up filling"
- 		x := x1.
- 		w := 0.
- 		[x >= 0 and:[(spanBits at: x+1) = old]] whileTrue:[
- 			w := w + 1.
- 			x := x - 1].
- 		w > 0 ifTrue:[
- 			"overwrite pixels"
- 			poker destOrigin: x+1 at y; width: w; copyBits.
- 			box := box quickMerge: ((x+1 at y) extent: w at 1)].
- 		goRight := x < x1.
- 		left := x+1.
- 		(left < x1 and:[y-dy >= 0 and:[y-dy < height]]) 
- 			ifTrue:[stack addLast: {y. left. x1-1. 0-dy}].
- 		goRight ifTrue:[x := x1 + 1].
- 		[
- 			goRight ifTrue:[
- 				w := 0.
- 				[x < width and:[(spanBits at: x+1) = old]] whileTrue:[
- 					w := w + 1.
- 					x := x + 1].
- 				w > 0 ifTrue:[
- 					"overwrite pixels"
- 					poker destOrigin: (x-w)@y; width: w; copyBits.
- 					box := box quickMerge: ((x-w at y) extent: w at 1)].
- 				(y+dy >= 0 and:[y+dy < height]) 
- 					ifTrue:[stack addLast: {y. left. x-1. dy}].
- 				(x > (x2+1) and:[y-dy >= 0 and:[y-dy >= 0]]) 
- 					ifTrue:[stack addLast: {y. x2+1. x-1. 0-dy}]].
- 			[(x := x + 1) <= x2 and:[(spanBits at: x+1) ~= old]] whileTrue.
- 			left := x.
- 			goRight := true.
- 		x <= x2] whileTrue.
- 	].
- 	^box!

Item was removed:
- ----- Method: Form>>floodFillMapFrom:to:mappingColorsWithin:to: (in category 'filling') -----
- floodFillMapFrom: sourceForm to: scanlineForm mappingColorsWithin: dist to: centerPixVal
- 	"This is a helper routine for floodFill.  It's written for clarity (scanning the entire
- 	map using colors) rather than speed (which would require hacking rgb components
- 	in the nieghborhood of centerPixVal.  Note that some day a better proximity metric
- 	would be (h s v) where tolerance could be reduced in hue."
- 
- 	| colorMap centerColor |
- 	scanlineForm depth = 32 ifFalse: [self error: 'depth 32 assumed'].
- 	"First get a modifiable identity map"
- 	colorMap := 	(Color cachedColormapFrom: sourceForm depth to: scanlineForm depth) copy.
- 	centerColor := Color colorFromPixelValue: (centerPixVal bitOr: 16rFFe6) depth: scanlineForm depth.
- 	"Now replace all entries that are close to the centerColor"
- 	1 to: colorMap size do:
- 		[:i | ((Color colorFromPixelValue: ((colorMap at: i) bitOr: 16rFFe6) depth: scanlineForm depth)
- 				diff: centerColor) <= dist ifTrue: [colorMap at: i put: centerPixVal]].
- 	^ colorMap!

Item was removed:
- ----- Method: Form>>flush (in category 'initialize-release') -----
- flush
- 	"If there are any pending operations on the receiver start doing them. In time, they will show up on the receiver but not necessarily immediately after this method returns."!

Item was removed:
- ----- Method: Form>>form (in category 'accessing') -----
- form
- 	"Answer the receiver's form.  For vanilla Forms, this degenerates to self.  Makes several methods that operate on both Forms and MaskedForms much more straightforward.   6/1/96 sw"
- 
- 	^ self!

Item was removed:
- ----- Method: Form>>formForColorCount: (in category 'other') -----
- formForColorCount: colorCount
- 	"Return a ColorForm of sufficient depth to represent the given number of colors. The maximum number of colors is 256."
- 
- 	colorCount > 256 ifTrue: [^ self error: 'too many colors'].
- 
- 	colorCount > 16 ifTrue: [^ ColorForm extent: self extent depth: 8].
- 	colorCount > 4 ifTrue: [^ ColorForm extent: self extent depth: 4].
- 	colorCount > 2 ifTrue: [^ ColorForm extent: self extent depth: 2].
- 	^ ColorForm extent: self extent depth: 1
- !

Item was removed:
- ----- Method: Form>>fromDisplay: (in category 'initialize-release') -----
- fromDisplay: aRectangle 
- 	"Create a virtual bit map from a user specified rectangular area on the 
- 	display screen. Reallocates bitmap only if aRectangle ~= the receiver's 
- 	extent."
- 
- 	(width = aRectangle width and: [height = aRectangle height])
- 		ifFalse: [self setExtent: aRectangle extent depth: depth].
- 	self
- 		copyBits: (aRectangle origin extent: self extent)
- 		from: Display
- 		at: 0 @ 0
- 		clippingBox: self boundingBox
- 		rule: Form over
- 		fillColor: nil!

Item was removed:
- ----- Method: Form>>getCanvas (in category 'accessing') -----
- getCanvas
- 	"Return a Canvas that can be used to draw onto the receiver"
- 	^self defaultCanvasClass on: self!

Item was removed:
- ----- Method: Form>>hackBits: (in category 'private') -----
- hackBits: bitThing
- 	"This method provides an initialization so that BitBlt may be used, eg, to 
- 	copy ByteArrays and other non-pointer objects efficiently.
- 	The resulting form looks 4 wide, 8 deep, and bitThing-size-in-words high."
- 	width := 4.
- 	depth := 8.
- 	bitThing class isBits ifFalse: [self error: 'bitThing must be a non-pointer object'].
- 	height := bitThing basicSize * bitThing bytesPerBasicElement // width.
- 	bits := bitThing!

Item was removed:
- ----- Method: Form>>hasBeenModified (in category 'accessing') -----
- hasBeenModified
- 	"Return true if something *might* have been drawn into the receiver"
- 	^(bits == nil or:[bits class == ByteArray]) not
- 	"Read the above as: If the receiver has forgotten its contents (bits == nil) 
- 	or is still hibernated it can't be modified."!

Item was removed:
- ----- Method: Form>>hasBeenModified: (in category 'accessing') -----
- hasBeenModified: aBool
- 	"Change the receiver to reflect the modification state"
- 	aBool ifTrue:[^self unhibernate].
- 	self shouldPreserveContents
- 		ifTrue:[self hibernate]
- 		ifFalse:[bits := nil]!

Item was removed:
- ----- Method: Form>>hasNonStandardPalette (in category 'testing') -----
- hasNonStandardPalette
- 	"Return true if the receiver has a non-standard palette.
- 	Non-standard means that RGBA components may be located
- 	at positions differing from the standard Squeak RGBA layout
- 	at the receiver's depth."
- 	^false!

Item was removed:
- ----- Method: Form>>height (in category 'display box access') -----
- height
- 	^ height!

Item was removed:
- ----- Method: Form>>hibernate (in category 'fileIn/Out') -----
- hibernate
- 	"Replace my bitmap with a compactly encoded representation (a ByteArray).  It is vital that BitBlt and any other access to the bitmap (such as writing to a file) not be used when in this state.  Since BitBlt will fail if the bitmap size is wrong (not = bitsSize), we do not allow replacement by a byteArray of the same (or larger) size."
- 
- 	"NOTE: This method copies code from Bitmap compressToByteArray so that it can
- 	nil out the old bits during the copy, thus avoiding 2x need for extra storage."
- 	| compactBits lastByte |
- 	(bits isMemberOf: Bitmap) ifFalse: [^ self  "already hibernated or weird state"].
- 	compactBits := ByteArray new: (bits size*4) + 7 + (bits size//1984*3).
- 	lastByte := bits compress: bits toByteArray: compactBits.
- 	lastByte < (bits size*4) ifTrue:
- 		[bits := nil.  "Let GC reclaim the old bits before the copy if necessary"
- 		bits := compactBits copyFrom: 1 to: lastByte]!

Item was removed:
- ----- Method: Form>>initFromArray: (in category 'private') -----
- initFromArray: array
- 	"Fill the bitmap from array.  If the array is shorter,
- 	then cycle around in its contents until the bitmap is filled."
- 	| ax aSize array32 i j word16 |
- 	ax := 0.
- 	aSize := array size.
- 	aSize > bits size ifTrue:
- 		["backward compatibility with old 16-bit bitmaps and their forms"
- 		array32 := Array new: height * (width + 31 // 32).
- 		i := j := 0.
- 		1 to: height do:
- 			[:y | 1 to: width+15//16 do:
- 				[:x16 | word16 := array at: (i := i + 1).
- 				x16 odd ifTrue: [array32 at: (j := j+1) put: (word16 bitShift: 16)]
- 						ifFalse: [array32 at: j put: ((array32 at: j) bitOr: word16)]]].
- 		^ self initFromArray: array32].
- 	1 to: bits size do:
- 		[:index |
- 		(ax := ax + 1) > aSize ifTrue: [ax := 1].
- 		bits at: index put: (array at: ax)]!

Item was removed:
- ----- Method: Form>>innerPixelRectFor:orNot: (in category 'analyzing') -----
- innerPixelRectFor: pv orNot: not
- 	"Return a rectangle describing the smallest part of me that includes 
- 	all pixels of value pv.
- 	Note:  If orNot is true, then produce a copy that includes all pixels
- 	that are DIFFERENT from the supplied (background) value"
- 
- 	| xTally yTally |
- 	xTally := self xTallyPixelValue: pv orNot: not.
- 	yTally := self yTallyPixelValue: pv orNot: not.
- 	^ ((xTally findFirst: [:t | t>0]) - 1) @ ((yTally findFirst: [:t | t>0]) - 1)
- 		corner:
- 			(xTally findLast: [:t | t>0])@(yTally findLast: [:t | t>0])!

Item was removed:
- ----- Method: Form>>isAllWhite (in category 'testing') -----
- isAllWhite
- 	"Answer whether all bits in the receiver are white"
- 	| word |
- 	self unhibernate.
- 	word := Color white pixelWordForDepth: self depth.
- 	1 to: bits size do: [:i | (bits at: i) = word ifFalse: [^ false]].
- 	^ true!

Item was removed:
- ----- Method: Form>>isBigEndian (in category 'testing') -----
- isBigEndian
- 	"Return true if the receiver contains big endian pixels, meaning the left-most pixel is stored in the most significant bits of a word."
- 	^depth > 0!

Item was removed:
- ----- Method: Form>>isDisplayScreen (in category 'testing') -----
- isDisplayScreen
- 	^false!

Item was removed:
- ----- Method: Form>>isForm (in category 'testing') -----
- isForm
- 	^true!

Item was removed:
- ----- Method: Form>>isGrayScale (in category 'testing') -----
- isGrayScale
- 	^ false!

Item was removed:
- ----- Method: Form>>isLittleEndian (in category 'testing') -----
- isLittleEndian
- 	"Return true if the receiver contains little endian pixels, meaning the left-most pixel is stored in the least significant bits of a word."
- 	^depth < 0!

Item was removed:
- ----- Method: Form>>isStatic (in category 'testing') -----
- isStatic
- 
- 	^false!

Item was removed:
- ----- Method: Form>>isTranslucent (in category 'testing') -----
- isTranslucent
- 	"Answer whether this form may be translucent"
- 	^self depth = 32!

Item was removed:
- ----- Method: Form>>isTransparentAt: (in category 'pixel access') -----
- isTransparentAt: aPoint 
- 	"Return true if the receiver is transparent at the given point."
- 
- 	self depth = 1 ifTrue: [^ false].  "no transparency at depth 1"
- 	^ (self pixelValueAt: aPoint) = (self pixelValueFor: Color transparent)
- !

Item was removed:
- ----- Method: Form>>isVirtualScreen (in category 'testing') -----
- isVirtualScreen
- 	"Am I a virtual display screen?"
- 	^false!

Item was removed:
- ----- Method: Form>>lighter (in category 'converting') -----
- lighter
- 	"Answer a lighter variant of this form"
- 	^self collectColors:[:color| color lighter lighter].!

Item was removed:
- ----- Method: Form>>magnify:by: (in category 'scaling, rotation') -----
- magnify: aRectangle by: scale 
- 	"Answer a Form created as a scaling of the receiver.
- 	Scale may be a Float, and may be greater or less than 1.0."
- 	^ self magnify: aRectangle by: scale smoothing: 1
- 
- "Dynamic test...
- [Sensor anyButtonPressed] whileFalse:
- 	[(Display magnify: (Sensor cursorPoint extent: 31 at 41) by: 5 at 3) display]
- "
- "Scaling test...
- | f cp | f := Form fromDisplay: (Rectangle originFromUser: 100 at 100).
- Display restoreAfter: [Sensor waitNoButton.
- [Sensor anyButtonPressed] whileFalse:
- 	[cp := Sensor cursorPoint.
- 	(f magnify: f boundingBox by: (cp x asFloat at cp y asFloat)/f extent) display]]
- "
- "Consistency test...
-  | f f2 p | [Sensor anyButtonPressed] whileFalse:
- 	[f := Form fromDisplay: ((p := Sensor cursorPoint) extent: 31 at 41).
- 	Display fillBlack: (p extent: 31 at 41).
- 	f2 := f magnify: f boundingBox by: 5 at 3.
- 	(f2 shrink: f2 boundingBox by: 5 at 3) displayAt: p]
- "
- !

Item was removed:
- ----- Method: Form>>magnify:by:smoothing: (in category 'scaling, rotation') -----
- magnify: aRectangle by: scale smoothing: cellSize
-         "Answer a Form created as a scaling of the receiver.
-         Scale may be a Float or even a Point, and may be greater or less than 1.0."
-         | newForm |
-         newForm := self blankCopyOf: aRectangle scaledBy: scale.
-         (WarpBlt toForm: newForm)
-                 sourceForm: self;
-                 colorMap: (self colormapIfNeededFor: newForm);
-                 cellSize: cellSize;  "installs a new colormap if cellSize > 1"
-                 combinationRule: 3;
-                 copyQuad: aRectangle innerCorners toRect: newForm boundingBox.
-         ^ newForm
- 
- "Dynamic test...
- [Sensor anyButtonPressed] whileFalse:
-         [(Display magnify: (Sensor cursorPoint extent: 131 at 81) by: 0.5 smoothing: 2) display]
- "
- "Scaling test...
- | f cp | f := Form fromDisplay: (Rectangle originFromUser: 100 at 100).
- Display restoreAfter: [Sensor waitNoButton.
- [Sensor anyButtonPressed] whileFalse:
-         [cp := Sensor cursorPoint.
-         (f magnify: f boundingBox by: (cp x asFloat at cp y asFloat)/f extent smoothing: 2) display]]
- "!

Item was removed:
- ----- Method: Form>>magnifyBy: (in category 'scaling, rotation') -----
- magnifyBy: scale 
- 	"Answer a Form created as a scaling of the receiver.
- 	Scale may be a Float or even a Point, and may be greater or less than 1.0."
- 	| effectiveScale |
- 	effectiveScale := scale isPoint ifTrue: [scale r] ifFalse: [scale].
- 	^ self magnify: self boundingBox by: scale
- 			smoothing: (effectiveScale < 1 ifTrue: [2] ifFalse: [1])!

Item was removed:
- ----- Method: Form>>makeBWForm: (in category 'color mapping') -----
- makeBWForm: foregroundColor
- 	"Map this form into a B/W form with 1's in the foreground regions."
- 	| bwForm map |
- 	bwForm := Form extent: self extent.
- 	map := self newColorMap.  "All non-foreground go to 0's"
- 	map at: (foregroundColor indexInMap: map) put: 1.
- 	bwForm copyBits: self boundingBox from: self at: 0 at 0 colorMap: map.
- 	^ bwForm!

Item was removed:
- ----- Method: Form>>mapColor:to: (in category 'color mapping') -----
- mapColor: oldColor to: newColor
- 	"Make all pixels of the given color in this Form to the given new color."
- 	"Warnings: This method modifies the receiver. It may lose some color accuracy on 32-bit Forms, since the transformation uses a color map with only 15-bit resolution."
- 
- 	| map |
- 	map := (Color cachedColormapFrom: self depth to: self depth) copy.
- 	map at: (oldColor indexInMap: map) put: (newColor pixelWordForDepth: self depth).
- 	(BitBlt toForm: self)
- 		sourceForm: self;
- 		sourceOrigin: 0 at 0;
- 		combinationRule: Form over;
- 		destX: 0 destY: 0 width: width height: height;
- 		colorMap: map;
- 		copyBits.
- !

Item was removed:
- ----- Method: Form>>mapColors:to: (in category 'color mapping') -----
- mapColors: oldColorBitsCollection to: newColorBits
- 	"Make all pixels of the given color in this Form to the given new color."
- 	"Warnings: This method modifies the receiver. It may lose some color accuracy on 32-bit Forms, since the transformation uses a color map with only 15-bit resolution."
- 
- 	| map |
- 	self depth < 16
- 		ifTrue: [map := (Color cachedColormapFrom: self depth to: self depth) copy]
- 		ifFalse: [
- 			"use maximum resolution color map"
- 			"source is 16-bit or 32-bit RGB; use colormap with 5 bits per color component"
- 			map := Color computeRGBColormapFor: self depth bitsPerColor: 5].
- 	oldColorBitsCollection do:[ :oldColor | map at: oldColor put: newColorBits].
- 
- 	(BitBlt toForm: self)
- 		sourceForm: self;
- 		sourceOrigin: 0 at 0;
- 		combinationRule: Form over;
- 		destX: 0 destY: 0 width: width height: height;
- 		colorMap: map;
- 		copyBits.
- !

Item was removed:
- ----- Method: Form>>maskingMap (in category 'color mapping') -----
- maskingMap
- 	"Return a color map that maps all colors except transparent to words of all ones. Used to create a mask for a Form whose transparent pixel value is zero."
- 	^Color maskingMap: self depth!

Item was removed:
- ----- Method: Form>>nativeDepth (in category 'accessing') -----
- nativeDepth
- 	"Return the 'native' depth of the receiver, e.g., including the endianess"
- 	^depth!

Item was removed:
- ----- Method: Form>>newColorMap (in category 'color mapping') -----
- newColorMap 
- 	"Return an uninitialized color map array appropriate to this Form's depth."
- 
- 	^ Bitmap new: (1 bitShift: (self depth min: 15))
- !

Item was removed:
- ----- Method: Form>>numComponents (in category 'postscript generation') -----
- numComponents
- 	^self depth <= 8 ifTrue:[1] ifFalse:[3].
- !

Item was removed:
- ----- Method: Form>>objectForDataStream: (in category 'fileIn/Out') -----
- objectForDataStream: refStream
- 	| prj repl |
- 	prj := refStream project.
- 	prj ifNil:[^super objectForDataStream: refStream].
- 	ResourceCollector current ifNil:[^super objectForDataStream: refStream].
- 	repl := ResourceCollector current objectForDataStream: refStream fromForm: self.
- 	^repl!

Item was removed:
- ----- Method: Form>>offset (in category 'accessing') -----
- offset
- 	^offset ifNil:[0 at 0]!

Item was removed:
- ----- Method: Form>>offset: (in category 'accessing') -----
- offset: aPoint
- 
- 	offset := aPoint!

Item was removed:
- ----- Method: Form>>orderedDither32To16 (in category 'converting') -----
- orderedDither32To16
- 	"Do an ordered dithering for converting from 32 to 16 bit depth."
- 	| ditherMatrix ii out inBits outBits index pv dmv r di dmi dmo g b pvOut outIndex |
- 	self depth = 32 ifFalse:[^self error:'Must be 32bit for this'].
- 	ditherMatrix := #(	0	8	2	10
- 						12	4	14	6
- 						3	11	1	9
- 						15	7	13	5).
- 	ii := (0 to: 31) collect:[:i| i].
- 	out := Form extent: self extent depth: 16.
- 	inBits := self bits.
- 	outBits := out bits.
- 	index := outIndex := 0.
- 	pvOut := 0.
- 	0 to: self height-1 do:[:y|
- 		0 to: self width-1 do:[:x|
- 			pv := inBits at: (index := index + 1).
- 			dmv := ditherMatrix at: (y bitAnd: 3) * 4 + (x bitAnd: 3) + 1.
- 			r := pv bitAnd: 255.	di := r * 496 bitShift: -8.
- 			dmi := di bitAnd: 15.	dmo := di bitShift: -4.
- 			r := dmv < dmi ifTrue:[ii at: 2+dmo] ifFalse:[ii at: 1+dmo].
- 			g := (pv bitShift: -8) bitAnd: 255.	di := g * 496 bitShift: -8.
- 			dmi := di bitAnd: 15.	dmo := di bitShift: -4.
- 			g := dmv < dmi ifTrue:[ii at: 2+dmo] ifFalse:[ii at: 1+dmo].
- 			b := (pv bitShift: -16) bitAnd: 255.	di := b * 496 bitShift: -8.
- 			dmi := di bitAnd: 15.	dmo := di bitShift: -4.
- 			b := dmv < dmi ifTrue:[ii at: 2+dmo] ifFalse:[ii at: 1+dmo].
- 			pvOut := (pvOut bitShift: 16) + 
- 						(b bitShift: 10) + (g bitShift: 5) + r.
- 			(x bitAnd: 1) = 1 ifTrue:[
- 				outBits at: (outIndex := outIndex+1) put: pvOut.
- 				pvOut := 0].
- 		].
- 		(self width bitAnd: 1) = 1 ifTrue:[
- 			outBits at: (outIndex := outIndex+1) put: (pvOut bitShift: -16).
- 			pvOut := 0].
- 	].
- 	^out!

Item was removed:
- ----- Method: Form>>paddedWidth (in category 'postscript generation') -----
- paddedWidth
- 	^ (self width + (self rowPadding-1)// self rowPadding) * self rowPadding.!

Item was removed:
- ----- Method: Form>>pageImage:at:corner: (in category 'transitions') -----
- pageImage: otherImage at: topLeft corner: corner
- 	"Produce a page-turning illusion that gradually reveals otherImage
- 	located at topLeft in this form.  Corner specifies which corner, as
- 		1=topLeft, 2=topRight, 3=bottomRight, 4=bottomLeft."
- 	| bb maskForm resultForm delta maskLoc maskRect stepSize cornerSel smallRect |
- 	stepSize := 10.
- 	bb := otherImage boundingBox.
- 	resultForm := self copy: (topLeft extent: bb extent).
- 	maskForm := Form extent: ((otherImage width min: otherImage height) + stepSize) asPoint.
- 
- 	"maskLoc := starting loc rel to topLeft"
- 	otherImage width > otherImage height
- 		ifTrue: ["wide image; motion is horizontal."
- 				(corner between: 2 and: 3) not ifTrue:
- 					["motion is to the right"
- 					delta := 1 @ 0.
- 					maskLoc := bb topLeft - (corner = 1
- 						ifTrue: [maskForm width @ 0]
- 						ifFalse: [maskForm width @ stepSize])]
- 					ifFalse:
- 					["motion is to the left"
- 					delta := -1 @ 0.
- 					maskLoc := bb topRight - (corner = 2
- 						ifTrue: [0 @ 0]
- 						ifFalse: [0 @ stepSize])]]
- 		ifFalse: ["tall image; motion is vertical."
- 				corner <= 2 ifTrue:
- 					["motion is downward"
- 					delta := 0 @ 1.
- 					maskLoc := bb topLeft - (corner = 1
- 						ifTrue: [0 @ maskForm height]
- 						ifFalse: [stepSize @ maskForm height])]
- 					ifFalse:
- 					["motion is upward"
- 					delta := 0 @ -1.
- 					maskLoc := bb bottomLeft - (corner = 3
- 						ifTrue: [stepSize @ 0]
- 						ifFalse: [0 @ 0])]].
- 
- 	"Build a solid triangle in the mask form"
- 	(Pen newOnForm: maskForm) in: [:p |
- 		corner even  "Draw 45-degree line"
- 			ifTrue: [p place: 0 @ 0; turn: 135; go: maskForm width * 3 // 2]
- 			ifFalse: [p place: 0 @ (maskForm height - 1); turn: 45; go: maskForm width * 3 // 2]].
- 	maskForm smear: delta negated distance: maskForm width.
- 	"Copy the mask to full resolution for speed.  Make it be the reversed
- 	so that it can be used for ORing in the page-corner color"
- 	maskForm := (Form extent: maskForm extent depth: otherImage depth)
- 		copyBits: maskForm boundingBox from: maskForm at: 0 @ 0
- 		colorMap: (Bitmap with: 16rFFFFFFFF with: 0).
- 
- 	"Now move the triangle maskForm across the resultForm selecting the
- 	triangular part of otherImage to display, and across the resultForm,
- 	selecting the part of the original image to erase."
- 	cornerSel := #(topLeft topRight bottomRight bottomLeft) at: corner.
- 	1 to: (otherImage width + otherImage height // stepSize) + 1 do:
- 		[:i |		"Determine the affected square"
- 		maskRect := (maskLoc extent: maskForm extent) intersect: bb.
- 		((maskLoc x * delta x) + (maskLoc y * delta y)) < 0 ifTrue:
- 			[smallRect := 0 @ 0 extent: (maskRect width min: maskRect height) asPoint.
- 			maskRect := smallRect align: (smallRect perform: cornerSel)
- 								with: (maskRect perform: cornerSel)].
- 
- 		"AND otherForm with triangle mask, and OR into result"
- 		resultForm copyBits: bb from: otherImage at: 0 @ 0
- 				clippingBox: maskRect rule: Form over fillColor: nil.
- 		resultForm copyBits: maskForm boundingBox from: maskForm at: maskLoc
- 				clippingBox: maskRect rule: Form erase fillColor: nil.
- 		resultForm copyBits: maskForm boundingBox from: maskForm at: maskLoc
- 				clippingBox: maskRect rule: Form under fillColor: Color lightBrown.
- 
- 		"Now update Display in a single BLT."
- 		self copyBits: maskRect from: resultForm at: topLeft + maskRect topLeft
- 				clippingBox: self boundingBox rule: Form over fillColor: nil.
- 		Display forceDisplayUpdate.
- 		maskLoc := maskLoc + (delta * stepSize)]
- "
- 1 to: 4 do: [:corner | Display pageImage:
- 				(Form fromDisplay: (10 at 10 extent: 200 at 300)) reverse
- 			at: 10 at 10 corner: corner]
- "
- !

Item was removed:
- ----- Method: Form>>pageWarp:at:forward: (in category 'transitions') -----
- pageWarp: otherImage at: topLeft forward: forward
- 	"Produce a page-turning illusion that gradually reveals otherImage
- 	located at topLeft in this form.
- 	forward == true means turn pages toward you, else away. [ignored for now]"
- 	| pageRect oldPage nSteps buffer p leafRect sourceQuad warp oldBottom d |
- 	pageRect := otherImage boundingBox.
- 	oldPage := self copy: (pageRect translateBy: topLeft).
- 	(forward ifTrue: [oldPage] ifFalse: [otherImage])
- 		border: pageRect
- 		widthRectangle: (Rectangle
- 				left: 0
- 				right: 2
- 				top: 1
- 				bottom: 1)
- 		rule: Form over
- 		fillColor: Color black.
- 	oldBottom := self copy: ((pageRect bottomLeft + topLeft) extent: (pageRect width@(pageRect height//4))).
- 	nSteps := 8.
- 	buffer := Form extent: otherImage extent + (0@(pageRect height//4)) depth: self depth.
- 	d := pageRect topLeft + (0@(pageRect height//4)) - pageRect topRight.
- 	1 to: nSteps-1 do:
- 		[:i | forward
- 			ifTrue: [buffer copy: pageRect from: otherImage to: 0 at 0 rule: Form over.
- 					p := pageRect topRight + (d * i // nSteps)]
- 			ifFalse: [buffer copy: pageRect from: oldPage to: 0 at 0 rule: Form over.
- 					p := pageRect topRight + (d * (nSteps-i) // nSteps)].
- 		buffer copy: oldBottom boundingBox from: oldBottom to: pageRect bottomLeft rule: Form over.
- 		leafRect := pageRect topLeft corner: p x @ (pageRect bottom + p y).
- 		sourceQuad := Array with: pageRect topLeft
- 			with: pageRect bottomLeft + (0 at p y)
- 			with: pageRect bottomRight
- 			with: pageRect topRight - (0 at p y).
- 		warp := (WarpBlt toForm: buffer)
- 				clipRect: leafRect;
- 				sourceForm: (forward ifTrue: [oldPage] ifFalse: [otherImage]);
- 				combinationRule: Form paint.
- 		warp copyQuad: sourceQuad toRect: leafRect.
- 		self copy: buffer boundingBox from: buffer to: topLeft rule: Form over.
- 		Display forceDisplayUpdate].
- 
- 	buffer copy: pageRect from: otherImage to: 0 at 0 rule: Form over.
- 	buffer copy: oldBottom boundingBox from: oldBottom to: pageRect bottomLeft rule: Form over.
- 	self copy: buffer boundingBox from: buffer to: topLeft rule: Form over.
- 	Display forceDisplayUpdate.
- "
- 1 to: 4 do: [:corner | Display pageWarp:
- 				(Form fromDisplay: (10 at 10 extent: 200 at 300)) reverse
- 			at: 10 at 10 forward: false]
- "
- !

Item was removed:
- ----- Method: Form>>paintBits:at:translucent: (in category 'displaying') -----
- paintBits: sourceForm at: destOrigin translucent: factor
- 	"Make up a BitBlt table and copy the bits with the given colorMap."
- 	(BitBlt destForm: self
- 		sourceForm: sourceForm
- 		halftoneForm: nil
- 		combinationRule: 31
- 		destOrigin: destOrigin
- 		sourceOrigin: 0 at 0
- 		extent: sourceForm extent
- 		clipRect: self boundingBox)
- 		copyBitsTranslucent: ((0 max: (factor*255.0) asInteger) min: 255)
- "
-  | f f2 f3 | f := Form fromUser. f replaceColor: f peripheralColor withColor: Color transparent.
- f2 := Form fromDisplay: (0 at 0 extent: f extent). f3 := f2 deepCopy.
- 0.0 to: 1.0 by: 1.0/32 do:
- 	[:t | f3 := f2 deepCopy. f3 paintBits: f at: 0 at 0 translucent: t.
- 	f3 displayAt: 0 at 0. (Delay forMilliseconds: 100) wait].
- "!

Item was removed:
- ----- Method: Form>>pixelCompare:with:at: (in category 'analyzing') -----
- pixelCompare: aRect with: otherForm at: otherLoc
- 	"Compare the selected bits of this form (those within aRect) against
- 	those in a similar rectangle of otherFrom.  Return the sum of the
- 	absolute value of the differences of the color values of every pixel.
- 	Obviously, this is most useful for rgb (16- or 32-bit) pixels but,
- 	in the case of 8-bits or less, this will return the sum of the differing
- 	bits of the corresponding pixel values (somewhat less useful)"
- 	| pixPerWord temp |
- 	pixPerWord := 32//self depth.
- 	(aRect left\\pixPerWord = 0 and: [aRect right\\pixPerWord = 0]) ifTrue:
- 		["If word-aligned, use on-the-fly difference"
- 		^ (BitBlt toForm: self) copy: aRect from: otherLoc in: otherForm
- 				fillColor: nil rule: 32].
- 	"Otherwise, combine in a word-sized form and then compute difference"
- 	temp := self copy: aRect.
- 	temp copy: aRect from: otherLoc in: otherForm rule: 21.
- 	^ (BitBlt toForm: temp) copy: aRect from: otherLoc in: nil
- 				fillColor: (Bitmap with: 0) rule: 32
- "  Dumb example prints zero only when you move over the original rectangle...
-  | f diff | f := Form fromUser.
- [Sensor anyButtonPressed] whileFalse:
- 	[diff := f pixelCompare: f boundingBox
- 		with: Display at: Sensor cursorPoint.
- 	diff printString , '        ' displayAt: 0 at 0]
- "!

Item was removed:
- ----- Method: Form>>pixelValueAt: (in category 'pixel access') -----
- pixelValueAt: aPoint 
- 	"Return the raw pixel value at the given point. This pixel value depends on the receiver's depth. Typical clients use colorAt: to get a Color.  "
- 
- 	^ self primPixelValueAtX: aPoint x y: aPoint y!

Item was removed:
- ----- Method: Form>>pixelValueAt:put: (in category 'pixel access') -----
- pixelValueAt: aPoint put: pixelValue
- 	"Store the given raw pixel value at the given point. Typical clients use colorAt:put: to store a color. "
- 
- 	(BitBlt bitPokerToForm: self) pixelAt: aPoint put: pixelValue.
- !

Item was removed:
- ----- Method: Form>>pixelValueFor: (in category 'color mapping') -----
- pixelValueFor: aColor
- 	"Return the pixel word for representing the given color on the receiver"
- 	^aColor pixelValueForDepth: self depth!

Item was removed:
- ----- Method: Form>>pixelWordFor: (in category 'color mapping') -----
- pixelWordFor: aColor
- 	"Return the pixel word for representing the given color on the receiver"
- 	^aColor pixelWordForDepth: self depth!

Item was removed:
- ----- Method: Form>>postCopy (in category 'copying') -----
- postCopy
- 	super postCopy.
- 	bits := bits copy
- !

Item was removed:
- ----- Method: Form>>preMultiplyAlpha (in category 'other') -----
- preMultiplyAlpha
- 	"Pre-multiply each pixel by its alpha, for proper alpha compositing (BitBlt rule 34).
- 	E.g., half-transparent green 16r7F00FF00 becomes 16r7F007F00"
- 
- 	depth = 32 ifFalse: [^self].
- 	1 to: bits size do: [:i |
- 		| v a r g b |
- 		v := bits at: i.
- 		a := v bitShift: -24.
- 		r := ((v bitShift: -16) bitAnd: 255) * a // 255.
- 		g := ((v bitShift: -8) bitAnd: 255) * a // 255.
- 		b := (v bitAnd: 255) * a // 255.
- 		bits at: i put: (a bitShift: 24) + (r bitShift: 16) + (g bitShift: 8) + b].!

Item was removed:
- ----- Method: Form>>primCountBits (in category 'analyzing') -----
- primCountBits
- 	"Count the non-zero pixels of this form."
- 	self depth > 8 ifTrue:
- 		[^(self asFormOfDepth: 8) primCountBits].
- 	^ (BitBlt toForm: self)
- 		fillColor: (Bitmap with: 0);
- 		destRect: (0 at 0 extent: width at height);
- 		combinationRule: 32;
- 		copyBits!

Item was removed:
- ----- Method: Form>>primPixelValueAtX:y: (in category 'pixel access') -----
- primPixelValueAtX: x y: y 
- 	"Return the raw pixel value at the given point. This pixel value depends on the receiver's depth. Typical clients use colorAt: to get a Color. Make sure the colorMap is nil for ColorForms "
- 
- 	<primitive: 'primitivePixelValueAt' module:'BitBltPlugin'>
- 	^(BitBlt bitPeekerFromForm: self) colorMap: nil;  pixelAt: x at y!

Item was removed:
- ----- Method: Form>>primPrintHScale:vScale:landscape: (in category 'other') -----
- primPrintHScale: hScale vScale: vScale landscape: aBoolean
- 	"On platforms that support it, this primitive prints the receiver, assumed to be a Form, to the default printer."
- 	"(Form extent: 10 at 10) primPrintHScale: 1.0 vScale: 1.0 landscape: true"
- 
- 	<primitive: 232>
- 	self primitiveFailed
- !

Item was removed:
- ----- Method: Form>>printOn: (in category 'fileIn/Out') -----
- printOn: aStream
-     aStream
-         nextPutAll: self class name;
-         nextPut: $(; print: width;
-         nextPut: $x; print: height;
-         nextPut: $x; print: depth;
-         nextPut: $).
- !

Item was removed:
- ----- Method: Form>>printPostscript:operator: (in category 'postscript generation') -----
- printPostscript: aStream operator: operator 
- 	aStream preserveStateDuring: 
- 			[:inner | 
- 			inner rectclip: (0 @ 0 extent: width @ height).
- 			self setColorspaceOn: inner.
- 			inner
- 				print: '[ ';
- 				cr;
- 				print: '/ImageType 1';
- 				cr;
- 				print: '/ImageMatrix [1 0 0 1 0 0]';
- 				cr;
- 				print: '/MultipleDataSources false';
- 				cr;
- 				print: '/DataSource level1 { { currentfile ';
- 				write: self bytesPerRow;
- 				print: ' string readhexstring pop }} bind { currentfile /ASCIIHexDecode filter } ifelse';
- 				cr;
- 				print: '/Width ';
- 				write: self paddedWidth;
- 				cr;
- 				print: '/Height ';
- 				write: self height;
- 				cr;
- 				print: '/Decode ';
- 				print: self decodeArray;
- 				cr;
- 				print: '/BitsPerComponent ';
- 				write: self bitsPerComponent;
- 				cr;
- 				print: 'makeDict ';
- 				print: operator;
- 				cr.
- 			self storePostscriptHexOn: inner.
- 			inner
- 				print: $>;
- 				cr.
- 			inner cr].
- 	aStream cr!

Item was removed:
- ----- Method: Form>>privateFloodFillValue: (in category 'private') -----
- privateFloodFillValue: aColor
- 	"Private. Compute the pixel value in the receiver's depth but take into account implicit color conversions by BitBlt."
- 	| f1 f2 bb |
- 	f1 := Form extent: 1 at 1 depth: depth.
- 	f2 := Form extent: 1 at 1 depth: 32.
- 	bb := BitBlt toForm: f1.
- 	bb fillColor: aColor; 
- 		destRect: (0 at 0 corner: 1 at 1); 
- 		combinationRule: 3; 
- 		copyBits.
- 	bb := BitBlt toForm: f2.
- 	bb sourceForm: f1; 
- 		sourceOrigin: 0 at 0;
- 		destRect: (0 at 0 corner: 1 at 1);
- 		combinationRule: 3;
- 		copyBits.
- 	^f2 pixelValueAt: 0 at 0.!

Item was removed:
- ----- Method: Form>>processUsingKernel: (in category 'processing') -----
- processUsingKernel: filter
- 
- 	^ self processUsingKernel: filter factor: 1.0 bias: 0.0!

Item was removed:
- ----- Method: Form>>processUsingKernel:factor:bias: (in category 'processing') -----
- processUsingKernel: filter factor: factor bias: bias
- 	| image result |
- 
- 	image := self.
- 	result := Form extent: image extent depth: image depth.
- 
- 	0 to: image height - 1 do: [:y |
- 		0 to: image width - 1 do: [:x |
- 			| r g b |
- 			r := g := b := 0.0.
- 
- 			0 to: filter rowCount - 1 do: [:filterY |
- 				0 to: filter columnCount - 1 do: [:filterX |
- 					| imageX imageY |
- 					imageX := (x - (filter columnCount // 2) + filterX + image width) \\
- 								image width.
- 					imageY := (y - (filter rowCount // 2) + filterY + image height) \\
- 								image height.
- 					r := r + ((image colorAt: imageX at imageY) red *
- 								(filter at: filterY + 1 at: filterX + 1)).
- 					g := g + ((image colorAt: imageX at imageY) green *
- 								(filter at: filterY + 1 at: filterX + 1)).
- 					b := b + ((image colorAt: imageX at imageY) blue *
- 								(filter at: filterY + 1 at: filterX + 1))]].
- 
- 			result colorAt: x at y put: (Color
- 				r: ((factor * r + bias) min: 1.0 max: 0.0)
- 				g: ((factor * g + bias) min: 1.0 max: 0.0)
- 				b: ((factor * b + bias) min: 1.0 max: 0.0))]].
- 	^ result
- !

Item was removed:
- ----- Method: Form>>readAttributesFrom: (in category 'fileIn/Out') -----
- readAttributesFrom: aBinaryStream
- 	| offsetX offsetY |
- 	depth := aBinaryStream next.
- 	(self depth isPowerOfTwo and: [self depth between: 1 and: 32])
- 		ifFalse: [self error: 'invalid depth; bad Form file?'].
- 	width := aBinaryStream nextWord.
- 	height := aBinaryStream nextWord.
- 	offsetX  := aBinaryStream nextWord.
- 	offsetY := aBinaryStream nextWord.
- 	offsetX > 32767 ifTrue: [offsetX := offsetX - 65536].
- 	offsetY > 32767 ifTrue: [offsetY := offsetY - 65536].
- 	offset := Point x: offsetX y: offsetY.
- 	
- !

Item was removed:
- ----- Method: Form>>readBitsFrom: (in category 'fileIn/Out') -----
- readBitsFrom: aBinaryStream
- 	
- 	bits := Bitmap newFromStream: aBinaryStream.
- 	bits size = self bitsSize ifFalse: [self error: 'wrong bitmap size; bad Form file?'].
- 	^ self
- !

Item was removed:
- ----- Method: Form>>readFrom: (in category 'fileIn/Out') -----
- readFrom: aBinaryStream
- 	"Reads the receiver from the given binary stream with the format:
- 		depth, extent, offset, bits."
- 	self readAttributesFrom: aBinaryStream.
- 	self readBitsFrom: aBinaryStream!

Item was removed:
- ----- Method: Form>>readFromOldFormat: (in category 'fileIn/Out') -----
- readFromOldFormat: aBinaryStream
- 	"Read a Form in the original ST-80 format."
- 
- 	| w h offsetX offsetY newForm theBits pos |
- 	self error: 'this method must be updated to read into 32-bit word bitmaps'.
- 	w := aBinaryStream nextWord.
- 	h := aBinaryStream nextWord.
- 	offsetX  := aBinaryStream nextWord.
- 	offsetY := aBinaryStream nextWord.
- 	offsetX > 32767 ifTrue: [offsetX := offsetX - 65536].
- 	offsetY > 32767 ifTrue: [offsetY := offsetY - 65536].
- 	newForm := Form extent: w @ h offset: offsetX @ offsetY.
- 	theBits := newForm bits.
- 	pos := 0.
- 	1 to: w + 15 // 16 do: [:j |
- 		1 to: h do: [:i |
- 			theBits at: (pos := pos+1) put: aBinaryStream nextWord]].
- 	newForm bits: theBits.
- 	^ newForm
- !

Item was removed:
- ----- Method: Form>>readNativeResourceFrom: (in category 'resources') -----
- readNativeResourceFrom: byteStream
- 	| img aStream |
- 	aStream := byteStream.
- 	img := [ImageReadWriter formFromStream: aStream] on: Error do:[:ex| nil].
- 	img ifNil:[^nil].
- 	(img isColorForm and:[self isColorForm]) ifTrue:[
- 		| cc |
- 		cc := img colors.
- 		img colors: nil.
- 		img displayOn: self.
- 		img colors: cc.
- 	] ifFalse:[
- 		img displayOn: self.
- 	].
- 	img := nil.!

Item was removed:
- ----- Method: Form>>readResourceFrom: (in category 'resources') -----
- readResourceFrom: aStream 
- 	"Store a resource representation of the receiver on aStream.
- 	Must be specific to the receiver so that no code is filed out."
- 
- 	| bitsSize msb |
- 	(aStream next: 4) asString = self resourceTag 
- 		ifFalse: 
- 			[aStream position: aStream position - 4.
- 			^self readNativeResourceFrom: aStream].
- 	width := aStream nextNumber: 4.
- 	height := aStream nextNumber: 4.
- 	depth := aStream nextNumber: 4.
- 	bitsSize := aStream nextNumber: 4.
- 	bitsSize = 0 
- 		ifFalse: 
- 			[bits := aStream next: bitsSize.
- 			^self].
- 	msb := (aStream nextNumber: 4) = 1.
- 	bitsSize := aStream nextNumber: 4.
- 	bits := Bitmap new: self bitsSize.
- 	(Form 
- 		extent: width @ height
- 		depth: depth
- 		bits: (aStream next: bitsSize * 4)) displayOn: self.
- 	msb = Smalltalk isBigEndian 
- 		ifFalse: 
- 			[Bitmap 
- 				swapBytesIn: bits
- 				from: 1
- 				to: bits size]!

Item was removed:
- ----- Method: Form>>rectangleEnclosingPixelsNotOfColor: (in category 'analyzing') -----
- rectangleEnclosingPixelsNotOfColor: aColor
- 	"Answer the smallest rectangle enclosing all the pixels of me that are different from the given color. Useful for extracting a foreground graphic from its background."
- 
- 	| cm slice copyBlt countBlt top bottom newH left right |
- 	"map the specified color to 1 and all others to 0"
- 	cm := Bitmap new: (1 bitShift: (self depth min: 15)).
- 	cm primFill: 1.
- 	cm at: (aColor indexInMap: cm) put: 0.
- 
- 	"build a 1-pixel high horizontal slice and BitBlts for counting pixels of interest"
- 	slice := Form extent: width at 1 depth: 1.
- 	copyBlt := (BitBlt toForm: slice)
- 		sourceForm: self;
- 		combinationRule: Form over;
- 		destX: 0 destY: 0 width: width height: 1;
- 		colorMap: cm.
- 	countBlt := (BitBlt toForm: slice)
- 		fillColor: (Bitmap with: 0);
- 		destRect: (0 at 0 extent: slice extent);
- 		combinationRule: 32.
- 
- 	"scan in from top and bottom"
- 	top := (0 to: height)
- 		detect: [:y |
- 			copyBlt sourceOrigin: 0 at y; copyBits.
- 			countBlt copyBits > 0]
- 		ifNone: [^ 0 at 0 extent: 0 at 0].
- 	bottom := (height - 1 to: top by: -1)
- 		detect: [:y |
- 			copyBlt sourceOrigin: 0 at y; copyBits.
- 			countBlt copyBits > 0].
- 
- 	"build a 1-pixel wide vertical slice and BitBlts for counting pixels of interest"
- 	newH := bottom - top + 1.
- 	slice := Form extent: 1 at newH depth: 1.
- 	copyBlt := (BitBlt toForm: slice)
- 		sourceForm: self;
- 		combinationRule: Form over;
- 		destX: 0 destY: 0 width: 1 height: newH;
- 		colorMap: cm.
- 	countBlt := (BitBlt toForm: slice)
- 		fillColor: (Bitmap with: 0);
- 		destRect: (0 at 0 extent: slice extent);
- 		combinationRule: 32.
- 
- 	"scan in from left and right"
- 	left := (0 to: width)
- 		detect: [:x |
- 			copyBlt sourceOrigin: x at top; copyBits.
- 			countBlt copyBits > 0].
- 	right := (width - 1 to: left by: -1)
- 		detect: [:x |
- 			copyBlt sourceOrigin: x at top; copyBits.
- 			countBlt copyBits > 0].
- 
- 	^ left at top corner: (right + 1)@(bottom + 1)
- !

Item was removed:
- ----- Method: Form>>reducedPaletteOfSize: (in category 'color mapping') -----
- reducedPaletteOfSize: nColors
- 	"Return an array of colors of size nColors, such that those colors
- 	represent well the pixel values actually found in this form."
- 	| threshold tallies colorTallies dist delta palette cts top cluster |
- 	tallies := self tallyPixelValues.  "An array of tallies for each pixel value"
- 	threshold := width * height // 500.
- 
- 	"Make an array of (color -> tally) for all tallies over threshold"
- 	colorTallies := Array streamContents:
- 		[:s | tallies withIndexDo:
- 			[:v :i | v >= threshold ifTrue:
- 				[s nextPut: (Color colorFromPixelValue: i-1 depth: depth) -> v]]].
- 
- 	"Extract a set of clusters by picking the top tally, and then removing all others
- 	whose color is within dist of it.  Iterate the process, adjusting dist until we get nColors."
- 	dist := 0.2.  delta := dist / 2.
- 		[cts := colorTallies copy.
- 		palette := Array streamContents: [:s |
- 			[cts isEmpty] whileFalse:
- 				[top := cts detectMax: [:a | a value].
- 				cluster := cts select: [:a | (a key diff: top key) < dist].
- 				s nextPut: top key -> (cluster detectSum: [:a | a value]).
- 				cts := cts copyWithoutAll: cluster]].
- 		palette size = nColors or: [delta < 0.001]]
- 		whileFalse:
- 			[palette size > nColors
- 				ifTrue: [dist := dist + delta]
- 				ifFalse: [dist := dist - delta].
- 			delta := delta / 2].
- 	^ palette collect: [:a | a key]
- !

Item was removed:
- ----- Method: Form>>relativeTextAnchorPosition (in category 'other') -----
- relativeTextAnchorPosition
- 
- 	^nil		"so forms can be in TextAnchors"!

Item was removed:
- ----- Method: Form>>replaceByResource: (in category 'fileIn/Out') -----
- replaceByResource: aForm
- 	"Replace the receiver by some resource that just got loaded"
- 	(self extent = aForm extent and:[self depth = aForm depth]) ifTrue:[
- 		bits := aForm bits.
- 	].!

Item was removed:
- ----- Method: Form>>replaceColor:withColor: (in category 'image manipulation') -----
- replaceColor: oldColor withColor: newColor
- 	"Replace one color with another everywhere is this form"
- 
- 	| cm newInd target ff |
- 	self depth = 32
- 		ifTrue: [cm := (Color  cachedColormapFrom: 16 to: 32) copy]
- 		ifFalse: [cm := Bitmap new: (1 bitShift: (self depth min: 15)).
- 				1 to: cm size do: [:i | cm at: i put: i - 1]].
- 	newInd := newColor pixelValueForDepth: self depth.
- 	cm at: (oldColor pixelValueForDepth: (self depth min: 16))+1 put: newInd.
- 	target := newColor isTransparent 
- 		ifTrue: [ff := Form extent: self extent depth: depth.
- 			ff fillWithColor: newColor.  ff]
- 		ifFalse: [self].
- 	(BitBlt toForm: target)
- 		sourceForm: self;
- 		sourceOrigin: 0 at 0;
- 		combinationRule: Form paint;
- 		destX: 0 destY: 0 width: width height: height;
- 		colorMap: cm;
- 		copyBits.
- 	newColor = Color transparent 
- 		ifTrue: [target displayOn: self].!

Item was removed:
- ----- Method: Form>>resourceTag (in category 'resources') -----
- resourceTag
- 	^'FORM'!

Item was removed:
- ----- Method: Form>>rgbaBitMasks (in category 'color mapping') -----
- rgbaBitMasks
- 	"Return the masks for specifying the R,G,B, and A components in the receiver"
- 	self depth <= 8
- 		ifTrue:[^#(16rFF0000 16rFF00 16rFF 16rFF000000)].
- 	self depth = 16
- 		ifTrue:[^#(16r7C00 16r3E0 16r1F 16r0)].
- 	self depth = 32
- 		ifTrue:[^#(16rFF0000 16rFF00 16rFF 16rFF000000)].
- 	self error:'Bad depth for form'!

Item was removed:
- ----- Method: Form>>rotateBy: (in category 'scaling, rotation') -----
- rotateBy: deg
- 	"Rotate the receiver by the indicated number of degrees."
- 	"rot is the destination form, bit enough for any angle."
- 
- 	^ self rotateBy: deg smoothing: 1
- "
-  | a f |  f := Form fromDisplay: (0 at 0 extent: 200 at 200).  a := 0.
- [Sensor anyButtonPressed] whileFalse:
- 	[((Form fromDisplay: (Sensor cursorPoint extent: 130 at 66))
- 		rotateBy: (a := a+5)) display].
- f display
- "!

Item was removed:
- ----- Method: Form>>rotateBy:centerAt: (in category 'scaling, rotation') -----
- rotateBy: direction centerAt: aPoint
- 	"Return a rotated copy of the receiver. 
- 	direction = #none, #right, #left, or #pi"
- 	| newForm quad rot scale |
- 	direction == #none ifTrue: [^ self].
- 	scale :=  (direction = #pi ifTrue: [width at height] ifFalse: [height at width]) / self extent .
- 	newForm := self blankCopyOf: self boundingBox scaledBy: scale.
- 	quad := self boundingBox innerCorners.
- 	rot := #(right pi left) indexOf: direction.
- 	(WarpBlt toForm: newForm)
- 		sourceForm: self;
- 		colorMap: (self colormapIfNeededFor: newForm);
- 		combinationRule: 3;
- 		copyQuad: ((1+rot to: 4+rot) collect: [:i | quad atWrap: i])
- 			 toRect: newForm boundingBox.
- 	newForm offset: (self offset rotateBy: direction centerAt: aPoint).
- 	^ newForm
- "
- [Sensor anyButtonPressed] whileFalse:
- 	[((Form fromDisplay: (Sensor cursorPoint extent: 130 at 66))
- 		rotateBy: #left centerAt: 0 at 0) display]
- "
- "Consistency test...
-  | f f2 p | [Sensor anyButtonPressed] whileFalse:
- 	[f := Form fromDisplay: ((p := Sensor cursorPoint) extent: 31 at 41).
- 	Display fillBlack: (p extent: 31 at 41).
- 	f2 := f rotateBy: #left centerAt: 0 at 0.
- 	(f2 rotateBy: #right centerAt: 0 at 0) displayAt: p]
- "
- !

Item was removed:
- ----- Method: Form>>rotateBy:magnify:smoothing: (in category 'scaling, rotation') -----
- rotateBy: deg magnify: scale smoothing: cellSize
- 	"Rotate the receiver by the indicated number of degrees and magnify. scale can be a Point to make for interesting 3D effects "
- 	"rot is the destination form, big enough for any angle."
- 
- 	| side rot warp r1 pts bigSide |
- 	side := 1 + self extent r asInteger.
- 	bigSide := (side asPoint * scale) rounded.
- 	rot := self blankCopyOf: self boundingBox scaledBy: ( bigSide / self extent ).
- 	warp := (WarpBlt toForm: rot)
- 		sourceForm: self;
- 		colorMap: (self colormapIfNeededFor: rot);
- 		cellSize: cellSize;  "installs a new colormap if cellSize > 1"
- 		combinationRule: Form paint.
- 	r1 := (0 at 0 extent: side at side) align: (side at side)//2 with: self boundingBox center.
- 
- 	"Rotate the corners of the source rectangle." 
- 	pts := r1 innerCorners collect:
- 		[:pt | | p |
- 		p := pt - r1 center.
- 		(r1 center x asFloat + (p x asFloat*deg degreeCos) + (p y asFloat*deg degreeSin)) @
- 		(r1 center y asFloat - (p x asFloat*deg degreeSin) + (p y asFloat*deg degreeCos))].
- 	warp copyQuad: pts toRect: rot boundingBox.
- 	^ rot
- "
-  | a f |  f := Form fromDisplay: (0 at 0 extent: 200 at 200).  a := 0.
- [Sensor anyButtonPressed] whileFalse:
- 	[((Form fromDisplay: (Sensor cursorPoint extent: 130 at 66))
- 		rotateBy: (a := a+5) magnify: 0.75 at 2 smoothing: 2) display].
- f display
- "!

Item was removed:
- ----- Method: Form>>rotateBy:smoothing: (in category 'scaling, rotation') -----
- rotateBy: deg smoothing: cellSize
- 	"Rotate the receiver by the indicated number of degrees."
- 	^self rotateBy: deg magnify: 1 smoothing: cellSize
- "
-  | a f |  f := Form fromDisplay: (0 at 0 extent: 200 at 200).  a := 0.
- [Sensor anyButtonPressed] whileFalse:
- 	[((Form fromDisplay: (Sensor cursorPoint extent: 130 at 66))
- 		rotateBy: (a := a+5) smoothing: 2) display].
- f display
- "!

Item was removed:
- ----- Method: Form>>rowPadding (in category 'postscript generation') -----
- rowPadding
- 	^ 32 // self depth!

Item was removed:
- ----- Method: Form>>scaledToSize: (in category 'scaling, rotation') -----
- scaledToSize: numberOrPoint
- 
- 	^ self scaledToSize: numberOrPoint smoothing: 2!

Item was removed:
- ----- Method: Form>>scaledToSize:smoothing: (in category 'scaling, rotation') -----
- scaledToSize: numberOrPoint smoothing: factor
- 
- 	| scale newExtent |
- 	newExtent := numberOrPoint asPoint.
- 	
- 	newExtent = self extent ifTrue: [^ self copy].
- 	
- 	(self height isZero or: [self width isZero])
- 		ifTrue: [^ self species extent: newExtent depth: self depth].
- 		
- 	scale := newExtent x / self width min: newExtent y / self height.
- 	^ self magnify: self boundingBox by: scale smoothing: factor!

Item was removed:
- ----- Method: Form>>setAsBackground (in category 'other') -----
- setAsBackground
- 	"Set this form as a background image."
- 
- 	Project current setAsBackground: self
- !

Item was removed:
- ----- Method: Form>>setColorspaceOn: (in category 'postscript generation') -----
- setColorspaceOn:aStream
- 	self numComponents = 1 ifTrue:[aStream print:'/DeviceGray setcolorspace 0 setgray'; cr.]
- 		ifFalse:[aStream print:'/DeviceRGB setcolorspace'; cr.].!

Item was removed:
- ----- Method: Form>>setExtent:depth: (in category 'private') -----
- setExtent: extent depth: bitsPerPixel
- 	"Create a virtual bit map with the given extent and bitsPerPixel."
- 
- 	width := extent x asInteger.
- 	width < 0 ifTrue: [width := 0].
- 	height := extent y asInteger.
- 	height < 0 ifTrue: [height := 0].
- 	depth := bitsPerPixel.
- 	bits := Bitmap new: self bitsSize!

Item was removed:
- ----- Method: Form>>setExtent:depth:bits: (in category 'private') -----
- setExtent: extent depth: bitsPerPixel bits: bitmap
- 	"Create a virtual bit map with the given extent and bitsPerPixel."
- 	| bitsClass |
- 	(width := extent x asInteger) < 0 ifTrue: [width := 0].
- 	(height := extent y asInteger) < 0 ifTrue: [height := 0].
- 	depth := bitsPerPixel.
- 	(bits isNil
- 	 or: [(bitsClass := bits class) isBits
- 		and: [self bitsSize * 4 "bytes per pixel" = (bitmap size * bitsClass elementSize)]]) ifFalse:
- 		[^self error: 'Bad dimensions and/or bitmap kind'].
- 	bits := bitmap!

Item was removed:
- ----- Method: Form>>setResourceBits: (in category 'private') -----
- setResourceBits: aForm
- 	"Private. Really. Used for setting the 'resource bits' when externalizing some form"
- 	bits := aForm.!

Item was removed:
- ----- Method: Form>>shapeBorder:width: (in category 'bordering') -----
- shapeBorder: aColor width: borderWidth
- 	"A simplified version for shapes surrounded by transparency (as SketchMorphs).
- 	Note also this returns a new form that may be larger, and does not affect the original."
- 	| shapeForm borderForm newForm |
- 	newForm := Form extent: self extent + (borderWidth*2) depth: self depth.
- 	newForm fillColor: Color transparent.
- 	self displayOn: newForm at: (0 at 0) + borderWidth.
- 	"First identify the shape in question as a B/W form"
- 	shapeForm := (newForm makeBWForm: Color transparent) reverse.
- 	"Now find the border of that shape"
- 	borderForm := shapeForm borderFormOfWidth: borderWidth sharpCorners: false.
- 	"Finally use that shape as a mask to paint the border with color"
- 	^ newForm fillShape: borderForm fillColor: aColor!

Item was removed:
- ----- Method: Form>>shapeBorder:width:interiorPoint:sharpCorners:internal: (in category 'bordering') -----
- shapeBorder: aColor width: borderWidth interiorPoint: interiorPoint
- 	sharpCorners: sharpen internal: internal
- 	"Identify the shape (region of identical color) at interiorPoint,
- 	and then add an outline of width=borderWidth and color=aColor.
- 	If sharpen is true, then cause right angles to be outlined by
- 	right angles.  If internal is true, then produce a border that lies
- 	within the identified shape.  Thus one can put an internal border
- 	around the whole background, thus effecting a normal border
- 	around every other foreground image."
- 	| shapeForm borderForm interiorColor |
- 	"First identify the shape in question as a B/W form"
- 	interiorColor := self colorAt: interiorPoint.
- 	shapeForm := (self makeBWForm: interiorColor) reverse
- 				findShapeAroundSeedBlock:
- 					[:form | form pixelValueAt: interiorPoint put: 1].
- 	"Reverse the image to grow the outline inward"
- 	internal ifTrue: [shapeForm reverse].
- 	"Now find the border fo that shape"
- 	borderForm := shapeForm borderFormOfWidth: borderWidth sharpCorners: sharpen.
- 	"Finally use that shape as a mask to paint the border with color"
- 	self fillShape: borderForm fillColor: aColor!

Item was removed:
- ----- Method: Form>>shapeFill:interiorPoint: (in category 'filling') -----
- shapeFill: aColor interiorPoint: interiorPoint
- 	"Identify the shape (region of identical color) at interiorPoint,
- 	and then fill that shape with the new color, aColor
- 	: modified di's original method such that it returns the bwForm, for potential use by the caller"
- 
- 	| bwForm interiorPixVal map ppd color ind |
- 	self depth = 1 ifTrue:
- 		[^ self shapeFill: aColor
- 			seedBlock: [:form | form pixelValueAt: interiorPoint put: 1]].
- 
- 	"First map this form into a B/W form with 0's in the interior region."
- 		"bwForm := self makeBWForm: interiorColor."	"won't work for two whites"
- 	interiorPixVal := self pixelValueAt: interiorPoint.
- 	bwForm := Form extent: self extent.
- 	map := Bitmap new: (1 bitShift: (self depth min: 12)).  "Not calling newColorMap.  All 
- 			non-foreground go to 0.  Length is 2 to 4096."
- 	ppd := self depth.	"256 long color map in depth 8 is not one of the following cases"
- 	3 to: 5 do: [:bitsPerColor | 
- 		(2 raisedTo: bitsPerColor*3) = map size 
- 			ifTrue: [ppd := bitsPerColor*3]].	"ready for longer maps than 512"
- 
- 	ppd <= 8
- 		ifTrue: [map at: interiorPixVal+1 put: 1]
- 		ifFalse: [interiorPixVal = 0 
- 			ifFalse: [color := Color colorFromPixelValue: interiorPixVal depth: self depth.
- 				ind := color pixelValueForDepth: ppd.
- 				map at: ind+1 put: 1]
- 			ifTrue: [map at: 1 put: 1]].
- 	bwForm copyBits: self boundingBox from: self at: 0 at 0 colorMap: map.
- 	bwForm reverse.  "Make interior region be 0's"
- 
- 	"Now fill the interior region and return that shape"
- 	bwForm := bwForm findShapeAroundSeedBlock:
- 					[:form | form pixelValueAt: interiorPoint put: 1].
- 
- 	"Finally use that shape as a mask to flood the region with color"
- 	self eraseShape: bwForm.
- 	self fillShape: bwForm fillColor: aColor.
- 	^ bwForm!

Item was removed:
- ----- Method: Form>>shapeFill:seedBlock: (in category 'filling') -----
- shapeFill: aColor seedBlock: seedBlock
- 	self depth > 1 ifTrue: [self error: 'This call only meaningful for B/W forms'].
- 	(self findShapeAroundSeedBlock: seedBlock)
- 		displayOn: self at: 0 at 0 clippingBox: self boundingBox
- 		rule: Form under fillColor: aColor !

Item was removed:
- ----- Method: Form>>sharpen (in category 'processing') -----
- sharpen
- 
- 	^ self processUsingKernel: (Matrix rows: 3 columns: 3 contents: #(
- 		 0 -1  0
- 		-1  5 -1
- 		 0 -1  0
- 	))!

Item was removed:
- ----- Method: Form>>shouldPreserveContents (in category 'testing') -----
- shouldPreserveContents
- 	"Return true if the receiver should preserve it's contents when flagged to be clean. Most forms can not be trivially restored by some drawing operation but some may."
- 	^true!

Item was removed:
- ----- Method: Form>>shrink:by: (in category 'scaling, rotation') -----
- shrink: aRectangle by: scale 
- 	| scalePt |
- 	scalePt := scale asPoint.
- 	^ self magnify: aRectangle by: (1.0 / scalePt x asFloat) @ (1.0 / scalePt y asFloat)!

Item was removed:
- ----- Method: Form>>shutDown (in category 'initialize-release') -----
- shutDown
- 	"The system is going down. Try to preserve some space"
- 	self hibernate!

Item was removed:
- ----- Method: Form>>size (in category 'accessing') -----
- size
- 	"Should no longer be used -- use bitsSize instead.  length of variable part of instance."
- 	^ super size!

Item was removed:
- ----- Method: Form>>slideImage:at:delta: (in category 'transitions') -----
- slideImage: otherImage at: topLeft delta: delta
- 	"Display slideImage: (Form fromDisplay: (40 at 40 extent: 300 at 300)) reverse
- 		at: 40 at 40 delta: 3 at -4"
- 	| bb nSteps clipRect |
- 	bb := otherImage boundingBox.
- 	clipRect := topLeft extent: otherImage extent.
- 	nSteps := 1.
- 	delta x = 0 ifFalse: [nSteps := nSteps max: (bb width//delta x abs) + 1].
- 	delta y = 0 ifFalse: [nSteps := nSteps max: (bb height//delta y abs) + 1].
- 	1 to: nSteps do:
- 			[:i | self copyBits: bb from: otherImage
- 				at: delta*(i-nSteps) + topLeft
- 				clippingBox: clipRect rule: Form paint fillColor: nil.
- 			Display forceDisplayUpdate]!

Item was removed:
- ----- Method: Form>>smear:distance: (in category 'image manipulation') -----
- smear: dir distance: dist
- 	"Smear any black pixels in this form in the direction dir in Log N steps"
- 	| skew bb |
- 	bb := BitBlt destForm: self sourceForm: self fillColor: nil
- 		combinationRule: Form under destOrigin: 0 at 0 sourceOrigin: 0 at 0
- 		extent: self extent clipRect: self boundingBox.
- 	skew := 1.
- 	[skew < dist] whileTrue:
- 		[bb destOrigin: dir*skew; copyBits.
- 		skew := skew+skew]!

Item was removed:
- ----- Method: Form>>store15To24HexBitsOn: (in category 'postscript generation') -----
- store15To24HexBitsOn:aStream
- 
- 	| buf lineWidth |
- 
- 	"write data for 16-bit form, optimized for encoders writing directly to files to do one single file write rather than 12. I'm not sure I understand the significance of the shifting pattern, but I think I faithfully translated it from the original"
- 
- 	lineWidth := 0.
- 	buf := String new: 12.
- 	self unhibernate.
- 	bits do: [:word | | i | 
- 		i := 0.
- 		"upper pixel"
- 		buf at: (i := i + 1) put: ((word bitShift: -27) bitAnd: 15) asHexDigit.
- 		buf at: (i := i + 1) put: ((word bitShift: -32) bitAnd: 8) asHexDigit.
- 
- 		buf at: (i := i + 1) put: ((word bitShift: -22) bitAnd: 15) asHexDigit.
- 		buf at: (i := i + 1) put: ((word bitShift: -27) bitAnd: 8) asHexDigit.
- 
- 		buf at: (i := i + 1) put: ((word bitShift: -17) bitAnd: 15) asHexDigit.
- 		buf at: (i := i + 1) put: ((word bitShift: -22) bitAnd: 8) asHexDigit.
- 
- 		"lower pixel"
- 
- 		buf at: (i := i + 1) put: ((word bitShift: -11) bitAnd: 15) asHexDigit.
- 		buf at: (i := i + 1) put: ((word bitShift: -16) bitAnd: 8) asHexDigit.
- 
- 		buf at: (i := i + 1) put: ((word bitShift: -6) bitAnd: 15) asHexDigit.
- 		buf at: (i := i + 1) put: ((word bitShift: -11) bitAnd: 8) asHexDigit.
- 
- 		buf at: (i := i + 1) put: ((word bitShift: -1) bitAnd: 15) asHexDigit.
- 		buf at: (i := i + 1) put: ((word bitShift: -6) bitAnd: 8) asHexDigit.
- 		aStream nextPutAll: buf.
- 		lineWidth := lineWidth + 12.
- 		lineWidth > 100 ifTrue: [ aStream cr. lineWidth := 0 ].
- 		"#( 31 26 21 15 10 5 )  do:[:startBit | ]"
- 	].!

Item was removed:
- ----- Method: Form>>store32To24HexBitsOn: (in category 'postscript generation') -----
- store32To24HexBitsOn:aStream
- 	^self storeBits:20 to:0 on:aStream.!

Item was removed:
- ----- Method: Form>>storeBits:to:on: (in category 'postscript generation') -----
- storeBits:startBit to:stopBit on:aStream
- 	self unhibernate.
- 	bits storeBits:startBit to:stopBit on:aStream.!

Item was removed:
- ----- Method: Form>>storeBitsOn:base: (in category 'fileIn/Out') -----
- storeBitsOn:aStream base:anInteger
- 	self unhibernate.
- 	bits do: [:word | 
- 		anInteger = 10
- 			ifTrue: [aStream space]
- 			ifFalse: [aStream crtab: 2].
- 		word storeOn: aStream base: anInteger].
- !

Item was removed:
- ----- Method: Form>>storeHexBitsOn: (in category 'postscript generation') -----
- storeHexBitsOn:aStream
- 	^self storeBits:28 to:0 on:aStream.!

Item was removed:
- ----- Method: Form>>storeOn: (in category 'fileIn/Out') -----
- storeOn: aStream
- 
- 	self storeOn: aStream base: 10!

Item was removed:
- ----- Method: Form>>storeOn:base: (in category 'fileIn/Out') -----
- storeOn: aStream base: anInteger 
- 	"Store the receiver out as an expression that can be evaluated to recreate a Form with the same contents as the original."
- 
- 	self unhibernate.
- 	aStream nextPut: $(.
- 	aStream nextPutAll: self species name.
- 	aStream crtab: 1.
- 	aStream nextPutAll: 'extent: '.
- 	self extent printOn: aStream.
- 	aStream crtab: 1.
- 	aStream nextPutAll: 'depth: '.
- 	self depth printOn: aStream.
- 	aStream crtab: 1.
- 	aStream nextPutAll: 'fromArray: #('.
- 	self storeBitsOn:aStream base:anInteger.
- 	aStream nextPut: $).
- 	aStream crtab: 1.
- 	aStream nextPutAll: 'offset: '.
- 	self offset printOn: aStream.
- 	aStream nextPut: $).
- !

Item was removed:
- ----- Method: Form>>storePostscriptHexOn: (in category 'postscript generation') -----
- storePostscriptHexOn: inner 
- 	self depth <= 8 ifTrue: [self storeHexBitsOn: inner].
- 	self depth = 16 ifTrue: [self store15To24HexBitsOn: inner].
- 	self depth = 32 ifTrue: [self store32To24HexBitsOn: inner]!

Item was removed:
- ----- Method: Form>>storeResourceOn: (in category 'resources') -----
- storeResourceOn: aStream
- 	"Store a resource representation of the receiver on aStream.
- 	Must be specific to the receiver so that no code is filed out."
- 	self hibernate.
- 	aStream nextPutAll: self resourceTag asByteArray. "tag"
- 	aStream nextNumber: 4 put: width.
- 	aStream nextNumber: 4 put: height.
- 	aStream nextNumber: 4 put: depth.
- 	(bits isMemberOf: ByteArray) ifFalse:[
- 		"must store bitmap"
- 		aStream nextNumber: 4 put: 0. "tag"
- 		aStream nextNumber: 4 put: (Smalltalk isBigEndian ifTrue:[1] ifFalse:[0]).
- 	].
- 	aStream nextNumber: 4 put: bits size.
- 	aStream nextPutAll: bits.
- !

Item was removed:
- ----- Method: Form>>swapEndianness (in category 'initialize-release') -----
- swapEndianness
- 	"Swap from big to little endian pixels and vice versa"
- 	depth := 0 - depth.!

Item was removed:
- ----- Method: Form>>tallyPixelValues (in category 'analyzing') -----
- tallyPixelValues
- 	"Answer a Bitmap whose elements contain the number of pixels in this Form with the pixel value corresponding to their index. Note that the pixels of multiple Forms can be tallied together using tallyPixelValuesInRect:into:."
- 
- 	^ self tallyPixelValuesInRect: self boundingBox
- 		into: (Bitmap new: (1 bitShift: (self depth min: 15)))
- "
- Move a little rectangle around the screen and print its tallies...
-  | r tallies nonZero |
- Cursor blank showWhile: [
- [Sensor anyButtonPressed] whileFalse:
- 	[r := Sensor cursorPoint extent: 10 at 10.
- 	Display border: (r expandBy: 2) width: 2 rule: Form reverse fillColor: nil.
- 	tallies := (Display copy: r) tallyPixelValues.
- 	nonZero := (1 to: tallies size) select: [:i | (tallies at: i) > 0]
- 			thenCollect: [:i | (tallies at: i) -> (i-1)].
- 	nonZero printString , '          ' displayAt: 0 at 0.
- 	Display border: (r expandBy: 2) width: 2 rule: Form reverse fillColor: nil]]
- "
- !

Item was removed:
- ----- Method: Form>>tallyPixelValuesInRect:into: (in category 'analyzing') -----
- tallyPixelValuesInRect: destRect into: valueTable
- 	"Tally the selected pixels of this Form into valueTable, a Bitmap of depth 2^depth similar to a color map. Answer valueTable."
- 
- 	(BitBlt toForm: self)
- 		sourceForm: self;  "src must be given for color map ops"
- 		sourceOrigin: 0 at 0;
- 		tallyMap: valueTable;
- 		combinationRule: 33;
- 		destRect: destRect;
- 		copyBits.
- 	^ valueTable
- 
- "
- Move a little rectangle around the screen and print its tallies...
-  | r tallies nonZero |
- Cursor blank showWhile: [
- [Sensor anyButtonPressed] whileFalse:
- 	[r := Sensor cursorPoint extent: 10 at 10.
- 	Display border: (r expandBy: 2) width: 2 rule: Form reverse fillColor: nil.
- 	tallies := (Display copy: r) tallyPixelValues.
- 	nonZero := (1 to: tallies size) select: [:i | (tallies at: i) > 0]
- 			thenCollect: [:i | (tallies at: i) -> (i-1)].
- 	nonZero printString , '          ' displayAt: 0 at 0.
- 	Display border: (r expandBy: 2) width: 2 rule: Form reverse fillColor: nil]]
- "!

Item was removed:
- ----- Method: Form>>trimBordersOfColor: (in category 'image manipulation') -----
- trimBordersOfColor: aColor
- 	"Answer a copy of this Form with each edge trimmed in to the first pixel that is not of the given color. (That is, border strips of the given color are removed)."
- 
- 	| r |
- 	r := self rectangleEnclosingPixelsNotOfColor: aColor.
- 	^ self copy: r
- !

Item was removed:
- ----- Method: Form>>unhibernate (in category 'fileIn/Out') -----
- unhibernate
- 	"If my bitmap has been compressed into a ByteArray,
- 	then expand it now, and return true."
- 	| resBits |
- 	bits isForm ifTrue:[
- 		resBits := bits.
- 		bits := Bitmap new: self bitsSize.
- 		resBits displayResourceFormOn: self.
- 		^true].
- 	bits == nil ifTrue:[bits := Bitmap new: self bitsSize. ^true].
- 	(bits isMemberOf: ByteArray)
- 		ifTrue: [bits := Bitmap decompressFromByteArray: bits. ^ true].
- 	^ false!

Item was removed:
- ----- Method: Form>>veryDeepCopyWith: (in category 'copying') -----
- veryDeepCopyWith: deepCopier
- 	"Return self.  I am immutable in the Morphic world.  Do not record me."
- 	^ self!

Item was removed:
- ----- Method: Form>>width (in category 'display box access') -----
- width
- 	^ width!

Item was removed:
- ----- Method: Form>>wipeImage:at:clippingBox:rectForIndex: (in category 'transitions') -----
- wipeImage: otherImage at: topLeft clippingBox: clipBox rectForIndex: rectForIndexBlock
- 
- 	| i clipRect t rectOrList waitTime |
- 	i := 0.
- 	clipRect := topLeft extent: otherImage extent.
- 	clipBox ifNotNil: [clipRect := clipRect intersect: clipBox].
- 	[rectOrList := rectForIndexBlock value: (i := i + 1).
- 	 rectOrList == nil]
- 		whileFalse: [
- 			t := Time millisecondClockValue.
- 			rectOrList asOrderedCollection do: [:r |
- 				self copyBits: r from: otherImage at: topLeft + r topLeft
- 					clippingBox: clipRect rule: Form over fillColor: nil].
- 			Display forceDisplayUpdate.
- 			waitTime := 3 - (Time millisecondClockValue - t).
- 			waitTime > 0 ifTrue:
- 				["(Delay forMilliseconds: waitTime) wait"]].
- !

Item was removed:
- ----- Method: Form>>wipeImage:at:delta: (in category 'transitions') -----
- wipeImage: otherImage at: topLeft delta: delta
- 	"Display wipeImage: (Form fromDisplay: (40 at 40 extent: 300 at 300)) reverse
- 		at: 40 at 40 delta: 0 at -2"
- 
- 	self wipeImage: otherImage at: topLeft delta: delta clippingBox: nil.
- !

Item was removed:
- ----- Method: Form>>wipeImage:at:delta:clippingBox: (in category 'transitions') -----
- wipeImage: otherImage at: topLeft delta: delta clippingBox: clipBox
- 
- 	| wipeRect bb nSteps |
- 	bb := otherImage boundingBox.
- 	wipeRect := delta x = 0
- 		ifTrue:
- 		[delta y = 0 ifTrue: [nSteps := 1. bb "allow 0 at 0"] ifFalse: [
- 		nSteps := bb height//delta y abs + 1.  "Vertical movement"
- 		delta y > 0
- 			ifTrue: [bb topLeft extent: bb width at delta y]
- 			ifFalse: [bb bottomLeft+delta extent: bb width at delta y negated]]]
- 		ifFalse:
- 		[nSteps := bb width//delta x abs + 1.  "Horizontal movement"
- 		delta x > 0
- 			ifTrue: [bb topLeft extent: delta x at bb height]
- 			ifFalse: [bb topRight+delta extent: delta x negated at bb height]].
- 	^ self wipeImage: otherImage at: topLeft clippingBox: clipBox rectForIndex:
- 		[:i | i <= nSteps
- 			ifTrue: [wipeRect translateBy: (delta* (i-1))]
- 			ifFalse: [nil]]!

Item was removed:
- ----- Method: Form>>writeAttributesOn: (in category 'fileIn/Out') -----
- writeAttributesOn: file
- 	self unhibernate.
- 	file nextPut: depth.
- 	file nextWordPut: width.
- 	file nextWordPut: height.
- 	file nextWordPut: ((self offset x) >=0
- 					ifTrue: [self offset x]
- 					ifFalse: [self offset x + 65536]).
- 	file nextWordPut: ((self offset y) >=0
- 					ifTrue: [self offset y]
- 					ifFalse: [self offset y + 65536]).
- 	!

Item was removed:
- ----- Method: Form>>writeBMPfileNamed: (in category 'fileIn/Out') -----
- writeBMPfileNamed: fName  "Display writeBMPfileNamed: 'display.bmp'"
- 	BMPReadWriter putForm: self onFileNamed: fName!

Item was removed:
- ----- Method: Form>>writeBitsOn: (in category 'fileIn/Out') -----
- writeBitsOn: file
- 	bits writeOn: file!

Item was removed:
- ----- Method: Form>>writeJPEGfileNamed: (in category 'fileIn/Out') -----
- writeJPEGfileNamed: fileName 
- 	"Write a JPEG file to the given filename using default settings"
- 
- 	self writeJPEGfileNamed: fileName progressive: false
- 
- "
- Display writeJPEGfileNamed: 'display.jpeg'
- Form fromUser writeJPEGfileNamed: 'yourPatch.jpeg'
- "!

Item was removed:
- ----- Method: Form>>writeJPEGfileNamed:progressive: (in category 'fileIn/Out') -----
- writeJPEGfileNamed: fileName  progressive: aBoolean
- 	"Write a JPEG file to the given filename using default settings.  Make it progressive or not, depending on the boolean argument"
- 
- 	JPEGReadWriter2 putForm: self quality: -1 "default" progressiveJPEG: aBoolean onFileNamed: fileName
- 
- "
- Display writeJPEGfileNamed: 'display.jpeg' progressive: false.
- Form fromUser writeJPEGfileNamed: 'yourPatch.jpeg' progressive: true
- "!

Item was removed:
- ----- Method: Form>>writeOn: (in category 'fileIn/Out') -----
- writeOn: file
- 	"Write the receiver on the file in the format
- 		depth, extent, offset, bits."
- 	self writeAttributesOn: file.
- 	self writeBitsOn: file!

Item was removed:
- ----- Method: Form>>writeOnMovie: (in category 'fileIn/Out') -----
- writeOnMovie: file
- 	"Write just my bits on the file."
- 	self unhibernate.
- 	bits writeUncompressedOn: file!

Item was removed:
- ----- Method: Form>>writePNGfileNamed: (in category 'fileIn/Out') -----
- writePNGfileNamed: fName  "Display writePNGfileNamed: 'display.png'"
- 	PNGReadWriter putForm: self onFileNamed: fName!

Item was removed:
- ----- Method: Form>>writeUncompressedOn: (in category 'fileIn/Out') -----
- writeUncompressedOn: file
- 	"Write the receiver on the file in the format depth, extent, offset, bits.  Warning:  Caller must put header info on file!!  Use writeUncompressedOnFileNamed: instead."
- 	self unhibernate.
- 	file binary.
- 	file nextPut: depth.
- 	file nextWordPut: width.
- 	file nextWordPut: height.
- 	file nextWordPut: ((self offset x) >=0
- 					ifTrue: [self offset x]
- 					ifFalse: [self offset x + 65536]).
- 	file nextWordPut: ((self offset y) >=0
- 					ifTrue: [self offset y]
- 					ifFalse: [self offset y + 65536]).
- 	bits writeUncompressedOn: file!

Item was removed:
- ----- Method: Form>>xTallyPixelValue:orNot: (in category 'analyzing') -----
- xTallyPixelValue: pv orNot: not
- 	"Return an array of the number of pixels with value pv by x-value.
- 	Note that if not is true, then this will tally those different from pv."
- 	| cm slice countBlt copyBlt |
- 	cm := self newColorMap.		"Map all colors but pv to zero"
- 	not ifTrue: [cm atAllPut: 1].		"... or all but pv to one"
- 	cm at: pv+1 put: 1 - (cm at: pv+1).
- 	slice := Form extent: 1 at height.
- 	copyBlt := (BitBlt destForm: slice sourceForm: self
- 				halftoneForm: nil combinationRule: Form over
- 				destOrigin: 0 at 0 sourceOrigin: 0 at 0 extent: 1 @ slice height
- 				clipRect: slice boundingBox) colorMap: cm.
- 	countBlt := (BitBlt toForm: slice)
- 				fillColor: (Bitmap with: 0);
- 				destRect: (0 at 0 extent: slice extent);
- 				combinationRule: 32.
- 	^ (0 to: width-1) collect:
- 		[:x |
- 		copyBlt sourceOrigin: x at 0; copyBits.
- 		countBlt copyBits]!

Item was removed:
- ----- Method: Form>>yTallyPixelValue:orNot: (in category 'analyzing') -----
- yTallyPixelValue: pv orNot: not
- 	"Return an array of the number of pixels with value pv by y-value.
- 	Note that if not is true, then this will tally those different from pv."
- 	| cm slice copyBlt countBlt |
- 	cm := self newColorMap.		"Map all colors but pv to zero"
- 	not ifTrue: [cm atAllPut: 1].		"... or all but pv to one"
- 	cm at: pv+1 put: 1 - (cm at: pv+1).
- 	slice := Form extent: width at 1.
- 	copyBlt := (BitBlt destForm: slice sourceForm: self
- 				halftoneForm: nil combinationRule: Form over
- 				destOrigin: 0 at 0 sourceOrigin: 0 at 0 extent: slice width @ 1
- 				clipRect: slice boundingBox) colorMap: cm.
- 	countBlt := (BitBlt toForm: slice)
- 				fillColor: (Bitmap with: 0);
- 				destRect: (0 at 0 extent: slice extent);
- 				combinationRule: 32.
- 	^ (0 to: height-1) collect:
- 		[:y |
- 		copyBlt sourceOrigin: 0 at y; copyBits.
- 		countBlt copyBits]!

Item was removed:
- ----- Method: Form>>zoomIn:orOutTo:at:vanishingPoint: (in category 'transitions') -----
- zoomIn: goingIn orOutTo: otherImage at: topLeft vanishingPoint: vp 
- 	"Display zoomInTo: (Form fromDisplay: (40 at 40 extent: 300 at 300)) reverse at: 40 at 40.
- 	Display zoomOutTo: (Form fromDisplay: (40 at 40 extent: 300 at 300)) reverse at: 40 at 40."
- 	| nSteps minTime startTime |
- 	nSteps := 16.
- 	minTime := 500.  "milliseconds"
- 	startTime := Time millisecondClockValue.
- 	^ self wipeImage: otherImage at: topLeft clippingBox: nil rectForIndex:
- 		[:i | | lead bigR j lilR | "i runs from 1 to nsteps"
- 		i > nSteps
- 			ifTrue: [nil "indicates all done"]
- 			ifFalse:
- 			["If we are going too fast, delay for a bit"
- 			lead := startTime + (i-1*minTime//nSteps) - Time millisecondClockValue.
- 			lead > 10 ifTrue: [(Delay forMilliseconds: lead) wait].
- 
- 			"Return an array with the difference rectangles for this step."
- 			j := goingIn ifTrue: [i] ifFalse: [nSteps+1-i].
- 			bigR := vp - (vp*(j)//nSteps) corner:
- 				vp + (otherImage extent-vp*(j)//nSteps).
- 			lilR := vp - (vp*(j-1)//nSteps) corner:
- 				vp + (otherImage extent-vp*(j-1)//nSteps).
- 			bigR areasOutside: lilR]]!

Item was removed:
- ----- Method: Form>>zoomInTo:at: (in category 'transitions') -----
- zoomInTo: otherImage at: topLeft
- 	"Display zoomInTo: (Form fromDisplay: (40 at 40 extent: 300 at 300)) reverse at: 40 at 40"
- 	^ self zoomIn: true orOutTo: otherImage at: topLeft
- 		vanishingPoint: otherImage extent//2+topLeft!

Item was removed:
- ----- Method: Form>>zoomOutTo:at: (in category 'transitions') -----
- zoomOutTo: otherImage at: topLeft
- 	"Display zoomOutTo: (Form fromDisplay: (40 at 40 extent: 300 at 300)) reverse at: 40 at 40"
- 	^ self zoomIn: false orOutTo: otherImage at: topLeft
- 		vanishingPoint: otherImage extent//2+topLeft!

Item was removed:
- StrikeFont subclass: #FormSetFont
- 	instanceVariableNames: 'tintable combinationRule'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Fonts'!
- 
- !FormSetFont commentStamp: 'ct 2/14/2020 16:49' prior: 0!
- FormSetFonts are designed to capture individual images as character forms for imbedding in normal text.  While most often used to insert an isolated glyph in some text, the code is actually designed to support an entire user-defined font.  The TextAttribute subclass TextFontReference is specifically designed for such in-line insertion of exceptional fonts in normal text.!

Item was removed:
- ----- Method: FormSetFont class>>copy:toClipBoardAs:ascent: (in category 'examples') -----
- copy: charForm toClipBoardAs: char ascent: ascent
- 	Clipboard clipboardText:
- 		(Text string: char asString
- 			attribute: (TextFontReference toFont: 
- 				(FormSetFont new
- 					fromFormArray: (Array with: charForm)
- 					asciiStart: char asciiValue
- 					ascent: ascent)))
- "
- 	The S in the Squeak welcome window was installed by doing the following
- 	in a workspace (where the value of, eg, charForm will persist through BitEdit...
- 	f := TextStyle default fontAt: 4.
- 	oldS := f characterFormAt: $S.
- 	charForm := Form extent: oldS extent depth: 8.
- 	oldS displayOn: charForm.
- 	charForm bitEdit.
- 	...Play around with the BitEditor, then accept and close...
- 	FormSetFont copy: charForm toClipBoardAs: $S ascent: f ascent.
- 	...Then do a paste into the Welcome window
- "!

Item was removed:
- ----- Method: FormSetFont class>>example (in category 'examples') -----
- example    "FormSetFont example"
- 	"Lets the user select a (small) area of the screen to represent the
- 	character A, then copies 'A' to the clipboard with that as the letter form.
- 	Thereafter, a paste operation will imbed that character in any text."
- 	| charForm |
- 	charForm := Form fromUser.
- 	self copy: charForm toClipBoardAs: $A ascent: charForm height!

Item was removed:
- ----- Method: FormSetFont>>combinationRule (in category 'accessing') -----
- combinationRule
- 
- 	^ combinationRule!

Item was removed:
- ----- Method: FormSetFont>>combinationRule: (in category 'accessing') -----
- combinationRule: anObject
- 
- 	combinationRule := anObject!

Item was removed:
- ----- Method: FormSetFont>>displayString:on:from:to:at:kern: (in category 'displaying') -----
- displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta
- 	"Draw the given string from startIndex to stopIndex "
- 
- 	combinationRule ifNotNil: [:r | aBitBlt combinationRule: r].
- 	tintable == false ifTrue: [aBitBlt colorMap: nil].
- 	
- 	^ super displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta!

Item was removed:
- ----- Method: FormSetFont>>fromFormArray:asciiStart:ascent: (in category 'initialize-release') -----
- fromFormArray: formArray asciiStart: asciiStart ascent: ascentVal
- 	| height width x badChar |
- 	type := 2.
- 	name := 'aFormFont'.
- 	minAscii := asciiStart.
- 	maxAscii := minAscii + formArray size - 1.
- 	ascent := ascentVal.
- 	subscript := superscript := emphasis := 0.
- 	height := width := 0.
- 	maxWidth := 0.
- 	formArray do:
- 		[:f | width := width + f width.
- 		maxWidth := maxWidth max: f width.
- 		height := height max: f height + f offset y].
- 	badChar := (Form extent: 7 at height) borderWidth: 1.
- 	width := width + badChar width.
- 	descent := height - ascent.
- 	pointSize := height.
- 	glyphs := Form extent: width @ height depth: formArray first depth.
- 	xTable := Array new: maxAscii + 3 withAll: 0.
- 	x := 0.
- 	formArray withIndexDo:
- 		[:f :i | f displayOn: glyphs at: x at 0.
- 		xTable at: minAscii + i+1 put: (x := x + f width)].
- 	badChar displayOn: glyphs at: x at 0.
- 	xTable at: maxAscii + 3 put: x + badChar width.
- 	characterToGlyphMap := nil.!

Item was removed:
- ----- Method: FormSetFont>>initialize (in category 'initialize-release') -----
- initialize
- 
- 	super initialize.
- 	self preserveColors.!

Item was removed:
- ----- Method: FormSetFont>>makeTintable (in category 'tinting') -----
- makeTintable
- 	"Default."
- 	
- 	self tintable: true.
- 	self combinationRule: Form over.!

Item was removed:
- ----- Method: FormSetFont>>preserveColors (in category 'tinting') -----
- preserveColors
- 
- 	self tintable: false.
- 	self combinationRule: Form paint.!

Item was removed:
- ----- Method: FormSetFont>>preserveColorsWithAlpha (in category 'tinting') -----
- preserveColorsWithAlpha
- 	"Useful for rendering Emojis."
- 	
- 	self tintable: false.
- 	self combinationRule: Form blend.!

Item was removed:
- ----- Method: FormSetFont>>reset (in category 'emphasis') -----
- reset  "Ignored by FormSetFonts"!

Item was removed:
- ----- Method: FormSetFont>>tintable (in category 'accessing') -----
- tintable
- 
- 	^ tintable!

Item was removed:
- ----- Method: FormSetFont>>tintable: (in category 'accessing') -----
- tintable: anObject
- 
- 	tintable := anObject!

Item was removed:
- Form subclass: #FormStub
- 	instanceVariableNames: 'locator'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Display Objects'!

Item was removed:
- ----- Method: FormStub>>locator (in category 'accessing') -----
- locator
- 	^locator!

Item was removed:
- ----- Method: FormStub>>locator: (in category 'accessing') -----
- locator: aString
- 	locator := aString!

Item was removed:
- ----- Method: FormStub>>objectForDataStream: (in category 'fileIn/Out') -----
- objectForDataStream: refStream
- 	"Force me into outPointers so that I get notified about startup"
- 	refStream replace: self with: self.
- 	^self!

Item was removed:
- ImageReadWriter subclass: #GIFReadWriter
- 	instanceVariableNames: 'width height bitsPerPixel colorPalette rowByteSize xpos ypos pass interlace transparentIndex localColorTable loopCount offset frames canvasWidth canvasHeight backgroundColorIndex comment'
- 	classVariableNames: 'Extension ImageSeparator Terminator'
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!
- 
- !GIFReadWriter commentStamp: 'ct 6/10/2022 13:02' prior: 0!
- I am GIFReadWriter.
- I am a concrete ImageReadWriter.
- 
- Updated implementation of a GIF file (byte-level) decoder.
- 
- I implement a Stream-like behavior over a GIF image file, and can both read and write GIF files.
- 
- Previously, two classes distinguished between "still" and "animated" GIFs. However, the standard specifies that any GIF can have "frames" and be animated. This reimplementation treats this as normal.
- 
- See these links for more detailed information:
-  
-  https://www.w3.org/Graphics/GIF/spec-gif89a.txt
-  https://en.wikipedia.org/wiki/GIF
-  http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
- 
- For writing GIF files, I take a collection of AnimatedImageFrame objects and write the appropriate headers, Graphics Control Extensions, and everything else needed for writing an animated GIF.
- 
- For reading GIF files, I take a binary filestream and set my own `frames` variable to be a collection of AnimatedImageFrames, which themselves contain decoded Forms and instructions for disposal, delay, etc.
- 
- NOTE: I make use of the LzwGifDecoder and LzwGifEncoder classes in order to encode/decode individual bitmap data for each image frame of the GIF.
- 
- See `GIFReadWriter exampleAnim` for more information.  !

Item was removed:
- ----- Method: GIFReadWriter class>>exampleAnim (in category 'examples') -----
- exampleAnim
- 	"This example writes out an animated gif of
- 	 a red circle"
- 
- 	| writer extent center frameDelay |
- 	writer := GIFReadWriter on: (FileStream fileNamed: 'anim.gif').
- 	writer loopCount: 20.		"Repeat 20 times"
- 	frameDelay := 10.		"Wait 10/100 seconds"
- 	extent := 42 at 42.
- 	center := extent / 2.
- 	Cursor write showWhile: [
- 		[2 to: center x - 1 by: 2 do: [:r |
- 			"Make a fancy anim without using Canvas - inefficient as hell"
- 			| frame |
- 			frame := AnimatedImageFrame new
- 				delay: frameDelay;
- 				form: (ColorForm extent: extent depth: 8).
- 			0.0 to: 359.0 do: [:theta | frame form colorAt: (center + (Point r: r degrees: theta)) rounded put: Color red].
- 			writer nextPutFrame: frame ]
- 		]	ensure: [writer close]].!

Item was removed:
- ----- Method: GIFReadWriter class>>formsFromFileNamed: (in category 'image reading/writing') -----
- formsFromFileNamed: aFile
- 	^ (self on: aFile asDirectoryEntry readStream binary)
- 			readHeader;
- 			readBody;
- 			yourself!

Item was removed:
- ----- Method: GIFReadWriter class>>formsFromStream: (in category 'image reading/writing') -----
- formsFromStream: aBinaryStream
- 	^ (self on: aBinaryStream)
- 		readHeader;
- 		readBody;
- 		yourself!

Item was removed:
- ----- Method: GIFReadWriter class>>grabScreenAndSaveOnDisk (in category 'examples') -----
- grabScreenAndSaveOnDisk
- 	"GIFReadWriter grabScreenAndSaveOnDisk"
- 
- 	| form fileName |
- 	form := Form fromUser.
- 	form bits size = 0 ifTrue: [^Beeper beep].
- 	fileName := FileDirectory default nextNameFor: 'Squeak' extension: 'gif'.
- 	Project uiManager
- 		informUser: ('Writing {1}' translated format: {fileName})
- 		during: [GIFReadWriter putForm: form onFileNamed: fileName].!

Item was removed:
- ----- Method: GIFReadWriter class>>initialize (in category 'initialization') -----
- initialize
- 	"GIFReadWriter initialize"
- 	ImageSeparator := $, asInteger.
- 	Extension := $!! asInteger.
- 	Terminator := $; asInteger!

Item was removed:
- ----- Method: GIFReadWriter class>>typicalFileExtensions (in category 'image reading/writing') -----
- typicalFileExtensions
- 	"Answer a collection of file extensions (lowercase) which files that I can 
- 	read might commonly have"
- 
- 	^ self allSubclasses
- 		detect: [ :cls | cls wantsToHandleGIFs ]
- 		ifFound: [ #() ]
- 		ifNone: [ 
- 			"if none of my subclasses wants , then i''ll have to do"
- 			#('gif') ]!

Item was removed:
- ----- Method: GIFReadWriter class>>wantsToHandleGIFs (in category 'image reading/writing') -----
- wantsToHandleGIFs
- 	^ true!

Item was removed:
- ----- Method: GIFReadWriter>>backgroundColor (in category 'accessing') -----
- backgroundColor
- 	backgroundColorIndex ifNotNil: [ 
- 		colorPalette ifNotNil: [ 
- 			^ colorPalette at: backgroundColorIndex + 1]].
- 	^ Color transparent.!

Item was removed:
- ----- Method: GIFReadWriter>>canvasHeight (in category 'accessing') -----
- canvasHeight
- 	^ canvasHeight!

Item was removed:
- ----- Method: GIFReadWriter>>canvasHeight: (in category 'accessing') -----
- canvasHeight: aNumber
- 	canvasHeight := aNumber!

Item was removed:
- ----- Method: GIFReadWriter>>canvasWidth (in category 'accessing') -----
- canvasWidth
- 	^ canvasWidth!

Item was removed:
- ----- Method: GIFReadWriter>>canvasWidth: (in category 'accessing') -----
- canvasWidth: aNumber
- 	canvasWidth := aNumber!

Item was removed:
- ----- Method: GIFReadWriter>>close (in category 'stream access') -----
- close
- 	"A read close"
- 	^super close!

Item was removed:
- ----- Method: GIFReadWriter>>delays (in category 'accessing') -----
- delays
- 	"Respond with an ordered collection of Frame delay values"
- 	^ frames collect: [ :frame | frame delay ]!

Item was removed:
- ----- Method: GIFReadWriter>>form (in category 'accessing') -----
- form
- 	"By default, answer with the first Form available in the
- 	ImageFrames collection. If there are not any frames, answer nil"
- 	frames ifNil: [ ^ nil ].
- 	frames ifEmpty: [ ^ nil ].
- 	^ frames first form.!

Item was removed:
- ----- Method: GIFReadWriter>>forms (in category 'accessing') -----
- forms
- 	frames ifNil: [ ^ nil ].
- 	^ frames collect: [ :f | f form ].!

Item was removed:
- ----- Method: GIFReadWriter>>frames (in category 'accessing') -----
- frames
- 	^ frames!

Item was removed:
- ----- Method: GIFReadWriter>>frames: (in category 'accessing') -----
- frames: aCollectionOfImageFrames
- 	"Set the receiver's underlying collection of
- 	ImageFrame objects. Used when attempting to write
- 	out GIF images"
- 	frames := aCollectionOfImageFrames!

Item was removed:
- ----- Method: GIFReadWriter>>isAnimated (in category 'testing') -----
- isAnimated
- 	frames ifNil: [ ^ false ].
- 	^ frames size > 1!

Item was removed:
- ----- Method: GIFReadWriter>>loopCount: (in category 'accessing') -----
- loopCount: aNumber
- 	"Set looping. This must be done before any image is written!!"
- 	loopCount := aNumber!

Item was removed:
- ----- Method: GIFReadWriter>>nextImage (in category 'accessing') -----
- nextImage
- 	"This method ensures older compatibility with ImageReadWriter.
- 	We respond with the Form corresponding to the *first image* on
- 	the receiver's read byte stream"
- 	self
- 		readHeader;
- 		readBody.
- 	^ self form.!

Item was removed:
- ----- Method: GIFReadWriter>>nextPutFrame: (in category 'accessing') -----
- nextPutFrame: anAnimatedImageFrame
- 	"Given the current settings, write the bytes onto the
- 	output stream for the given ImageFrame and its form"
- 	| aForm reduced tempForm tempFrame |
- 	
- 	aForm := anAnimatedImageFrame form copy.
- 	aForm unhibernate.
- 	aForm depth > 8 ifTrue:[
- 		reduced := aForm colorReduced.  "minimize depth"
- 		reduced depth > 8 ifTrue: [
- 			"Not enough color space; do it the hard way."
- 			reduced := reduced asFormOfDepth: 8].
- 	] ifFalse:[reduced := aForm].
- 	reduced depth < 8 ifTrue: [
- 		"writeBitData: expects depth of 8"
- 		tempForm := reduced class extent: reduced extent depth: 8.
- 		(reduced isColorForm) ifTrue:[
- 			tempForm
- 				copyBits: reduced boundingBox
- 				from: reduced at: 0 at 0
- 				clippingBox: reduced boundingBox
- 				rule: Form over
- 				fillColor: nil
- 				map: nil.
- 			tempForm colors: reduced colors.
- 		] ifFalse: [reduced displayOn: tempForm].
- 		reduced := tempForm.
- 	].
- 	(reduced isColorForm) ifTrue:[
- 		(reduced colorsUsed includes: Color transparent) ifTrue: [
- 			transparentIndex := (reduced colors indexOf: Color transparent) - 1.
- 		]
- 	] ifFalse: [transparentIndex := nil].
- 	width := reduced width.
- 	height := reduced height.
- 	bitsPerPixel := reduced depth.
- 	colorPalette := reduced colormapIfNeededForDepth: 32.
- 	interlace := false.
- 	tempFrame := AnimatedImageFrame new 
- 		form: reduced;
- 		offset: anAnimatedImageFrame offset;
- 		delay: anAnimatedImageFrame delay;
- 		disposal: anAnimatedImageFrame disposal.
- 	self writeHeader.
- 	self writeFrameHeader: tempFrame.
- 	self writeBitData: reduced bits.!

Item was removed:
- ----- Method: GIFReadWriter>>nextPutImage: (in category 'accessing') -----
- nextPutImage: aForm
- 	"Given the current settings, write the bytes onto the
- 	output stream for the given ImageFrame and its form"
- 	| reduced tempForm tempFrame |
- 	
- 	aForm unhibernate.
- 	aForm depth > 8 ifTrue:[
- 		reduced := aForm colorReduced.  "minimize depth"
- 		reduced depth > 8 ifTrue: [
- 			"Not enough color space; do it the hard way."
- 			reduced := reduced asFormOfDepth: 8].
- 	] ifFalse:[reduced := aForm].
- 	reduced depth < 8 ifTrue: [
- 		"writeBitData: expects depth of 8"
- 		tempForm := reduced class extent: reduced extent depth: 8.
- 		(reduced isColorForm) ifTrue:[
- 			tempForm
- 				copyBits: reduced boundingBox
- 				from: reduced at: 0 at 0
- 				clippingBox: reduced boundingBox
- 				rule: Form over
- 				fillColor: nil
- 				map: nil.
- 			tempForm colors: reduced colors.
- 		] ifFalse: [reduced displayOn: tempForm].
- 		reduced := tempForm.
- 	].
- 	(reduced isColorForm) ifTrue:[
- 		(reduced colorsUsed includes: Color transparent) ifTrue: [
- 			transparentIndex := (reduced colors indexOf: Color transparent) - 1.
- 		]
- 	] ifFalse: [transparentIndex := nil].
- 	width := reduced width.
- 	height := reduced height.
- 	bitsPerPixel := reduced depth.
- 	colorPalette := reduced colormapIfNeededForDepth: 32.
- 	interlace := false.
- 	tempFrame := AnimatedImageFrame new 
- 		form: reduced;
- 		offset: reduced offset.
- 	self writeHeader.
- 	self writeFrameHeader: tempFrame.
- 	self writeBitData: reduced bits.!

Item was removed:
- ----- Method: GIFReadWriter>>processColorsFor: (in category 'private - decoding') -----
- processColorsFor: anImageFrame
- 	"Colors can only be mapped after the GCE has been evaluated
- 	for a given image frame. We perform this action using either
- 	the local or global color table for this frame's form"
- 	| colorTable |
- 	colorTable := localColorTable ifNil: [ colorPalette ].
- 	
- 	"Use a copy so we don't mess up the global color table as we parse"
- 	colorTable := colorTable copyFrom: 1 to: colorTable size.
- 	
- 	transparentIndex 
- 		ifNotNil: [ 
- 			transparentIndex + 1 > colorTable size
- 				ifTrue: [ 
- 					colorTable := colorTable
- 										forceTo: transparentIndex + 1
- 										paddingWith: Color white ].
- 				colorTable
- 					at: transparentIndex + 1
- 					put: Color transparent ].
- 	anImageFrame form colors: colorTable.!

Item was removed:
- ----- Method: GIFReadWriter>>readApplicationExtension (in category 'private - decoding') -----
- readApplicationExtension
- 	"Uses the underlying stream to read a so-called
- 	Application Extension to the GIF Image. These extensions
- 	are at the whole file -- not individual frame like a GCE --
- 	level. It appears the only kind widely used is the NETSCAPE
- 	extension for determining the number of times an animated
- 	GIF should loop."
- 	| bytesFollow appName appAuthCode caughtInfo numSubBlocks loopVal1 loopVal2 |
- 	"How many bytes before data begins?
- 	Usually 11"
- 	bytesFollow := self next.
- 	appName := (String streamContents: [ :s |
- 		1 to: 8 do: [ :num |
- 			s
- 				nextPut: self next asCharacter ] ]).
- 	appAuthCode := (String streamContents: [ :s |
- 		1 to: 3 do: [ :num |
- 			s
- 				nextPut: self next asCharacter ] ]).
- 	caughtInfo := (appName size + appAuthCode size).
- 	caughtInfo = bytesFollow ifFalse: [ 
- 		(bytesFollow = caughtInfo) timesRepeat: [ 
- 			self next ] ].
- 	numSubBlocks := self next.
- 	appName = 'NETSCAPE' 
- 		ifTrue: [ 
- 			self next. "Data sub-block index (always 1)"
- 			"If it's the NETSCAPE extension, the next
- 			byte will set the loopCount. This is stored in
- 			a 2-byte lo-hi unsigned format"
- 			loopVal1 := self next.
- 			loopVal2 := self next.
- 			loopCount := (loopVal2 * 256) + loopVal1.
- 			self next = 0 ifFalse: [ ^ self error: 'Corrupt NETSCAPE Application Block' ].
- 			^ self ].
- 
- 	"For now we ignore Application Extensions
- 	that are not the NETSCAPE kind"
- 	[ numSubBlocks = 0 ] whileFalse: [ 
- 		self next: numSubBlocks.
- 		numSubBlocks := self next ].
- 	!

Item was removed:
- ----- Method: GIFReadWriter>>readBitDataOnFrame: (in category 'private - decoding') -----
- readBitDataOnFrame: aFrame
- 	"using modified Lempel-Ziv Welch algorithm."
- 	| initCodeSize  packedBits hasLocalColor localColorSize maxOutCodes decoder c  bytes |
- 	maxOutCodes := 4096.
- 	offset := self readWord @ self readWord.	"Image Left at Image Top"
- 	width := self readWord.
- 	height := self readWord.
- 	"---
- 	Local Color Table Flag        1 Bit
- 	Interlace Flag                1 Bit
- 	Sort Flag                     1 Bit
- 	Reserved                      2 Bits
- 	Size of Local Color Table     3 Bits
- 	----"
- 	packedBits := self next.
- 	interlace := (packedBits bitAnd: 64) ~= 0.
- 	aFrame interlace: interlace.
- 	hasLocalColor := (packedBits bitAnd: 128) ~= 0.
- 	localColorSize := 1 bitShift: (packedBits bitAnd: 7) + 1.
- 	hasLocalColor 
- 		ifTrue: [ 
- 			localColorTable := self readColorTable: localColorSize ]
- 		ifFalse: [ localColorTable := nil ].
- 	pass := 0.
- 	xpos := 0.
- 	ypos := 0.
- 	rowByteSize := (width + 3) // 4 * 4.
- 	bytes := (ByteArray new: rowByteSize * height).
- 
- 	initCodeSize := self next.
- 
- 	c := ColorForm 
- 		extent: width at height
- 		depth: 8. 
- 
- 	decoder := LzwGifDecoder new.
- 	decoder 
- 		codeStream: stream;
- 		minimumCodeSize: initCodeSize;
- 		maxCode: maxOutCodes;
- 		onDecodedBit: [ :bit |
- 			bytes
- 				at: (ypos * rowByteSize + xpos + 1)
- 				put: bit.
- 			self updatePixelPosition ].
- 	decoder decode.
- 	c bits copyFromByteArray: bytes.
- 	^ c!

Item was removed:
- ----- Method: GIFReadWriter>>readBody (in category 'private - decoding') -----
- readBody
- 	"Read the GIF blocks. Modified to return a frame."
- 	| block frame |
- 	frame := nil.
- 	frames := OrderedCollection new.
- 	[ stream atEnd ] whileFalse: [ 
- 		block := self next.
- 		
- 		"If we have reached the terminator byte, return."
- 		block = Terminator ifTrue: [ ^ frame ].
- 		block = ImageSeparator 
- 			ifTrue: [ 
- 				frame ifNil: [ frame := AnimatedImageFrame new ].
- 				frame form: (self readBitDataOnFrame: frame). "Adjusting message for testing"
- 				frame offset: offset. "Set from instance var, which is set in readBitData"
- 				frame form offset: offset. "Set the offset on the underlying Form as well"
- 				
- 				frames add: frame.
- 				self processColorsFor: frame.
- 				frame := nil. ]
- 			ifFalse: 
- 				[ "If it's not actual image data, perhaps
- 					it's an Extension of some kind (there can be several)"
- 					block = Extension 
- 						ifTrue: [ 
- 							frame ifNil: [ frame := AnimatedImageFrame new ].
- 							self readExtensionBlock: block withFrame: frame ]
- 						ifFalse: [ ^ self error: 'Unknown Bytes!!' ] ] 
- 		].
- 	^ frames.!

Item was removed:
- ----- Method: GIFReadWriter>>readColorTable: (in category 'private - decoding') -----
- readColorTable: numberOfEntries 
- 	| array r g b |
- 	array := Array new: numberOfEntries.
- 	1 
- 		to: array size
- 		do: 
- 			[ :i | 
- 			r := self next.
- 			g := self next.
- 			b := self next.
- 			array 
- 				at: i
- 				put: (Color 
- 						r: r
- 						g: g
- 						b: b
- 						range: 255) ].
- 	^ array!

Item was removed:
- ----- Method: GIFReadWriter>>readCommentExtension (in category 'private - decoding') -----
- readCommentExtension
- 	| blockTerminator |
- 	blockTerminator := self next.
- 	blockTerminator > 0
- 		ifTrue: [ comment := self next: blockTerminator.
- 			blockTerminator := self next ].
- 	blockTerminator = 0
- 		ifFalse: [ ^ self error: 'Invalid Block Terminator' ]!

Item was removed:
- ----- Method: GIFReadWriter>>readDisposal: (in category 'private - decoding') -----
- readDisposal: aPackedByte
- 	"Read the three-bit disposal flag from
- 	the packed byte in the Graphic Control Extension block.
- 	Disposal is three-bits with the following codes:
- 	 |0 0 0 [0 0 0] 0 0|
- 	1 => leave current frame and draw on top of it (#leaveCurrent)
- 	2 => Restore to background color (#restoreBackground)
- 	3 => Restore to state before current frame was drawn (#restorePrevState)"
- 	| least middle both |
- 	(both := (aPackedByte bitAnd: 12) = 12).
- 	both ifTrue: [ ^ #restorePrevState ].
- 	
- 	least := (aPackedByte bitAnd: 4) = 4.
- 	least ifTrue: [ ^ #leaveCurrent ].
- 	
- 	middle := (aPackedByte bitAnd: 8) = 8.
- 	middle ifTrue: [ ^ #restoreBackground ].
- 	
- 	^ #otherDisposal
- 	!

Item was removed:
- ----- Method: GIFReadWriter>>readExtensionBlock:withFrame: (in category 'private - decoding') -----
- readExtensionBlock: aGifBlock withFrame: anImageFrame
- 	"Determine which type of extension block we are
- 	looking at. The most common is the Graphic Control Extension (GCE)
- 	which tells us information about the image frame, including delays
- 	offsets in the canvas, and how to dispose of the frame in animation"
- 	| extensionType packedByte delayByte1 delayByte2 |
- 	extensionType := self next.
- 	
- 	"255 is an Application Extension.
- 	 This seems to always be the NETSCAPE
- 	 extension, which has looping information.
- 	This extension does not affect individual frames,
- 	but rather sets the loopCount for the whole image"
- 	extensionType = 255 ifTrue: [ 
- 		^ self readApplicationExtension ].
- 	
- 	
- 	"249 Corresponds to the GCE"
- 	extensionType = 249 ifTrue: [ 
- 		self next = 4 ifFalse: [ ^ self "The GIF is likely corrupt in this case" ].
- 		"====
- 		Reserved                      3 Bits (Ignore)
- 		Disposal Method               3 Bits 
- 		User Input Flag               1 Bit  (Ignore)
- 		Transparent Color Flag        1 Bit  (Need to Implement)
- 		==="
- 		packedByte := self next.
- 		delayByte1 := self next.
- 		delayByte2 := self next.
- 		transparentIndex := self next.
- 		(packedByte bitAnd: 1) = 0 "Changed to see if other endian is the real end..."
- 			ifTrue: [ transparentIndex := nil ].
- 		anImageFrame 
- 			disposal: (self readDisposal: packedByte);
- 			"Delay time is stored as 2 bytes unsigned"
- 			delay: (delayByte2 * 256 + delayByte1) * 10.
- 		self next = 0 ifFalse: [ ^ self error: 'Corrupt GCE Block!!' ].
- 		^ self ].
- 
- 	extensionType = 254 ifTrue: [ 
- 		^ self readCommentExtension ].
- 
- 	"If you get to this point, we don't know the Extension Type"
- 	^ self error: 'Unknown GIF Extension: ',(extensionType asString).!

Item was removed:
- ----- Method: GIFReadWriter>>readHeader (in category 'private - decoding') -----
- readHeader
- 	| is89 byte hasColorMap |
- 	(self hasMagicNumber: 'GIF87a' asByteArray) 
- 		ifTrue: [ is89 := false ]
- 		ifFalse: 
- 			[ (self hasMagicNumber: 'GIF89a' asByteArray) 
- 				ifTrue: [ is89 := true ]
- 				ifFalse: [ ^ self error: 'This does not appear to be a GIF file' translated ] ].
- 	"Width and Height for whole canvas, not
- 	just an invididual frame/form"
- 	canvasWidth := self readWord.
- 	canvasHeight := self readWord.
- 	byte := self next.
- 	hasColorMap := (byte bitAnd: 128) ~= 0.
- 	bitsPerPixel := (byte bitAnd: 7) + 1.
- 	backgroundColorIndex := self next.
- 	self next ~= 0 ifTrue: 
- 		[ is89 ifFalse: [ ^ self error: 'corrupt GIF file (screen descriptor)' ] ].
- 	hasColorMap 
- 		ifTrue: [ colorPalette := self readColorTable: (1 bitShift: bitsPerPixel) ]
- 		ifFalse: 
- 			[ colorPalette := nil	"Palette monochromeDefault" ]!

Item was removed:
- ----- Method: GIFReadWriter>>readPixelFrom: (in category 'private-encoding') -----
- readPixelFrom: bits
- 	"Since bits is a Bitmap with 32 bit values, watch out for the
- padding at the end of each row.  But, GIF format already wants padding to
- 32 bit boundary!!  OK as is.  tk 9/14/97"
- 
- 	| pixel |
- 	ypos >= height ifTrue: [^nil].
- 	pixel := bits byteAt: (ypos * rowByteSize + xpos + 1).
- 	self updatePixelPosition.
- 	^pixel!

Item was removed:
- ----- Method: GIFReadWriter>>readWord (in category 'private - decoding') -----
- readWord
- 	^self next + (self next bitShift: 8)!

Item was removed:
- ----- Method: GIFReadWriter>>setStream: (in category 'accessing') -----
- setStream: aStream 
- 	"Feed it in from an existing source"
- 	stream := aStream!

Item was removed:
- ----- Method: GIFReadWriter>>understandsImageFormat (in category 'accessing') -----
- understandsImageFormat
- 	^('abc' collect: [:x | stream next asCharacter]) = 'GIF'!

Item was removed:
- ----- Method: GIFReadWriter>>updatePixelPosition (in category 'private') -----
- updatePixelPosition
- 	(xpos := xpos + 1) >= width ifFalse: [ ^ self ].
- 	xpos := 0.
- 	interlace ifFalse: 
- 		[ ypos := ypos + 1.
- 		^ self ].
- 	pass = 0 ifTrue: 
- 		[ (ypos := ypos + 8) >= height ifTrue: 
- 			[ pass := pass + 1.
- 			ypos := 4 ].
- 		^ self ].
- 	pass = 1 ifTrue: 
- 		[ (ypos := ypos + 8) >= height ifTrue: 
- 			[ pass := pass + 1.
- 			ypos := 2 ].
- 		^ self ].
- 	pass = 2 ifTrue: 
- 		[ (ypos := ypos + 4) >= height ifTrue: 
- 			[ pass := pass + 1.
- 			ypos := 1 ].
- 		^ self ].
- 	pass = 3 ifTrue: 
- 		[ ypos := ypos + 2.
- 		^ self ].
- 	^ self caseError!

Item was removed:
- ----- Method: GIFReadWriter>>writeBitData: (in category 'private - encoding') -----
- writeBitData: bits 
- 	"using modified Lempel-Ziv Welch algorithm."
- 	| encoder initCodeSize |
- 	encoder := LzwGifEncoder new
- 		rowByteSize: (width * 8 + 31) // 32 * 4;
- 		extent: width at height;
- 		codeStream: stream.
- 	initCodeSize := bitsPerPixel <= 1 
- 		ifTrue: [ 2 ]
- 		ifFalse: [ bitsPerPixel ].
- 	encoder minimumCodeSize: initCodeSize.
- 	encoder encode: bits.!

Item was removed:
- ----- Method: GIFReadWriter>>writeDisposal:toPackedByte: (in category 'writing') -----
- writeDisposal: aSymbol toPackedByte: aByte
- 	"Using the GIF Graphics Control Extension
- 	packed byte format, respond with a modified version
- 	of the passed byte that includes the correct 3-bit
- 	disposal code corresponding to the passed in symbol"
- 	
- 	aSymbol = #restoreBackground
- 		ifTrue: [ 
- 			"This is a value of 2 in the 3-bit structure,
- 			so 010, then shifted two to the left (equal to 8)"
- 			^ aByte + (2 bitShift: 2) ].
- 	
- 	aSymbol = #leaveCurrent
- 		ifTrue: [ 
- 			"This is a value of 1 in the 3-bit structure,
- 			so 001, then shifted two to the left (equal to 4)"
- 			^ aByte + (1 bitShift: 2) ].
- 	
- 	aSymbol = #restorePrevState
- 		ifTrue: [ 
- 			"This is a value of 3 in the 3-bit structure,
- 			so 011, then shifted two to the left (equal to 12)"
- 			^ aByte + (3 bitShift: 2) ].
- 	^ aByte
- 		!

Item was removed:
- ----- Method: GIFReadWriter>>writeFrameHeader: (in category 'accessing') -----
- writeFrameHeader: anImageFrame
- 	"Write any Extensions and/or headers that apply
- 	to individual frames/subimages"
- 	| interlaceByte |
- 	anImageFrame delay notNil | transparentIndex notNil ifTrue: [ 
- 		self writeGCEForFrame: anImageFrame ].
- 	
- 	"Next is the image descriptor"
- 	self 
- 		nextPut: ImageSeparator;
- 		writeWord: (anImageFrame offset x);
- 		writeWord: (anImageFrame offset y);
- 		writeWord: (anImageFrame form extent x);
- 		writeWord: (anImageFrame form extent y).
- 	
- 	interlaceByte := interlace
- 		ifTrue: [ 64 ]
- 		ifFalse: [ 0 ].
- 	self nextPut: interlaceByte
- 	!

Item was removed:
- ----- Method: GIFReadWriter>>writeGCEForFrame: (in category 'private - encoding') -----
- writeGCEForFrame: anAnimatedImageFrame
- 	"Writes a Graphics Control Extension onto
- 	the output stream for the given image frame"
- 	| nextDelay packedByte |
- 	nextDelay := anAnimatedImageFrame delay.
- 	anAnimatedImageFrame delay ifNil: [ nextDelay := 0 ].
- 	"Set the bits of the packed byte"
- 	"====
- 		Reserved                      3 Bits (Ignore)
- 		Disposal Method               3 Bits 
- 		User Input Flag               1 Bit  (Ignore)
- 		Transparent Color Flag        1 Bit 
- 		==="
- 	packedByte := 0.
- 	transparentIndex
- 		ifNotNil: [ packedByte := 1 ].
- 	packedByte := self 
- 		writeDisposal: (anAnimatedImageFrame disposal)
- 		toPackedByte: packedByte.
- 	
- 	self 
- 		nextPut: Extension;
- 		nextPutAll: #(249 4) asByteArray;
- 		nextPut: packedByte;
- 		"nextPut: (transparentIndex
- 				ifNil: [ 0 ]
- 				ifNotNil: [ 9 ]);"
- 		writeWord: nextDelay // 10;
- 		nextPut: (transparentIndex ifNil: [ 0 ]);
- 		nextPut: 0.!

Item was removed:
- ----- Method: GIFReadWriter>>writeHeader (in category 'private - encoding') -----
- writeHeader
- 	| byte |
- 	"Write the overall image file header onto the
- 	output stream. This includes the global information
- 	about the file, such as canvasWidth etc. Only do so
- 	if the stream is in the initial position."
- 	stream position = 0 ifFalse: [ ^ self ].
- 
- 	self nextPutAll: 'GIF89a' asByteArray.
- 	self writeWord: width.	"Screen Width"
- 	self writeWord: height.	"Screen Height"
- 	byte := 128.	"has color map"
- 	byte := byte bitOr: (bitsPerPixel - 1 bitShift: 5).	"color resolution"
- 	byte := byte bitOr: bitsPerPixel - 1.	"bits per pixel"
- 	self nextPut: byte.
- 	self nextPut: 0.	"background color."
- 	self nextPut: 0.	"reserved / unused 'pixel aspect ratio"
- 	colorPalette do: 
- 		[ :pixelValue | 
- 		self
- 			nextPut: ((pixelValue bitShift: -16) bitAnd: 255);
- 			nextPut: ((pixelValue bitShift: -8) bitAnd: 255);
- 			nextPut: (pixelValue bitAnd: 255) ].
- 	loopCount notNil ifTrue: 
- 		[ self writeNetscapeExtension ].!

Item was removed:
- ----- Method: GIFReadWriter>>writeNetscapeExtension (in category 'private - encoding') -----
- writeNetscapeExtension
- 	"Writes a GIF Application Extension corresponding
- 	to the NETSCAPE2.0 version, with specifies the loopCount."
- 	self
- 		nextPut: Extension;
- 		nextPut: 255; "Indicates Application Extension"
- 		nextPut: 11; "Indicates how many bytes follow, almost always 11"
- 		nextPutAll: ('NETSCAPE2.0' asByteArray);
- 		nextPut: 3;
- 		nextPut: 1;
- 		writeWord: (loopCount ifNil: [ 0 ]);
- 		nextPut: 0.!

Item was removed:
- ----- Method: GIFReadWriter>>writeWord: (in category 'private - encoding') -----
- writeWord: aWord
- 	self nextPut: (aWord bitAnd: 255).
- 	self nextPut: ((aWord bitShift: -8) bitAnd: 255).
- 	^aWord!

Item was removed:
- StrikeFont subclass: #HostFont
- 	instanceVariableNames: 'fullWidth kernPairs ranges'
- 	classVariableNames: 'IsoToSqueakMap'
- 	poolDictionaries: 'TextConstants'
- 	category: 'Graphics-Fonts'!

Item was removed:
- ----- Method: HostFont class>>defaultRanges (in category 'accessing') -----
- defaultRanges
- 
- 	^ Array with: (Array with: 0 with: 16r2AFF).
- !

Item was removed:
- ----- Method: HostFont class>>fontName:size:emphasis: (in category 'instance creation') -----
- fontName: fontName size: ptSize emphasis: emphasisCode
- 	"
- 		^HostFont fontName: (HostFont fontNameFromUser) size: 12 emphasis: 0.
- 	"
- 	^self new fontName: fontName size: ptSize emphasis: emphasisCode!

Item was removed:
- ----- Method: HostFont class>>fontName:size:emphasis:rangesArray: (in category 'instance creation') -----
- fontName: fontName size: ptSize emphasis: emphasisCode rangesArray: ranges
- 	"
- 		^HostFont fontName: (HostFont fontNameFromUser) size: 12 emphasis: 0.
- 	"
- 	^self new fontName: fontName size: ptSize emphasis: emphasisCode rangesArray: ranges!

Item was removed:
- ----- Method: HostFont class>>fontNameFromUser (in category 'accessing') -----
- fontNameFromUser
- 	"HostFont fontNameFromUser"
- 	| fontNames index labels |
- 	fontNames := self listFontNames sort.
- 	labels := WriteStream on: (String new: 100).
- 	fontNames do:[:fn| labels nextPutAll: fn] separatedBy:[labels cr].
- 	index := (UIManager default chooseFrom: (labels contents substrings) title: 'Choose your font').
- 	index = 0 ifTrue:[^nil].
- 	^fontNames at: index!

Item was removed:
- ----- Method: HostFont class>>initWin32 (in category 'system defaults') -----
- initWin32
- 	"HostFont initWin32"
- 	#(
- 			"Basic fonts"
- 			('Arial'				"menu/text serifless"
- 				(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90))
- 			('Times New Roman'	"menu/text serifs"
- 				(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90))
- 			('Courier New'			"menu/text fixed"
- 				(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90))
- 			('Wingdings'			"deco"
- 				(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90))
- 			('Symbol'				"deco"
- 				(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90))
- 
- 			"Nice fonts"
- 			('Verdana'			"menu/text serifless"
- 				(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90))
- 
- 			('Tahoma'			"menu/text serifless"
- 				(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90))
- 
- 			('Garamond'			"menu/text serifs"
- 				(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90))
- 			('Georgia'			"menu/text serifs"
- 				(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90))
- 
- 			('Comic Sans MS'	"eToy"
- 				(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90))
- 
- 			"Optional fonts"
- 			('Impact'			"flaps"
- 				(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90))
- 
- 			('Webdings'			"deco"
- 				(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90))
- 
- 			('System'		"12pt only"
- 				(12))
- 			('Fixedsys'		"12pt only"
- 				(12))
- 		) do:[:spec| HostFont textStyleFrom: spec first sizes: spec last].
- 
- 	TextConstants removeKey: #Atlanta ifAbsent: [].
- 	TextConstants removeKey: #ComicPlain ifAbsent: [].
- 	TextConstants removeKey: #ComicBold ifAbsent: [].
- 	TextConstants removeKey: #Courier ifAbsent: [].
- 	TextConstants removeKey: #Palatino ifAbsent: [].
- 
- 	TextConstants at: #DefaultFixedTextStyle put: (TextConstants at: #'Courier New').
- 	TextConstants at: #Helvetica put:  (TextConstants at: #'Arial').
- 
- !

Item was removed:
- ----- Method: HostFont class>>listFontName: (in category 'accessing') -----
- listFontName: index
- 	<primitive:'primitiveListFont' module:'FontPlugin'>
- 	^nil!

Item was removed:
- ----- Method: HostFont class>>listFontNames (in category 'accessing') -----
- listFontNames
- 	"HostFont listFontNames"
- 	"List all the OS font names"
- 	| font fontNames index |
- 	fontNames := WriteStream on: Array new.
- 	index := 0.
- 	[font := self listFontName: index.
- 	font == nil] whileFalse:[
- 		fontNames nextPut: font.
- 		index := index + 1].
- 	^fontNames contents!

Item was removed:
- ----- Method: HostFont class>>rangesForJapanese (in category 'accessing') -----
- rangesForJapanese
- 
- 	| basics etc |
- 	basics := {
- 		Array with: 0 with: 255
- 	}.
- 	etc := {
- 		Array with: 16r370 with: 16r3FF. "greek"
- 		Array with: 16r400 with: 16r52F. "cyrillic"
- 		Array with: 16r1D00 with: 16r1D7F. "phonetic"
- 		Array with: 16r1E00 with: 16r1EFF. "latin extended additional"
- 		Array with: 16r2000 with: 16r206F. "general punctuation"
- 		Array with: 16r20A0 with: 16r20CF. "currency symbols"
- 		Array with: 16r2100 with: 16r214F. "letterlike"
- 		Array with: 16r2150 with: 16r218F. "number form"
- 		Array with: 16r2190 with: 16r21FF. "arrows"
- 		Array with: 16r2200 with: 16r22FF. "math operators"
- 		Array with: 16r2300 with: 16r23FF. "misc tech"
- 		Array with: 16r2460 with: 16r24FF. "enclosed alnum"
- 		Array with: 16r2500 with: 16r257F. "box drawing"
- 		Array with: 16r2580 with: 16r259F. "box elem"
- 		Array with: 16r25A0 with: 16r25FF. "geometric shapes"
- 		Array with: 16r2600 with: 16r26FF. "misc symbols"
- 		Array with: 16r2700 with: 16r27BF. "dingbats"
- 		Array with: 16r27C0 with: 16r27EF. "misc math A"
- 		Array with: 16r27F0 with: 16r27FF. "supplimental arrow A"
- 		Array with: 16r2900 with: 16r297F. "supplimental arrow B"
- 		Array with: 16r2980 with: 16r29FF. "misc math B"
- 		Array with: 16r2A00 with: 16r2AFF. "supplimental math op"
- 		Array with: 16r2900 with: 16r297F. "supplimental arrow B"
- 		Array with: 16r2E80 with: 16r2EFF. "cjk radicals suppliment"
- 		Array with: 16r2F00 with: 16r2FDF. "kangxi radicals"
- 		Array with: 16r3000 with: 16r303F. "cjk symbols"
- 		Array with: 16r3040 with: 16r309F. "hiragana"
- 		Array with: 16r30A0 with: 16r30FF. "katakana"
- 		Array with: 16r3190 with: 16r319F. "kanbun"
- 		Array with: 16r31F0 with: 16r31FF. "katakana extension"
- 		Array with: 16r3200 with: 16r32FF. "enclosed CJK"
- 		Array with: 16r3300 with: 16r33FF. "CJK compatibility"
- 		Array with: 16r3400 with: 16r4DBF. "CJK unified extension A"
- 		Array with: 16r4E00 with: 16r9FAF. "CJK ideograph"
- 		Array with: 16rF900 with: 16rFAFF. "CJK compatiblity ideograph"
- 		Array with: 16rFE30 with: 16rFE4F. "CJK compatiblity forms"
- 		Array with: 16rFF00 with: 16rFFEF. "half and full"
- 	}.
- 
- 	^ basics, etc.
- !

Item was removed:
- ----- Method: HostFont class>>textStyleFrom: (in category 'accessing') -----
- textStyleFrom: fontName
- 	"HostFont textStyleFromUser"
- 	| styleName fonts |
- 	styleName := fontName asSymbol.
- 	"(TextConstants includesKey: styleName)
- 		ifTrue:[(self confirm: 
- styleName , ' is already defined in TextConstants.
- Do you want to replace that definition?')
- 			ifFalse: [^ self]]."
- 	fonts := #(10 11 12 13 14 16 18 20 22 24 26 28 30 36 48 60 72 90).
- 	('Rendering ', styleName) displayProgressFrom: 1 to: fonts size during:[:bar|
- 			fonts := fonts
- 				collect:[:ptSize| bar value: (fonts indexOf: ptSize).
- 							   self fontName: styleName 
- 									size: ptSize
- 									emphasis: 0]
- 				thenSelect:[:font| font notNil]]. "reject those that failed"
- 	fonts size = 0 ifTrue:[^self error:'Could not create font style', styleName].
- 	TextConstants
- 		at: styleName
- 		put: (TextStyle fontArray: fonts).!

Item was removed:
- ----- Method: HostFont class>>textStyleFrom:sizes: (in category 'accessing') -----
- textStyleFrom: fontName sizes: ptSizes
- 	| styleName fonts |
- 	styleName := fontName asSymbol.
- 	(TextConstants includesKey: styleName)
- 		ifTrue:[(self confirm: 
- styleName , ' is already defined in TextConstants.
- Do you want to replace that definition?')
- 			ifFalse: [^ self]].
- 	('Rendering ', styleName) displayProgressFrom: 1 to: ptSizes size during:[:bar|
- 			fonts := ptSizes
- 				collect:[:ptSize| bar value: (ptSizes indexOf: ptSize).
- 							   self fontName: styleName 
- 									size: ptSize
- 									emphasis: 0]
- 				thenSelect:[:font| font notNil]]. "reject those that failed"
- 	fonts size = 0 ifTrue:[^self error:'Could not create font style', styleName].
- 	TextConstants
- 		at: styleName
- 		put: (TextStyle fontArray: fonts).!

Item was removed:
- ----- Method: HostFont class>>textStyleFrom:sizes:ranges: (in category 'accessing') -----
- textStyleFrom: fontName sizes: ptSizes ranges: ranges
- 	| styleName fonts |
- 	styleName := fontName asSymbol.
- 	(TextConstants includesKey: styleName)
- 		ifTrue:[(self confirm: 
- styleName , ' is already defined in TextConstants.
- Do you want to replace that definition?')
- 			ifFalse: [^ self]].
- 	('Rendering ', styleName) displayProgressFrom: 1 to: ptSizes size during:[:bar|
- 			fonts := ptSizes
- 				collect:[:ptSize| bar value: (ptSizes indexOf: ptSize).
- 							   self fontName: styleName 
- 									size: ptSize
- 									emphasis: 0 rangesArray: ranges
- 				]
- 				thenSelect:[:font| font notNil]]. "reject those that failed"
- 	fonts size = 0 ifTrue:[^self error:'Could not create font style', styleName].
- 	TextConstants
- 		at: styleName
- 		put: (TextStyle fontArray: fonts).!

Item was removed:
- ----- Method: HostFont class>>textStyleFromUser (in category 'accessing') -----
- textStyleFromUser
- 	"HostFont textStyleFromUser"
- 	| styleName fonts |
- 	styleName := self fontNameFromUser ifNil:[^self].
- 	styleName := styleName asSymbol.
- 	(TextConstants includesKey: styleName)
- 		ifTrue:[(self confirm: 
- styleName , ' is already defined in TextConstants.
- Do you want to replace that definition?')
- 			ifFalse: [^ self]].
- 	fonts := #(10 12 14 16 18 20 22 24 26 28 30 36 48 60 72 90).
- 	('Rendering ', styleName) displayProgressFrom: 1 to: fonts size during:[:bar|
- 			fonts := fonts
- 				collect:[:ptSize| bar value: (fonts indexOf: ptSize).
- 							   self fontName: styleName 
- 									size: ptSize
- 									emphasis: 0]
- 				thenSelect:[:font| font notNil]]. "reject those that failed"
- 	fonts size = 0 ifTrue:[^self error:'Could not create font style', styleName].
- 	TextConstants
- 		at: styleName
- 		put: (TextStyle fontArray: fonts).!

Item was removed:
- ----- Method: HostFont>>baseKern (in category 'accessing') -----
- baseKern
- 	^0!

Item was removed:
- ----- Method: HostFont>>createCharacterToGlyphMap (in category 'accessing') -----
- createCharacterToGlyphMap
- 
- 	^ IdentityGlyphMap new.
- !

Item was removed:
- ----- Method: HostFont>>descentKern (in category 'accessing') -----
- descentKern
- 	^0!

Item was removed:
- ----- Method: HostFont>>displayString:on:from:to:at:kern: (in category 'accessing') -----
- displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta 
- 
- 	^ self displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: aPoint y + self ascent.
- !

Item was removed:
- ----- Method: HostFont>>displayString:on:from:to:at:kern:baselineY: (in category 'accessing') -----
- displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY
- 
-  	^ super displayMultiString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY.
- !

Item was removed:
- ----- Method: HostFont>>emphasized: (in category 'emphasis') -----
- emphasized: code
- 	| derivative addedEmphasis base safeCode |
- 	code = 0 ifTrue: [^ self].
- 	derivativeFonts == nil ifTrue:[derivativeFonts := Array new: 32].
- 	derivative := derivativeFonts at: (safeCode := code min: derivativeFonts size).
- 	derivative == nil ifFalse: [^ derivative].  "Already have this style"
- 
- 	"Dont have it -- derive from another with one with less emphasis"
- 	addedEmphasis := 1 bitShift: safeCode highBit - 1.
- 	base := self emphasized: safeCode - addedEmphasis.  "Order is Bold, Ital, Under, Narrow"
- 	addedEmphasis = 1 ifTrue:   "Compute synthetic bold version of the font"
- 		[derivative := (base copy name: base name) makeBoldGlyphs].
- 	addedEmphasis = 2 ifTrue:   "Compute synthetic italic version of the font"
- 		[ derivative := (base copy name: base name) makeItalicGlyphs].
- 	addedEmphasis = 4 ifTrue:   "Compute underlined version of the font"
- 		[derivative := (base copy name: base name) makeUnderlinedGlyphs].
- 	addedEmphasis = 8 ifTrue:   "Compute narrow version of the font"
- 		[derivative := (base copy name: base name) makeCondensedGlyphs].
- 	addedEmphasis = 16 ifTrue:   "Compute struck-out version of the font"
- 		[derivative := (base copy name: base name) makeStruckOutGlyphs].
- 	derivative emphasis: safeCode.
- 	derivativeFonts at: safeCode put: derivative.
- 	^ derivative!

Item was removed:
- ----- Method: HostFont>>fontName:size:emphasis: (in category 'private-creation') -----
- fontName: fontName size: ptSize emphasis: emphasisCode
- 
- 	^ self fontName: fontName size: ptSize emphasis: emphasisCode rangesArray: (Array with: (Array with: 0 with: 255)).
- !

Item was removed:
- ----- Method: HostFont>>fontName:size:emphasis:rangesArray: (in category 'private-creation') -----
- fontName: fontName size: ptSize emphasis: emphasisCode rangesArray: rangesArray
- 	"
- 		^HostFont fontName: ('MS UI Gothic') size: 12 emphasis: 0 rangesArray: EFontBDFFontReaderForRanges basicNew rangesForJapanese.
- 	"
- 	| fontHandle xStart w glyphForm fontHeight fw enc rangesStream currentRange |
- 	fontHandle := self primitiveCreateFont: fontName size: ptSize emphasis: emphasisCode.
- 	fontHandle ifNil:[^nil].
- 	ranges := rangesArray.
- 	ranges ifNil: [ranges := Array with: (Array with: 0 with: 255)].
- 	pointSize := ptSize.
- 	name := fontName.
- 	emphasis := emphasisCode.
- 	minAscii := 0.
- 	maxAscii := ranges last last.
- 	ascent := self primitiveFontAscent: fontHandle.
- 	descent := self primitiveFontDescent: fontHandle.
- 	kernPairs := Array new: (self primitiveFontNumKernPairs: fontHandle).
- 	1 to: kernPairs size do:[:i|
- 		kernPairs at: i put: (self primitiveFont: fontHandle getKernPair: i)].
- 	fontHeight := ascent + descent.
- 	xTable := Array new: maxAscii + 3.
- 	fullWidth := Array new: maxAscii + 1.
- 	xStart := maxWidth := 0.
- 	rangesStream := ReadStream on: (ranges collect: [:e | (e first to: e second)]).
- 	currentRange := rangesStream next.
- 	0 to: maxAscii do:[:i|
- 		xTable at: i+1 put: xStart.
- 		i > currentRange last ifTrue: [
- 			[rangesStream atEnd not and: [currentRange := rangesStream next. currentRange last < i]] whileTrue.
- 			rangesStream atEnd ifTrue: [].
- 		].
- 		(currentRange includes: i) ifTrue: [
- 			xTable at: i+1 put: xStart.
- 			fw := self primitiveFont: fontHandle fullWidthOfChar: i.
- 			(#(	1 "anchored morph"
- 				9 "tab"
- 				10 "LF"
- 				13 "CR"
- 			) includes: i) ifTrue:[fw := {0. 0. 0}].
- 			fullWidth at: i+1 put: fw.
- 			w := fw at: 2.
- 			(fw at: 1) > 0 ifTrue:[w := w + (fw at: 1)].
- 			(fw at: 3) > 0 ifTrue:[w := w + (fw at: 3)].
- 			w > maxWidth ifTrue:[maxWidth := w].
- 			xStart := xStart + w].
- 		].
- 	xStart = 0 ifTrue:[^nil].
- 	strikeLength := xStart.
- 	xTable at: maxAscii+1 put: xStart.
- 	xTable at: maxAscii+2 put: xStart.
- 	xTable at: maxAscii+3 put: xStart.
- 	glyphs := Form extent: xTable last @ fontHeight depth: 1.
- 	glyphForm := Form extent: maxWidth @ fontHeight depth: 1.
- 	0 to: maxAscii do:[:i|
- 		glyphForm fillWhite.
- 		self primitiveFont: fontHandle glyphOfChar: i into: glyphForm.
- 		xStart := xTable at: i+1.
- 		glyphForm displayOn: glyphs at: xStart at 0.
- 		"glyphForm displayOn: Display at: xStart at 0."
- 	].
- 	enc := self primitiveFontEncoding: fontHandle.
- 	enc = 1 ifTrue:[characterToGlyphMap := self isoToSqueakMap].
- 	self primitiveDestroyFont: fontHandle.
- 	^self!

Item was removed:
- ----- Method: HostFont>>getFontData (in category 'accessing') -----
- getFontData
- 	| fontHandle bufSize buffer |
- 	fontHandle := self primitiveCreateFont: name size: pointSize emphasis: emphasis.
- 	fontHandle ifNil:[^nil].
- 	bufSize := self primitiveFontDataSize: fontHandle.
- 	buffer := ByteArray new: bufSize.
- 	self primitiveFont: fontHandle getData: buffer.
- 	^buffer!

Item was removed:
- ----- Method: HostFont>>isoToSqueakMap (in category 'private-creation') -----
- isoToSqueakMap
- 	^nil
- !

Item was removed:
- ----- Method: HostFont>>makeBoldGlyphs (in category 'emphasis') -----
- makeBoldGlyphs
- 	"First check if we can use some OS support for this"
- 	(self class listFontNames includes: name) ifFalse:[^super makeBoldGlyphs].
- 	"Now attempt a direct creation through the appropriate primitives"
- 	(self fontName: name size: pointSize emphasis: (emphasis bitOr: 1) rangesArray: ranges) 
- 		ifNil:[^super makeBoldGlyphs]. "nil means we failed"!

Item was removed:
- ----- Method: HostFont>>makeItalicGlyphs (in category 'emphasis') -----
- makeItalicGlyphs
- 	"First check if we can use some OS support for this"
- 	(self class listFontNames includes: name) ifFalse:[^super makeItalicGlyphs].
- 	"Now attempt a direct creation through the appropriate primitives"
- 	(self fontName: name size: pointSize emphasis: (emphasis bitOr: 2) rangesArray: ranges)
- 		ifNil:[^super makeItalicGlyphs]. "nil means we failed"!

Item was removed:
- ----- Method: HostFont>>makeStruckOutGlyphs (in category 'emphasis') -----
- makeStruckOutGlyphs
- 	"First check if we can use some OS support for this"
- 	(self class listFontNames includes: name) ifFalse:[^super makeStruckOutGlyphs].
- 	"Now attempt a direct creation through the appropriate primitives"
- 	(self fontName: name size: pointSize emphasis: (emphasis bitOr: 8) rangesArray: ranges)
- 		ifNil:[^super makeStruckOutGlyphs]. "nil means we failed"!

Item was removed:
- ----- Method: HostFont>>makeUnderlinedGlyphs (in category 'emphasis') -----
- makeUnderlinedGlyphs
- 	"First check if we can use some OS support for this"
- 	(self class listFontNames includes: name) ifFalse:[^super makeUnderlinedGlyphs].
- 	"Now attempt a direct creation through the appropriate primitives"
- 	(self fontName: name size: pointSize emphasis: (emphasis bitOr: 4) rangesArray: ranges)
- 		ifNil:[^super makeUnderlinedGlyphs]. "nil means we failed"!

Item was removed:
- ----- Method: HostFont>>primitiveCreateFont:size:emphasis: (in category 'primitives') -----
- primitiveCreateFont: fontName size: fontSize emphasis: fontFlags
- 	<primitive:'primitiveCreateFont' module:'FontPlugin'>
- 	^nil!

Item was removed:
- ----- Method: HostFont>>primitiveDestroyFont: (in category 'primitives') -----
- primitiveDestroyFont: fontHandle
- 	<primitive:'primitiveDestroyFont' module:'FontPlugin'>
- 	^self primitiveFailed!

Item was removed:
- ----- Method: HostFont>>primitiveFont:fullWidthOfChar: (in category 'primitives') -----
- primitiveFont: fontHandle fullWidthOfChar: aCharIndex 
- 	<primitive:'primitiveFontFullWidthOfChar' module:'FontPlugin'>
- 	^Array 
- 		with: 0
- 		with: (self primitiveFont: fontHandle widthOfChar: aCharIndex)
- 		with: 0!

Item was removed:
- ----- Method: HostFont>>primitiveFont:getData: (in category 'primitives') -----
- primitiveFont: fontHandle getData: buffer
- 	<primitive:'primitiveGetFontData' module:'FontPlugin'>
- 	^self primitiveFailed!

Item was removed:
- ----- Method: HostFont>>primitiveFont:getKernPair: (in category 'primitives') -----
- primitiveFont: fontHandle getKernPair: kernIndex
- 	<primitive:'primitiveFontGetKernPair' module:'FontPlugin'>
- 	^0!

Item was removed:
- ----- Method: HostFont>>primitiveFont:glyphOfChar:into: (in category 'primitives') -----
- primitiveFont: fontHandle glyphOfChar: aCharIndex into: glyphForm 
- 	<primitive:'primitiveFontGlyphOfChar' module:'FontPlugin'>
- 	^self primitiveFailed!

Item was removed:
- ----- Method: HostFont>>primitiveFont:widthOfChar: (in category 'primitives') -----
- primitiveFont: fontHandle widthOfChar: aCharIndex 
- 	<primitive:'primitiveFontWidthOfChar' module:'FontPlugin'>
- 	^self primitiveFailed!

Item was removed:
- ----- Method: HostFont>>primitiveFontAscent: (in category 'primitives') -----
- primitiveFontAscent: fontHandle
- 	<primitive:'primitiveFontAscent' module:'FontPlugin'>
- 	^self primitiveFailed!

Item was removed:
- ----- Method: HostFont>>primitiveFontDataSize: (in category 'primitives') -----
- primitiveFontDataSize: fontHandle
- 	<primitive:'primitiveFontDataSize' module:'FontPlugin'>
- 	^self primitiveFailed!

Item was removed:
- ----- Method: HostFont>>primitiveFontDescent: (in category 'primitives') -----
- primitiveFontDescent: fontHandle
- 	<primitive:'primitiveFontDescent' module:'FontPlugin'>
- 	^self primitiveFailed!

Item was removed:
- ----- Method: HostFont>>primitiveFontEmbeddingFlags: (in category 'primitives') -----
- primitiveFontEmbeddingFlags: fontHandle
- 	<primitive:'primitiveFontEmbeddingFlags' module:'FontPlugin'>
- 	^self primitiveFailed!

Item was removed:
- ----- Method: HostFont>>primitiveFontEncoding: (in category 'primitives') -----
- primitiveFontEncoding: fontHandle
- 	<primitive:'primitiveFontEncoding' module:'FontPlugin'>
- 	^self primitiveFailed!

Item was removed:
- ----- Method: HostFont>>primitiveFontNumKernPairs: (in category 'primitives') -----
- primitiveFontNumKernPairs: fontHandle
- 	<primitive:'primitiveFontNumKernPairs' module:'FontPlugin'>
- 	^0!

Item was removed:
- ----- Method: HostFont>>testEmbeddingFlags (in category 'accessing') -----
- testEmbeddingFlags
- 	"HostFont basicNew testEmbeddingFlags"
- 	| list |
- 	list := self class listFontNames.
- 	list do:[:fName| | fontHandle |
- 		fontHandle := self primitiveCreateFont: fName size: 12 emphasis: 0.
- 		fontHandle ifNotNil:[
- 			type := self primitiveFontEmbeddingFlags: fontHandle.
- 			Transcript cr; show: fName,': ', type printString.
- 			self primitiveDestroyFont: fontHandle.
- 		].
- 	].!

Item was removed:
- Object subclass: #HostWindowProxy
- 	instanceVariableNames: 'windowHandle sourceForm'
- 	classVariableNames: 'ActiveProxyClass Registry'
- 	poolDictionaries: ''
- 	category: 'Graphics-External-Ffenestri'!
- 
- !HostWindowProxy commentStamp: 'bf 1/4/2012 18:37' prior: 0!
- This is a proxy for a Host OS window and as such is considered a disposable item. When an image is restarted the client must recreate suitable instances from the information they hold. Platform specific subclasses are available to translate abstract requirements into possible platform concrete data.
- There is a registry of instances so that when users let go they can be guaranteed to close down properly. Because the instances point to the source Form in use this can on occasion result in a cycle that defeats the Weak mechanism - hence the implementation of #executor & #asExecutor.
- The only requirements placed on the sourceForm instvar are those of being like a DisplayScreen - can return a bits array, the width, depth etc PLUS implement processEvent: AND able to respond to #resetProxy to remove and rebuild the window proxy!

Item was removed:
- ----- Method: HostWindowProxy class>>activeWindowProxyClass (in category 'system startup') -----
- activeWindowProxyClass
- 	"Return the concrete HostWindowProxy subclass for the platform on which we are
- currently running."
- 
- 	HostWindowProxy allSubclasses do: [:class |
- 		class isActiveHostWindowProxyClass ifTrue: [^ class]].
- 
- 	"no responding subclass; use HostWindowProxy"
- 	^ HostWindowProxy
- !

Item was removed:
- ----- Method: HostWindowProxy class>>initialize (in category 'class initialization') -----
- initialize
- "Add me to the system startup list and make sure to do a file-in init for first time loading"
- "HostWindowProxy initialize"
- 	self setDefaultWindowProxyClass.
- 	Smalltalk addToStartUpList: self.!

Item was removed:
- ----- Method: HostWindowProxy class>>isActiveHostWindowProxyClass (in category 'system startup') -----
- isActiveHostWindowProxyClass
- "subclasses must override this"
- 	self subclassResponsibility!

Item was removed:
- ----- Method: HostWindowProxy class>>on: (in category 'initialize-release') -----
- on: aSourceForm
- "Build a new window proxy by finding the appropriate platform specific subclass
- and setting it up for this Form-like argument"
- 	^ActiveProxyClass new on: aSourceForm!

Item was removed:
- ----- Method: HostWindowProxy class>>processEvent: (in category 'events') -----
- processEvent: evt
- 	"evt is a raw event buffer from VM. Pass it on to the appropiate proxy."
- 	self registry keys do: [:proxy |
- 		(proxy wantsEvent: evt) ifTrue: [proxy processEvent: evt]].
- !

Item was removed:
- ----- Method: HostWindowProxy class>>register: (in category 'registry') -----
- register: anObject
- "boilerplate WeakRegistry usage"
- 	^self registry add: anObject!

Item was removed:
- ----- Method: HostWindowProxy class>>registry (in category 'registry') -----
- registry
- "boilerplate WeakRegistry usage"
- 	^Registry ifNil: [Registry := WeakRegistry new]!

Item was removed:
- ----- Method: HostWindowProxy class>>setDefaultWindowProxyClass (in category 'system startup') -----
- setDefaultWindowProxyClass
- 	"connect to the proper platform subclass of proxy"
- 	ActiveProxyClass := self activeWindowProxyClass!

Item was removed:
- ----- Method: HostWindowProxy class>>startUp: (in category 'system startup') -----
- startUp: resuming
- 	resuming ifFalse: [^self].
- 	"system startup - find the appropriate proxy class for this platform"
- 	self setDefaultWindowProxyClass.
- 	"any currently extant instances must tell their sourceForm to resetProxy in order to kill potentially wrong-platform versions and reset to correct-platform"
- 	self registry keys do: [:i | i resetProxy]!

Item was removed:
- ----- Method: HostWindowProxy class>>unregister: (in category 'registry') -----
- unregister: anObject
- "boilerplate WeakRegistry usage"
- 	^self registry remove: anObject ifAbsent:[]!

Item was removed:
- ----- Method: HostWindowProxy>>asExecutor (in category 'finalization') -----
- asExecutor
- 	sourceForm := nil!

Item was removed:
- ----- Method: HostWindowProxy>>attributes (in category 'window decorations') -----
- attributes
- "return the ByteArray representing the desired window attributes. This is utterly platform dependent and my default is an empty ByteArray to signify a default window"
- 	^ByteArray new!

Item was removed:
- ----- Method: HostWindowProxy>>bits (in category 'metrics') -----
- bits
- "return the bits - normally of the sourceForm"
- 	^sourceForm bits!

Item was removed:
- ----- Method: HostWindowProxy>>close (in category 'initialize-release') -----
- close
- 	"close this window"
- 	windowHandle ifNil: [^self].
- 	self unregister.
- 	self primitiveWindowClose: windowHandle.
- 	windowHandle := nil.
- !

Item was removed:
- ----- Method: HostWindowProxy>>defaultWindowType (in category 'window decorations') -----
- defaultWindowType
- "set up my attributes to be a default window - a titlebar, usual decorations etc"
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: HostWindowProxy>>depth (in category 'metrics') -----
- depth
- "return the depth - normally of the sourceForm"
- 	^sourceForm depth!

Item was removed:
- ----- Method: HostWindowProxy>>executor (in category 'finalization') -----
- executor
- 	^self shallowCopy asExecutor!

Item was removed:
- ----- Method: HostWindowProxy>>finalize (in category 'finalization') -----
- finalize
- 	"close this window"
- 	self close!

Item was removed:
- ----- Method: HostWindowProxy>>forceToScreen: (in category 'window manipulation') -----
- forceToScreen: damageRectangle 
- 	"update the area of the sourceForm defined by damageRectangle"
- 	self
- 		primitiveUpdateHostWindow: windowHandle
- 		bitmap: self bits
- 		width: self width
- 		height: self height
- 		depth: self depth
- 		left: damageRectangle left
- 		right: damageRectangle right
- 		top: damageRectangle top
- 		bottom: damageRectangle bottom!

Item was removed:
- ----- Method: HostWindowProxy>>height (in category 'metrics') -----
- height
- "return the height - normally of the sourceForm"
- 	^sourceForm height!

Item was removed:
- ----- Method: HostWindowProxy>>isOpen (in category 'accessing') -----
- isOpen
- "am I already opened?"
- 	^windowHandle notNil!

Item was removed:
- ----- Method: HostWindowProxy>>offset (in category 'metrics') -----
- offset
- "return the offset - normally of the sourceForm"
- 	^sourceForm offset!

Item was removed:
- ----- Method: HostWindowProxy>>on: (in category 'initialize-release') -----
- on: aSourceForm 
- 	"set my sourceForm; usually an actual Form but so long as methods like bits, height etc work, it can be anything"
- 	sourceForm := aSourceForm!

Item was removed:
- ----- Method: HostWindowProxy>>open (in category 'initialize-release') -----
- open
- 	"open a host window built around my position, size and bitmap"
- 	windowHandle
- 		ifNil: [sourceForm
- 				ifNotNil:[windowHandle := self
- 						primitiveCreateHostWindowWidth: self width
- 						height: self height
- 						originX: self offset x
- 						y: self offset y
- 						attributes: self attributes.
- 						windowHandle ifNotNil:[self register].
- 						^windowHandle]]!

Item was removed:
- ----- Method: HostWindowProxy>>primitiveCreateHostWindowWidth:height:originX:y:attributes: (in category 'system primitives') -----
- primitiveCreateHostWindowWidth: w height: h originX: x y: y attributes: list
- "create and open a host window. list is a ByteArray list of window attributes in some platform manner. See subclasses for information"
- 	<primitive: 'primitiveCreateHostWindow' module: 'HostWindowPlugin'>
- 	^self error: 'Unable to create Host Window'!

Item was removed:
- ----- Method: HostWindowProxy>>primitiveUpdateHostWindow:bitmap:width:height:depth:left:right:top:bottom: (in category 'system primitives') -----
- primitiveUpdateHostWindow: id bitmap: bitmap width: w height: h depth: d left: l
- right: r top: t bottom: b 
- 	"Force the pixels to the screen. The bitmap details and affected area are given
- explicitly to avoid dependence upon any object structure"
- 	<primitive: 'primitiveShowHostWindowRect' module:'HostWindowPlugin'>
- 	^self windowProxyError: 'update'!

Item was removed:
- ----- Method: HostWindowProxy>>primitiveWindowClose: (in category 'system primitives') -----
- primitiveWindowClose: id
- "Close the window"
- 	<primitive: 'primitiveCloseHostWindow' module: 'HostWindowPlugin'>
- 	^self windowProxyError: 'close'!

Item was removed:
- ----- Method: HostWindowProxy>>primitiveWindowPosition: (in category 'system primitives') -----
- primitiveWindowPosition: id
- "Find the topleft corner of the window"
- 	<primitive: 'primitiveHostWindowPosition' module: 'HostWindowPlugin'>
- 	^self windowProxyError: 'get position'!

Item was removed:
- ----- Method: HostWindowProxy>>primitiveWindowPosition:x:y: (in category 'system primitives') -----
- primitiveWindowPosition: id x: x y: y
- "Set the topleft corner of the window - return what is actually set"
- 	<primitive: 'primitiveHostWindowPositionSet' module: 'HostWindowPlugin'>
- 	^self windowProxyError: 'set position'!

Item was removed:
- ----- Method: HostWindowProxy>>primitiveWindowSize: (in category 'system primitives') -----
- primitiveWindowSize: id
- "Find the size of the window, just like primitiveScreenSize"
- 	<primitive: 'primitiveHostWindowSize' module: 'HostWindowPlugin'>
- 	^self windowProxyError: 'get size'!

Item was removed:
- ----- Method: HostWindowProxy>>primitiveWindowSize:x:y: (in category 'system primitives') -----
- primitiveWindowSize: id x: x y: y
- "Set the size of the window, just like primitiveScreenSize. Return the actually
- achieved size"
- 	<primitive: 'primitiveHostWindowSizeSet' module: 'HostWindowPlugin'>
- 	^self windowProxyError: 'set size'!

Item was removed:
- ----- Method: HostWindowProxy>>primitiveWindowTitle:string: (in category 'system primitives') -----
- primitiveWindowTitle: id string: titleString
- "Set the label of the title bar of the window"
- 	<primitive: 'primitiveHostWindowTitle' module: 'HostWindowPlugin'>
- 	^self error: 'Unable to set title of Host Window'!

Item was removed:
- ----- Method: HostWindowProxy>>printOn: (in category 'printing') -----
- printOn: aStream
- 	super printOn:aStream.
- 	aStream nextPutAll: ' (windowIndex '.
- 	windowHandle printOn: aStream.
- 	aStream nextPut: $)!

Item was removed:
- ----- Method: HostWindowProxy>>processEvent: (in category 'events') -----
- processEvent: evt
- 	"evt is a raw event buffer from VM. delegate to client window"
- 	sourceForm processEvent: evt!

Item was removed:
- ----- Method: HostWindowProxy>>recreate (in category 'window manipulation') -----
- recreate
- "something has changed that require deleting the host window before opening it
- with new attributes"
- 	self close; open!

Item was removed:
- ----- Method: HostWindowProxy>>register (in category 'finalization') -----
- register
- 	^self class register: self!

Item was removed:
- ----- Method: HostWindowProxy>>resetProxy (in category 'finalization') -----
- resetProxy
- "tell my sourceForm to kill me (gulp) and resurrect me in the correct clothing"
- 	sourceForm ifNotNil:[ sourceForm resetProxy]!

Item was removed:
- ----- Method: HostWindowProxy>>unregister (in category 'finalization') -----
- unregister
- 	^self class unregister: self!

Item was removed:
- ----- Method: HostWindowProxy>>wantsEvent: (in category 'events') -----
- wantsEvent: evt
- 	"evt is a raw event buffer from VM. check if its window field matches ours"
- 	^ windowHandle = (evt at: 8)!

Item was removed:
- ----- Method: HostWindowProxy>>width (in category 'metrics') -----
- width
- "return the width - normally of the sourceForm"
- 	^sourceForm width!

Item was removed:
- ----- Method: HostWindowProxy>>windowPosition (in category 'window manipulation') -----
- windowPosition
- 	"return the current position of the window"
- 		^self primitiveWindowPosition: windowHandle!

Item was removed:
- ----- Method: HostWindowProxy>>windowPosition: (in category 'window manipulation') -----
- windowPosition: aPoint
- 	"set the position of the window and then return the new position"
- 		^self primitiveWindowPosition: windowHandle x: aPoint x y: aPoint y!

Item was removed:
- ----- Method: HostWindowProxy>>windowProxyError: (in category 'accessing') -----
- windowProxyError: problemString
- 	"Could be useful to raise an exception but not yet"!

Item was removed:
- ----- Method: HostWindowProxy>>windowSize (in category 'window manipulation') -----
- windowSize
- 	"return the current size of the window "
- 		^self primitiveWindowSize: windowHandle!

Item was removed:
- ----- Method: HostWindowProxy>>windowSize: (in category 'window manipulation') -----
- windowSize: aPoint
- 	"Set the size of the window and then return the actually set size of the window - not neccessarily the same "
- 		^self primitiveWindowSize: windowHandle x: aPoint x y: aPoint y!

Item was removed:
- ----- Method: HostWindowProxy>>windowTitle: (in category 'window manipulation') -----
- windowTitle: titleString
- "set the label in the window titlebar to titleString"
- 	^self primitiveWindowTitle: windowHandle string: titleString squeakToUtf8!

Item was removed:
- Object subclass: #IdentityGlyphMap
- 	instanceVariableNames: ''
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Fonts'!

Item was removed:
- ----- Method: IdentityGlyphMap>>at: (in category 'accessing') -----
- at: index
- 
- 	^ index - 1.
- !

Item was removed:
- DisplayTransform subclass: #IdentityTransform
- 	instanceVariableNames: ''
- 	classVariableNames: 'Default'
- 	poolDictionaries: ''
- 	category: 'Graphics-Transformations'!

Item was removed:
- ----- Method: IdentityTransform class>>initialize (in category 'class initialization') -----
- initialize
- 	"IdentityTransform initialize"
- 	Default := self basicNew.!

Item was removed:
- ----- Method: IdentityTransform class>>new (in category 'instance creation') -----
- new
- 	"There can be only one"
- 	^Default!

Item was removed:
- ----- Method: IdentityTransform>>angle (in category 'accessing') -----
- angle
- 	^ 0.0!

Item was removed:
- ----- Method: IdentityTransform>>asMatrixTransform2x3 (in category 'converting') -----
- asMatrixTransform2x3
- 	"Represent the receiver as a 2x3 matrix transformation"
- 	^MatrixTransform2x3 identity!

Item was removed:
- ----- Method: IdentityTransform>>composedWith: (in category 'composing') -----
- composedWith: aTransform
- 	^aTransform!

Item was removed:
- ----- Method: IdentityTransform>>composedWithGlobal: (in category 'composing') -----
- composedWithGlobal: aTransformation
- 	^aTransformation!

Item was removed:
- ----- Method: IdentityTransform>>composedWithLocal: (in category 'composing') -----
- composedWithLocal: aTransformation
- 	^aTransformation!

Item was removed:
- ----- Method: IdentityTransform>>globalBoundsToLocal: (in category 'transforming rects') -----
- globalBoundsToLocal: aRectangle
- 	"Transform aRectangle from global coordinates into local coordinates"
- 	^aRectangle!

Item was removed:
- ----- Method: IdentityTransform>>globalPointToLocal: (in category 'transforming points') -----
- globalPointToLocal: aPoint
- 	"Transform aPoint from global coordinates into local coordinates"
- 	^aPoint!

Item was removed:
- ----- Method: IdentityTransform>>globalPointsToLocal: (in category 'transforming points') -----
- globalPointsToLocal: inArray
- 	"Transform all the points of inArray from global into local coordinates"
- 	^inArray!

Item was removed:
- ----- Method: IdentityTransform>>inverseTransformation (in category 'accessing') -----
- inverseTransformation
- 	"Return the inverse transformation of the receiver"
- 	^self!

Item was removed:
- ----- Method: IdentityTransform>>invertBoundsRect: (in category 'transforming points') -----
- invertBoundsRect: aRectangle
- 	"Return a rectangle whose coordinates have been transformed
- 	from local back to global coordinates. Since I am the identity matrix
- 	no transformation is made."
- 
- 	^aRectangle
- !

Item was removed:
- ----- Method: IdentityTransform>>isIdentity (in category 'testing') -----
- isIdentity
- 	"Return true if the receiver is the identity transform; that is, if applying to a point returns the point itself."
- 	^true!

Item was removed:
- ----- Method: IdentityTransform>>isPureTranslation (in category 'testing') -----
- isPureTranslation
- 	"Return true if the receiver specifies no rotation or scaling."
- 	^true!

Item was removed:
- ----- Method: IdentityTransform>>localBoundsToGlobal: (in category 'transforming rects') -----
- localBoundsToGlobal: aRectangle
- 	"Transform aRectangle from local coordinates into global coordinates"
- 	^aRectangle!

Item was removed:
- ----- Method: IdentityTransform>>localPointToGlobal: (in category 'transforming points') -----
- localPointToGlobal: aPoint
- 	"Transform aPoint from local coordinates into global coordinates"
- 	^aPoint!

Item was removed:
- ----- Method: IdentityTransform>>localPointsToGlobal: (in category 'transforming points') -----
- localPointsToGlobal: inArray
- 	"Transform all the points of inArray from local into global coordinates"
- 	^inArray!

Item was removed:
- ----- Method: IdentityTransform>>setIdentity (in category 'initialize') -----
- setIdentity
- 	"I *am* the identity transform"
- 	^self!

Item was removed:
- ----- Method: IdentityTransform>>sourceQuadFor: (in category 'transforming rects') -----
- sourceQuadFor: aRectangle
- 	^ aRectangle innerCorners!

Item was removed:
- Object subclass: #ImageReadWriter
- 	instanceVariableNames: 'stream'
- 	classVariableNames: 'ImageNotStoredSignal MagicNumberErrorSignal'
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!
- 
- !ImageReadWriter commentStamp: '<historical>' prior: 0!
- Copyright (c) Kazuki Yasumatsu, 1995. All rights reserved.
- 
- I am an abstract class to provide for encoding and/or decoding an image on a stream.
- 
- Instance Variables:
- 	stream		<ReadStream | WriteStream>	stream for image storages
- 
- Class Variables:
- 	ImageNotStoredSignal		<Signal>	image not stored error signal
- 	MagicNumberErrorSignal		<Signal>	magic number error signal
- 
- Subclasses must implement the following messages:
- 	accessing
- 		nextImage
- 		nextPutImage:
- 	testing
- 		canUnderstand         (added tao 10/26/97)!

Item was removed:
- ----- Method: ImageReadWriter class>>allTypicalFileExtensions (in category 'image reading/writing') -----
- allTypicalFileExtensions
- 	"Answer a collection of file extensions (lowercase) which files that my subclasses can read might commonly have"
- 	"ImageReadWriter allTypicalFileExtensions"
- 	| extensions |
- 	extensions := Set new.
- 	self allSubclassesDo: [ :cls | extensions addAll: cls typicalFileExtensions ].
- 	^extensions!

Item was removed:
- ----- Method: ImageReadWriter class>>formFromFileNamed: (in category 'image reading/writing') -----
- formFromFileNamed: fileName
- 	"Answer a ColorForm stored on the file with the given name."
- 	| stream |
- 	stream := FileStream readOnlyFileNamed: fileName.
- 	^self formFromStream: stream!

Item was removed:
- ----- Method: ImageReadWriter class>>formFromStream: (in category 'image reading/writing') -----
- formFromStream: aBinaryStream
- 	"Answer a ColorForm stored on the given stream.  closes the stream"
- 	| reader readerClass form  |
- 
- 	readerClass := self withAllSubclasses
- 		detect: [:subclass |
- 			aBinaryStream reset.
- 			subclass understandsImageFormat: aBinaryStream]
- 		ifNone: [
- 			aBinaryStream close.
- 			^self error: 'image format not recognized' translated].
- 	aBinaryStream reset.
- 	reader := readerClass new on: aBinaryStream.
- 	Cursor read showWhile: [
- 		form := reader nextImage.
- 		reader close].
- 	^ form
- !

Item was removed:
- ----- Method: ImageReadWriter class>>on: (in category 'instance creation') -----
- on: aStream
- 	"Answer an instance of the receiver for encoding and/or decoding images on the given."
- 
- 	^ self new on: aStream
- !

Item was removed:
- ----- Method: ImageReadWriter class>>putForm:onFileNamed: (in category 'image reading/writing') -----
- putForm: aForm onFileNamed: fileName
- 	"Store the given form on a file of the given name."
- 
- 	| writer theFile |
- 	theFile := FileStream newFileNamed: fileName.
- 	writer := self on: theFile binary.
- 	Cursor write showWhile: [writer nextPutImage: aForm].
- 	writer close.
- 	theFile directory setMacFileNamed: theFile localName type: '    ' creator: '    '.!

Item was removed:
- ----- Method: ImageReadWriter class>>putForm:onStream: (in category 'image reading/writing') -----
- putForm: aForm onStream: aWriteStream
- 	"Store the given form on a file of the given name."
- 
- 	| writer |
- 	writer := self on: aWriteStream.
- 	Cursor write showWhile: [writer nextPutImage: aForm].
- 	writer close.
- !

Item was removed:
- ----- Method: ImageReadWriter class>>typicalFileExtensions (in category 'image reading/writing') -----
- typicalFileExtensions
- 	"Answer a collection of file extensions (lowercase) which files that I can read might commonly have"
- 	^#()!

Item was removed:
- ----- Method: ImageReadWriter class>>understandsImageFormat: (in category 'image reading/writing') -----
- understandsImageFormat: aStream 
- 	^[(self new on: aStream) understandsImageFormat] on: Error do:[:ex| ex return: false]!

Item was removed:
- ----- Method: ImageReadWriter>>atEnd (in category 'stream access') -----
- atEnd
- 
- 	^stream atEnd!

Item was removed:
- ----- Method: ImageReadWriter>>changePadOfBits:width:height:depth:from:to: (in category 'private') -----
- changePadOfBits: bits width: width height: height depth: depth from: oldPad
- to: newPad
- 	"Change padding size of bits."
- 
- 	| srcRowByteSize dstRowByteSize newBits srcRowBase rowEndOffset |
- 	(#(8 16 32) includes: oldPad)
- 		ifFalse: [^self error: ('Invalid pad: {1}' translated format: {oldPad})].
- 	(#(8 16 32) includes: newPad)
- 		ifFalse: [^self error: ('Invalid pad: {1}' translated format: {newPad})].
- 	srcRowByteSize := width * depth + oldPad - 1 // oldPad * (oldPad / 8).
- 	srcRowByteSize * height = bits size
- 		ifFalse: [^self error: 'Incorrect bitmap array size.' translated].
- 	dstRowByteSize := width * depth + newPad - 1 // newPad * (newPad / 8).
- 	newBits := ByteArray new: dstRowByteSize * height.
- 	srcRowBase := 1.
- 	rowEndOffset := dstRowByteSize - 1.
- 	1 to: newBits size by: dstRowByteSize do:
- 		[:dstRowBase |
- 		newBits replaceFrom: dstRowBase
- 			to: dstRowBase + rowEndOffset
- 			with: bits
- 			startingAt: srcRowBase.
- 		srcRowBase := srcRowBase + srcRowByteSize].
- 	^newBits!

Item was removed:
- ----- Method: ImageReadWriter>>close (in category 'stream access') -----
- close
- 	
- 	stream close!

Item was removed:
- ----- Method: ImageReadWriter>>contents (in category 'stream access') -----
- contents
- 
- 	^stream contents!

Item was removed:
- ----- Method: ImageReadWriter>>cr (in category 'stream access') -----
- cr
- 
- 	^stream nextPut: Character cr asInteger!

Item was removed:
- ----- Method: ImageReadWriter>>hasMagicNumber: (in category 'private') -----
- hasMagicNumber: aByteArray
- 	| position |
- 	position := stream position.
- 	((stream size - position) >= aByteArray size and:
- 	[(stream next: aByteArray size)  = aByteArray])
- 		ifTrue: [^true].
- 	stream position: position.
- 	^false!

Item was removed:
- ----- Method: ImageReadWriter>>lf (in category 'stream access') -----
- lf
- 	"PPM and PBM are used LF as CR."
- 
- 	^stream nextPut: Character lf asInteger!

Item was removed:
- ----- Method: ImageReadWriter>>next (in category 'stream access') -----
- next
- 
- 	^stream next!

Item was removed:
- ----- Method: ImageReadWriter>>next: (in category 'stream access') -----
- next: size
- 
- 	^stream next: size!

Item was removed:
- ----- Method: ImageReadWriter>>nextImage (in category 'accessing') -----
- nextImage
- 	"Dencoding an image on stream and answer the image."
- 
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: ImageReadWriter>>nextLong (in category 'stream access') -----
- nextLong
- 	"Read a 32-bit quantity from the input stream."
- 
- 	^(stream next bitShift: 24) + (stream next bitShift: 16) +
- 		(stream next bitShift: 8) + stream next!

Item was removed:
- ----- Method: ImageReadWriter>>nextLongPut: (in category 'stream access') -----
- nextLongPut: a32BitW
- 	"Write out a 32-bit integer as 32 bits."
- 
- 	stream nextPut: ((a32BitW bitShift: -24) bitAnd: 16rFF).
- 	stream nextPut: ((a32BitW bitShift: -16) bitAnd: 16rFF).
- 	stream nextPut: ((a32BitW bitShift: -8) bitAnd: 16rFF).
- 	stream nextPut: (a32BitW bitAnd: 16rFF).
- 	^a32BitW!

Item was removed:
- ----- Method: ImageReadWriter>>nextPut: (in category 'stream access') -----
- nextPut: aByte
- 
- 	^stream nextPut: aByte!

Item was removed:
- ----- Method: ImageReadWriter>>nextPutAll: (in category 'stream access') -----
- nextPutAll: aByteArray
- 
- 	^stream nextPutAll: aByteArray!

Item was removed:
- ----- Method: ImageReadWriter>>nextPutImage: (in category 'accessing') -----
- nextPutImage: anImage
- 	"Encoding anImage on stream."
- 
- 	^self subclassResponsibility!

Item was removed:
- ----- Method: ImageReadWriter>>nextWord (in category 'stream access') -----
- nextWord
- 	"Read a 16-bit quantity from the input stream."
- 
- 	^(stream next bitShift: 8) + stream next!

Item was removed:
- ----- Method: ImageReadWriter>>nextWordPut: (in category 'stream access') -----
- nextWordPut: a16BitW
- 	"Write out a 16-bit integer as 16 bits."
- 
- 	stream nextPut: ((a16BitW bitShift: -8) bitAnd: 16rFF).
- 	stream nextPut: (a16BitW bitAnd: 16rFF).
- 	^a16BitW!

Item was removed:
- ----- Method: ImageReadWriter>>on: (in category 'private') -----
- on: aStream
- 	stream := aStream.
- 	stream binary.!

Item was removed:
- ----- Method: ImageReadWriter>>peekFor: (in category 'stream access') -----
- peekFor: aValue
- 
- 	^stream peekFor: aValue!

Item was removed:
- ----- Method: ImageReadWriter>>position (in category 'stream access') -----
- position
- 
- 	^stream position!

Item was removed:
- ----- Method: ImageReadWriter>>position: (in category 'stream access') -----
- position: anInteger
- 
- 	^stream position: anInteger!

Item was removed:
- ----- Method: ImageReadWriter>>size (in category 'stream access') -----
- size
- 
- 	^stream size!

Item was removed:
- ----- Method: ImageReadWriter>>skip: (in category 'stream access') -----
- skip: anInteger
- 
- 	^stream skip: anInteger!

Item was removed:
- ----- Method: ImageReadWriter>>space (in category 'stream access') -----
- space
- 
- 	^stream nextPut: Character space asInteger!

Item was removed:
- ----- Method: ImageReadWriter>>tab (in category 'stream access') -----
- tab
- 
- 	^stream nextPut: Character tab asInteger!

Item was removed:
- ----- Method: ImageReadWriter>>understandsImageFormat (in category 'testing') -----
- understandsImageFormat
- 	"Test to see if the image stream format is understood by this decoder.
- 	This should be implemented in each subclass of ImageReadWriter so that
- 	a proper decoder can be selected without ImageReadWriter having to know
- 	about all possible image file types."
- 
- 	^ false!

Item was removed:
- ----- Method: ImageReadWriter>>unpackBits:depthTo8From:with:height:pad: (in category 'private') -----
- unpackBits: bits depthTo8From: depth with: width height: height pad: pad
- 	"Unpack bits of depth 1, 2, or 4 image to it of depth 8 image."
- 
- 	| bitMask pixelInByte bitsWidth upBitsWidth stopWidth
- 	 trailingSize upBits bitIndex upBitIndex val |
- 	(#(1 2 4) includes: depth)
- 		ifFalse: [^self error: 'depth must be 1, 2, or 4' translated].
- 	(#(8 16 32) includes: pad)
- 		ifFalse: [^self error: 'pad must be 8, 16, or 32' translated].
- 	bitMask := (1 bitShift: depth) - 1.
- 	pixelInByte := 8 / depth.
- 	bitsWidth := width * depth + pad - 1 // pad * (pad / 8).
- 	upBitsWidth := width * 8 + pad - 1 // pad * (pad / 8).
- 	stopWidth := width * depth + 7 // 8.
- 	trailingSize := width - (stopWidth - 1 * pixelInByte).
- 	upBits := ByteArray new: upBitsWidth * height.
- 	1 to: height do: [:i |
- 		bitIndex := i - 1 * bitsWidth.
- 		upBitIndex := i - 1 * upBitsWidth.
- 		1 to: stopWidth - 1 do: [:j |
- 			val := bits at: (bitIndex := bitIndex + 1).
- 			upBitIndex := upBitIndex + pixelInByte.
- 			1 to: pixelInByte do: [:k |
- 				upBits at: (upBitIndex - k + 1) put: (val bitAnd: bitMask).
- 				val := val bitShift: depth negated]].
- 		val := (bits at: (bitIndex := bitIndex + 1))
- 				bitShift: depth negated * (pixelInByte - trailingSize).
- 		upBitIndex := upBitIndex + trailingSize.
- 		1 to: trailingSize do: [:k |
- 			upBits at: (upBitIndex - k + 1) put: (val bitAnd: bitMask).
- 			val := val bitShift: depth negated]].
- 	^ upBits
- !

Item was removed:
- DisplayObject subclass: #InfiniteForm
- 	instanceVariableNames: 'patternForm'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Display Objects'!
- 
- !InfiniteForm commentStamp: '<historical>' prior: 0!
- I represent a Form obtained by replicating a pattern form indefinitely in all directions.!

Item was removed:
- ----- Method: InfiniteForm class>>with: (in category 'instance creation') -----
- with: aForm 
- 	"Answer an instance of me whose pattern form is the argument, aForm."
- 
- 	^self new form: aForm!

Item was removed:
- ----- Method: InfiniteForm>>addFillStyleMenuItems:hand:from: (in category 'Morphic menu') -----
- addFillStyleMenuItems: aMenu hand: aHand from: aMorph
- 	"Add the items for changing the current fill style of the receiver"
- 
- 	"prevents a walkback when control menu is built for morph with me as color"!

Item was removed:
- ----- Method: InfiniteForm>>asColor (in category 'converting') -----
- asColor
- 	^ patternForm dominantColor!

Item was removed:
- ----- Method: InfiniteForm>>asForm (in category 'converting') -----
- asForm
- 	^ patternForm!

Item was removed:
- ----- Method: InfiniteForm>>bitPatternForDepth: (in category 'fillstyle protocol') -----
- bitPatternForDepth: suspectedDepth
- 	^ patternForm!

Item was removed:
- ----- Method: InfiniteForm>>colorForInsets (in category 'displaying') -----
- colorForInsets
- 	^ Color transparent!

Item was removed:
- ----- Method: InfiniteForm>>computeBoundingBox (in category 'display box access') -----
- computeBoundingBox 
- 	"Refer to the comment in DisplayObject|computeBoundingBox."
- 
- 	^0 @ 0 corner: SmallInteger maxVal @ SmallInteger maxVal!

Item was removed:
- ----- Method: InfiniteForm>>direction (in category 'fillstyle protocol') -----
- direction
- 	^patternForm width @ 0!

Item was removed:
- ----- Method: InfiniteForm>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
- 	"This is the real display message, but it doesn't get used until the new
- 	display protocol is installed."
- 	| targetBox patternBox bb |
- 	(patternForm isForm) ifFalse:
- 		[^ aDisplayMedium fill: clipRectangle rule: ruleInteger fillColor: patternForm].
- 
- 	"Do it iteratively"
- 	targetBox := aDisplayMedium boundingBox intersect: clipRectangle.
- 	patternBox := patternForm boundingBox.
- 	bb := BitBlt destForm: aDisplayMedium sourceForm: patternForm fillColor: aForm
- 		combinationRule: ruleInteger destOrigin: 0 at 0 sourceOrigin: 0 at 0
- 		extent: patternBox extent clipRect: clipRectangle.
- 	bb colorMap:
- 		(patternForm colormapIfNeededFor: aDisplayMedium).
- 	(targetBox left truncateTo: patternBox width)
- 		to: targetBox right - 1 by: patternBox width do:
- 		[:x |
- 		(targetBox top truncateTo: patternBox height)
- 			to: targetBox bottom - 1 by: patternBox height do:
- 			[:y |
- 			bb destOrigin: x at y; copyBits]]!

Item was removed:
- ----- Method: InfiniteForm>>displayOnPort:at: (in category 'displaying') -----
- displayOnPort: aPort at: offset
- 
- 	| targetBox patternBox savedMap top left |
- 
- 	self flag: #bob.
- 
- 	"this *may* not get called at the moment. I have been trying to figure out the right way for this to work and am using #displayOnPort:offsetBy: as my current offering - Bob"
- 
- 	(patternForm isForm) ifFalse: [
- 		"patternForm is a Pattern or Color; just use it as a mask for BitBlt"
- 		^ aPort fill: aPort clipRect fillColor: patternForm rule: Form over].
- 
- 	"do it iteratively"
- 	targetBox := aPort clipRect.
- 	patternBox := patternForm boundingBox.
- 	savedMap := aPort colorMap.
- 	aPort sourceForm: patternForm;
- 		fillColor: nil;
- 		combinationRule: Form paint;
- 		sourceRect: (0 at 0 extent: patternBox extent);
- 		colorMap: (patternForm colormapIfNeededFor: aPort destForm).
- 	top := (targetBox top truncateTo: patternBox height) "- (offset y \\ patternBox height)".
- 	left :=  (targetBox left truncateTo: patternBox width) "- (offset x \\ patternBox width)".
- 	left to: (targetBox right - 1) by: patternBox width do:
- 		[:x | top to: (targetBox bottom - 1) by: patternBox height do:
- 			[:y | aPort destOrigin: x at y; copyBits]].
- 	aPort colorMap: savedMap.
- !

Item was removed:
- ----- Method: InfiniteForm>>displayOnPort:offsetBy: (in category 'displaying') -----
- displayOnPort: aPort offsetBy: offset
- 
- 	| targetBox patternBox savedMap top left |
- 
- 	"this version tries to get the form aligned where the user wants it and not just aligned with the cliprect"
- 
- 	(patternForm isForm) ifFalse: [
- 		"patternForm is a Pattern or Color; just use it as a mask for BitBlt"
- 		^ aPort fill: aPort clipRect fillColor: patternForm rule: Form over].
- 
- 	"do it iteratively"
- 	targetBox := aPort clipRect.
- 	patternBox := patternForm boundingBox.
- 	savedMap := aPort colorMap.
- 	aPort sourceForm: patternForm;
- 		fillColor: nil;
- 		combinationRule: Form paint;
- 		sourceRect: (0 at 0 extent: patternBox extent);
- 		colorMap: (patternForm colormapIfNeededFor: aPort destForm).
- 	top := (targetBox top truncateTo: patternBox height) + offset y.
- 	left :=  (targetBox left truncateTo: patternBox width) + offset x.
- 
- 	left to: (targetBox right - 1) by: patternBox width do:
- 		[:x | top to: (targetBox bottom - 1) by: patternBox height do:
- 			[:y | aPort destOrigin: x at y; copyBits]].
- 	aPort colorMap: savedMap.
- !

Item was removed:
- ----- Method: InfiniteForm>>dominantColor (in category 'accessing') -----
- dominantColor
- 	^ patternForm dominantColor!

Item was removed:
- ----- Method: InfiniteForm>>form (in category 'fillstyle protocol') -----
- form
- 	"Bitmap fills respond to #form"
- 	^patternForm!

Item was removed:
- ----- Method: InfiniteForm>>form: (in category 'private') -----
- form: aForm
- 
- 	patternForm := aForm!

Item was removed:
- ----- Method: InfiniteForm>>isBitmapFill (in category 'fillstyle protocol') -----
- isBitmapFill
- 	^true!

Item was removed:
- ----- Method: InfiniteForm>>isGradientFill (in category 'fillstyle protocol') -----
- isGradientFill
- 	^false!

Item was removed:
- ----- Method: InfiniteForm>>isOrientedFill (in category 'fillstyle protocol') -----
- isOrientedFill
- 	^true!

Item was removed:
- ----- Method: InfiniteForm>>isSolidFill (in category 'fillstyle protocol') -----
- isSolidFill
- 	^false!

Item was removed:
- ----- Method: InfiniteForm>>isTiled (in category 'fillstyle protocol') -----
- isTiled
- 	"Return true if the receiver should be drawn as a tiled pattern"
- 	^true!

Item was removed:
- ----- Method: InfiniteForm>>isTranslucent (in category 'fillstyle protocol') -----
- isTranslucent
- 	"Return true since the bitmap may be translucent and we don't really want to check"
- 	^true!

Item was removed:
- ----- Method: InfiniteForm>>normal (in category 'fillstyle protocol') -----
- normal
- 	^0 @ patternForm height!

Item was removed:
- ----- Method: InfiniteForm>>offset (in category 'accessing') -----
- offset 
- 	"Refer to the comment in DisplayObject|offset."
- 
- 	^0 @ 0!

Item was removed:
- ----- Method: InfiniteForm>>origin (in category 'fillstyle protocol') -----
- origin
- 	^0 at 0!

Item was removed:
- ----- Method: InfiniteForm>>origin: (in category 'fillstyle protocol') -----
- origin: aPoint
- 	"Ignored"
- !

Item was removed:
- ----- Method: InfiniteForm>>raisedColor (in category 'displaying') -----
- raisedColor
- 	^ Color transparent!

Item was removed:
- ----- Method: Integer>>asColorOfDepth: (in category '*Graphics-converting') -----
- asColorOfDepth: d
- 	"Return a color value representing the receiver as color of the given depth"
- 	^Color colorFromPixelValue: self depth: d!

Item was removed:
- Object subclass: #JPEGColorComponent
- 	instanceVariableNames: 'currentX currentY hSampleFactor vSampleFactor mcuBlocks widthInBlocks heightInBlocks dctSize mcuWidth mcuHeight priorDCValue id qTableIndex dcTableIndex acTableIndex'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!
- 
- !JPEGColorComponent commentStamp: '<historical>' prior: 0!
- I represent a single component of color in JPEG YCbCr color space.  I can accept a list of blocks in my component from the current MCU, then stream the samples from this block for use in color conversion.  I also store the running DC sample value for my component, used by the Huffman decoder.
- 
- The following layout is fixed for the JPEG primitives to work:
- 	currentX 		<SmallInteger>
- 	currentY 		<SmallInteger>
- 	hSampleFactor 	<SmallInteger>
- 	vSampleFactor 	<SmallInteger>
- 	mcuBlocks 		<Array of: <IntegerArray of: DCTSize2 * Integer>>
- 	widthInBlocks 	<SmallInteger>
- 	heightInBlocks 	<SmallInteger>
- 	dctSize 			<SmallInteger>
- 	mcuWidth 		<SmallInteger>
- 	mcuHeight 		<SmallInteger>
- 	priorDCValue 	<SmallInteger>
- !

Item was removed:
- ----- Method: JPEGColorComponent>>acTableIndex (in category 'accessing') -----
- acTableIndex
- 
- 	^acTableIndex!

Item was removed:
- ----- Method: JPEGColorComponent>>acTableIndex: (in category 'accessing') -----
- acTableIndex: anInteger
- 
- 	acTableIndex := anInteger!

Item was removed:
- ----- Method: JPEGColorComponent>>dcTableIndex (in category 'accessing') -----
- dcTableIndex
- 
- 	^dcTableIndex!

Item was removed:
- ----- Method: JPEGColorComponent>>dcTableIndex: (in category 'accessing') -----
- dcTableIndex: anInteger
- 
- 	dcTableIndex := anInteger!

Item was removed:
- ----- Method: JPEGColorComponent>>heightInBlocks (in category 'accessing') -----
- heightInBlocks
- 
- 	^heightInBlocks!

Item was removed:
- ----- Method: JPEGColorComponent>>heightInBlocks: (in category 'accessing') -----
- heightInBlocks: anInteger
- 
- 	heightInBlocks := anInteger!

Item was removed:
- ----- Method: JPEGColorComponent>>id (in category 'accessing') -----
- id
- 
- 	^id!

Item was removed:
- ----- Method: JPEGColorComponent>>id: (in category 'accessing') -----
- id: anObject
- 
- 	id := anObject!

Item was removed:
- ----- Method: JPEGColorComponent>>initializeSampleStreamBlocks: (in category 'sample streaming') -----
- initializeSampleStreamBlocks: aCollection
- 
- 	mcuBlocks := aCollection.
- 	self resetSampleStream!

Item was removed:
- ----- Method: JPEGColorComponent>>mcuWidth:mcuHeight:dctSize: (in category 'accessing') -----
- mcuWidth: mw mcuHeight: mh dctSize: ds
- 
- 	mcuWidth := mw.
- 	mcuHeight := mh.
- 	dctSize := ds.
- 	hSampleFactor := mcuWidth // widthInBlocks.
- 	vSampleFactor := mcuHeight // heightInBlocks!

Item was removed:
- ----- Method: JPEGColorComponent>>nextSample (in category 'sample streaming') -----
- nextSample
- 
- 	| dx dy blockIndex sampleIndex sample |
- 	dx := currentX // hSampleFactor.
- 	dy := currentY // vSampleFactor.
- 	blockIndex := dy // dctSize * widthInBlocks + (dx // dctSize) + 1.
- 	sampleIndex := dy \\ dctSize * dctSize + (dx \\ dctSize) + 1.
- 	sample := (mcuBlocks at: blockIndex) at: sampleIndex.
- 	currentX := currentX + 1.
- 	currentX < (mcuWidth * dctSize)
- 		ifFalse:
- 			[currentX := 0.
- 			currentY := currentY + 1].
- 	^ sample!

Item was removed:
- ----- Method: JPEGColorComponent>>priorDCValue: (in category 'accessing') -----
- priorDCValue: aNumber
- 
- 	priorDCValue := aNumber!

Item was removed:
- ----- Method: JPEGColorComponent>>qTableIndex (in category 'accessing') -----
- qTableIndex
- 	^qTableIndex!

Item was removed:
- ----- Method: JPEGColorComponent>>qTableIndex: (in category 'accessing') -----
- qTableIndex: anInteger
- 
- 	qTableIndex := anInteger!

Item was removed:
- ----- Method: JPEGColorComponent>>resetSampleStream (in category 'sample streaming') -----
- resetSampleStream
- 
- 	currentX := 0.
- 	currentY := 0!

Item was removed:
- ----- Method: JPEGColorComponent>>totalMcuBlocks (in category 'accessing') -----
- totalMcuBlocks
- 
- 	^ heightInBlocks * widthInBlocks!

Item was removed:
- ----- Method: JPEGColorComponent>>updateDCValue: (in category 'accessing') -----
- updateDCValue: aNumber
- 
- 	priorDCValue := priorDCValue + aNumber.
- 	^priorDCValue!

Item was removed:
- ----- Method: JPEGColorComponent>>widthInBlocks (in category 'accessing') -----
- widthInBlocks
- 
- 	^widthInBlocks!

Item was removed:
- ----- Method: JPEGColorComponent>>widthInBlocks: (in category 'accessing') -----
- widthInBlocks: anInteger
- 
- 	widthInBlocks := anInteger!

Item was removed:
- Object subclass: #JPEGHuffmanTable
- 	instanceVariableNames: 'bits values mincode maxcode valptr lookaheadBits lookaheadSymbol'
- 	classVariableNames: 'BitBufferSize Lookahead'
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!
- 
- !JPEGHuffmanTable commentStamp: '<historical>' prior: 0!
- I represent the table of values used to decode Huffman entropy-encoded bitstreams.  From the JFIF file header entropy values, I build a derived table of codes and values for faster decoding.!

Item was removed:
- ----- Method: JPEGHuffmanTable class>>initialize (in category 'initialization') -----
- initialize
- 
- 	Lookahead := 8.
- 	BitBufferSize := 16!

Item was removed:
- ----- Method: JPEGHuffmanTable class>>lookahead (in category 'constants') -----
- lookahead
- 
- 	^ Lookahead!

Item was removed:
- ----- Method: JPEGHuffmanTable>>bits: (in category 'accessing') -----
- bits: anObject
- 
- 	bits := anObject!

Item was removed:
- ----- Method: JPEGHuffmanTable>>lookaheadBits (in category 'accessing') -----
- lookaheadBits
- 	^lookaheadBits!

Item was removed:
- ----- Method: JPEGHuffmanTable>>lookaheadSymbol (in category 'accessing') -----
- lookaheadSymbol
- 	^lookaheadSymbol!

Item was removed:
- ----- Method: JPEGHuffmanTable>>makeDerivedTables (in category 'computation') -----
- makeDerivedTables
- 
- 	| huffSize huffCode code si index lookbits |
- 	mincode := Array new: 16.
- 	maxcode := Array new: 17.
- 	valptr := Array new: 17.
- 	huffSize := OrderedCollection new.
- 	1 to: 16 do: [:l | 1 to: (bits at: l) do: [:i | huffSize add: l]].
- 	huffSize add: 0.
- 	code := 0.
- 	huffCode := Array new: huffSize size.
- 	si := huffSize at: 1.
- 	index := 1.
- 	[(huffSize at: index) ~= 0] whileTrue:
- 		[[(huffSize at: index) = si] whileTrue:
- 			[huffCode at: index put: code.
- 			index := index + 1.
- 			code := code + 1].
- 		code := code << 1.
- 		si := si + 1].
- 
- 	index := 1.
- 	1 to: 16 do:
- 		[:l |
- 		(bits at: l) ~= 0
- 			ifTrue:
- 				[valptr at: l put: index.
- 				mincode at: l put: (huffCode at: index).
- 				index := index + (bits at: l).
- 				maxcode at: l put: (huffCode at: index-1)]
- 			ifFalse:
- 				[maxcode at: l put: -1]].
- 	maxcode at: 17 put: 16rFFFFF.
- 
- 	lookaheadBits := (Array new: 1 << Lookahead) atAllPut: 0.
- 	lookaheadSymbol := Array new: 1 << Lookahead.
- 	index := 1.
- 	1 to: Lookahead do:
- 		[:l |
- 		1 to: (bits at: l) do:
- 			[:i |
- 			lookbits := (huffCode at: index) << (Lookahead - l) + 1.
- 			(1 << (Lookahead - l) to: 1 by: -1) do:
- 				[:ctr |
- 				lookaheadBits at: lookbits put: l.
- 				lookaheadSymbol at: lookbits put: (values at: index).
- 				lookbits := lookbits + 1].
- 			index := index + 1]]!

Item was removed:
- ----- Method: JPEGHuffmanTable>>maxcode (in category 'accessing') -----
- maxcode
- 	^maxcode!

Item was removed:
- ----- Method: JPEGHuffmanTable>>valueForCode:length: (in category 'computation') -----
- valueForCode: code length: length
- 
- 	^ values at: ((valptr at: length) + code - (mincode at: length))!

Item was removed:
- ----- Method: JPEGHuffmanTable>>values: (in category 'accessing') -----
- values: anObject
- 
- 	values := anObject!

Item was removed:
- ReadStream subclass: #JPEGReadStream
- 	instanceVariableNames: 'bitBuffer bitsInBuffer'
- 	classVariableNames: 'MaxBits'
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!
- 
- !JPEGReadStream commentStamp: '<historical>' prior: 0!
- Encapsulates huffman encoded access to JPEG data.
- 
- The following layout is fixed for the JPEG primitives to work:
- 
- 	collection	<ByteArray | String>
- 	position		<SmallInteger>
- 	readLimit	<SmallInteger>
- 	bitBuffer	<SmallInteger>
- 	bitsInBuffer	<SmallInteger>!

Item was removed:
- ----- Method: JPEGReadStream class>>initialize (in category 'class initialization') -----
- initialize
- 	"JPEGReadStream initialize"
- 	MaxBits := 16.!

Item was removed:
- ----- Method: JPEGReadStream>>buildLookupTable:counts: (in category 'huffman trees') -----
- buildLookupTable: values counts: counts
- 	| min max |
- 	min := max := nil.
- 	1 to: counts size do:[:i|
- 		(counts at: i) = 0 ifFalse:[
- 			min ifNil:[min := i-1].
- 			max := i]].
- 	^self
- 		createHuffmanTables: values 
- 		counts: {0},counts 
- 		from: min+1 
- 		to: max.!

Item was removed:
- ----- Method: JPEGReadStream>>createHuffmanTables:counts:from:to: (in category 'huffman trees') -----
- createHuffmanTables: values counts: counts from: minBits to: maxBits
- 	"Create the actual tables"
- 	| table tableStart tableSize tableEnd 
- 	valueIndex tableStack numValues deltaBits maxEntries
- 	lastTable lastTableStart tableIndex lastTableIndex |
- 
- 	table := WordArray new: ((4 bitShift: minBits) max: 16).
- 
- 	"Create the first entry - this is a dummy.
- 	It gives us information about how many bits to fetch initially."
- 	table at: 1 put: (minBits bitShift: 24) + 2. "First actual table starts at index 2"
- 
- 	"Create the first table from scratch."
- 	tableStart := 2. "See above"
- 	tableSize := 1 bitShift: minBits.
- 	tableEnd := tableStart + tableSize.
- 	"Store the terminal symbols"
- 	valueIndex := (counts at: minBits+1).
- 	tableIndex := 0.
- 	1 to: valueIndex do:[:i|
- 		table at: tableStart + tableIndex put: (values at: i).
- 		tableIndex := tableIndex + 1].
- 	"Fill up remaining entries with invalid entries"
- 	tableStack := OrderedCollection new: 10. "Should be more than enough"
- 	tableStack addLast: 
- 		(Array 
- 			with: minBits	"Number of bits (e.g., depth) for this table"
- 			with: tableStart	"Start of table"
- 			with: tableIndex "Next index in table"
- 			with: minBits	"Number of delta bits encoded in table"
- 			with: tableSize - valueIndex "Entries remaining in table").
- 	"Go to next value index"
- 	valueIndex := valueIndex + 1.
- 	"Walk over remaining bit lengths and create new subtables"
- 	minBits+1 to: maxBits do:[:bits|
- 		numValues := counts at: bits+1.
- 		[numValues > 0] whileTrue:["Create a new subtable"
- 			lastTable := tableStack last.
- 			lastTableStart := lastTable at: 2.
- 			lastTableIndex := lastTable at: 3.
- 			deltaBits := bits - (lastTable at: 1).
- 			"Make up a table of deltaBits size"
- 			tableSize := 1 bitShift: deltaBits.
- 			tableStart := tableEnd.
- 			tableEnd := tableEnd + tableSize.
- 			[tableEnd > table size ]
- 				whileTrue:[table := self growHuffmanTable: table].
- 			"Connect to last table"
- 			self assert:[(table at: lastTableStart + lastTableIndex) = 0]."Entry must be unused"
- 			table at: lastTableStart + lastTableIndex put: (deltaBits bitShift: 24) + tableStart.
- 			lastTable at: 3 put: lastTableIndex+1.
- 			lastTable at: 5 put: (lastTable at: 5) - 1.
- 			self assert:[(lastTable at: 5) >= 0]. "Don't exceed tableSize"
- 			"Store terminal values"
- 			maxEntries := numValues min: tableSize.
- 			tableIndex := 0.
- 			1 to: maxEntries do:[:i|
- 				table at: tableStart + tableIndex put: (values at: valueIndex).
- 				valueIndex := valueIndex + 1.
- 				numValues := numValues - 1.
- 				tableIndex := tableIndex+1].
- 			"Check if we have filled up the current table completely"
- 			maxEntries = tableSize ifTrue:[
- 				"Table has been filled. Back up to the last table with space left."
- 				[tableStack isEmpty not and:[(tableStack last at: 5) = 0]]
- 						whileTrue:[tableStack removeLast].
- 			] ifFalse:[
- 				"Table not yet filled. Put it back on the stack."
- 				tableStack addLast:
- 					(Array
- 						with: bits		"Nr. of bits in this table"
- 						with: tableStart	"Start of table"
- 						with: tableIndex "Index in table"
- 						with: deltaBits	"delta bits of table"
- 						with: tableSize - maxEntries "Unused entries in table").
- 			].
- 		].
- 	].
- 	 ^table copyFrom: 1 to: tableEnd-1!

Item was removed:
- ----- Method: JPEGReadStream>>decodeValueFrom: (in category 'huffman trees') -----
- decodeValueFrom: table
- 	"Decode the next value in the receiver using the given huffman table."
- 	| bits bitsNeeded tableIndex value |
- 	bitsNeeded := (table at: 1) bitShift: -24.	"Initial bits needed"
- 	tableIndex := 2.							"First real table"
- 	[bits := self getBits: bitsNeeded.			"Get bits"
- 	value := table at: (tableIndex + bits).		"Lookup entry in table"
- 	(value bitAnd: 16r3F000000) = 0] 			"Check if it is a non-leaf node"
- 		whileFalse:["Fetch sub table"
- 			tableIndex := value bitAnd: 16rFFFF.	"Table offset in low 16 bit"
- 			bitsNeeded := (value bitShift: -24) bitAnd: 255. "Additional bits in high 8 bit"
- 			bitsNeeded > MaxBits ifTrue:[^self error: 'Invalid huffman table entry' translated]].
- 	^value!

Item was removed:
- ----- Method: JPEGReadStream>>fillBuffer (in category 'accessing') -----
- fillBuffer
- 
- 	| byte |
- 	[bitsInBuffer <= 16]
- 		whileTrue:[
- 			byte := self next.
- 			(byte = 16rFF and: [(self peekFor: 16r00) not])
- 					ifTrue:
- 						[self position: self position - 1.
- 						^0].
- 			bitBuffer := (bitBuffer bitShift: 8) bitOr: byte.
- 			bitsInBuffer := bitsInBuffer + 8].
- 	^ bitsInBuffer!

Item was removed:
- ----- Method: JPEGReadStream>>getBits: (in category 'accessing') -----
- getBits: requestedBits
- 	| value |
- 	requestedBits > bitsInBuffer ifTrue:[
- 		self fillBuffer.
- 		requestedBits > bitsInBuffer ifTrue:[
- 			self error: 'not enough bits available to decode' translated]].
- 	value := bitBuffer bitShift: (requestedBits - bitsInBuffer).
- 	bitBuffer := bitBuffer bitAnd: (1 bitShift: (bitsInBuffer - requestedBits)) -1.
- 	bitsInBuffer := bitsInBuffer - requestedBits.
- 	^ value!

Item was removed:
- ----- Method: JPEGReadStream>>growHuffmanTable: (in category 'huffman trees') -----
- growHuffmanTable: table
- 	| newTable |
- 	newTable := table species new: table size * 2.
- 	newTable replaceFrom: 1 to: table size with: table startingAt: 1.
- 	^newTable!

Item was removed:
- ----- Method: JPEGReadStream>>nextByte (in category 'accessing') -----
- nextByte
- 	^self next asInteger!

Item was removed:
- ----- Method: JPEGReadStream>>nextBytes: (in category 'accessing') -----
- nextBytes: n
- 	^(self next: n) asByteArray!

Item was removed:
- ----- Method: JPEGReadStream>>reset (in category 'accessing') -----
- reset
- 	super reset.
- 	self resetBitBuffer!

Item was removed:
- ----- Method: JPEGReadStream>>resetBitBuffer (in category 'accessing') -----
- resetBitBuffer
- 	bitBuffer := 0.
- 	bitsInBuffer := 0.
- !

Item was removed:
- ImageReadWriter subclass: #JPEGReadWriter
- 	instanceVariableNames: 'width height components currentComponents qTable hACTable hDCTable restartInterval restartsToGo mcuWidth mcuHeight mcusPerRow mcuRowsInScan mcuMembership mcuSampleBuffer mcuImageBuffer majorVersion minorVersion dataPrecision densityUnit xDensity yDensity ss se ah al sosSeen residuals ditherMask'
- 	classVariableNames: 'ConstBits DCTK1 DCTK2 DCTK3 DCTK4 DCTSize DCTSize2 DitherMasks FIXn0n298631336 FIXn0n34414 FIXn0n390180644 FIXn0n541196100 FIXn0n71414 FIXn0n765366865 FIXn0n899976223 FIXn1n175875602 FIXn1n40200 FIXn1n501321110 FIXn1n77200 FIXn1n847759065 FIXn1n961570560 FIXn2n053119869 FIXn2n562915447 FIXn3n072711026 FloatSampleOffset HuffmanTableSize JFIFMarkerParser JPEGNaturalOrder MaxSample Pass1Bits Pass1Div Pass2Div QTableScaleFactor QuantizationTableSize SampleOffset'
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!
- 
- !JPEGReadWriter commentStamp: '<historical>' prior: 0!
- I am a subclass of ImageReadWriter that understands JFIF file streams, and can decode JPEG images.
- This code is based upon the Independent Joint Photographic Experts Group (IJPEG) software, originally written in C by Tom Lane, Philip Gladstone, Luis Ortiz, Jim Boucher, Lee Crocker, Julian Minguillon, George Phillips, Davide Rossi, Ge' Weijers, and other members of the Independent JPEG Group.
- 
- !

Item was removed:
- ----- Method: JPEGReadWriter class>>initialize (in category 'initialization') -----
- initialize
- 	"JPEGReadWriter initialize"
- 	"general constants"
- 	DCTSize := 8.
- 	MaxSample := (2 raisedToInteger: DCTSize) - 1.
- 	SampleOffset := MaxSample // 2.
- 	FloatSampleOffset := SampleOffset asFloat.
- 	DCTSize2 := DCTSize squared.
- 	QuantizationTableSize := 4.
- 	HuffmanTableSize := 4.
- 
- 	"floating-point Inverse Discrete Cosine Transform (IDCT) constants"
- 	ConstBits := 13.
- 	Pass1Bits := 2.
- 	DCTK1 := 2 sqrt.
- 	DCTK2 := 1.847759065.
- 	DCTK3 := 1.082392200.
- 	DCTK4 := -2.613125930.
- 	Pass1Div := 1 bitShift: ConstBits - Pass1Bits.
- 	Pass2Div := 1 bitShift: ConstBits + Pass1Bits + 3.
- 
- 	"fixed-point Inverse Discrete Cosine Transform (IDCT) constants"
- 	FIXn0n298631336 := 2446.
- 	FIXn0n390180644 := 3196.
- 	FIXn0n541196100 := 4433.
- 	FIXn0n765366865 := 6270.
- 	FIXn0n899976223 := 7373.
- 	FIXn1n175875602 := 9633.
- 	FIXn1n501321110 := 12299.
- 	FIXn1n847759065 := 15137.
- 	FIXn1n961570560 := 16069.
- 	FIXn2n053119869 := 16819.
- 	FIXn2n562915447 := 20995.
- 	FIXn3n072711026 := 25172.
- 
- 	"fixed-point color conversion constants"
- 	FIXn0n34414 := 22554.
- 	FIXn0n71414 := 46802.
- 	FIXn1n40200 := 91881.
- 	FIXn1n77200 :=  116130.
- 
- 	"reordering table from JPEG zig-zag order"
- 	JPEGNaturalOrder := #(
- 		1 2 9 17 10 3 4 11
- 		18 25 33 26 19 12 5 6
- 		13 20 27 34 41 49 42 35
- 		28 21 14 7 8 15 22 29
- 		36 43 50 57 58 51 44 37
- 		30 23 16 24 31 38 45 52
- 		59 60 53 46 39 32 40 47
- 		54 61 62 55 48 56 63 64).
- 
- 	"scale factors for the values in the Quantization Tables"
- 	QTableScaleFactor := (0 to: DCTSize-1) collect:
- 		[:k | k = 0
- 			ifTrue: [1.0]
- 			ifFalse: [(k * Float pi / 16) cos * 2 sqrt]].
- 
- 	"dithering masks"
- 	(DitherMasks := Dictionary new)
- 		add: 0 -> 0;
- 		add: 1 -> 127;
- 		add: 2 -> 63;
- 		add: 4 -> 63;
- 		add: 8 -> 31;
- 		add: 16 -> 7;
- 		add: 32 -> 0.
- 
- 	"dictionary of marker parsers"
- 	(JFIFMarkerParser := Dictionary new)
- 		add: (16r01 -> #parseNOP);
- 		add: (16rC0 -> #parseStartOfFile);
- 		add: (16rC4 -> #parseHuffmanTable);
- 		addAll: ((16rD0 to: 16rD7) collect: [:m | Association key: m value: #parseNOP]);
- 		add: (16rD8 -> #parseStartOfInput);
- 		add: (16rD9 -> #parseEndOfInput);
- 		add: (16rDA -> #parseStartOfScan);
- 		add: (16rDB -> #parseQuantizationTable);
- 		add: (16rDD -> #parseDecoderRestartInterval);
- 		add: (16rE0 -> #parseAPPn);
- 		add: (16rE1 -> #parseAPPn)!

Item was removed:
- ----- Method: JPEGReadWriter class>>typicalFileExtensions (in category 'image reading/writing') -----
- typicalFileExtensions
- 	"Answer a collection of file extensions (lowercase) which files that I can read might commonly have"
- 	^#('jpg' 'jpeg')!

Item was removed:
- ----- Method: JPEGReadWriter class>>understandsImageFormat: (in category 'image reading/writing') -----
- understandsImageFormat: aStream
- 	(JPEGReadWriter2 understandsImageFormat: aStream) ifTrue:[^false].
- 	aStream reset; binary.
- 	aStream next = 16rFF ifFalse: [^ false].
- 	aStream next = 16rD8 ifFalse: [^ false].
- 	^true!

Item was removed:
- ----- Method: JPEGReadWriter>>colorConvertFloatYCbCrMCU (in category 'colorspace conversion') -----
- colorConvertFloatYCbCrMCU
- 
- 	| ySampleStream crSampleStream cbSampleStream y cb cr red green blue bits |
- 	ySampleStream := currentComponents at: 1.
- 	cbSampleStream := currentComponents at: 2.
- 	crSampleStream := currentComponents at: 3.
- 	ySampleStream resetSampleStream.
- 	cbSampleStream resetSampleStream.
- 	crSampleStream resetSampleStream.
- 	bits := mcuImageBuffer bits.
- 	1 to: bits size do:
- 		[:i |
- 		y := ySampleStream nextSample.
- 		cb := cbSampleStream nextSample - FloatSampleOffset.
- 		cr := crSampleStream nextSample - FloatSampleOffset.
- 		red := self sampleFloatRangeLimit: (y + (1.40200 * cr)).
- 		green := self sampleFloatRangeLimit: (y - (0.34414 * cb) - (0.71414 * cr)).
- 		blue := self sampleFloatRangeLimit: (y + (1.77200 * cb)).
- 		bits at: i put: 16rFF000000 + (red << 16) + (green << 8) + blue].
- 	!

Item was removed:
- ----- Method: JPEGReadWriter>>colorConvertGrayscaleMCU (in category 'colorspace conversion') -----
- colorConvertGrayscaleMCU
- 
- 	| ySampleStream y bits |
- 	ySampleStream := currentComponents at: 1.
- 	ySampleStream resetSampleStream.
- 	bits := mcuImageBuffer bits.
- 	1 to: bits size do:
- 		[:i |
- 		y := (ySampleStream nextSample) + (residuals at: 2).
- 		y > MaxSample ifTrue: [y := MaxSample].
- 		residuals at: 2 put: (y bitAnd: ditherMask).
- 		y := y bitAnd: MaxSample - ditherMask.
- 		y < 1 ifTrue: [y := 1].
- 		bits at: i put: 16rFF000000 + (y<<16) + (y<<8) + y].
- 	!

Item was removed:
- ----- Method: JPEGReadWriter>>colorConvertIntYCbCrMCU (in category 'colorspace conversion') -----
- colorConvertIntYCbCrMCU
- 
- 	| ySampleStream crSampleStream cbSampleStream y cb cr red green blue bits |
- 	ySampleStream := currentComponents at: 1.
- 	cbSampleStream := currentComponents at: 2.
- 	crSampleStream := currentComponents at: 3.
- 	ySampleStream resetSampleStream.
- 	cbSampleStream resetSampleStream.
- 	crSampleStream resetSampleStream.
- 	bits := mcuImageBuffer bits.
- 	1 to: bits size do:
- 		[:i |
- 		y := ySampleStream nextSample.
- 		cb := cbSampleStream nextSample - SampleOffset.
- 		cr := crSampleStream nextSample - SampleOffset.
- 		red := y + ((FIXn1n40200 * cr) // 65536) + (residuals at: 1).
- 		red > MaxSample
- 			ifTrue: [red := MaxSample]
- 			ifFalse: [red < 0 ifTrue: [red := 0]].
- 		residuals at: 1 put: (red bitAnd: ditherMask).
- 		red := red bitAnd: MaxSample - ditherMask.
- 		red < 1 ifTrue: [red := 1].
- 		green := y - ((FIXn0n34414 * cb) // 65536) -
- 			((FIXn0n71414 * cr) // 65536) + (residuals at: 2).
- 		green > MaxSample
- 			ifTrue: [green := MaxSample]
- 			ifFalse: [green < 0 ifTrue: [green := 0]].
- 		residuals at: 2 put: (green bitAnd: ditherMask).
- 		green := green bitAnd: MaxSample - ditherMask.
- 		green < 1 ifTrue: [green := 1].
- 		blue := y + ((FIXn1n77200 * cb) // 65536) + (residuals at: 3).
- 		blue > MaxSample
- 			ifTrue: [blue := MaxSample]
- 			ifFalse: [blue < 0 ifTrue: [blue := 0]].
- 		residuals at: 3 put: (blue bitAnd: ditherMask).
- 		blue := blue bitAnd: MaxSample - ditherMask.
- 		blue < 1 ifTrue: [blue := 1].
- 		bits at: i put: 16rFF000000 + (red bitShift: 16) + (green bitShift: 8) + blue].
- 	!

Item was removed:
- ----- Method: JPEGReadWriter>>colorConvertMCU (in category 'colorspace conversion') -----
- colorConvertMCU
- 
- 	^ currentComponents size = 3
- 		ifTrue:
- 			[self useFloatingPoint
- 				ifTrue: [self colorConvertFloatYCbCrMCU]
- 				ifFalse: [self primColorConvertYCbCrMCU: currentComponents
- 								bits: mcuImageBuffer bits
- 								residuals: residuals
- 								ditherMask: ditherMask.]]
- 		ifFalse: [self primColorConvertGrayscaleMCU]!

Item was removed:
- ----- Method: JPEGReadWriter>>dctFloatRangeLimit: (in category 'dct') -----
- dctFloatRangeLimit: value
- 
- 	^ (value / 8.0) + FloatSampleOffset.!

Item was removed:
- ----- Method: JPEGReadWriter>>decodeBlockInto:component:dcTable:acTable: (in category 'huffman encoding') -----
- decodeBlockInto: anArray component: aColorComponent dcTable: huffmanDC acTable: huffmanAC
- 
- 	| byte i zeroCount |
- 	byte := stream decodeValueFrom: huffmanDC.
- 	byte ~= 0 ifTrue: [byte := self scaleAndSignExtend: ( self getBits: byte) inFieldWidth: byte].
- 	byte := aColorComponent updateDCValue: byte.
- 	anArray atAllPut: 0.
- 	anArray at: 1 put: byte.
- 	i := 2.
- 	[i <= DCTSize2] whileTrue:
- 		[byte := stream decodeValueFrom: huffmanAC.
- 		zeroCount := byte >> 4.
- 		byte := byte bitAnd: 16r0F.
- 		byte ~= 0
- 			ifTrue:
- 				[i := i + zeroCount.
- 				byte := self scaleAndSignExtend: ( self getBits: byte) inFieldWidth: byte.
- 				anArray at:	 (JPEGNaturalOrder at: i) put: byte]
- 			ifFalse:
- 				[zeroCount = 15 ifTrue: [i := i + zeroCount] ifFalse: [^ self]].
- 		i := i + 1]
- 		!

Item was removed:
- ----- Method: JPEGReadWriter>>decodeMCU (in category 'huffman encoding') -----
- decodeMCU
- 
- 	| comp ci |
- 	(restartInterval ~= 0 and: [restartsToGo = 0]) ifTrue: [self processRestart].
- 	1 to: mcuMembership size do:[:i|
- 		ci := mcuMembership at: i.
- 		comp := currentComponents at: ci.
- 		self
- 			primDecodeBlockInto: (mcuSampleBuffer at: i)
- 			component: comp
- 			dcTable: (hDCTable at: comp dcTableIndex)
- 			acTable: (hACTable at: comp acTableIndex)
- 			stream: stream.
- 	].
- 	restartsToGo := restartsToGo - 1.!

Item was removed:
- ----- Method: JPEGReadWriter>>getBits: (in category 'huffman encoding') -----
- getBits: requestedBits
- 	^stream getBits: requestedBits!

Item was removed:
- ----- Method: JPEGReadWriter>>hACTable (in category 'accessing') -----
- hACTable
- 
- 	hACTable ifNil: [hACTable := Array new: HuffmanTableSize].
- 	^ hACTable!

Item was removed:
- ----- Method: JPEGReadWriter>>hDCTable (in category 'accessing') -----
- hDCTable
- 
- 	hDCTable ifNil: [hDCTable := Array new: HuffmanTableSize].
- 	^ hDCTable!

Item was removed:
- ----- Method: JPEGReadWriter>>idctBlockFloat:component: (in category 'dct') -----
- idctBlockFloat: anArray component: aColorComponent
- 
- 	| t0 t1 t2 t3 t4 t5 t6 t7 t10 t11 t12 t13 z5 z10 z11 z12 z13 qt ws |
- 	qt := self qTable at: (aColorComponent qTableIndex).
- 	ws := Array new: DCTSize2.
- 
- 	"Pass 1: process columns from input, store into work array"
- 	1 to: DCTSize do: [:i |
- 		t0 := (anArray at: i) * (qt at: i).
- 		t1 := (anArray at: (DCTSize*2 + i)) * (qt at: (DCTSize*2 + i)).
- 		t2 := (anArray at: (DCTSize*4 + i)) * (qt at: (DCTSize*4 + i)).
- 		t3 := (anArray at: (DCTSize*6 + i)) * (qt at: (DCTSize*6 + i)).
- 		t10 := t0 + t2.
- 		t11 := t0 - t2.
- 		t13 := t1 + t3.
- 		t12 := (t1 - t3) * DCTK1 - t13.
- 		t0 := t10 + t13.
- 		t3 := t10 - t13.
- 		t1 := t11 + t12.
- 		t2 := t11 - t12.
- 		t4 := (anArray at: (DCTSize + i)) * (qt at: (DCTSize + i)).
- 		t5 := (anArray at: (DCTSize*3 + i)) * (qt at: (DCTSize*3 + i)).
- 		t6 := (anArray at: (DCTSize*5 + i)) * (qt at: (DCTSize*5 + i)).
- 		t7 := (anArray at: (DCTSize*7 + i)) * (qt at: (DCTSize*7 + i)).
- 		z13 := t6 + t5.
- 		z10 := t6 - t5.
- 		z11 := t4 + t7.
- 		z12 := t4 - t7.
- 		t7 := z11 + z13.
- 		t11 := (z11 - z13) * DCTK1.
- 		z5 := (z10 + z12) * DCTK2.
- 		t10 := DCTK3 * z12 - z5.
- 		t12 := DCTK4 * z10 + z5.
- 		t6 := t12 - t7.
- 		t5 := t11 - t6.
- 		t4 := t10 + t5.
- 		ws at: i put: t0 + t7.
- 		ws at: (DCTSize*7 + i) put: t0 - t7.
- 		ws at: (DCTSize + i) put: t1 + t6.
- 		ws at: (DCTSize*6 + i) put: t1 - t6.
- 		ws at: (DCTSize*2 + i) put: t2 + t5.
- 		ws at: (DCTSize*5 + i) put: t2 - t5.
- 		ws at: (DCTSize*4 + i) put: t3 + t4.
- 		ws at: (DCTSize*3 + i) put: t3 - t4].
- 
- 		"Pass 2: process rows from the workspace"
- 	0 to: DCTSize2-DCTSize by: DCTSize do: [:i |
- 		t10 := (ws at: (i+1)) + (ws at: (i+5)).
- 		t11 := (ws at: (i+1)) - (ws at: (i+5)).
- 		t13 := (ws at: (i+3)) + (ws at: (i+7)).
- 		t12 := ((ws at: (i+3)) - (ws at: (i+7))) * DCTK1 - t13.
- 		t0 := t10 + t13.
- 		t3 := t10 - t13.
- 		t1 := t11 + t12.
- 		t2 := t11 - t12.
- 		z13 := (ws at: (i+6)) + (ws at: (i+4)).
- 		z10 := (ws at: (i+6)) - (ws at: (i+4)).
- 		z11 := (ws at: (i+2)) + (ws at: (i+8)).
- 		z12 := (ws at: (i+2)) - (ws at: (i+8)).
- 		t7 := z11 + z13.
- 		t11 := (z11 - z13) * DCTK1.
- 		z5 := (z10 + z12) * DCTK2.
- 		t10 := DCTK3 * z12 - z5.
- 		t12 := DCTK4 * z10 + z5.
- 		t6 := t12 - t7.
- 		t5 := t11 - t6.
- 		t4 := t10 + t5.
- 
- 		"final output stage: scale down by a factor of 8 and range-limit"
- 		anArray at: (i+1) put: (self dctFloatRangeLimit: (t0 + t7)).
- 		anArray at: (i+8) put: (self dctFloatRangeLimit: (t0 - t7)).
- 		anArray at: (i+2) put: (self dctFloatRangeLimit: (t1 + t6)).
- 		anArray at: (i+7) put: (self dctFloatRangeLimit: (t1 - t6)).
- 		anArray at: (i+3) put: (self dctFloatRangeLimit: (t2 + t5)).
- 		anArray at: (i+6) put: (self dctFloatRangeLimit: (t2 - t5)).
- 		anArray at: (i+5) put: (self dctFloatRangeLimit: (t3 + t4)).
- 		anArray at: (i+4) put: (self dctFloatRangeLimit: (t3 - t4))]
- 
- 
- !

Item was removed:
- ----- Method: JPEGReadWriter>>idctBlockInt:component: (in category 'dct') -----
- idctBlockInt: anArray component: aColorComponent
- 	^self idctBlockInt: anArray qt: (self qTable at: aColorComponent qTableIndex)!

Item was removed:
- ----- Method: JPEGReadWriter>>idctBlockInt:qt: (in category 'dct') -----
- idctBlockInt: anArray qt: qt
- 
- 	|  ws anACTerm dcval z1 z2 z3 z4 z5 t0 t1 t2 t3 t10 t11 t12 t13 shift |
- 	ws := Array new: DCTSize2.
- 
- 	"Pass 1: process columns from anArray, store into work array"
- 	shift := 1 bitShift: ConstBits - Pass1Bits.
- 	1 to: DCTSize do:
- 		[:i |
- 		anACTerm := nil.
- 		1 to: DCTSize-1 do:[:row|
- 			anACTerm ifNil:[
- 				(anArray at: row * DCTSize + i) = 0 ifFalse:[anACTerm := row]]].
- 		anACTerm == nil
- 			ifTrue:
- 				[dcval := (anArray at: i) * (qt at: 1) bitShift: Pass1Bits.
- 				0 to: DCTSize-1 do: [:j | ws at: (j * DCTSize + i) put: dcval]]
- 			ifFalse:
- 				[z2 := (anArray at: (DCTSize * 2 + i)) * (qt at: (DCTSize * 2 + i)).
- 				z3 := (anArray at: (DCTSize * 6 + i)) * (qt at: (DCTSize * 6 + i)).
- 				z1 := (z2 + z3) * FIXn0n541196100.
- 				t2 := z1 + (z3 * FIXn1n847759065 negated).
- 				t3 := z1 + (z2 * FIXn0n765366865).
- 				z2 := (anArray at: i) * (qt at: i).
- 				z3 := (anArray at: (DCTSize * 4 + i)) * (qt at: (DCTSize * 4 + i)).
- 				t0 := (z2 + z3) bitShift: ConstBits.
- 				t1 := (z2 - z3) bitShift: ConstBits.
- 				t10 := t0 + t3.
- 				t13 := t0 - t3.
- 				t11 := t1 + t2.
- 				t12 := t1 - t2.
- 				t0 := (anArray at: (DCTSize * 7 + i)) * (qt at: (DCTSize * 7 + i)).
- 				t1 := (anArray at: (DCTSize * 5 + i)) * (qt at: (DCTSize * 5 + i)).
- 				t2 := (anArray at: (DCTSize * 3 + i)) * (qt at: (DCTSize * 3 + i)).
- 				t3 := (anArray at: (DCTSize + i)) * (qt at: (DCTSize + i)).
- 				z1 := t0 + t3.
- 				z2 := t1 + t2.
- 				z3 := t0 + t2.
- 				z4 := t1 + t3.
- 				z5 := (z3 + z4) * FIXn1n175875602.
- 				t0 := t0 * FIXn0n298631336.
- 				t1 := t1 * FIXn2n053119869.
- 				t2 := t2 * FIXn3n072711026.
- 				t3 := t3 * FIXn1n501321110.
- 				z1 := z1 * FIXn0n899976223 negated.
- 				z2 := z2 * FIXn2n562915447 negated.
- 				z3 := z3 * FIXn1n961570560 negated.
- 				z4 := z4 * FIXn0n390180644 negated.
- 				z3 := z3 + z5.
- 				z4 := z4 + z5.
- 				t0 := t0 + z1 + z3.
- 				t1 := t1 +z2 +z4.
- 				t2 := t2 + z2 + z3.
- 				t3 := t3 + z1 + z4.
- 				ws at: i put: (t10 + t3) >> (ConstBits - Pass1Bits).
- 				ws at: (DCTSize * 7 + i) put: (t10 - t3) // shift.
- 				ws at: (DCTSize * 1 + i) put: (t11 + t2) // shift.
- 				ws at: (DCTSize * 6 + i) put: (t11 - t2) // shift.
- 				ws at: (DCTSize * 2 + i) put: (t12 + t1) // shift.
- 				ws at: (DCTSize * 5 + i) put: (t12 - t1) // shift.
- 				ws at: (DCTSize * 3 + i) put: (t13 + t0) // shift.
- 				ws at: (DCTSize * 4 + i) put: (t13 - t0) // shift]].
- 
- 	"Pass 2: process rows from work array, store back into anArray"
- 	shift := 1 bitShift: ConstBits + Pass1Bits + 3.
- 	0 to: DCTSize2-DCTSize by: DCTSize do:
- 		[:i |
- 		z2 := ws at: i + 3.
- 		z3 := ws at: i + 7.
- 		z1 := (z2 + z3) * FIXn0n541196100.
- 		t2 := z1 + (z3 * FIXn1n847759065 negated).
- 		t3 := z1 + (z2 * FIXn0n765366865).
- 		t0 := (ws at: (i + 1)) + (ws at: (i + 5)) bitShift: ConstBits.
- 		t1 := (ws at: (i + 1)) - (ws at: (i + 5)) bitShift: ConstBits.
- 		t10 := t0 + t3.
- 		t13 := t0 - t3.
- 		t11 := t1 + t2.
- 		t12 := t1 -t2.
- 		t0 := ws at: (i + 8).
- 		t1 := ws at: (i + 6).
- 		t2 := ws at: (i + 4).
- 		t3 := ws at: (i + 2).
- 		z1 := t0 + t3.
- 		z2 := t1 + t2.
- 		z3 := t0 + t2.
- 		z4 := t1 + t3.
- 		z5 := (z3 + z4) * FIXn1n175875602.
- 		t0 := t0 * FIXn0n298631336.
- 		t1 := t1 * FIXn2n053119869.
- 		t2 := t2 * FIXn3n072711026.
- 		t3 := t3 * FIXn1n501321110.
- 		z1 := z1 * FIXn0n899976223 negated.
- 		z2 := z2 * FIXn2n562915447 negated.
- 		z3 := z3 * FIXn1n961570560 negated.
- 		z4 := z4 * FIXn0n390180644 negated.
- 		z3 := z3 + z5.
- 		z4 := z4 + z5.
- 		t0 := t0 + z1 + z3.
- 		t1 := t1 + z2 + z4.
- 		t2 := t2 + z2 + z3.
- 		t3 := t3 + z1 + z4.
- 		anArray at: (i + 1) put: (self sampleRangeLimit: (t10 + t3) // shift + SampleOffset).
- 		anArray at: (i + 8) put: (self sampleRangeLimit: (t10 - t3) // shift + SampleOffset).
- 		anArray at: (i + 2) put: (self sampleRangeLimit: (t11 + t2) // shift + SampleOffset).
- 		anArray at: (i + 7) put: (self sampleRangeLimit: (t11 - t2) // shift + SampleOffset).
- 		anArray at: (i + 3) put: (self sampleRangeLimit: (t12 + t1) // shift + SampleOffset).
- 		anArray at: (i + 6) put: (self sampleRangeLimit: (t12 - t1) // shift + SampleOffset).
- 		anArray at: (i + 4) put: (self sampleRangeLimit: (t13 + t0) // shift + SampleOffset).
- 		anArray at: (i + 5) put: (self sampleRangeLimit: (t13 - t0) // shift + SampleOffset)].
- 
- 
- !

Item was removed:
- ----- Method: JPEGReadWriter>>idctMCU (in category 'dct') -----
- idctMCU
- 
- 	| comp fp ci |
- 	fp := self useFloatingPoint.
- 	1 to: mcuMembership size do:[:i|
- 		ci := mcuMembership at: i.
- 		comp := currentComponents at: ci.
- 		fp ifTrue:[
- 			self idctBlockFloat: (mcuSampleBuffer at: i) component: comp.
- 		] ifFalse:[
- 			self primIdctInt: (mcuSampleBuffer at: i)
- 				qt: (qTable at: comp qTableIndex)]].!

Item was removed:
- ----- Method: JPEGReadWriter>>initialSOSSetup (in category 'marker parsing') -----
- initialSOSSetup
- 
- 	mcuWidth := (components detectMax: [:c | c widthInBlocks]) widthInBlocks.
- 	mcuHeight := (components detectMax: [:c | c heightInBlocks]) heightInBlocks.
- 	components do:[:c |
- 		c mcuWidth: mcuWidth mcuHeight: mcuHeight dctSize: DCTSize].
- 	stream resetBitBuffer.!

Item was removed:
- ----- Method: JPEGReadWriter>>nextImage (in category 'public access') -----
- nextImage
- 
- 	^ self nextImageDitheredToDepth: Display depth
- !

Item was removed:
- ----- Method: JPEGReadWriter>>nextImageDitheredToDepth: (in category 'public access') -----
- nextImageDitheredToDepth: depth
- 
- 	| form xStep yStep x y bb |
- 	ditherMask := DitherMasks
- 		at: depth
- 		ifAbsent: [self error: 'can only dither to display depths' translated].
- 	residuals := WordArray new: 3.
- 	sosSeen := false.
- 	self parseFirstMarker.
- 	[sosSeen] whileFalse: [self parseNextMarker].
- 	form := Form extent: (width @ height) depth: depth.
- 	bb := BitBlt toForm: form.
- 	bb sourceForm: mcuImageBuffer.
- 	bb colorMap: (mcuImageBuffer colormapIfNeededFor: form).
- 	bb sourceRect: mcuImageBuffer boundingBox.
- 	bb combinationRule: Form over.
- 	xStep := mcuWidth * DCTSize.
- 	yStep := mcuHeight * DCTSize.
- 	y := 0.
- 	1 to: mcuRowsInScan do:
- 		[:row |
- 		x := 0.
- 		1 to: mcusPerRow do:
- 			[:col |
- 			self decodeMCU.
- 			self idctMCU.
- 			self colorConvertMCU.
- 			bb destX: x; destY: y; copyBits.
- 			x := x + xStep].
- 		y := y + yStep].
- 	^ form!

Item was removed:
- ----- Method: JPEGReadWriter>>okToIgnoreMarker: (in category 'marker parsing') -----
- okToIgnoreMarker: aMarker
- 
- 	^ (((16rE0 to: 16rEF) includes: aMarker) "unhandled APPn markers"
- 		or: [aMarker = 16rDC or: [aMarker = 16rFE]]) "DNL or COM markers"
- 		or: [aMarker = 16r99] "Whatever that is"!

Item was removed:
- ----- Method: JPEGReadWriter>>on: (in category 'private') -----
- on: aStream
- 	super on: aStream.
- 	stream := JPEGReadStream on: stream upToEnd.!

Item was removed:
- ----- Method: JPEGReadWriter>>parseAPPn (in category 'marker parsing') -----
- parseAPPn
- 
- 	| length buffer thumbnailLength markerStart |
- 	markerStart := self position.
- 	length := self nextWord.
- 	buffer := self next: 4.
- 	(buffer asString = 'JFIF') ifFalse: [
- 		"Skip APPs that we're not interested in"
- 		stream next: length-6.
- 		^self].
- 	self next.
- 	majorVersion := self next.
- 	minorVersion := self next.
- 	densityUnit := self next.
- 	xDensity := self nextWord.
- 	yDensity := self nextWord.
- 	thumbnailLength := self next * self next * 3.
- 	length := length - (self position - markerStart).
- 	length = thumbnailLength ifFalse: [self error: 'APP0 thumbnail length is incorrect.' translated].
- 	self next: length!

Item was removed:
- ----- Method: JPEGReadWriter>>parseDecoderRestartInterval (in category 'marker parsing') -----
- parseDecoderRestartInterval
- 
- 	| length |
- 	length := self nextWord.
- 	length = 4 ifFalse: [self error: 'DRI length is incorrect.' translated].
- 	restartInterval := self nextWord.!

Item was removed:
- ----- Method: JPEGReadWriter>>parseFirstMarker (in category 'marker parsing') -----
- parseFirstMarker
- 
- 	| marker |
- 	self next = 16rFF ifFalse: [self error: 'JFIF marker expected' translated].
- 	marker := self next.
- 	marker = 16rD9
- 		ifTrue: [^self "halt: 'EOI encountered.'"].
- 	marker = 16rD8 ifFalse: [self error: 'SOI marker expected' translated].
- 	self parseStartOfInput.
- !

Item was removed:
- ----- Method: JPEGReadWriter>>parseHuffmanTable (in category 'marker parsing') -----
- parseHuffmanTable
- 
- 	| length markerStart index bits count huffVal isACTable hTable |
- 	markerStart := self position.
- 	length := self nextWord.
- 	[self position - markerStart >= length] whileFalse:
- 		[index := self next.
- 		isACTable := (index bitAnd: 16r10) ~= 0.
- 		index := (index bitAnd: 16r0F) + 1.
- 		index > HuffmanTableSize
- 			ifTrue: [self error: ('image has more than {1} quantization tables' translated format: {HuffmanTableSize})].
- 		bits := self next: 16.
- 		count := bits sum.
- 		(count > 256 or: [(count > (length - (self position - markerStart)))])
- 			ifTrue: [self error: 'Huffman Table count is incorrect' translated].
- 		huffVal := self next: count.
- 		hTable := stream buildLookupTable: huffVal counts: bits.
- 		isACTable
- 			ifTrue:
- 				[self hACTable at: index put: hTable]
- 			ifFalse:
- 				[self hDCTable at: index put: hTable]].!

Item was removed:
- ----- Method: JPEGReadWriter>>parseNOP (in category 'marker parsing') -----
- parseNOP
- 
- 	"don't need to do anything, here"!

Item was removed:
- ----- Method: JPEGReadWriter>>parseNextMarker (in category 'marker parsing') -----
- parseNextMarker
- 	"Parse the next marker of the stream"
- 
- 	| byte discardedBytes |
- 	discardedBytes := 0.
- 	[(byte := self next) = 16rFF] whileFalse: [discardedBytes := discardedBytes + 1].	
- 	[[(byte := self next) = 16rFF] whileTrue. byte = 16r00] whileTrue:
- 		[discardedBytes := discardedBytes + 2].
- 	discardedBytes > 0 ifTrue: [self "notifyWithLabel: 'warning: extraneous data discarded'"].
- 	self perform:
- 		(JFIFMarkerParser
- 			at: byte
- 			ifAbsent:
- 				[(self okToIgnoreMarker: byte)
- 					ifTrue: [#skipMarker]
- 					ifFalse: [self error: ('marker {1} cannot be handled' translated format: {byte printStringHex})]])!

Item was removed:
- ----- Method: JPEGReadWriter>>parseQuantizationTable (in category 'marker parsing') -----
- parseQuantizationTable
- 
- 	| length markerStart n prec value table |
- 	markerStart := self position.
- 	length := self nextWord.
- 	[self position - markerStart >= length] whileFalse:
- 		[value := self next.
- 		n := (value bitAnd: 16r0F) + 1.
- 		prec := (value >> 4) > 0.
- 		n > QuantizationTableSize
- 			 ifTrue: [self error: ('image has more than {1} quantization tables' translated format: {QuantizationTableSize})].
- 		table := IntegerArray new: DCTSize2.
- 		1 to: DCTSize2 do:
- 			[:i |
- 			value := (prec
- 				ifTrue: [self nextWord]
- 				ifFalse: [self next]).
- 			table at: (JPEGNaturalOrder at: i) put: value].
- 		self useFloatingPoint ifTrue: [self scaleQuantizationTable: table].
- 		self qTable at: n put: table]!

Item was removed:
- ----- Method: JPEGReadWriter>>parseStartOfFile (in category 'marker parsing') -----
- parseStartOfFile
- 
- 	| length markerStart value n |
- 	markerStart := self position.
- 	length := self nextWord.
- 	dataPrecision := self next.
- 	dataPrecision = 8
- 		ifFalse: [self error: ('cannot handle {1}-bit components' translated format: {dataPrecision})].
- 	height := self nextWord.
- 	width := self nextWord.
- 	n := self next.
- 	(height = 0) | (width = 0) | (n = 0) ifTrue: [self error: 'empty image' translated].
- 	(length - (self position - markerStart)) ~= (n * 3)
- 		ifTrue: [self error: 'component length is incorrect' translated].
- 	components := Array new: n.
- 	1 to: components size do:
- 		[:i |
- 		components
- 			at: i
- 			put:
- 				(JPEGColorComponent new
- 					id: self next;
- 					"heightInBlocks: (((value := self next) >> 4) bitAnd: 16r0F);
- 					widthInBlocks: (value bitAnd: 16r0F);"
- 					widthInBlocks: (((value := self next) >> 4) bitAnd: 16r0F);
- 					heightInBlocks: (value bitAnd: 16r0F);
- 
- 					qTableIndex: self next + 1)]!

Item was removed:
- ----- Method: JPEGReadWriter>>parseStartOfInput (in category 'marker parsing') -----
- parseStartOfInput
- 
- 	restartInterval := 0.
- 	densityUnit := 0.
- 	xDensity := 1.
- 	yDensity := 1
- !

Item was removed:
- ----- Method: JPEGReadWriter>>parseStartOfScan (in category 'marker parsing') -----
- parseStartOfScan
- 
- 	| length n id value dcNum acNum comp |
- 	length := self nextWord.
- 	n := self next.
- 	(length ~= (n*2 + 6)) | (n < 1) ifTrue: [self error: 'SOS length is incorrect' translated].
- 	currentComponents := Array new: n.
- 	1 to: n do: [:i |
- 		id := self next.
- 		value := self next.
- 		dcNum := (value >> 4) bitAnd: 16r0F.
- 		acNum := value bitAnd: 16r0F.
- 		comp := components detect: [:c | c id = id].
- 		comp
- 			dcTableIndex: dcNum+1;
- 			acTableIndex: acNum+1.
- 		currentComponents at: i put: comp].
- 	ss := self next.
- 	se := self next.
- 	value := self next.
- 	ah := (value >> 4) bitAnd: 16r0F.
- 	al := value bitAnd: 16r0F.
- 	self initialSOSSetup.
- 	self perScanSetup.
- 	sosSeen := true!

Item was removed:
- ----- Method: JPEGReadWriter>>perScanSetup (in category 'marker parsing') -----
- perScanSetup
- 
- 	mcusPerRow := (width / (mcuWidth * DCTSize)) ceiling.
- 	mcuRowsInScan := (height / (mcuHeight * DCTSize)) ceiling.
- 	(currentComponents size = 3 or: [currentComponents size = 1])
- 		ifFalse: [self error: 'JPEG color space not recognized' translated].
- 	mcuMembership := OrderedCollection new.
- 	currentComponents withIndexDo:
- 		[:c :i |
- 		c priorDCValue: 0.
- 		mcuMembership addAll: ((1 to: c totalMcuBlocks) collect: [:b | i])].
- 	mcuMembership := mcuMembership asArray.
- 	mcuSampleBuffer := (1 to: mcuMembership size) collect: [:i | IntegerArray new: DCTSize2].
- 	currentComponents withIndexDo:
- 		[:c :i |
- 			c initializeSampleStreamBlocks:
- 				((1 to: mcuMembership size)
- 					select: [:j | i = (mcuMembership at: j)]
- 					thenCollect: [:j | mcuSampleBuffer at: j])].
- 	mcuImageBuffer := Form
- 		extent: (mcuWidth @ mcuHeight) * DCTSize
- 		depth: 32.
- 	restartsToGo := restartInterval.!

Item was removed:
- ----- Method: JPEGReadWriter>>primColorConvertGrayscaleMCU (in category 'colorspace conversion') -----
- primColorConvertGrayscaleMCU
- 	self primColorConvertGrayscaleMCU: (currentComponents at: 1)
- 			bits: mcuImageBuffer bits
- 			residuals: residuals
- 			ditherMask: ditherMask.!

Item was removed:
- ----- Method: JPEGReadWriter>>primColorConvertGrayscaleMCU:bits:residuals:ditherMask: (in category 'colorspace conversion') -----
- primColorConvertGrayscaleMCU: componentArray bits: bits residuals: residualArray ditherMask: mask
- 	<primitive: 'primitiveColorConvertGrayscaleMCU' module: 'JPEGReaderPlugin'>
- 	"JPEGReaderPlugin doPrimitive: #primitiveColorConvertGrayscaleMCU."
- 	^self colorConvertGrayscaleMCU!

Item was removed:
- ----- Method: JPEGReadWriter>>primColorConvertIntYCbCrMCU (in category 'colorspace conversion') -----
- primColorConvertIntYCbCrMCU
- 	self primColorConvertYCbCrMCU: currentComponents
- 			bits: mcuImageBuffer bits
- 			residuals: residuals
- 			ditherMask: ditherMask.!

Item was removed:
- ----- Method: JPEGReadWriter>>primColorConvertYCbCrMCU:bits:residuals:ditherMask: (in category 'colorspace conversion') -----
- primColorConvertYCbCrMCU: componentArray bits: bits residuals: residualArray ditherMask: mask
- 	<primitive: 'primitiveColorConvertMCU' module: 'JPEGReaderPlugin'>
- 	^self colorConvertIntYCbCrMCU!

Item was removed:
- ----- Method: JPEGReadWriter>>primDecodeBlockInto:component:dcTable:acTable:stream: (in category 'huffman encoding') -----
- primDecodeBlockInto: sampleBuffer component: comp dcTable: dcTable acTable: acTable stream: jpegStream
- 	<primitive: 'primitiveDecodeMCU' module: 'JPEGReaderPlugin'>
- 	^self decodeBlockInto: sampleBuffer component: comp dcTable: dcTable acTable: acTable!

Item was removed:
- ----- Method: JPEGReadWriter>>primIdctBlockInt:component: (in category 'dct') -----
- primIdctBlockInt: anArray component: aColorComponent
- 	^self primIdctInt: anArray qt: (self qTable at: aColorComponent qTableIndex)!

Item was removed:
- ----- Method: JPEGReadWriter>>primIdctInt:qt: (in category 'dct') -----
- primIdctInt: anArray qt: qt
- 	<primitive: 'primitiveIdctInt' module: 'JPEGReaderPlugin'>
- 	^self idctBlockInt: anArray qt: qt!

Item was removed:
- ----- Method: JPEGReadWriter>>processRestart (in category 'huffman encoding') -----
- processRestart
- 	stream resetBitBuffer.
- 	self parseNextMarker.
- 	currentComponents do: [:c | c priorDCValue: 0].
- 	restartsToGo := restartInterval.!

Item was removed:
- ----- Method: JPEGReadWriter>>qTable (in category 'accessing') -----
- qTable
- 
- 	qTable ifNil: [qTable := Array new: QuantizationTableSize].
- 	^ qTable!

Item was removed:
- ----- Method: JPEGReadWriter>>sampleFloatRangeLimit: (in category 'colorspace conversion') -----
- sampleFloatRangeLimit: aNumber
- 
- 	^ (aNumber rounded max: 0) min: MaxSample!

Item was removed:
- ----- Method: JPEGReadWriter>>sampleRangeLimit: (in category 'colorspace conversion') -----
- sampleRangeLimit: aNumber
- 
- 	aNumber < 0 ifTrue: [^ 0].
- 	aNumber > MaxSample ifTrue: [^ MaxSample].
- 	^ aNumber!

Item was removed:
- ----- Method: JPEGReadWriter>>scaleAndSignExtend:inFieldWidth: (in category 'huffman encoding') -----
- scaleAndSignExtend: aNumber inFieldWidth: w
- 
- 	aNumber < (1 bitShift: (w - 1))
- 		ifTrue: [^aNumber - (1 bitShift: w) + 1]
- 		ifFalse: [^aNumber]!

Item was removed:
- ----- Method: JPEGReadWriter>>scaleQuantizationTable: (in category 'dct') -----
- scaleQuantizationTable: table
- 
- 	| index |
- 
- 	index := 1.
- 	1 to: DCTSize do:
- 		[:row |
- 		1 to: DCTSize do:
- 			[:col |
- 			table at: index
- 				put: ((table at: index) * (QTableScaleFactor at: row) *
- 					(QTableScaleFactor at: col)) rounded.
- 			index := index + 1]].
- 	^ table
- !

Item was removed:
- ----- Method: JPEGReadWriter>>setStream: (in category 'public access') -----
- setStream: aStream
- 	"Feed it in from an existing source"
- 	stream := JPEGReadStream on: aStream upToEnd.!

Item was removed:
- ----- Method: JPEGReadWriter>>skipMarker (in category 'marker parsing') -----
- skipMarker
- 
- 	| length markerStart |
- 	markerStart := self position.
- 	length := self nextWord.
- 	self next: length - (self position - markerStart)
- !

Item was removed:
- ----- Method: JPEGReadWriter>>understandsImageFormat (in category 'testing') -----
- understandsImageFormat
- 	"Answer true if the image stream format is understood by this decoder."
- 	self next = 16rFF ifFalse: [^ false].
- 	self next = 16rD8 ifFalse: [^ false].
- 	^ true
- !

Item was removed:
- ----- Method: JPEGReadWriter>>useFloatingPoint (in category 'preferences') -----
- useFloatingPoint
- 
- 	^ false!

Item was removed:
- ImageReadWriter subclass: #JPEGReadWriter2
- 	instanceVariableNames: ''
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!
- 
- !JPEGReadWriter2 commentStamp: '<historical>' prior: 0!
- I provide fast JPEG compression and decompression. I require the VM pluginJPEGReadWriter2Plugin, which is typically stored in same directory as the Squeak virtual machine.
- 
- JPEGReadWriter2Plugin is based on LIBJPEG library. This sentence applies to the plugin:
-    "This software is based in part on the work of the Independent JPEG Group".
- 
- The LIBJPEG license allows it to be used free for any purpose so long as its origin and copyright are acknowledged. You can read more about LIBJPEG and get the complete source code at www.ijg.org.
- !

Item was removed:
- ----- Method: JPEGReadWriter2 class>>primJPEGPluginIsPresent (in category 'image reading/writing') -----
- primJPEGPluginIsPresent
- 	<primitive: 'primJPEGPluginIsPresent' module: 'JPEGReadWriter2Plugin'>
- 	^false!

Item was removed:
- ----- Method: JPEGReadWriter2 class>>putForm:quality:progressiveJPEG:onFileNamed: (in category 'image reading/writing') -----
- putForm: aForm quality: quality progressiveJPEG: progressiveFlag onFileNamed: fileName
- 	"Store the given Form as a JPEG file of the given name, overwriting any existing file of that name. Quality goes from 0 (low) to 100 (high), where -1 means default. If progressiveFlag is true, encode as a progressive JPEG."
- 
- 	| writer theFile |
- 	FileDirectory deleteFilePath: fileName.
- 	theFile := FileStream newFileNamed: fileName.
- 	writer := self on: theFile binary.
- 	Cursor write showWhile: [
- 		writer nextPutImage: aForm quality: quality progressiveJPEG: progressiveFlag].
- 	writer close.
- 	theFile directory setMacFileNamed: theFile localName type: '    ' creator: '    '.!

Item was removed:
- ----- Method: JPEGReadWriter2 class>>typicalFileExtensions (in category 'image reading/writing') -----
- typicalFileExtensions
- 	"Answer a collection of file extensions (lowercase) which files that I can read might commonly have"
- 	^#('jpg' 'jpeg')!

Item was removed:
- ----- Method: JPEGReadWriter2>>compress:quality: (in category 'public access') -----
- compress: aForm quality: quality
- 	"Encode the given Form and answer the compressed ByteArray. Quality goes from 0 (low) to 100 (high), where -1 means default.
- 	We can only compress:
- 		* 32-bit deep Forms 
- 		* -32-bit deep Forms
- 		* 16-bit deep Forms
- 		* -16-bit deep Forms
- 		* GrayScale ColorForms (see #isGrayScale)"
- 	| sourceForm jpegCompressStruct jpegErrorMgr2Struct buffer byteCount |
- 	
- 	aForm unhibernate.
- 	
- 	sourceForm := self supports8BitGrayscaleJPEGs 
- 		ifTrue: [ 
- 			(aForm depth = 32) | (aForm depth = 16) | (aForm isGrayScale)
- 				ifTrue: [aForm]
- 				ifFalse: [aForm asFormOfDepth: 32 ]]
- 		ifFalse: [
- 			(aForm nativeDepth > 0) & ((aForm depth = 32) | ((aForm depth = 16) & (aForm width even)))
- 				ifTrue: [aForm]
- 				ifFalse: [aForm asFormOfDepth: 32 ]].
- 	
- 	jpegCompressStruct := ByteArray new: self primJPEGCompressStructSize.
- 	jpegErrorMgr2Struct := ByteArray new: self primJPEGErrorMgr2StructSize.
- 	buffer := ByteArray new: sourceForm width * sourceForm height + 1024.
- 	byteCount := self primJPEGWriteImage: jpegCompressStruct 
- 		onByteArray: buffer
- 		form: sourceForm
- 		quality: quality
- 		progressiveJPEG: false
- 		errorMgr: jpegErrorMgr2Struct.
- 	byteCount = 0 ifTrue: [self error: 'buffer too small for compressed data' translated].
- 	^ buffer copyFrom: 1 to: byteCount
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>imageExtent: (in category 'public access') -----
- imageExtent: aByteArray 
- 	"Answer the extent of the compressed image encoded in the given ByteArray."
- 
- 	| jpegDecompressStruct jpegErrorMgr2Struct w h |
- 	jpegDecompressStruct := ByteArray new: self primJPEGDecompressStructSize.
- 	jpegErrorMgr2Struct := ByteArray new: self primJPEGErrorMgr2StructSize.
- 	self
- 		primJPEGReadHeader: jpegDecompressStruct 
- 		fromByteArray: aByteArray
- 		errorMgr: jpegErrorMgr2Struct.
- 	w := self primImageWidth: jpegDecompressStruct.
- 	h := self primImageHeight: jpegDecompressStruct.
- 	^ w @ h
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>isPluginPresent (in category 'testing') -----
- isPluginPresent
- 	^self primJPEGPluginIsPresent!

Item was removed:
- ----- Method: JPEGReadWriter2>>nextImage (in category 'public access') -----
- nextImage
- 	"Decode and answer a Form from my stream."
- 
- 	^ self nextImageSuggestedDepth: Display depth
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>nextImageSuggestedDepth: (in category 'public access') -----
- nextImageSuggestedDepth: suggestedDepth
- 	"Decode and answer a Form of the given depth from my stream. Close the stream if it is a file stream.
- 	We can read RGB JPEGs into:
- 		* 32-bit Forms
- 		* -32-bit Forms
- 		* 16-bit Forms (with or without dithering!!)
- 		* -16-bit Forms (with or without dithering!!)
- 	We can read grayscale JPEGs into:
- 		* 32-bit Forms
- 		* -32-bit Forms
- 		* 16-bit Forms (with or without dithering!!)
- 		* -16-bit Forms (with or without dithering!!)
- 		* 8-bit grayScale ColorForms (see #isGrayScale)
- 		* -8-bit grayScale ColorForms (see #isGrayScale)"
- 
- 	| bytes width height components form jpegDecompressStruct jpegErrorMgr2Struct |
- 	bytes := stream upToEnd.
- 	stream close.
- 	jpegDecompressStruct := ByteArray new: self primJPEGDecompressStructSize.
- 	jpegErrorMgr2Struct := ByteArray new: self primJPEGErrorMgr2StructSize.
- 	self 
- 		primJPEGReadHeader: jpegDecompressStruct 
- 		fromByteArray: bytes
- 		errorMgr: jpegErrorMgr2Struct.
- 	width := self primImageWidth: jpegDecompressStruct.
- 	height := self primImageHeight: jpegDecompressStruct.
- 	components := self primImageNumComponents: jpegDecompressStruct.
- 	form :=
- 		self supports8BitGrayscaleJPEGs
- 			ifTrue: [
- 				components = 3
- 					ifTrue: [ Form extent: width at height depth: suggestedDepth ]
- 					ifFalse: [ (Form extent: width at height depth: suggestedDepth) asGrayScale ]]
- 			ifFalse: [
- 				Form
- 					extent: width at height
- 					depth: 
- 						(suggestedDepth = 32 
- 							ifTrue: [ 32 ]
- 							ifFalse: [
- 								((suggestedDepth = 16) & (width even))
- 									ifTrue: [ 16 ]
- 									ifFalse: [ 32 ]])].
- 					
- 	self
- 		primJPEGReadImage: jpegDecompressStruct
- 		fromByteArray: bytes
- 		onForm: form
- 		doDithering: true
- 		errorMgr: jpegErrorMgr2Struct.
- 	^ form!

Item was removed:
- ----- Method: JPEGReadWriter2>>nextPutImage: (in category 'public access') -----
- nextPutImage: aForm
- 	"Encode the given Form on my stream with default quality."
- 
- 	^ self nextPutImage: aForm quality: -1 progressiveJPEG: false
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>nextPutImage:quality:progressiveJPEG: (in category 'public access') -----
- nextPutImage: aForm quality: quality progressiveJPEG: progressiveFlag
- 	"Encode the given Form on my stream with the given settings. Quality goes from 0 (low) to 100 (high), where -1 means default. If progressiveFlag is true, encode as a progressive JPEG.
- 	We can compress:
- 		* 32-bit deep Forms 
- 		* -32-bit deep Forms
- 		* 16-bit deep
- 		* -16-bit deep
- 		* GrayScale ColorForms (see #isGrayScale)"
- 
- 	| sourceForm jpegCompressStruct jpegErrorMgr2Struct buffer byteCount |
- 	
- 	aForm unhibernate.
- 	
- 	sourceForm := self supports8BitGrayscaleJPEGs 
- 		ifTrue: [ 
- 			(aForm depth = 32) | (aForm depth = 16) | (aForm isGrayScale)
- 				ifTrue: [aForm]
- 				ifFalse: [aForm asFormOfDepth: 32 ]]
- 		ifFalse: [
- 			(aForm nativeDepth > 0) & ((aForm depth = 32) | ((aForm depth = 16) & (aForm width even)))
- 				ifTrue: [aForm]
- 				ifFalse: [aForm asFormOfDepth: 32 ]].
- 	
- 	jpegCompressStruct := ByteArray new: self primJPEGCompressStructSize.
- 	jpegErrorMgr2Struct := ByteArray new: self primJPEGErrorMgr2StructSize.
- 	buffer := ByteArray new: sourceForm width * sourceForm height + 1024.
- 	"Try to write the image. Retry with a larger buffer if needed."
- 	[
- 		byteCount := self primJPEGWriteImage: jpegCompressStruct 
- 			onByteArray: buffer
- 			form: sourceForm
- 			quality: quality
- 			progressiveJPEG: progressiveFlag
- 			errorMgr: jpegErrorMgr2Struct.
- 		byteCount = 0 and: [ buffer size < (sourceForm width * sourceForm height * 3 + 1024) ] ]
- 			whileTrue: [ buffer := ByteArray new: buffer size * 2 ].
- 	byteCount = 0 ifTrue: [ self error: 'buffer too small for compressed data' translated ].
- 	stream next: byteCount putAll: buffer startingAt: 1.
- 	self close.
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>primImageHeight: (in category 'primitives') -----
- primImageHeight: aJPEGCompressStruct
- 
- 	<primitive: 'primImageHeight' module: 'JPEGReadWriter2Plugin'>
- 	self primitiveFailed
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>primImageNumComponents: (in category 'primitives') -----
- primImageNumComponents: aJPEGDecompressStruct
- 
- 	<primitive: 'primImageNumComponents' module: 'JPEGReadWriter2Plugin'>
- 	^ 3!

Item was removed:
- ----- Method: JPEGReadWriter2>>primImageWidth: (in category 'primitives') -----
- primImageWidth: aJPEGCompressStruct
- 
- 	<primitive: 'primImageWidth' module: 'JPEGReadWriter2Plugin'>
- 	self primitiveFailed
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>primJPEGCompressStructSize (in category 'primitives') -----
- primJPEGCompressStructSize
- 
- 	<primitive: 'primJPEGCompressStructSize' module: 'JPEGReadWriter2Plugin'>
- 	self primitiveFailed
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>primJPEGDecompressStructSize (in category 'primitives') -----
- primJPEGDecompressStructSize
- 
- 	<primitive: 'primJPEGDecompressStructSize' module: 'JPEGReadWriter2Plugin'>
- 	self primitiveFailed
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>primJPEGErrorMgr2StructSize (in category 'primitives') -----
- primJPEGErrorMgr2StructSize
- 
- 	<primitive: 'primJPEGErrorMgr2StructSize' module: 'JPEGReadWriter2Plugin'>
- 	self primitiveFailed
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>primJPEGPluginIsPresent (in category 'primitives') -----
- primJPEGPluginIsPresent
- 	<primitive: 'primJPEGPluginIsPresent' module: 'JPEGReadWriter2Plugin'>
- 	^false!

Item was removed:
- ----- Method: JPEGReadWriter2>>primJPEGReadHeader:fromByteArray:errorMgr: (in category 'primitives') -----
- primJPEGReadHeader: aJPEGDecompressStruct fromByteArray: source errorMgr: aJPEGErrorMgr2Struct
- 
- 	<primitive: 'primJPEGReadHeaderfromByteArrayerrorMgr' module: 'JPEGReadWriter2Plugin'>
- 	self primitiveFailed
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>primJPEGReadImage:fromByteArray:onForm:doDithering:errorMgr: (in category 'primitives') -----
- primJPEGReadImage: aJPEGDecompressStruct fromByteArray: source onForm: form doDithering: ditherFlag errorMgr: aJPEGErrorMgr2Struct
- 
- 	<primitive: 'primJPEGReadImagefromByteArrayonFormdoDitheringerrorMgr' module: 'JPEGReadWriter2Plugin'>
- 	self primitiveFailed
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>primJPEGWriteImage:onByteArray:form:quality:progressiveJPEG:errorMgr: (in category 'primitives') -----
- primJPEGWriteImage: aJPEGCompressStruct onByteArray: destination form: form quality: quality progressiveJPEG: progressiveFlag errorMgr: aJPEGErrorMgr2Struct
- 
- 	<primitive: 'primJPEGWriteImageonByteArrayformqualityprogressiveJPEGerrorMgr' module: 'JPEGReadWriter2Plugin'>
- 	self primitiveFailed
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>primSupports8BitGrayscaleJPEGs (in category 'primitives') -----
- primSupports8BitGrayscaleJPEGs
- 	<primitive: 'primSupports8BitGrayscaleJPEGs' module: 'JPEGReadWriter2Plugin'>
- 	^ false!

Item was removed:
- ----- Method: JPEGReadWriter2>>supports8BitGrayscaleJPEGs (in category 'testing') -----
- supports8BitGrayscaleJPEGs
- 	^ self primSupports8BitGrayscaleJPEGs!

Item was removed:
- ----- Method: JPEGReadWriter2>>uncompress:into: (in category 'public access') -----
- uncompress: aByteArray into: aForm
- 	^ self uncompress: aByteArray into: aForm doDithering: true
- !

Item was removed:
- ----- Method: JPEGReadWriter2>>uncompress:into:doDithering: (in category 'public access') -----
- uncompress: aByteArray into: aForm doDithering: ditherFlag
- 	"Uncompress an image from the given ByteArray into the given Form. 
- 	Fails if the given Form has the wrong dimensions or depth.
- 	We can read RGB JPEGs into:
- 		* 32-bit Forms
- 		* -32-bit Forms
- 		* 16-bit Forms (with or without dithering!!)
- 		* -16-bit Forms (with or without dithering!!)
- 	We can read grayscale JPEGs into:
- 		* 32-bit Forms
- 		* -32-bit Forms
- 		* 16-bit Forms (with or without dithering!!)
- 		* -16-bit Forms (with or without dithering!!)
- 		* 8-bit grayScale ColorForms (see #isGrayScale)
- 		* -8-bit grayScale ColorForms (see #isGrayScale)"
- 
- 	| jpegDecompressStruct jpegErrorMgr2Struct width height components |
- 	
- 	aForm unhibernate.
- 	
- 	jpegDecompressStruct := ByteArray new: self primJPEGDecompressStructSize.
- 	jpegErrorMgr2Struct := ByteArray new: self primJPEGErrorMgr2StructSize.
- 	self 
- 		primJPEGReadHeader: jpegDecompressStruct 
- 		fromByteArray: aByteArray
- 		errorMgr: jpegErrorMgr2Struct.
- 	width := self primImageWidth: jpegDecompressStruct.
- 	height := self primImageHeight: jpegDecompressStruct.
- 	components := self primImageNumComponents: jpegDecompressStruct.
- 	
- 	((aForm width = width) & (aForm height = height)) ifFalse: [
- 		^ self error: 'form dimensions do not match' translated ].
- 	self supports8BitGrayscaleJPEGs
- 		ifTrue: [
- 			components = 3
- 				ifTrue: [
- 					aForm depth = 8
- 						ifTrue: [ ^ self error: 'Cannot uncompress multi-channel JPEGs into 8-bit deep forms' translated ]].
- 			components = 1
- 				ifTrue: [
- 					aForm depth = 8
- 						ifTrue: [
- 							aForm isGrayScale 
- 								ifFalse: [ ^ self error: 'Cannot uncompress single-channel JPEGs into 8-bit deep forms that are not grayscale' translated ]]]]
- 						
- 		ifFalse: [
- 			aForm nativeDepth < 0
- 				ifTrue: [ ^ self error: 'Current plugin version doesn''t support uncompressing JPEGs into little-endian forms' translated ]
- 				ifFalse: [
- 					aForm depth = 16
- 						ifTrue: [
- 							width odd
- 								ifTrue: [ ^ self error: 'Current plugin version doesn''t support uncompressing JPEGs with an odd width into 16-bit deep forms' translated ]].
- 					aForm depth = 8
- 						ifTrue: [ ^ self error: 'Current plugin version doesn''t support uncompressing JPEGs into 8-bit deep forms' translated ]]].
- 
- 	self primJPEGReadImage: jpegDecompressStruct
- 		fromByteArray: aByteArray
- 		onForm: aForm
- 		doDithering: ditherFlag
- 		errorMgr: jpegErrorMgr2Struct.!

Item was removed:
- ----- Method: JPEGReadWriter2>>understandsImageFormat (in category 'testing') -----
- understandsImageFormat
- 	"Answer true if the image stream format is understood by this decoder."
- 	self isPluginPresent ifFalse:[^false]. "cannot read it otherwise"
- 	self next = 16rFF ifFalse: [^ false].
- 	self next = 16rD8 ifFalse: [^ false].
- 	^ true
- !

Item was removed:
- Object subclass: #LayoutFrame
- 	instanceVariableNames: 'leftFraction leftOffset topFraction topOffset rightFraction rightOffset bottomFraction bottomOffset'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Primitives'!
- 
- !LayoutFrame commentStamp: '<historical>' prior: 0!
- I define a frame for positioning some morph in a proportional layout.
- 
- Instance variables:
- 	leftFraction 
- 	topFraction 
- 	rightFraction 
- 	bottomFraction 	<Float>		The fractional distance (between 0 and 1) to place the morph in its owner's bounds
- 	leftOffset 
- 	topOffset 
- 	rightOffset 
- 	bottomOffset 	<Integer>	Fixed pixel offset to apply after fractional positioning (e.g., "10 pixel right of the center of the owner")!

Item was removed:
- ----- Method: LayoutFrame class>>classVersion (in category 'accessing') -----
- classVersion
- 	^ 2 "fractions and offsets are never 'nil' anymore"
- !

Item was removed:
- ----- Method: LayoutFrame class>>fractions: (in category 'instance creation') -----
- fractions: fractionsOrNil
- 	^self fractions: fractionsOrNil offsets: nil!

Item was removed:
- ----- Method: LayoutFrame class>>fractions:offsets: (in category 'instance creation') -----
- fractions: fractionsOrNil offsets: offsetsOrNil
- 
- 	| fractions offsets |
- 
- 	fractions := fractionsOrNil ifNil: [0 at 0 extent: 0 at 0].
- 	offsets := offsetsOrNil ifNil: [0 at 0 extent: 0 at 0].
- 	^self new
- 		topFraction: fractions top offset: offsets top;
- 		leftFraction: fractions left offset: offsets left;
- 		bottomFraction: fractions bottom offset: offsets bottom;
- 		rightFraction: fractions right offset: offsets right
- !

Item was removed:
- ----- Method: LayoutFrame class>>fullFrame (in category 'instance creation') -----
- fullFrame
- 
- 	^ self fractions: (0 @ 0 corner: 1 @ 1)!

Item was removed:
- ----- Method: LayoutFrame class>>offsets: (in category 'instance creation') -----
- offsets: offsetsOrNil
- 	^self fractions: nil offsets: offsetsOrNil!

Item was removed:
- ----- Method: LayoutFrame class>>withClassVersion: (in category 'objects from disk') -----
- withClassVersion: aVersion
- 
- 	aVersion <= self classVersion ifTrue: [^ self].
- 	^ super withClassVersion: aVersion!

Item was removed:
- ----- Method: LayoutFrame>>bottomFraction (in category 'accessing') -----
- bottomFraction
- 	^bottomFraction!

Item was removed:
- ----- Method: LayoutFrame>>bottomFraction: (in category 'accessing') -----
- bottomFraction: aNumber
- 	bottomFraction := aNumber!

Item was removed:
- ----- Method: LayoutFrame>>bottomFraction:offset: (in category 'accessing') -----
- bottomFraction: aNumber offset: anInteger
- 
- 	bottomFraction := aNumber.
- 	bottomOffset := anInteger!

Item was removed:
- ----- Method: LayoutFrame>>bottomOffset (in category 'accessing') -----
- bottomOffset
- 	^bottomOffset!

Item was removed:
- ----- Method: LayoutFrame>>bottomOffset: (in category 'accessing') -----
- bottomOffset: anInteger
- 	bottomOffset := anInteger!

Item was removed:
- ----- Method: LayoutFrame>>convertToCurrentVersion:refStream: (in category 'objects from disk') -----
- convertToCurrentVersion: varDict refStream: smartRefStrm
- 	| className oldClassVersion |
- 
- 	"JW 2/1/2001"
- 	"Since class version isn't passed in varDict, look it up through smartRefSrm."
- 	className := varDict at: #ClassName.
- 	oldClassVersion := (smartRefStrm structures at: className) first.
- 	(oldClassVersion = 0) ifTrue: [ self negateBottomRightOffsets; fixup ].
- 	(oldClassVersion = 1) ifTrue: [ self fixup ].
- 	^super convertToCurrentVersion: varDict refStream: smartRefStrm.
- !

Item was removed:
- ----- Method: LayoutFrame>>fixup (in category 'objects from disk') -----
- fixup
- 	"Set-up default value for un-initialized layout frames"
- 	
- 	"LayoutFrame allInstancesDo: [:e | e fixup]."
- 	
- 	leftFraction ifNil: [leftFraction := 0].
- 	leftOffset ifNil: [leftOffset := 0].
- 	topFraction ifNil: [topFraction := 0].
- 	topOffset ifNil: [topOffset := 0].
- 	rightFraction ifNil: [rightFraction := 0].
- 	rightOffset ifNil: [rightOffset := 0].
- 	bottomFraction ifNil: [bottomFraction := 0].
- 	bottomOffset ifNil: [bottomOffset := 0].!

Item was removed:
- ----- Method: LayoutFrame>>hasFixedHeight (in category 'testing') -----
- hasFixedHeight
- 
- 	^ self topFraction = self bottomFraction!

Item was removed:
- ----- Method: LayoutFrame>>hasFixedWidth (in category 'testing') -----
- hasFixedWidth
- 
- 	^ self leftFraction = self rightFraction!

Item was removed:
- ----- Method: LayoutFrame>>initialize (in category 'initialize-release') -----
- initialize
- 	"By default, let the frame be empty.
- 	This way, we can later define a proportional layout via fractions,
- 	or a fixed layout via offsets, or whatever mixture of both."
- 	
- 	leftFraction := leftOffset := topFraction := topOffset := rightFraction := rightOffset := bottomFraction := bottomOffset := 0!

Item was removed:
- ----- Method: LayoutFrame>>layout:in: (in category 'layout') -----
- layout: oldBounds in: newBounds
- 	"Return the proportional rectangle insetting the given bounds"
- 	| left right top bottom | 
- 	left := newBounds left + (newBounds width * leftFraction).
- 	left := left + leftOffset.
- 	right := newBounds right - (newBounds width * (1.0 - rightFraction)).
- 	right := right + rightOffset.
- 	top := newBounds top + (newBounds height * topFraction).
- 	top := top + topOffset.
- 	bottom := newBounds bottom - (newBounds height * (1.0 - bottomFraction)).
- 	bottom := bottom + bottomOffset.
- 	^(left rounded @ top rounded) corner: (right rounded @ bottom rounded)!

Item was removed:
- ----- Method: LayoutFrame>>leftFraction (in category 'accessing') -----
- leftFraction
- 	^leftFraction!

Item was removed:
- ----- Method: LayoutFrame>>leftFraction: (in category 'accessing') -----
- leftFraction: aNumber
- 	leftFraction := aNumber!

Item was removed:
- ----- Method: LayoutFrame>>leftFraction:offset: (in category 'accessing') -----
- leftFraction: aNumber offset: anInteger
- 
- 	leftFraction := aNumber.
- 	leftOffset := anInteger!

Item was removed:
- ----- Method: LayoutFrame>>leftOffset (in category 'accessing') -----
- leftOffset
- 	^leftOffset!

Item was removed:
- ----- Method: LayoutFrame>>leftOffset: (in category 'accessing') -----
- leftOffset: anInteger
- 	leftOffset := anInteger!

Item was removed:
- ----- Method: LayoutFrame>>minExtentFrom: (in category 'layout') -----
- minExtentFrom: minExtent
- 	"Return the minimal extent the given bounds can be represented in"
- 	^ (self minWidthFrom: minExtent x) @ (self minHeightFrom: minExtent y)!

Item was removed:
- ----- Method: LayoutFrame>>minHeightFrom: (in category 'layout') -----
- minHeightFrom: minHeight
- 	"Return the minimal height the given bounds can be represented in
- 	we have:
- 		top = (height * topFraction + topOffset)
- 		bottom = (height * bottomFraction + bottomOffset)
- 	we want to fullfill those constraints if possible:
- 		0 <= top <= height
- 		0 <= bottom <= heigth
- 		bottom - top >= minHeight"
- 	| height |
- 	height := bottomFraction = topFraction
- 		ifTrue: [0]
- 		ifFalse: [minHeight + topOffset - bottomOffset / (bottomFraction - topFraction) max: 0].
- 	topFraction < 1 ifTrue: [height := height max: topOffset / (1 - topFraction)].
- 	bottomFraction < 1 ifTrue: [height := height max: bottomOffset / (1 - bottomFraction)].
- 	topFraction > 0 ifTrue: [height := height max: topOffset negated / topFraction].
- 	bottomFraction > 0 ifTrue: [height := height max: bottomOffset negated / bottomFraction].
- 	^ height truncated!

Item was removed:
- ----- Method: LayoutFrame>>minWidthFrom: (in category 'layout') -----
- minWidthFrom: minWidth
- 	"Return the minimal width the given bounds can be represented in
- 	we have:
- 		left = (width * leftFraction + leftOffset)
- 		right = (width * rightFraction + rightOffset)
- 	we want to fullfill those constraints if possible:
- 		0 <= left <= width
- 		0 <= right <= heigth
- 		right - left >= minwidth"
- 	| width |
- 	width := rightFraction = leftFraction
- 		ifTrue: [0]
- 		ifFalse: [minWidth + leftOffset - rightOffset / (rightFraction - leftFraction) max: 0].
- 	leftFraction < 1 ifTrue: [width := width max: leftOffset / (1 - leftFraction)].
- 	rightFraction < 1 ifTrue: [width := width max: rightOffset / (1 - rightFraction)].
- 	leftFraction > 0 ifTrue: [width := width max: leftOffset negated / leftFraction].
- 	rightFraction > 0 ifTrue: [width := width max: rightOffset negated / rightFraction].
- 	^ width truncated!

Item was removed:
- ----- Method: LayoutFrame>>negateBottomRightOffsets (in category 'objects from disk') -----
- negateBottomRightOffsets
- 
- 	bottomOffset ifNotNil: [ bottomOffset := bottomOffset negated ].
- 	rightOffset ifNotNil: [ rightOffset := rightOffset negated ].
- 
- !

Item was removed:
- ----- Method: LayoutFrame>>printOn: (in category 'printing') -----
- printOn: aStream
- 
- 	super printOn: aStream.
- 	
- 	aStream nextPutAll: '( '.
- 	
- 	{ {'l'. self leftFraction. self leftOffset}. {'t'. self topFraction. self topOffset}. {'r'. self rightFraction. self rightOffset}. {'b'. self bottomFraction. self bottomOffset} } do: [:spec |
- 		aStream nextPutAll: spec first; space.
- 		
- 		spec second printOn: aStream maxDecimalPlaces: 2.
- 		
- 		aStream nextPutAll: (spec third >= 0 ifTrue: ['+'] ifFalse: ['-']).
- 		spec third abs printOn: aStream maxDecimalPlaces: 0]
- 			separatedBy: [aStream space].
- 			
- 	aStream nextPutAll: ' )'.!

Item was removed:
- ----- Method: LayoutFrame>>rightFraction (in category 'accessing') -----
- rightFraction
- 	^rightFraction!

Item was removed:
- ----- Method: LayoutFrame>>rightFraction: (in category 'accessing') -----
- rightFraction: aNumber
- 	rightFraction := aNumber!

Item was removed:
- ----- Method: LayoutFrame>>rightFraction:offset: (in category 'accessing') -----
- rightFraction: aNumber offset: anInteger
- 
- 	rightFraction := aNumber.
- 	rightOffset := anInteger!

Item was removed:
- ----- Method: LayoutFrame>>rightOffset (in category 'accessing') -----
- rightOffset
- 	^rightOffset!

Item was removed:
- ----- Method: LayoutFrame>>rightOffset: (in category 'accessing') -----
- rightOffset: anInteger
- 	rightOffset := anInteger!

Item was removed:
- ----- Method: LayoutFrame>>topFraction (in category 'accessing') -----
- topFraction
- 	^topFraction!

Item was removed:
- ----- Method: LayoutFrame>>topFraction: (in category 'accessing') -----
- topFraction: aNumber
- 	topFraction := aNumber!

Item was removed:
- ----- Method: LayoutFrame>>topFraction:offset: (in category 'accessing') -----
- topFraction: aNumber offset: anInteger
- 
- 	topFraction := aNumber.
- 	topOffset := anInteger!

Item was removed:
- ----- Method: LayoutFrame>>topOffset (in category 'accessing') -----
- topOffset
- 	^topOffset!

Item was removed:
- ----- Method: LayoutFrame>>topOffset: (in category 'accessing') -----
- topOffset: anInteger
- 	topOffset := anInteger!

Item was removed:
- Object subclass: #LzwGifDecoder
- 	instanceVariableNames: 'suffixTable prefixTable eoiCode clearCode bitMask codeSize minimumCodeSize maxCode nextAvailableCode numLeftoverBits codeStream codeStreamBuffer outBlock'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!
- 
- !LzwGifDecoder commentStamp: '' prior: 0!
- I implement the modified Lempel-Ziv-Welch (LZW) algorithm for lossless GIF decompression. My primary purpose is to decode streams of bytes that have been encoded with this modified version of LZW as used in the GIF standard.
- 
- My instances require, at minimum, a maximum code size (via #maxCode:), a minimum code size (via #minimumCodeSize:), and of course a stream of bytes to decode (via #codeStream:). Once these are set, implementors can simply send the #decode message, which will respond with a decoded ByteArray.
- 
- Optionally, implementors can make use of the #onDecodedBit: message, which takes a Block with a single argument corresponding to a decoded bit. This Block is called each time a complete byte/bit-level value for the bitmap has been decoded.
- 
- For an example of use, see GIFReadWriter >> #readBitDataOnFrame:.
- 
- I am separated out from GIFReadWriter for clarity and better debugging.
- 
- 
- 
- See:
- https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Welch
- https://www.w3.org/Graphics/GIF/spec-gif89a.txt
- 
- !

Item was removed:
- ----- Method: LzwGifDecoder>>bufferData (in category 'as yet unclassified') -----
- bufferData
- 	"The GIF Format stores the data for each image in sub-blocks of up to 255 bytes.
- 	Decoding LZW for such small chunks adds a LOT of overhead.
- 	So instead, we buffer *all* of the data into one ByteArray and provide stream access
- 	to it.
- 	Data sub-blocks are structured such that the first byte gives the size of the data chunk
- 	that follows. A size of 0 indicates that there is no more data to deal with"
- 	| chunkSize buff |
- 	buff := WriteStream on: ByteArray new.
- 	chunkSize := codeStream next.
- 	[ chunkSize > 0 ] whileTrue: [
- 		buff nextPutAll: (codeStream next: chunkSize).
- 		chunkSize := codeStream next ].
- 	"chunkSize > 0 ifTrue: [ buff nextPutAll: (codeStream next: chunkSize)]."
- 	codeStreamBuffer := buff contents readStream!

Item was removed:
- ----- Method: LzwGifDecoder>>checkCodeSize (in category 'private') -----
- checkCodeSize
- 	"Ensure that the next available code to enter
- 	into the table is not equal to the bitMask.
- 	If it is, we increment the code size and update the
- 	mask value."
- 	nextAvailableCode := nextAvailableCode + 1.
- 	(nextAvailableCode bitAnd: bitMask) = 0
- 		ifTrue: [ 
- 			"GIF89a specifies a 'deferred' clearCode
- 			implementation, which means we keep going
- 			with the current table even if its full but
- 			a clear hasn't been found. We use the max
- 			code size at that point."
- 			nextAvailableCode >= maxCode ifTrue: [ ^ self ].
- 			codeSize := codeSize + 1.
- 			bitMask := bitMask + nextAvailableCode ].!

Item was removed:
- ----- Method: LzwGifDecoder>>codeStream: (in category 'private') -----
- codeStream: aReadableStream 
- 	"Set the stream of encoded bytes we will decode
- 	to be the internal codeStream. We read off the first
- 	byte immediately, which tells us how many subsequent bytes
- 	to use in our buffer for decoding"
- 	| chunkSize buff |
- 	codeStream := aReadableStream.
- 	"chunkSize := codeStream next.
- 	codeStreamBuffer := ReadStream on: (codeStream next: chunkSize)."
- 	self bufferData
- 	!

Item was removed:
- ----- Method: LzwGifDecoder>>decode (in category 'api') -----
- decode
- 	| currentCode prevCode outStream |
- 	self initializeTables.
- 	outStream := WriteStream with: (ByteArray new).
- 	numLeftoverBits := 0.
- 	currentCode := self nextCode.
- 	currentCode = clearCode ifFalse: [ ^ self error: 'First code on the stream should always be the clear code!!' ].
- 	
- 	"The first real code simply gets output
- 	onto the stream, then we enter the loop"
- 	currentCode := self nextCode.
- 	self writeBit: currentCode on: outStream.
- 	prevCode := currentCode.
- 	currentCode := self nextCode.
- 	[ currentCode = eoiCode ] whileFalse: [ 
- 		currentCode = clearCode
- 			ifTrue: [ 
- 				self initializeTables.
- 				currentCode := self nextCode.
- 				self
- 					writeBit: (suffixTable at: (currentCode + 1))
- 					on: outStream.
- 				prevCode := nil ]
- 			ifFalse: [ self handleCode: currentCode withPreviousCode: prevCode on: outStream ].
- 		prevCode := currentCode.
- 		currentCode := self nextCode ].
- 	^ outStream contents.
- 
- 	
- 	!

Item was removed:
- ----- Method: LzwGifDecoder>>handleCode:withPreviousCode:on: (in category 'private') -----
- handleCode: anInteger withPreviousCode: prevInteger on: aWriteStream
- 	"Check for the code in the tables
- 	and perform the appropriate LZW action"
- 	| first searchIndex searchStack |
- 	"The code already exists in the table"
- 	anInteger < nextAvailableCode
- 		ifTrue: [ 
- 			anInteger < clearCode
- 				"If it's less than the clearCode
- 				then it is one of the original entries
- 				and we can simply use the suffix"
- 				ifTrue: [ 
- 					first := (suffixTable at: (anInteger + 1)).
- 					self writeBit: first on: aWriteStream ]
- 				"Otherwise we need to loop backwards along
- 				the prefix index values and take the suffix each
- 				time"
- 				ifFalse: [ 
- 					searchStack := OrderedCollection new.
- 					searchIndex := anInteger + 1.
- 					[ searchIndex > clearCode ] whileTrue: [ 
- 						searchStack add: (suffixTable at: searchIndex).
- 						searchIndex := (prefixTable at: searchIndex) + 1 ].
- 					searchStack add: (suffixTable at: searchIndex).
- 					first := searchStack last.
- 					searchStack reverseDo: [ :int |
- 						self writeBit: int on: aWriteStream ] ]. 
- 			]
- 		ifFalse: [ 
- 			"Here, the incoming code is not yet in the code tables"
- 			prevInteger < clearCode
- 				ifTrue: [ 
- 					first := (suffixTable at: (prevInteger + 1)).
- 					self
- 						writeBit: first on: aWriteStream;
- 						writeBit: first on: aWriteStream.
- 					 ]
- 				ifFalse: [ 
- 					searchStack := OrderedCollection new.
- 					searchIndex := prevInteger + 1.
- 					[ searchIndex > clearCode ] whileTrue: [ 
- 						searchStack add: (suffixTable at: searchIndex).
- 						searchIndex := (prefixTable at: searchIndex) + 1 ].
- 					searchStack add: (suffixTable at: searchIndex).
- 					first := searchStack last.
- 					searchStack reverseDo: [ :int |
- 						self writeBit: int on: aWriteStream ].
- 					self writeBit: first on: aWriteStream ]. 
- 			].
- 		"We add prevCode and the new
- 		suffix to a new entry in the code table, but
- 		only if we aren't at the max. NOTE: due to
- 		GIF 89a spec's 'deferred clear', if you get to
- 		the maxCode and haven't seen a clear, you stop
- 		writing to the tables but continue querying."
- 		nextAvailableCode >= maxCode
- 			ifFalse: [ 
- 				suffixTable at: (nextAvailableCode + 1) put: first.
- 				prefixTable at: (nextAvailableCode + 1) put: prevInteger ].
- 		self checkCodeSize.!

Item was removed:
- ----- Method: LzwGifDecoder>>initializeTables (in category 'initialization') -----
- initializeTables
- 	"The two arrays are our lookup tables.
- 	We do this instead of Dictionaries because
- 	the method is much, much faster"
- 	prefixTable := Array new: (maxCode).
- 	suffixTable := Array new: (maxCode).
- 	
- 	"The initial code size and mask settings
- 	also get reinitialized each time"
- 	codeSize := minimumCodeSize + 1.
- 	clearCode := (1 bitShift: minimumCodeSize).
- 	eoiCode := clearCode + 1.
- 	nextAvailableCode := clearCode + 2.
- 	bitMask := (1 bitShift: codeSize) - 1.
- 	
- 	"Fill the tables with the initial values"
- 	1 to: clearCode do: [ :n |
- 		prefixTable at: n put: (n - 1).
- 		suffixTable at: n put: (n - 1) ].!

Item was removed:
- ----- Method: LzwGifDecoder>>maxCode: (in category 'accessing') -----
- maxCode: anInteger 
- 	maxCode := anInteger!

Item was removed:
- ----- Method: LzwGifDecoder>>minimumCodeSize: (in category 'accessing') -----
- minimumCodeSize: anInteger 
- 	minimumCodeSize := anInteger!

Item was removed:
- ----- Method: LzwGifDecoder>>nextByte (in category 'private - packing') -----
- nextByte
- 	^ codeStreamBuffer next!

Item was removed:
- ----- Method: LzwGifDecoder>>nextCode (in category 'private') -----
- nextCode
- 	| integer numBitsRead newRemainder shiftAmount byte |
- 	"Retrieve the next code of codeSize bits.
- 	Store the remaining bits etc for later computation"
- 	integer := 0.
- 	numLeftoverBits = 0
- 		ifTrue: [ 
- 			numBitsRead := 8.
- 			shiftAmount := 0 ]
- 		ifFalse: [ 
- 			numBitsRead := numLeftoverBits.
- 			shiftAmount := numLeftoverBits - 8 ].
- 		[ numBitsRead < codeSize ] whileTrue: [ 
- 			byte := self nextByte.
- 			byte == nil ifTrue: [ ^ eoiCode ].
- 			integer := integer + (byte bitShift: shiftAmount).
- 			shiftAmount := shiftAmount + 8.
- 			numBitsRead := numBitsRead + 8 ].
- 		(newRemainder := numBitsRead - codeSize) = 0
- 			ifTrue: [ byte := self nextByte ]
- 			ifFalse: [ byte := self peekByte ].
- 		byte == nil ifTrue: [ ^ eoiCode ].
- 		numLeftoverBits := newRemainder.
- 		^ integer + (byte bitShift: shiftAmount) bitAnd: bitMask.!

Item was removed:
- ----- Method: LzwGifDecoder>>onDecodedBit: (in category 'accessing') -----
- onDecodedBit: aBlock
- 	"This block will be executed once each time a new
- 	value is decoded from the stream, with the value
- 	as the sole argument passed to the block"
- 	outBlock := aBlock!

Item was removed:
- ----- Method: LzwGifDecoder>>peekByte (in category 'private - packing') -----
- peekByte
- 	^ codeStreamBuffer peek!

Item was removed:
- ----- Method: LzwGifDecoder>>writeBit:on: (in category 'writing') -----
- writeBit: anInteger on: aWriteStream
- 	"Write the incoming decoded value onto a
- 	writestream. If I have an outBlock set, 
- 	send this value also"
- 	aWriteStream nextPut: anInteger.
- 	outBlock ifNil: [ ^ self ].
- 	outBlock value: anInteger.!

Item was removed:
- Object subclass: #LzwGifEncoder
- 	instanceVariableNames: 'suffixTable prefixTable eoiCode clearCode codeSize minimumCodeSize maxCode nextAvailableCode numLeftoverBits bitBuffer codeStream codeStreamBuffer rowByteSize xPos yPos dimensions'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!
- 
- !LzwGifEncoder commentStamp: '' prior: 0!
- I implement the modified Lempel-Ziv-Welch (LZW) algorithm for lossless GIF bitmap compression. My primary purpose is to encode/compress streams of bitmap bytes as specified by the GIF standard.
- 
- My instances require at minimum:
- - A size of bytes in a row of bitmap bits for the image (#rowByteSize:)
- - The extent of the image being encoded (#extent:)
- - An array of bits in a bitmap (as bytes) for encoding (sent with #encode:)
- - A stream of Bytes on which to output the encoded bytes (#codeStream:)
- - A minimum code size as specified from GIF header information (#minimimCodeSize:)
- 
- Once all of these are set, implementors simply send the #encode: message along with a
- collection of bitmap values as bytes that need to be encoded. Instead of responding with a collection of encoded bytes, #encode: will write to the output stream specified by #codeStream: directly.
- 
- For an example of use, see GIFReadWriter >> #writeBitData:
- 
- NOTE: LZW compression for GIFs is complex and the #encode: method is largely taken verbatim from Kazuki Yasumatsu's 1995 Squeak implementation (as opposed to the Decoder, which was heavily refactored for readability and comprehension). Any contributions to fleshing this out in a comprehensible way are much appreciated!!
- 
- See:
- https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Welch
- https://www.w3.org/Graphics/GIF/spec-gif89a.txt!

Item was removed:
- ----- Method: LzwGifEncoder>>checkCodeSize (in category 'private') -----
- checkCodeSize
- 	"Determine whether or not we need to increment
- 	the codeSize"
- 	(nextAvailableCode > maxCode and: [ codeSize < 12 ])
- 		ifTrue: [ 
- 			codeSize := codeSize + 1.
- 			maxCode := (1 bitShift: codeSize) - 1 ].!

Item was removed:
- ----- Method: LzwGifEncoder>>checkSettings (in category 'private') -----
- checkSettings
- 	"Ensure that the appropriate variables
- 	that are needed for proper encoding
- 	have been set"
- 	codeStream ifNil: [ ^ self error: 'You must set a codeStream (byte stream) to write onto!!' ].
- 	dimensions ifNil: [ ^ self error: 'You must provide the extent of the image we will encode!!' ].
- 	rowByteSize ifNil: [ ^ self error: 'You must provide a rowByteSize for the supplied image bits!!' ].!

Item was removed:
- ----- Method: LzwGifEncoder>>codeStream: (in category 'accessing') -----
- codeStream: aByteStream
- 	codeStream := aByteStream.!

Item was removed:
- ----- Method: LzwGifEncoder>>dimensions: (in category 'accessing') -----
- dimensions: anExtentPoint
- 	"Set the extent (as point) of the
- 	image that will be encoded"
- 	dimensions := anExtentPoint!

Item was removed:
- ----- Method: LzwGifEncoder>>encode: (in category 'converting') -----
- encode: bits
- 	| maxBits maxMaxCode tSize tShift fCode ent pixel index nomatch disp |
- 	self checkSettings.
- 	xPos := yPos := 0.
- 	codeStream nextPut: minimumCodeSize.
- 	bitBuffer := 0.
- 	numLeftoverBits := 0.
- 	codeStreamBuffer := WriteStream on: (ByteArray new: 256).
- 	self initializeParameters.
- 	
- 	"These temp vars are taken from the
- 	original GIFReadWriter implementation"
- 	maxBits := 12.
- 	maxMaxCode := 1 bitShift: maxBits.
- 	tSize := 5003.
- 	prefixTable := Array new: tSize.
- 	suffixTable := Array new: tSize.
- 	tShift := 0.
- 	fCode := tSize.
- 	[ fCode < 65536 ] whileTrue: [ 
- 		tShift := tShift + 1.
- 		fCode := fCode * 2 ].
- 	tShift := 8 - tShift.
- 	1 to: tSize do: [ :i |
- 		suffixTable at: i put: -1 ].
- 	
- 	"We immediately write the clearCode
- 	to the output stream"
- 	self writeCodeAndCheckCodeSize: clearCode.
- 	
- 	"This loop is also taken from the original
- 	GIFReadWriter implementation"
- 	ent := self readPixelFrom: bits.
- 	[ (pixel := self readPixelFrom: bits) == nil ] whileFalse: 
- 		[ fCode := (pixel bitShift: maxBits) + ent.
- 		index := ((pixel bitShift: tShift) bitXor: ent) + 1.
- 		(suffixTable at: index) = fCode 
- 			ifTrue: [ ent := prefixTable at: index ]
- 			ifFalse: 
- 				[ nomatch := true.
- 				(suffixTable at: index) >= 0 ifTrue: 
- 					[ disp := tSize - index + 1.
- 					index = 1 ifTrue: [ disp := 1 ].
- 					"probe"
- 					
- 					[ (index := index - disp) < 1 ifTrue: [ index := index + tSize ].
- 					(suffixTable at: index) = fCode ifTrue: 
- 						[ ent := prefixTable at: index.
- 						nomatch := false
- 						"continue whileFalse:" ].
- 					nomatch and: [ (suffixTable at: index) > 0 ] ] whileTrue: 
- 						[ "probe"
- 						 ] ].
- 				"nomatch"
- 				nomatch ifTrue: 
- 					[ self writeCodeAndCheckCodeSize: ent.
- 					ent := pixel.
- 					nextAvailableCode < maxMaxCode 
- 						ifTrue: 
- 							[ prefixTable 
- 								at: index
- 								put: nextAvailableCode.
- 							suffixTable 
- 								at: index
- 								put: fCode.
- 							nextAvailableCode := nextAvailableCode + 1 ]
- 						ifFalse: 
- 							[ self writeCodeAndCheckCodeSize: clearCode.
- 							1 
- 								to: tSize
- 								do: 
- 									[ :i | 
- 									suffixTable 
- 										at: i
- 										put: -1 ].
- 							self initializeParameters ] ] ] ].
- 	prefixTable := suffixTable := nil.
- 	self writeCodeAndCheckCodeSize: ent.
- 	self writeCodeAndCheckCodeSize: eoiCode.
- 	self flushBits.
- 	codeStream nextPut: 0.
- 				!

Item was removed:
- ----- Method: LzwGifEncoder>>extent: (in category 'accessing') -----
- extent: anExtentPoint
- 	"Set the extent (as point) of the
- 	image that will be encoded"
- 	dimensions := anExtentPoint!

Item was removed:
- ----- Method: LzwGifEncoder>>flushBits (in category 'private - bits access') -----
- flushBits
- 	numLeftoverBits = 0 ifFalse: 
- 		[ self nextBytePut: bitBuffer.
- 		numLeftoverBits := 0 ].
- 	self flushBuffer!

Item was removed:
- ----- Method: LzwGifEncoder>>flushBuffer (in category 'private') -----
- flushBuffer
- 	"Write out the current codeStreamBuffer size,
- 	followed by its actual contents, to the true
- 	output codeStream"
- 	codeStreamBuffer isEmpty ifTrue: [ ^ self ].
- 	codeStream
- 		nextPut: codeStreamBuffer size;
- 		nextPutAll: codeStreamBuffer contents.
- 	codeStreamBuffer := (ByteArray new: 256) writeStream.!

Item was removed:
- ----- Method: LzwGifEncoder>>initializeParameters (in category 'initialization') -----
- initializeParameters
- 	"The initial code size and mask settings
- 	also get reinitialized each time"
- 	codeSize := minimumCodeSize + 1.
- 	clearCode := (1 bitShift: minimumCodeSize).
- 	eoiCode := clearCode + 1.
- 	nextAvailableCode := clearCode + 2.
- 	maxCode := (1 bitShift: codeSize) - 1.!

Item was removed:
- ----- Method: LzwGifEncoder>>minimumCodeSize: (in category 'accessing') -----
- minimumCodeSize: anInteger
- 	minimumCodeSize := anInteger!

Item was removed:
- ----- Method: LzwGifEncoder>>nextBytePut: (in category 'private - packing') -----
- nextBytePut: anInteger
- 	"Write a complete byte to the output byteStream.
- 	Be sure to reset one we reach the limit, which is
- 	255 for GIF files. Then write the length of the next
- 	byte chunks to the stream also"
- 	codeStreamBuffer nextPut: anInteger.
- 	codeStreamBuffer size >= 254
- 		ifTrue: [ self flushBuffer ].!

Item was removed:
- ----- Method: LzwGifEncoder>>nextCodePut: (in category 'private - bits access') -----
- nextCodePut: anInteger
- 	"Attempt to put the bits on the
- 	output stream. If we have remaining bits,
- 	then we need to use bitwise operations to
- 	fill the next byte properly before putting
- 	it on the output stream"
- 	| numBitsWritten shiftCount newInteger |
- 	shiftCount := 0.
- 	numLeftoverBits = 0
- 		ifTrue: [ 
- 			numBitsWritten := 8.
- 			newInteger := anInteger ]
- 		ifFalse: [ 
- 			numBitsWritten := numLeftoverBits.
- 			newInteger := bitBuffer + (anInteger bitShift: 8 - numLeftoverBits) ].
- 	[ numBitsWritten < codeSize ] whileTrue: [ 
- 		self nextBytePut: ((newInteger bitShift: shiftCount) bitAnd: 255).
- 		shiftCount := shiftCount - 8.
- 		numBitsWritten := numBitsWritten + 8 ].
- 	(numLeftoverBits := numBitsWritten - codeSize) = 0
- 		ifTrue: [ self nextBytePut: (newInteger bitShift: shiftCount) ]
- 		ifFalse: [ bitBuffer := newInteger bitShift: shiftCount ].
- 	^ anInteger
- 	!

Item was removed:
- ----- Method: LzwGifEncoder>>readPixelFrom: (in category 'private - encoding') -----
- readPixelFrom: bits
- 	"Using the current x and y positions and
- 	the specified byte size for a row, determine
- 	the value for the next pixel in the provided bits"
- 	| pixel |
- 	yPos >= (dimensions y) ifTrue: [ ^ nil ].
- 	pixel := bits byteAt: yPos * rowByteSize + xPos + 1.
- 	self updatePixelPosition.
- 	^ pixel
- 	!

Item was removed:
- ----- Method: LzwGifEncoder>>rowByteSize: (in category 'accessing') -----
- rowByteSize: anInteger
- 	rowByteSize := anInteger!

Item was removed:
- ----- Method: LzwGifEncoder>>updatePixelPosition (in category 'private') -----
- updatePixelPosition
- 	"Increment the xPos. If we are at the width
- 	position, set xPos to 0 and increment the yPos"
- 	xPos := xPos + 1.
- 	xPos >= (dimensions x) ifFalse: [ ^ self ].
- 	xPos := 0.
- 	yPos := yPos + 1.!

Item was removed:
- ----- Method: LzwGifEncoder>>writeCodeAndCheckCodeSize: (in category 'writing') -----
- writeCodeAndCheckCodeSize: aCode
- 	self nextCodePut: aCode.
- 	self checkCodeSize.!

Item was removed:
- HostWindowProxy subclass: #MacOS9WindowProxy
- 	instanceVariableNames: 'windowClass windowAttributes'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-External-Ffenestri'!

Item was removed:
- ----- Method: MacOS9WindowProxy class>>altDBoxProc (in category 'constants') -----
- altDBoxProc
- 	^3
- !

Item was removed:
- ----- Method: MacOS9WindowProxy class>>closeBoxAttribute (in category 'constants') -----
- closeBoxAttribute
- 	^1!

Item was removed:
- ----- Method: MacOS9WindowProxy class>>dBoxProc (in category 'constants') -----
- dBoxProc
- 	^1!

Item was removed:
- ----- Method: MacOS9WindowProxy class>>documentProc (in category 'constants') -----
- documentProc
- 	^0!

Item was removed:
- ----- Method: MacOS9WindowProxy class>>documentWindowClass (in category 'constants') -----
- documentWindowClass
- 	^self zoomDocProc!

Item was removed:
- ----- Method: MacOS9WindowProxy class>>floatGrowProc (in category 'constants') -----
- floatGrowProc
- 	^1987
- !

Item was removed:
- ----- Method: MacOS9WindowProxy class>>floatProc (in category 'constants') -----
- floatProc
- 	^1985
- !

Item was removed:
- ----- Method: MacOS9WindowProxy class>>floatSideGrowProc (in category 'constants') -----
- floatSideGrowProc
- 	^1995
- !

Item was removed:
- ----- Method: MacOS9WindowProxy class>>floatSideProc (in category 'constants') -----
- floatSideProc
- 	^1993
- !

Item was removed:
- ----- Method: MacOS9WindowProxy class>>floatSideZoomGrowProc (in category 'constants') -----
- floatSideZoomGrowProc
- 	^1999!

Item was removed:
- ----- Method: MacOS9WindowProxy class>>floatSideZoomProc (in category 'constants') -----
- floatSideZoomProc
- 	^1997!

Item was removed:
- ----- Method: MacOS9WindowProxy class>>floatZoomGrowProc (in category 'constants') -----
- floatZoomGrowProc
- 	^1991
- !

Item was removed:
- ----- Method: MacOS9WindowProxy class>>floatZoomProc (in category 'constants') -----
- floatZoomProc
- 	^1989
- !

Item was removed:
- ----- Method: MacOS9WindowProxy class>>isActiveHostWindowProxyClass (in category 'system startup') -----
- isActiveHostWindowProxyClass
- "Am I active?"
- 	^Smalltalk platformName  = 'Mac OS' and: [Smalltalk osVersion asInteger < 1000]!

Item was removed:
- ----- Method: MacOS9WindowProxy class>>movableDBoxProc (in category 'constants') -----
- movableDBoxProc
- 	^5
- !

Item was removed:
- ----- Method: MacOS9WindowProxy class>>noAttributes (in category 'constants') -----
- noAttributes
- 	^0!

Item was removed:
- ----- Method: MacOS9WindowProxy class>>noGrowDocProc (in category 'constants') -----
- noGrowDocProc
- 	^4
- !

Item was removed:
- ----- Method: MacOS9WindowProxy class>>plainDBox (in category 'constants') -----
- plainDBox
- 	^2!

Item was removed:
- ----- Method: MacOS9WindowProxy class>>rDocProc (in category 'constants') -----
- rDocProc
- 	^16
- !

Item was removed:
- ----- Method: MacOS9WindowProxy class>>standardDocumentAttributes (in category 'constants') -----
- standardDocumentAttributes 
- 	^self closeBoxAttribute!

Item was removed:
- ----- Method: MacOS9WindowProxy class>>zoomDocProc (in category 'constants') -----
- zoomDocProc
- 	^8!

Item was removed:
- ----- Method: MacOS9WindowProxy class>>zoomNoGrow (in category 'constants') -----
- zoomNoGrow
- 	^12
- !

Item was removed:
- ----- Method: MacOS9WindowProxy>>attributes (in category 'accessing') -----
- attributes
- 	| val |
- 	val := ByteArray new: 8.
- 	val 
- 		unsignedLongAt: 1
- 		put: windowClass
- 		bigEndian: Smalltalk isBigEndian.
- 	val 
- 		unsignedLongAt: 5
- 		put: windowAttributes
- 		bigEndian: Smalltalk isBigEndian.
- 	^ val!

Item was removed:
- ----- Method: MacOS9WindowProxy>>defaultWindowType (in category 'metrics') -----
- defaultWindowType
- 	self windowClass: self class documentWindowClass.
- 	self windowAttributes: self class standardDocumentAttributes.!

Item was removed:
- ----- Method: MacOS9WindowProxy>>windowAttributes (in category 'accessing') -----
- windowAttributes
- 	^windowAttributes
- !

Item was removed:
- ----- Method: MacOS9WindowProxy>>windowAttributes: (in category 'accessing') -----
- windowAttributes: aNumber
- 	windowAttributes := aNumber!

Item was removed:
- ----- Method: MacOS9WindowProxy>>windowClass (in category 'accessing') -----
- windowClass
- 	^windowClass
- !

Item was removed:
- ----- Method: MacOS9WindowProxy>>windowClass: (in category 'accessing') -----
- windowClass: aNumber
- 	windowClass := aNumber!

Item was removed:
- HostWindowProxy subclass: #MacOSXWindowProxy
- 	instanceVariableNames: 'windowClass windowAttributes'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-External-Ffenestri'!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>activatesAttribute (in category 'constants') -----
- activatesAttribute 
- 	^2 raisedTo: 17!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>alertWindowClass (in category 'constants') -----
- alertWindowClass
- 	^1!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>altPlainWindowClass (in category 'constants') -----
- altPlainWindowClass
- 	^16!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>asyncDragAttribute (in category 'constants') -----
- asyncDragAttribute 
- 	^2 raisedTo: 23!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>closeBoxAttribute (in category 'constants') -----
- closeBoxAttribute
- 	^2 raisedTo: 0!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>collapseBoxAttribute (in category 'constants') -----
- collapseBoxAttribute
- 	^2 raisedTo: 3!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>compositingAttribute (in category 'constants') -----
- compositingAttribute 
- 	^2 raisedTo: 19!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>documentWindowClass (in category 'constants') -----
- documentWindowClass
- 	^6!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>doesNotCycleAttribute (in category 'constants') -----
- doesNotCycleAttribute
- 	^2 raisedTo: 15!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>drawerWindowClass (in category 'constants') -----
- drawerWindowClass
- 	^20!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>floatingWindowClass (in category 'constants') -----
- floatingWindowClass
- 	^5!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>fullZoomAttribute (in category 'constants') -----
- fullZoomAttribute
- 	^self verticalZoomAttribute bitOr: self horizontalZoomAttribute!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>helpWindowClass (in category 'constants') -----
- helpWindowClass
- 	^10!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>hideOnFullScreenAttribute (in category 'constants') -----
- hideOnFullScreenAttribute 
- 	^2 raisedTo: 26!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>hideOnSuspendAttribute (in category 'constants') -----
- hideOnSuspendAttribute 
- 	^2 raisedTo: 24!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>horizontalZoomAttribute (in category 'constants') -----
- horizontalZoomAttribute
- 	^2 raisedTo: 1!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>ignoreClicksAttribute (in category 'constants') -----
- ignoreClicksAttribute 
- 	^2 raisedTo: 29!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>inWindowMenuAttribute (in category 'constants') -----
- inWindowMenuAttribute 
- 	^2 raisedTo: 27!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>isActiveHostWindowProxyClass (in category 'system startup') -----
- isActiveHostWindowProxyClass
- "Am I active?"
- 	^Smalltalk platformName  = 'Mac OS' and: [Smalltalk osVersion asInteger >= 1000]!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>liveResizeAttribute (in category 'constants') -----
- liveResizeAttribute 
- 	^2 raisedTo: 28!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>metalAttribute (in category 'constants') -----
- metalAttribute
- 	^2 raisedTo: 8!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>modalWindowClass (in category 'constants') -----
- modalWindowClass
- 	^3!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>movableAlertWindowClass (in category 'constants') -----
- movableAlertWindowClass
- 	^2!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>movableModalWindowClass (in category 'constants') -----
- movableModalWindowClass
- 	^4!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>noAttributes (in category 'constants') -----
- noAttributes
- 	^0!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>noConstrainAttribute (in category 'constants') -----
- noConstrainAttribute 
- 	^2 raisedTo: 31!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>noShadowAttribute (in category 'constants') -----
- noShadowAttribute 
- 	^2 raisedTo: 21!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>noUpdatesAttribute (in category 'constants') -----
- noUpdatesAttribute 
- 	^2 raisedTo: 16!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>opaqueForEventsAttribute (in category 'constants') -----
- opaqueForEventsAttribute 
- 	^2 raisedTo: 18!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>overlayWindowClass (in category 'constants') -----
- overlayWindowClass
- 	^14!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>plainWindowClass (in category 'constants') -----
- plainWindowClass
- 	^13!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>resizableAttribute (in category 'constants') -----
- resizableAttribute
- 	^2 raisedTo: 4!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>sheetAlertWindowClass (in category 'constants') -----
- sheetAlertWindowClass
- 	^15!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>sheetWindowClass (in category 'constants') -----
- sheetWindowClass
- 	^11!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>sideTitlebarAttribute (in category 'constants') -----
- sideTitlebarAttribute
- 	^2 raisedTo: 5!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>simpleWindowClass (in category 'constants') -----
- simpleWindowClass
- 	^18!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>standardDocumentAttributes (in category 'constants') -----
- standardDocumentAttributes 
- 	^self noConstrainAttribute + self standardHandlerAttribute + self closeBoxAttribute + self fullZoomAttribute + self collapseBoxAttribute + self resizableAttribute
- 
- 
- "16r8200001E printStringBase: 2 '2r 10000010 00000000 00000000 00011110'"!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>standardFloatingAttributes (in category 'constants') -----
- standardFloatingAttributes
- 	^self closeBoxAttribute + self collapseBoxAttribute
- !

Item was removed:
- ----- Method: MacOSXWindowProxy class>>standardHandlerAttribute (in category 'constants') -----
- standardHandlerAttribute 
- 	^2 raisedTo: 25!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>toolbarButtonAttribute (in category 'constants') -----
- toolbarButtonAttribute
- 	^2 raisedTo: 6!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>toolbarWindowClass (in category 'constants') -----
- toolbarWindowClass
- 	^12!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>utilityWindowClass (in category 'constants') -----
- utilityWindowClass
- 	^8!

Item was removed:
- ----- Method: MacOSXWindowProxy class>>verticalZoomAttribute (in category 'constants') -----
- verticalZoomAttribute
- 	^2 raisedTo: 2!

Item was removed:
- ----- Method: MacOSXWindowProxy>>attributes (in category 'accessing') -----
- attributes
- 	| val |
- 	val := ByteArray new: 8.
- 	val 
- 		unsignedLongAt: 1
- 		put: windowClass
- 		bigEndian: Smalltalk isBigEndian.
- 	val 
- 		unsignedLongAt: 5
- 		put: windowAttributes
- 		bigEndian: Smalltalk isBigEndian.
- 	^ val!

Item was removed:
- ----- Method: MacOSXWindowProxy>>defaultWindowType (in category 'metrics') -----
- defaultWindowType
- 	self windowClass: self class documentWindowClass.
- 	self windowAttributes: self class standardDocumentAttributes.!

Item was removed:
- ----- Method: MacOSXWindowProxy>>windowAttributes (in category 'accessing') -----
- windowAttributes
- 	^windowAttributes
- !

Item was removed:
- ----- Method: MacOSXWindowProxy>>windowAttributes: (in category 'accessing') -----
- windowAttributes: aNumber
- 	windowAttributes := aNumber!

Item was removed:
- ----- Method: MacOSXWindowProxy>>windowClass (in category 'accessing') -----
- windowClass
- 	^windowClass
- !

Item was removed:
- ----- Method: MacOSXWindowProxy>>windowClass: (in category 'accessing') -----
- windowClass: aNumber
- 	windowClass := aNumber!

Item was removed:
- DisplayTransform variableWordSubclass: #MatrixTransform2x3
- 	instanceVariableNames: ''
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Transformations'!
- 
- !MatrixTransform2x3 commentStamp: '<historical>' prior: 0!
- This class represents a transformation for points, that is a combination of scale, offset, and rotation. It is implemented as a 2x3 matrix containing the transformation from the local coordinate system in the global coordinate system. Thus, transforming points from local to global coordinates is fast and cheap whereas transformations from global to local coordinate systems are relatively expensive.
- 
- Implementation Note: It is assumed that the transformation deals with Integer points. All transformations will return Integer coordinates (even though float points may be passed in here).!

Item was removed:
- ----- Method: MatrixTransform2x3 class>>identity (in category 'instance creation') -----
- identity
- 	^self new setScale: 1.0!

Item was removed:
- ----- Method: MatrixTransform2x3 class>>new (in category 'instance creation') -----
- new
- 	^self new: 6!

Item was removed:
- ----- Method: MatrixTransform2x3 class>>newFromStream: (in category 'instance creation') -----
- newFromStream: s
- 	"Only meant for my subclasses that are raw bits and word-like.  For quick unpack form the disk."
- 	self isPointers | self isWords not ifTrue: [^ super newFromStream: s].
- 		"super may cause an error, but will not be called."
- 	^ s nextWordsInto: (self new: 6)!

Item was removed:
- ----- Method: MatrixTransform2x3 class>>transformFromLocal:toGlobal: (in category 'instance creation') -----
- transformFromLocal: localBounds toGlobal: globalBounds
- 	^((self withOffset: (globalBounds center)) composedWithLocal:
- 		(self withScale: (globalBounds extent / localBounds extent) asFloatPoint))
- 			composedWithLocal: (self withOffset: localBounds center negated)
- "
- 	^(self identity)
- 		setScale: (globalBounds extent / localBounds extent) asFloatPoint;
- 		setOffset: localBounds center negated asFloatPoint;
- 		composedWithGlobal:(self withOffset: globalBounds center asFloatPoint)
- "!

Item was removed:
- ----- Method: MatrixTransform2x3 class>>withAngle: (in category 'instance creation') -----
- withAngle: angle
- 	^self new setAngle: angle!

Item was removed:
- ----- Method: MatrixTransform2x3 class>>withOffset: (in category 'instance creation') -----
- withOffset: aPoint
- 	^self identity setOffset: aPoint!

Item was removed:
- ----- Method: MatrixTransform2x3 class>>withRotation: (in category 'instance creation') -----
- withRotation: angle
- 	^self new setAngle: angle!

Item was removed:
- ----- Method: MatrixTransform2x3 class>>withScale: (in category 'instance creation') -----
- withScale: aPoint
- 	^self new setScale: aPoint!

Item was removed:
- ----- Method: MatrixTransform2x3>>= (in category 'comparing') -----
- = aMatrixTransform2x3 
- 	| length |
- 	<primitive: 'primitiveEqual' module: 'FloatArrayPlugin'>
- 	self class = aMatrixTransform2x3 class ifFalse: [^ false].
- 	length := self size.
- 	length = aMatrixTransform2x3 size ifFalse: [^ false].
- 	1 to: self size do: [:i | (self at: i)
- 			= (aMatrixTransform2x3 at: i) ifFalse: [^ false]].
- 	^ true!

Item was removed:
- ----- Method: MatrixTransform2x3>>a11 (in category 'element access') -----
- a11
- 	^self at: 1!

Item was removed:
- ----- Method: MatrixTransform2x3>>a11: (in category 'element access') -----
- a11: value
- 	 self at: 1 put: value!

Item was removed:
- ----- Method: MatrixTransform2x3>>a12 (in category 'element access') -----
- a12
- 	^self at: 2!

Item was removed:
- ----- Method: MatrixTransform2x3>>a12: (in category 'element access') -----
- a12: value
- 	 self at: 2 put: value!

Item was removed:
- ----- Method: MatrixTransform2x3>>a13 (in category 'element access') -----
- a13
- 	^self at: 3!

Item was removed:
- ----- Method: MatrixTransform2x3>>a13: (in category 'element access') -----
- a13: value
- 	 self at: 3 put: value!

Item was removed:
- ----- Method: MatrixTransform2x3>>a21 (in category 'element access') -----
- a21
- 	 ^self at: 4!

Item was removed:
- ----- Method: MatrixTransform2x3>>a21: (in category 'element access') -----
- a21: value
- 	 self at: 4 put: value!

Item was removed:
- ----- Method: MatrixTransform2x3>>a22 (in category 'element access') -----
- a22
- 	 ^self at: 5!

Item was removed:
- ----- Method: MatrixTransform2x3>>a22: (in category 'element access') -----
- a22: value
- 	 self at: 5 put: value!

Item was removed:
- ----- Method: MatrixTransform2x3>>a23 (in category 'element access') -----
- a23
- 	 ^self at: 6!

Item was removed:
- ----- Method: MatrixTransform2x3>>a23: (in category 'element access') -----
- a23: value
- 	 self at: 6 put: value!

Item was removed:
- ----- Method: MatrixTransform2x3>>asMatrixTransform2x3 (in category 'converting') -----
- asMatrixTransform2x3
- 	^self!

Item was removed:
- ----- Method: MatrixTransform2x3>>at: (in category 'accessing') -----
- at: index
- 	<primitive: 'primitiveAt' module: 'FloatArrayPlugin'>
- 	^Float fromIEEE32Bit: (self basicAt: index)!

Item was removed:
- ----- Method: MatrixTransform2x3>>at:put: (in category 'accessing') -----
- at: index put: value
- 	<primitive: 'primitiveAtPut' module: 'FloatArrayPlugin'>
- 	value isFloat 
- 		ifTrue:[self basicAt: index put: value asIEEE32BitWord]
- 		ifFalse:[self at: index put: value asFloat].
- 	^value!

Item was removed:
- ----- Method: MatrixTransform2x3>>byteSize (in category 'objects from disk') -----
- byteSize
- 	^self basicSize * self bytesPerBasicElement!

Item was removed:
- ----- Method: MatrixTransform2x3>>bytesPerBasicElement (in category 'objects from disk') -----
- bytesPerBasicElement
- 	"Answer the number of bytes that each of my basic elements requires.
- 	In other words:
- 		self basicSize * self bytesPerBasicElement
- 	should equal the space required on disk by my variable sized representation."
- 	^4!

Item was removed:
- ----- Method: MatrixTransform2x3>>bytesPerElement (in category 'objects from disk') -----
- bytesPerElement
- 
- 	^ 4.
- !

Item was removed:
- ----- Method: MatrixTransform2x3>>composedWithLocal: (in category 'composing') -----
- composedWithLocal: aTransformation
- 	"Return the composition of the receiver and the local transformation passed in"
- 	aTransformation isMatrixTransform2x3 ifFalse:[^super composedWithLocal: aTransformation].
- 	^self composedWithLocal: aTransformation asMatrixTransform2x3 into: self class new!

Item was removed:
- ----- Method: MatrixTransform2x3>>composedWithLocal:into: (in category 'composing') -----
- composedWithLocal: aTransformation into: result
- 	"Return the composition of the receiver and the local transformation passed in.
- 	Store the composed matrix into result."
- 	| a11 a12 a13 a21 a22 a23 b11 b12 b13 b21 b22 b23 matrix |
- 	<primitive: 'primitiveComposeMatrix' module: 'Matrix2x3Plugin'>
- 	matrix := aTransformation asMatrixTransform2x3.
- 	a11 := self a11.		b11 := matrix a11.
- 	a12 := self a12.		b12 := matrix a12.
- 	a13 := self a13.		b13 := matrix a13.
- 	a21 := self a21.		b21 := matrix a21.
- 	a22 := self a22.		b22 := matrix a22.
- 	a23 := self a23.		b23 := matrix a23.
- 	result a11: (a11 * b11) + (a12 * b21).
- 	result a12: (a11 * b12) + (a12 * b22).
- 	result a13: a13 + (a11 * b13) + (a12 * b23).
- 	result a21: (a21 * b11) + (a22 * b21).
- 	result a22: (a21 * b12) + (a22 * b22).
- 	result a23: a23 + (a21 * b13) + (a22 * b23).
- 	^result!

Item was removed:
- ----- Method: MatrixTransform2x3>>explorerContents (in category 'explorer') -----
- explorerContents
- 	^(Float32Array newFrom: self) explorerContents!

Item was removed:
- ----- Method: MatrixTransform2x3>>globalBounds:toLocal: (in category 'transforming rects') -----
- globalBounds: srcRect toLocal: dstRect
- 	"Transform aRectangle from global coordinates into local coordinates"
- 	<primitive: 'primitiveInvertRectInto' module: 'Matrix2x3Plugin'>
- 	^super globalBoundsToLocal: srcRect!

Item was removed:
- ----- Method: MatrixTransform2x3>>globalBoundsToLocal: (in category 'transforming rects') -----
- globalBoundsToLocal: aRectangle
- 	"Transform aRectangle from global coordinates into local coordinates"
- 	^self globalBounds: aRectangle toLocal: Rectangle new!

Item was removed:
- ----- Method: MatrixTransform2x3>>globalPointToLocal: (in category 'transforming points') -----
- globalPointToLocal: aPoint
- 	"Transform aPoint from global coordinates into local coordinates"
- 	<primitive: 'primitiveInvertPoint' module: 'Matrix2x3Plugin'>
- 	^(self invertPoint: aPoint) rounded!

Item was removed:
- ----- Method: MatrixTransform2x3>>hash (in category 'comparing') -----
- hash
- 	| result |
- 	<primitive: 'primitiveHashArray' module: 'FloatArrayPlugin'>
- 	result := 0.
- 	1 to: self size do:[:i| result := result + (self basicAt: i) ].
- 	^result bitAnd: 16r1FFFFFFF!

Item was removed:
- ----- Method: MatrixTransform2x3>>inverseTransformation (in category 'accessing') -----
- inverseTransformation
- 	"Return the inverse transformation of the receiver.
- 	The inverse transformation is computed by first calculating
- 	the inverse offset and then computing transformations
- 	for the two identity vectors (1 at 0) and (0 at 1)"
- 	| r1 r2 r3 m |
- 	r3 := self invertPoint: 0 at 0.
- 	r1 := (self invertPoint: 1 at 0) - r3.
- 	r2 := (self invertPoint: 0 at 1) - r3.
- 	m := self species new.
- 	m
- 		a11: r1 x; a12: r2 x; a13: r3 x;
- 		a21: r1 y; a22: r2 y; a23: r3 y.
- 	^m!

Item was removed:
- ----- Method: MatrixTransform2x3>>invertPoint: (in category 'transforming points') -----
- invertPoint: aPoint
- 	"Transform aPoint from global coordinates into local coordinates"
- 	| x y det a11 a12 a21 a22 detX detY |
- 	x := aPoint x asFloat - (self a13).
- 	y := aPoint y asFloat - (self a23).
- 	a11 := self a11.	a12 := self a12.
- 	a21 := self a21.	a22 := self a22.
- 	det := (a11 * a22) - (a12 * a21).
- 	det = 0.0 ifTrue:[^0 at 0]. "So we have at least a valid result"
- 	det := 1.0 / det.
- 	detX := (x * a22) - (a12 * y).
- 	detY := (a11 * y) - (x * a21).
- 	^(detX * det) @ (detY * det)!

Item was removed:
- ----- Method: MatrixTransform2x3>>isIdentity (in category 'testing') -----
- isIdentity
- 	"Return true if the receiver is the identity transform; that is, if applying to a point returns the point itself."
- 	<primitive: 'primitiveIsIdentity' module: 'Matrix2x3Plugin'>
- 	^self isPureTranslation and:[self a13 = 0.0 and:[self a23 = 0.0]]!

Item was removed:
- ----- Method: MatrixTransform2x3>>isMatrixTransform2x3 (in category 'testing') -----
- isMatrixTransform2x3
- 	"Return true if the receiver is 2x3 matrix transformation"
- 	^true!

Item was removed:
- ----- Method: MatrixTransform2x3>>isPureTranslation (in category 'testing') -----
- isPureTranslation
- 	"Return true if the receiver specifies no rotation or scaling."
- 	<primitive: 'primitiveIsPureTranslation' module: 'Matrix2x3Plugin'>
- 	^self a11 = 1.0 and:[self a12 = 0.0 and:[self a22 = 1.0 and:[self a21 = 0.0]]]!

Item was removed:
- ----- Method: MatrixTransform2x3>>localBounds:toGlobal: (in category 'transforming rects') -----
- localBounds: srcRect toGlobal: dstRect
- 	"Transform aRectangle from local coordinates into global coordinates"
- 	<primitive: 'primitiveTransformRectInto' module: 'Matrix2x3Plugin'>
- 	^super localBoundsToGlobal: srcRect!

Item was removed:
- ----- Method: MatrixTransform2x3>>localBoundsToGlobal: (in category 'transforming rects') -----
- localBoundsToGlobal: aRectangle
- 	"Transform aRectangle from local coordinates into global coordinates"
- 	^self localBounds: aRectangle toGlobal: Rectangle new!

Item was removed:
- ----- Method: MatrixTransform2x3>>localPointToGlobal: (in category 'transforming points') -----
- localPointToGlobal: aPoint
- 	"Transform aPoint from local coordinates into global coordinates"
- 	<primitive: 'primitiveTransformPoint' module: 'Matrix2x3Plugin'>
- 	^(self transformPoint: aPoint) rounded!

Item was removed:
- ----- Method: MatrixTransform2x3>>offset (in category 'accessing') -----
- offset
- 	"The translation applied to all transformed points."
- 	"Note: While other transform types also implement this method their actual behavior can differ. Only use it if you know what kind of transform you have on hand. Otherwise, use #localPointToGlobal: instead."
- 	^self a13 @ self a23!

Item was removed:
- ----- Method: MatrixTransform2x3>>offset: (in category 'accessing') -----
- offset: aPoint
- 	self a13: aPoint x asFloat.
- 	self a23: aPoint y asFloat.!

Item was removed:
- ----- Method: MatrixTransform2x3>>printOn: (in category 'printing') -----
- printOn: aStream
- 	aStream 
- 		nextPutAll: self class name;
- 		nextPut: $(;
- 		cr; print: self a11; tab; print: self a12; tab; print: self a13;
- 		cr; print: self a21; tab; print: self a22; tab; print: self a23;
- 		cr; nextPut:$).!

Item was removed:
- ----- Method: MatrixTransform2x3>>restoreEndianness (in category 'objects from disk') -----
- restoreEndianness
- 	"This word object was just read in from a stream.  It was stored in Big Endian (Mac) format.  Swap each pair of bytes (16-bit word), if the current machine is Little Endian.
- 	Why is this the right thing to do?  We are using memory as a byteStream.  High and low bytes are reversed in each 16-bit word, but the stream of words ascends through memory.  Different from a Bitmap."
- 
- 	| w b1 b2 b3 b4 |
- 	Smalltalk  isLittleEndian ifTrue: [
- 		1 to: self basicSize do: [:i |
- 			w := self basicAt: i.
- 			b1 := w digitAt: 1.
- 			b2 := w digitAt: 2.
- 			b3 := w digitAt: 3.
- 			b4 := w digitAt: 4.
- 			w := (b1 << 24) + (b2 << 16) + (b3 << 8) + b4.
- 			self basicAt: i put: w.
- 		]
- 	].
- 
- !

Item was removed:
- ----- Method: MatrixTransform2x3>>setAngle: (in category 'private') -----
- setAngle: angle
- 	"Set the raw rotation angle in the receiver"
- 	| rad s c |
- 	rad := angle degreesToRadians.
- 	s := rad sin.
- 	c := rad cos.
- 	self a11: c.
- 	self a12: s negated.
- 	self a21: s.
- 	self a22: c.!

Item was removed:
- ----- Method: MatrixTransform2x3>>setIdentiy (in category 'initialize') -----
- setIdentiy
- 	"Initialize the receiver to the identity transformation (e.g., not affecting points)"
- 	self
- 		a11: 1.0; a12: 0.0; a13: 0.0;
- 		a21: 0.0; a22: 1.0; a23: 0.0.!

Item was removed:
- ----- Method: MatrixTransform2x3>>setOffset: (in category 'private') -----
- setOffset: aPoint
- 	"Set the raw offset in the receiver"
- 	| pt |
- 	pt := aPoint asPoint.
- 	self a13: pt x asFloat.
- 	self a23: pt y asFloat.!

Item was removed:
- ----- Method: MatrixTransform2x3>>setScale: (in category 'private') -----
- setScale: aPoint
- 	"Set the raw scale in the receiver"
- 	| pt |
- 	pt := aPoint asPoint.
- 	self a11: pt x asFloat.
- 	self a22: pt y asFloat.!

Item was removed:
- ----- Method: MatrixTransform2x3>>transformDirection: (in category 'transforming points') -----
- transformDirection: aPoint
- 	"Transform aPoint from local coordinates into global coordinates"
- 	| x y |
- 	x := (aPoint x * self a11) + (aPoint y * self a12).
- 	y := (aPoint x * self a21) + (aPoint y * self a22).
- 	^x @ y!

Item was removed:
- ----- Method: MatrixTransform2x3>>transformPoint: (in category 'transforming points') -----
- transformPoint: aPoint
- 	"Transform aPoint from local coordinates into global coordinates"
- 	| x y |
- 	x := (aPoint x * self a11) + (aPoint y * self a12) + self a13.
- 	y := (aPoint x * self a21) + (aPoint y * self a22) + self a23.
- 	^x @ y!

Item was removed:
- ----- Method: MatrixTransform2x3>>writeOn: (in category 'objects from disk') -----
- writeOn: aStream
- 	aStream nextWordsPutAll: self.!

Item was removed:
- Notification subclass: #MissingFont
- 	instanceVariableNames: 'familyName pixelSize'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Fonts'!
- 
- !MissingFont commentStamp: '<historical>' prior: 0!
- signaled by font loading code when reading a DiskProxy that calls for a missing font.!

Item was removed:
- ----- Method: MissingFont class>>forFamilyName:pixelSize: (in category 'instance creation') -----
- forFamilyName: aName pixelSize: aSize
- 	^(self new)
- 		familyName: aName;
- 		pixelSize: aSize;
- 		yourself.!

Item was removed:
- ----- Method: MissingFont>>defaultAction (in category 'handling') -----
- defaultAction
- 	familyName ifNil: [ familyName := 'NoName' ].
- 	pixelSize ifNil: [ pixelSize := 12 ].
- 
- 	^((familyName beginsWith: 'Comic')
- 		ifTrue: [ TextStyle named: (Preferences standardEToysFont familyName) ]
- 		ifFalse: [ TextStyle default ]) fontOfSize: pixelSize.!

Item was removed:
- ----- Method: MissingFont>>familyName (in category 'accessing') -----
- familyName
- 	"Answer the value of familyName"
- 
- 	^ familyName!

Item was removed:
- ----- Method: MissingFont>>familyName: (in category 'accessing') -----
- familyName: anObject
- 	"Set the value of familyName"
- 
- 	familyName := anObject!

Item was removed:
- ----- Method: MissingFont>>pixelSize (in category 'accessing') -----
- pixelSize
- 	"Answer the value of pixelSize"
- 
- 	^ pixelSize!

Item was removed:
- ----- Method: MissingFont>>pixelSize: (in category 'accessing') -----
- pixelSize: anObject
- 	"Set the value of pixelSize"
- 
- 	pixelSize := anObject!

Item was removed:
- ----- Method: MissingFont>>printOn: (in category 'printing') -----
- printOn: aStream
- 	super printOn: aStream.
- 	aStream nextPut: $(;
- 		nextPutAll: familyName;
- 		nextPut: $-;
- 		print: pixelSize;
- 		nextPut: $).!

Item was removed:
- DisplayTransform subclass: #MorphicTransform
- 	instanceVariableNames: 'offset angle scale'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Transformations'!
- 
- !MorphicTransform commentStamp: '<historical>' prior: 0!
- This class implements simple translation, scaling and rotation for points, as well as inverse transformations.  These transformations are used in TransformMorphs (clipping scrollers) and TransformationMorphs (general flex-morph wrappers) to map, eg, global mouse coords into local coords, and to invert, eg, local damage rectangles into global damage rectangles.!

Item was removed:
- ----- Method: MorphicTransform class>>identity (in category 'instance creation') -----
- identity
- 
- 	^ self offset: 0 at 0 angle: 0.0 scale: 1.0!

Item was removed:
- ----- Method: MorphicTransform class>>new (in category 'instance creation') -----
- new
- 
- 	^ self offset: 0 at 0
- !

Item was removed:
- ----- Method: MorphicTransform class>>offset: (in category 'instance creation') -----
- offset: aPoint
- 
- 	^ self offset: aPoint angle: 0.0 scale: 1.0!

Item was removed:
- ----- Method: MorphicTransform class>>offset:angle:scale: (in category 'instance creation') -----
- offset: aPoint angle: radians scale: factor
- 
- 	^ self basicNew setOffset: aPoint angle: radians scale: factor!

Item was removed:
- ----- Method: MorphicTransform>>angle (in category 'accessing') -----
- angle
- 	^ angle!

Item was removed:
- ----- Method: MorphicTransform>>asMatrixTransform2x3 (in category 'converting') -----
- asMatrixTransform2x3
- 	^((MatrixTransform2x3 withRotation: angle radiansToDegrees negated) composedWithLocal:
- 		(MatrixTransform2x3 withScale: scale))
- 			offset: offset negated!

Item was removed:
- ----- Method: MorphicTransform>>asMorphicTransform (in category 'converting') -----
- asMorphicTransform
- 
- 	^ self!

Item was removed:
- ----- Method: MorphicTransform>>composedWith: (in category 'transformations') -----
- composedWith: aTransform
- 	"Return a new transform that has the effect of transforming points first by the receiver and then by the argument."
- 
- 	self isIdentity ifTrue: [^ aTransform].
- 	aTransform isIdentity ifTrue: [^ self].
- 	^ CompositeTransform new globalTransform: self
- 							localTransform: aTransform!

Item was removed:
- ----- Method: MorphicTransform>>composedWithLocal: (in category 'composing') -----
- composedWithLocal: aTransform
- 	aTransform isIdentity ifTrue:[^self].
- 	self isIdentity ifTrue:[^aTransform].
- 	aTransform isMorphicTransform ifFalse:[^super composedWithLocal: aTransform].
- 	self isPureTranslation ifTrue:[
- 		^aTransform withOffset: aTransform offset + self offset].
- 	aTransform isPureTranslation ifTrue:[
- 		^self withOffset: (self localPointToGlobal: aTransform offset negated) negated].
- 	^super composedWithLocal: aTransform.!

Item was removed:
- ----- Method: MorphicTransform>>globalPointToLocal: (in category 'transforming points') -----
- globalPointToLocal: aPoint
- 	"Transform aPoint from global coordinates into local coordinates"
- 	^self transform: aPoint!

Item was removed:
- ----- Method: MorphicTransform>>inverseTransformation (in category 'accessing') -----
- inverseTransformation
- 	"Return the inverse transformation of the receiver"
- 	^MorphicTransform
- 		offset: (self transform: 0 at 0) - (self transform: offset)
- 		angle: angle negated
- 		scale: scale reciprocal!

Item was removed:
- ----- Method: MorphicTransform>>invert: (in category 'transformations') -----
- invert: aPoint
- 	"Transform the given point from local to global coordinates."
- 	| p3 p2 |
- 	self isPureTranslation ifTrue: [^ aPoint - offset].
- 	p3 :=  aPoint * scale.
- 	p2 := ((p3 x * angle cos) + (p3 y * angle sin))
- 		@ ((p3 y * angle cos) - (p3 x * angle sin)).
- 	^ (p2 - offset)
- !

Item was removed:
- ----- Method: MorphicTransform>>invertBoundsRect: (in category 'transformations') -----
- invertBoundsRect: aRectangle
- 	"Return a rectangle whose coordinates have been transformed
- 	from local back to global coordinates.  NOTE: if the transformation
- 	is not just a translation, then it will compute the bounding box
- 	in global coordinates."
- 	| outerRect |
- 	self isPureTranslation
- 	ifTrue:
- 		[^ (self invert: aRectangle topLeft)
- 			corner: (self invert: aRectangle bottomRight)]
- 	ifFalse:
- 		[outerRect := Rectangle encompassing:
- 			(aRectangle innerCorners collect: [:p | self invert: p]).
- 		"Following asymmetry due to likely subsequent truncation"
- 		^ outerRect topLeft - (1 at 1) corner: outerRect bottomRight + (2 at 2)]!

Item was removed:
- ----- Method: MorphicTransform>>invertRect: (in category 'transformations') -----
- invertRect: aRectangle
- 
- 	self error: 'method name changed to emphasize enclosing bounds'.
- 	^ self invertBoundsRect: aRectangle!

Item was removed:
- ----- Method: MorphicTransform>>isIdentity (in category 'testing') -----
- isIdentity
- 	"Return true if the receiver is the identity transform; that is, if applying to a point returns the point itself."
- 
- 	^ self isPureTranslation and: [offset = (0 at 0)]
- !

Item was removed:
- ----- Method: MorphicTransform>>isMorphicTransform (in category 'testing') -----
- isMorphicTransform
- 	^true!

Item was removed:
- ----- Method: MorphicTransform>>isPureTranslation (in category 'testing') -----
- isPureTranslation
- 	"Return true if the receiver specifies no rotation or scaling."
- 
- 	^ angle = 0.0 and: [scale = 1.0]
- !

Item was removed:
- ----- Method: MorphicTransform>>localPointToGlobal: (in category 'transforming points') -----
- localPointToGlobal: aPoint
- 	"Transform aPoint from global coordinates into local coordinates"
- 	^self invert: aPoint!

Item was removed:
- ----- Method: MorphicTransform>>offset (in category 'accessing') -----
- offset
- 	"The translation applied to the transformed coordinate system's origin."
- 	"Note: While other transform types also implement this method their actual behavior can differ. Only use it if you know what kind of transform you have on hand. Otherwise, use #localPointToGlobal: instead."
- 	^ offset
- !

Item was removed:
- ----- Method: MorphicTransform>>printOn: (in category 'printing') -----
- printOn: aStream
- 	super printOn: aStream.
- 	aStream nextPut:$(;
- 		nextPutAll:'angle = '; print: angle;
- 		nextPutAll:'; scale = '; print: scale;
- 		nextPutAll:'; offset = '; print: offset;
- 		nextPut:$).!

Item was removed:
- ----- Method: MorphicTransform>>scale (in category 'accessing') -----
- scale
- 	^ scale!

Item was removed:
- ----- Method: MorphicTransform>>setAngle: (in category 'private') -----
- setAngle: aFloat
- 
- 	angle := aFloat.
- !

Item was removed:
- ----- Method: MorphicTransform>>setIdentiy (in category 'initialize') -----
- setIdentiy
- 	scale := 1.0.
- 	offset := 0 at 0.
- 	angle := 0.0.!

Item was removed:
- ----- Method: MorphicTransform>>setOffset: (in category 'private') -----
- setOffset: aPoint
- 
- 	offset := aPoint.
- !

Item was removed:
- ----- Method: MorphicTransform>>setOffset:angle:scale: (in category 'private') -----
- setOffset: aPoint angle: a scale: s
- 
- 	offset := aPoint.
- 	angle := a.
- 	scale := s!

Item was removed:
- ----- Method: MorphicTransform>>setScale: (in category 'private') -----
- setScale: aFloat
- 
- 	scale := aFloat.
- !

Item was removed:
- ----- Method: MorphicTransform>>transform: (in category 'transformations') -----
- transform: aPoint
- 	"Transform the given point from global to local coordinates."
- 	| p2 p3 |
- 	self isPureTranslation ifTrue: [^ aPoint + offset].
- 	p2 := aPoint + offset.
- 	p3 := (((p2 x * angle cos) - (p2 y * angle sin))
- 		@ ((p2 y * angle cos) + (p2 x * angle sin)))
- 			/ scale.
- 	^ p3!

Item was removed:
- ----- Method: MorphicTransform>>transformBoundsRect: (in category 'transformations') -----
- transformBoundsRect: aRectangle
- 	"Return a rectangle whose coordinates have been transformed
- 	from global to local coordinates.  NOTE: if the transformation
- 	is not just a translation, then it will compute the bounding box
- 	in global coordinates."
- 	| outerRect |
- 	self isPureTranslation
- 	ifTrue:
- 		[^ (self transform: aRectangle topLeft)
- 			corner: (self transform: aRectangle bottomRight)]
- 	ifFalse:
- 		[outerRect := Rectangle encompassing:
- 			(aRectangle innerCorners collect: [:p | self transform: p]).
- 		"Following asymmetry due to likely subsequent truncation"
- 		^ outerRect topLeft - (1 at 1) corner: outerRect bottomRight + (2 at 2)]!

Item was removed:
- ----- Method: MorphicTransform>>transformPoint: (in category 'transformations') -----
- transformPoint: aPoint
- 	"Point transform double dispatch"
- 	^self transform: aPoint!

Item was removed:
- ----- Method: MorphicTransform>>withAngle: (in category 'accessing') -----
- withAngle: a
- 	"Return a copy of me with a different Angle"
- 	^ self copy setAngle: a!

Item was removed:
- ----- Method: MorphicTransform>>withOffset: (in category 'accessing') -----
- withOffset: a
- 	"Return a copy of me with a different Offset"
- 	^ self copy setOffset: a!

Item was removed:
- ----- Method: MorphicTransform>>withScale: (in category 'accessing') -----
- withScale: a
- 	"Return a copy of me with a different Scale"
- 	^ self copy setScale: a!

Item was removed:
- ----- Method: Number>>@ (in category '*Graphics-converting') -----
- @ y 
- 	"Primitive. Answer a Point whose x value is the receiver and whose y 
- 	value is the argument. Optional. No Lookup. See Object documentation 
- 	whatIsAPrimitive."
- 
- 	<primitive: 18>
- 	^Point x: self y: y!

Item was removed:
- ----- Method: Number>>em (in category '*Graphics-scale factor') -----
- em
- 	"Documentation only. Please use #pt or #px instead. Convert the receiver from multiples of width-of-capital-letter-M to pixels using the system's default font. Works also with pre-rendered fonts."
- 	
- 	^ (self * (TextStyle defaultFont widthOf: $M)) rounded!

Item was removed:
- ----- Method: Number>>ex (in category '*Graphics-scale factor') -----
- ex
- 	"Documentation only. Please use #pt or #px instead. Convert the receiver from multiples of x-height-of-font to pixels using the system's default TrueType font."
- 
- 	| font description |
- 	font := TextStyle defaultTTFont.
- 	description :=  font ttcDescription.
- 	^ (self asFloat
- 		* (description xHeight asFloat / description unitsPerEm)
- 		* (font widthOf: $M)) rounded!

Item was removed:
- ----- Method: Number>>pt (in category '*Graphics-scale factor') -----
- pt
- 	"Convert the receiver from points to pixels. Note that this will not work correctly for 'faked' scale factors where larger (pre-rendered) fonts are used instead of adjusting the system's current ppi value."
- 
- 	^ (TextStyle pointsToPixels: self) rounded
- 
- "
- (TextStyle pixelsPerInch = 96.0 ifTrue: [
- 	| extra |
- 	extra := TextStyle defaultFont pointSize / TTCFont referencePointSize.
- 	^ (TextStyle pointsToPixels: self * extra) rounded]
- "!

Item was removed:
- ----- Method: Number>>px (in category '*Graphics-scale factor') -----
- px
- 	"Convert the receiver representing raw pixels at 100% (96ppi) to the current scale factor. Note that you currently have to do this manually for all graphics-related properties and layout-specific measures such as #borderWidth: and #layoutInset:. Only for model windows (see #initialExtent) that are no dialogs, that scaling will happen automatically in ToolBuilder."
- 
- 	self flag: #discuss. "mt: For self > 4, I would recommend #rounded instead of #truncated. For smaller values, however, rounding makes no sense because we have no sub-pixel access and things would look too big too soon."
- 	^ (self * RealEstateAgent scaleFactor) truncated!

Item was removed:
- ----- Method: Object>>fullScreenSize (in category '*Graphics-KernelExtensions') -----
- fullScreenSize
- 	"Answer the size to which a window displaying the receiver should be set"
- 	| adj |
- 	adj := (3 * Preferences scrollBarWidth) @ 0.
- 	^ Rectangle origin: adj extent: (DisplayScreen actualScreenSize - adj)!

Item was removed:
- ImageReadWriter subclass: #PCXReadWriter
- 	instanceVariableNames: 'version encoding colorPlanes isGrayScale width height bitsPerPixel colorPalette rowByteSize'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!

Item was removed:
- ----- Method: PCXReadWriter class>>typicalFileExtensions (in category 'image reading/writing') -----
- typicalFileExtensions
- 	"Answer a collection of file extensions (lowercase) which files that I can read might commonly have"
- 	^#('pcx')!

Item was removed:
- ----- Method: PCXReadWriter>>nextImage (in category 'accessing') -----
- nextImage
- 	"Read in the next PCX image from the stream."
- 
- 	| bytes form |
- 	self readHeader.
- 	bytes := self readBody.
- 	colorPalette := self readPalette.
- 	self close.
- 	form := ColorForm extent: width at height depth: bitsPerPixel.
- 	(Form new hackBits: bytes) displayOn: (Form new hackBits: form bits).
- 	form colors: colorPalette.
- 	^ form
- !

Item was removed:
- ----- Method: PCXReadWriter>>nextWord (in category 'private-decoding') -----
- nextWord
- 	^self next + (self next bitShift: 8)!

Item was removed:
- ----- Method: PCXReadWriter>>readBody (in category 'private-decoding') -----
- readBody
- 
- 	| array scanLine rowBytes position byte count pad |
- 	pad := #(0 3 2 1) at: (width \\ 4 + 1).
- 	array := ByteArray new: ((width + pad) * height * bitsPerPixel) // 8.
- 	scanLine := ByteArray new: rowByteSize.
- 	position := 1.
- 	1 to: height do:
- 		[:line |
- 		rowBytes := 0.
- 		[rowBytes < rowByteSize] whileTrue:
- 			[byte := self next.
- 			byte < 16rC0
- 				ifTrue:
- 					[rowBytes := rowBytes + 1.
- 					scanLine at: rowBytes put: byte]
- 				ifFalse:
- 					[count := byte - 16rC0.
- 					byte := self next.
- 					1 to: count do: [:i | scanLine at: rowBytes + i put: byte].
- 					rowBytes := rowBytes + count]].
- 		array
- 			replaceFrom: position
- 			to: position + width - 1
- 			with: scanLine
- 			startingAt: 1.
- 		position := position + width + pad].
- 	^ array
- !

Item was removed:
- ----- Method: PCXReadWriter>>readHeader (in category 'private-decoding') -----
- readHeader
- 
- 	| xMin xMax yMin yMax |
- 	self next.	"skip over manufacturer field"
- 	version := self next.
- 	encoding := self next.
- 	bitsPerPixel := self next.
- 	xMin := self nextWord.
- 	yMin := self nextWord.
- 	xMax := self nextWord.
- 	yMax := self nextWord.
- 	width := xMax - xMin + 1.
- 	height := yMax - yMin + 1.
- 	self next: 4. "skip over device resolution"
- 	self next: 49. "skip over EGA color palette"
- 	colorPlanes := self next.
- 	rowByteSize := self nextWord.
- 	isGrayScale := (self next: 2) = 2.
- 	self next: 58. "skip over filler"
- 
- 
- 
- !

Item was removed:
- ----- Method: PCXReadWriter>>readPalette (in category 'private-decoding') -----
- readPalette
- 
- 	| r g b array |
- 	self next = 12 ifFalse: [self error: 'no Color Palette!!' translated].
- 	array := Array new: (1 bitShift: bitsPerPixel).
- 	1 to: array size do:
- 		[:i |
- 		r := self next.  g := self next.  b := self next.
- 		array at: i put: (Color r: r g: g b: b range: 255)].
- 	^ array.
- !

Item was removed:
- ImageReadWriter subclass: #PNGReadWriter
- 	instanceVariableNames: 'chunk form width height depth backColor bitsPerChannel colorType interlaceMethod bitsPerPixel bytesPerScanline thisScanline prevScanline rowSize idatChunkStream unknownChunks palette transparentPixelValue filtersSeen swizzleMap cachedDecoderMap bigEndian'
- 	classVariableNames: 'BPP BlockHeight BlockWidth Debugging StandardColors StandardSwizzleMaps'
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!
- 
- !PNGReadWriter commentStamp: '<historical>' prior: 0!
- I am a subclass of ImageReadWriter that decodes Portable Network Graphics
- (PNG) images.
- 
- Submitted by Duane Maxwell!

Item was removed:
- ----- Method: PNGReadWriter class>>computeSwizzleMapForDepth: (in category 'class initialization') -----
- computeSwizzleMapForDepth: depth
- 	"Answer a map that maps pixels in a word to their opposite location. Used for 'middle-endian' forms where the byte-order is different from the bit order (good joke, eh?)."
- 	| map swizzled |
- 	map := Bitmap new: 256.
- 	depth = 4 ifTrue:[
- 		0 to: 255 do:[:pix|
- 			swizzled := 0.
- 			swizzled := swizzled bitOr: (((pix bitShift: 0) bitAnd: 15) bitShift: 4).
- 			swizzled := swizzled bitOr: (((pix bitShift: -4) bitAnd: 15) bitShift: 0).
- 			map at: pix+1 put: swizzled.
- 		].
- 		^ColorMap colors: map
- 	].
- 
- 	depth = 2 ifTrue:[
- 		0 to: 255 do:[:pix|
- 			swizzled := 0.
- 			swizzled := swizzled bitOr: (((pix bitShift: 0) bitAnd: 3) bitShift: 6).
- 			swizzled := swizzled bitOr: (((pix bitShift: -2) bitAnd: 3) bitShift: 4).
- 			swizzled := swizzled bitOr: (((pix bitShift: -4) bitAnd: 3) bitShift: 2).
- 			swizzled := swizzled bitOr: (((pix bitShift: -6) bitAnd: 3) bitShift: 0).
- 			map at: pix+1 put: swizzled.
- 		].
- 		^ColorMap colors: map
- 	].
- 
- 	depth = 1 ifTrue:[
- 		0 to: 255 do:[:pix|
- 			swizzled := 0.
- 			swizzled := swizzled bitOr: (((pix bitShift: 0) bitAnd: 1) bitShift: 7).
- 			swizzled := swizzled bitOr: (((pix bitShift: -1) bitAnd: 1) bitShift: 6).
- 			swizzled := swizzled bitOr: (((pix bitShift: -2) bitAnd: 1) bitShift: 5).
- 			swizzled := swizzled bitOr: (((pix bitShift: -3) bitAnd: 1) bitShift: 4).
- 			swizzled := swizzled bitOr: (((pix bitShift: -4) bitAnd: 1) bitShift: 3).
- 			swizzled := swizzled bitOr: (((pix bitShift: -5) bitAnd: 1) bitShift: 2).
- 			swizzled := swizzled bitOr: (((pix bitShift: -6) bitAnd: 1) bitShift: 1).
- 			swizzled := swizzled bitOr: (((pix bitShift: -7) bitAnd: 1) bitShift: 0).
- 			map at: pix+1 put: swizzled.
- 		].
- 		^ColorMap colors: map
- 	].
- 	self error: 'Unrecognized depth'!

Item was removed:
- ----- Method: PNGReadWriter class>>debugging: (in category 'support') -----
- debugging: aBoolean
- 
- 	Debugging := aBoolean!

Item was removed:
- ----- Method: PNGReadWriter class>>initialize (in category 'class initialization') -----
- initialize
- 	"
- 	PNGReadWriter initialize
- 	"
- 
- 	BPP := {	#(1 2 4 8 16).
- 			#(0 0 0 0 0).
- 			#(0 0 0 24 48).
- 			#(1 2 4 8 0).
- 			#(0 0 0 16 32).
- 			#(0 0 0 0 0).
- 			#(0 0 0 32 64).
- 			#(0 0 0 0 0) }.
- 
- 	BlockHeight := #(8 8 4 4 2 2 1).
- 	BlockWidth := #(8 4 4 2 2 1 1).
- 
- 	StandardColors := Color indexedColors collect:[:aColor|
- 		Color 
- 			r: (aColor red * 255) truncated / 255
- 			g: (aColor green * 255) truncated / 255
- 			b: (aColor blue * 255) truncated / 255.
- 	].
- 
- 	StandardSwizzleMaps := Array new: 4.
- 	#(1 2 4) do:[:i| StandardSwizzleMaps at: i put: (self computeSwizzleMapForDepth: i)].!

Item was removed:
- ----- Method: PNGReadWriter class>>typicalFileExtensions (in category 'image reading/writing') -----
- typicalFileExtensions
- 	"Answer a collection of file extensions (lowercase) which files that I can read might commonly have"
- 	^#('png')!

Item was removed:
- ----- Method: PNGReadWriter>>copyPixels: (in category 'pixel copies') -----
- copyPixels: y
- 	"Handle non-interlaced pixels of supported colorTypes"
- 
- 	| s |
- 	s := #(copyPixelsGray: nil copyPixelsRGB: copyPixelsIndexed:
- 		  copyPixelsGrayAlpha: nil copyPixelsRGBA:) at: colorType+1.
- 	self perform: s asSymbol with: y
- !

Item was removed:
- ----- Method: PNGReadWriter>>copyPixels:at:by: (in category 'pixel copies') -----
- copyPixels: y at: startX by: incX
- 	"Handle interlaced pixels of supported colorTypes"
- 
- 	| s |
- 	s := #(copyPixelsGray:at:by: nil copyPixelsRGB:at:by: copyPixelsIndexed:at:by:
- 		  copyPixelsGrayAlpha:at:by: nil copyPixelsRGBA:at:by:) at: colorType+1.
- 	self perform: s asSymbol with: y with: startX with: incX
- !

Item was removed:
- ----- Method: PNGReadWriter>>copyPixelsGray: (in category 'pixel copies') -----
- copyPixelsGray: y 
- 	"Handle non-interlaced grayscale color mode (colorType = 0)"
- 
- 	| base bits bytesLeft word |
- 	bitsPerChannel = 16 ifTrue: [
- 		"Warning: This is extremely slow. Besides we are downsampling to 8 bits!!"
- 		| blitter |
- 		blitter := BitBlt bitPokerToForm: form.
- 		0 to: width - 1 do: [ :x |
- 			| high low value |
- 			high := thisScanline at: x * 2 + 1.
- 			low := thisScanline at: x * 2 + 2.
- 			value := (high * 256 + low = transparentPixelValue)
- 				ifTrue: [0 "transparent"]
- 				ifFalse: [high max: 1].
- 			blitter pixelAt: x @ y put: value ].
- 			^self ].
- 
- 	"Just copy the bits"
- 
- 	"This Smalltalk version might be easier to understand than the others below."
- 	base := y * (form width * bitsPerChannel + 31 // 32) + 1.
- 	bits := form bits.
- 	0 to: thisScanline size // 4 - 1 do: [ :i |
- 		| ii |
- 		ii := i * 4.
- 		"This somewhat weird mixture of (#* and #+) with (#bitShift: and #bitOr:) 
- 		is to make use of faster arithmetic bytecodes, but not of slow largeintegers."
- 		word :=
- 			(((thisScanline at: ii + 1) * 256 + 
- 			(thisScanline at: ii + 2) * 256 + 
- 			(thisScanline at: ii + 3)) bitShift: 8) bitOr: 
- 			(thisScanline at: ii + 4).
- 		bits at: base + i put: word ].	
- 	(bytesLeft := thisScanline size bitAnd: 3) = 0 ifFalse: [
- 		word := 0.
- 		thisScanline size - bytesLeft + 1 to: thisScanline size do: [ :ii |
- 			word := word * 256 + (thisScanline at: ii) ].
- 		word := word bitShift: 8 * (4 - bytesLeft).
- 		bits at: base + (thisScanline size // 4) put: word ].
- 
- 	"This interesting technique (By Andreas Raab) is faster for very large images, but might be slower for small ones"
- 	"^self copyPixelsGrayWeirdBitBltHack: y ".
- 	"It uses the following method:
- 	PNGReadWriter >> copyPixelsGrayWeirdBitBltHack: y 
- 	""Handle non-interlaced black and white color mode (colorType = 0)
- 	By Andreas Raab""
- 	
- 	| source dest cmap |
- 	source := Form extent: 1 @ (thisScanline size // 4) depth: 32 bits: thisScanline.
- 	dest := Form extent: 1 @ (form bits size) depth: 32 bits: form bits.
- 	cmap := Smalltalk isLittleEndian
- 		ifTrue:[ColorMap 
- 					shifts: #(-24 -8 8 24) 
- 					masks: #(16rFF000000 16r00FF0000 16r0000FF00 16r000000FF)].
- 	(BitBlt toForm: dest)
- 		sourceForm: source;
- 		destX: 0 destY: (y * form width*bitsPerChannel//32) width: 1 height: (form width+31*bitsPerChannel//32);
- 		colorMap: cmap;
- 		combinationRule: 3;
- 		copyBits."
- 		
- 	"This interesting technique  (By Yoshiki Ohshima) is faster for very large images, but might be slower for small ones"
- 	"form bits copyFromByteArray2: thisScanline to: y * (form width* bitsPerChannel // 32)".
- 	"It uses the following method:
- 	BitMap >> copyFromByteArray2: byteArray to: i
- 	""This method should work with either byte orderings""
- 
- 	| myHack byteHack |
- 	myHack := Form new hackBits: self.
- 	byteHack := Form new hackBits: byteArray.
- 	Smalltalk  isLittleEndian ifTrue: [byteHack swapEndianness].
- 	byteHack displayOn: myHack at:  0 at i"!

Item was removed:
- ----- Method: PNGReadWriter>>copyPixelsGray:at:by: (in category 'pixel copies') -----
- copyPixelsGray: y at: startX by: incX
- 	"Handle interlaced grayscale color mode (colorType = 0)"
- 
- 	| offset bits blitter pixPerByte shifts b pixel mask pixelNumber |
- 	bitsPerChannel = 16
- 		ifTrue: [
- 			"Warning: This is extremely slow. Besides we are downsampling to 8 bits!!"
- 			blitter := BitBlt bitPokerToForm: form.
- 			startX to: width-1 by: incX do: [ :x |
- 				| high low value |
- 				high := thisScanline at: x//incX<<1 + 1.
- 				low := thisScanline at: x//incX<<1 + 2.
- 				value := (high * 256 + low = transparentPixelValue)
- 					ifTrue: [0 "transparent"]
- 					ifFalse: [high max: 1].
- 				blitter pixelAt: x @ y put: value ].
- 				^self ].
- 	offset := y*rowSize+1.
- 	bits := form bits.
- 	bitsPerChannel = 8 ifTrue: [
- 		startX to: width-1 by: incX do: [ :x | | w |
- 			w := offset + (x>>2).
- 			b := 3- (x \\ 4) * 8.
- 			pixel := (thisScanline at: x // incX + 1)<<b.
- 			mask := (255<<b) bitInvert32.
- 			bits at: w put: (((bits at: w) bitAnd: mask) bitOr: pixel)
- 		].
- 		^ self
- 	].
- 	bitsPerChannel = 1 ifTrue: [
- 		pixPerByte := 8.
- 		mask := 1.
- 		shifts := #(7 6 5 4 3 2 1 0).
- 	].
- 	bitsPerChannel = 2 ifTrue: [
- 		pixPerByte := 4.
- 		mask := 3.
- 		shifts := #(6 4 2 0).
- 	].
- 	bitsPerChannel = 4 ifTrue: [
- 		pixPerByte := 2.
- 		mask := 15.
- 		shifts := #(4 0).
- 	].
- 
- 	blitter := BitBlt bitPokerToForm: form.
- 	pixelNumber := 0.
- 	startX to: width-1 by: incX do: [ :x | | rawByte |
- 		rawByte := thisScanline at: (pixelNumber // pixPerByte) + 1.
- 		pixel := (rawByte >> (shifts at: (pixelNumber \\ pixPerByte) + 1)) bitAnd: mask.
- 		blitter pixelAt: (x at y) put: pixel.
- 		pixelNumber := pixelNumber + 1.
- 	].
- !

Item was removed:
- ----- Method: PNGReadWriter>>copyPixelsGrayAlpha: (in category 'pixel copies') -----
- copyPixelsGrayAlpha: y
- 	"Handle non-interlaced grayscale with alpha color mode (colorType = 4)"
- 
- 	| i pixel gray b |
- 	b := BitBlt bitPokerToForm: form.
- 	bitsPerChannel = 8
- 		ifTrue: [
- 			0 to: width-1 do: [ :x |
- 				i := (x << 1) + 1.
- 				gray := thisScanline at: i.
- 				pixel := ((thisScanline at: i+1)<<24) + (gray<<16) + (gray<<8) + gray.
- 				b pixelAt: x at y put: pixel.
- 				]
- 			]
- 		ifFalse: [
- 			0 to: width-1 do: [ :x |
- 				i := (x << 2) + 1.
- 				gray := thisScanline at: i.
- 				pixel := ((thisScanline at: i+2)<<24) + (gray<<16) + (gray<<8) + gray.
- 				b pixelAt: x at y put: pixel.
- 				]
- 			]
- !

Item was removed:
- ----- Method: PNGReadWriter>>copyPixelsGrayAlpha:at:by: (in category 'pixel copies') -----
- copyPixelsGrayAlpha: y at: startX by: incX
- 	"Handle interlaced grayscale with alpha color mode (colorType = 4)"
- 
- 	| i pixel gray b |
- 	b := BitBlt bitPokerToForm: form.
- 	bitsPerChannel = 8
- 		ifTrue: [
- 			startX to: width-1 by: incX do: [ :x |
- 				i := (x // incX << 1) + 1.
- 				gray := thisScanline at: i.
- 				pixel := ((thisScanline at: i+1)<<24) + (gray<<16) + (gray<<8) + gray.
- 				b pixelAt: x at y put: pixel.
- 				]
- 			]
- 		ifFalse: [
- 			startX to: width-1 by: incX do: [ :x |
- 				i := (x // incX << 2) + 1.
- 				gray := thisScanline at: i.
- 				pixel := ((thisScanline at: i+2)<<24) + (gray<<16) + (gray<<8) + gray.
- 				b pixelAt: x at y put: pixel.
- 				]
- 			]
- !

Item was removed:
- ----- Method: PNGReadWriter>>copyPixelsIndexed: (in category 'pixel copies') -----
- copyPixelsIndexed: y
- 	"Handle non-interlaced indexed color mode (colorType = 3)"
- 	| hack hackBlt swizzleHack swizzleBlt scanline hackDepth |
- 	scanline := ByteArray new: bytesPerScanline + 3 // 4 * 4.
- 	scanline replaceFrom: 1 to: thisScanline size with: thisScanline startingAt: 1.
- 	hackDepth := bigEndian ifTrue:[form depth] ifFalse:[form depth negated].
- 	hack := Form extent: width at 1 depth: hackDepth bits: scanline.
- 	hackBlt := BitBlt toForm: form.
- 	hackBlt sourceForm: hack.
- 	hackBlt combinationRule: Form over.
- 	hackBlt destOrigin: 0 at y.
- 	hackBlt width: width; height: 1.
- 
- 	(form depth < 8 and:[bigEndian not]) ifTrue:[
- 		swizzleHack := Form new hackBits: scanline.
- 		swizzleBlt := BitBlt toForm: swizzleHack.
- 		swizzleBlt sourceForm: swizzleHack.
- 		swizzleBlt combinationRule: Form over.
- 		swizzleBlt colorMap: (StandardSwizzleMaps at: form depth).
- 		swizzleBlt copyBits.
- 	].
- 
- 	hackBlt copyBits.!

Item was removed:
- ----- Method: PNGReadWriter>>copyPixelsIndexed:at:by: (in category 'pixel copies') -----
- copyPixelsIndexed: y at: startX by: incX
- 	"Handle interlaced indexed color mode (colorType = 3)"
- 
- 	| offset bits pixPerByte shifts blitter pixel mask pixelNumber |
- 	offset := y*rowSize+1.
- 	bits := form bits.
- 	bitsPerChannel = 8
- 		ifTrue: [
- 			startX to: width-1 by: incX do: [ :x | | b w |
- 				w := offset + (x>>2).
- 				b := 3 - (x \\ 4) * 8.
- 				pixel := (thisScanline at: x // incX + 1)<<b.
- 				mask := (255<<b) bitInvert32.
- 				bits at: w put: (((bits at: w) bitAnd: mask) bitOr: pixel)].
- 			^ self ].
- 	bitsPerChannel = 1 ifTrue: [
- 		pixPerByte := 8.
- 		mask := 1.
- 		shifts := #(7 6 5 4 3 2 1 0).
- 	].
- 	bitsPerChannel = 2 ifTrue: [
- 		pixPerByte := 4.
- 		mask := 3.
- 		shifts := #(6 4 2 0).
- 	].
- 	bitsPerChannel = 4 ifTrue: [
- 		pixPerByte := 2.
- 		mask := 15.
- 		shifts := #(4 0).
- 	].
- 
- 	blitter := BitBlt bitPokerToForm: form.
- 	pixelNumber := 0.
- 	startX to: width-1 by: incX do: [ :x | | rawByte |
- 		rawByte := thisScanline at: (pixelNumber // pixPerByte) + 1.
- 		pixel := (rawByte >> (shifts at: (pixelNumber \\ pixPerByte) + 1)) bitAnd: mask.
- 		blitter pixelAt: (x at y) put: pixel.
- 		pixelNumber := pixelNumber + 1.
- 	].
- !

Item was removed:
- ----- Method: PNGReadWriter>>copyPixelsRGB: (in category 'pixel copies') -----
- copyPixelsRGB: y
- 	"Handle non-interlaced RGB color mode (colorType = 2)"
- 
- 	| i pixel tempForm tempBits |
- 	(transparentPixelValue isNil and: [ bitsPerChannel = 8 ]) ifTrue: [ "Do the same trick as in #copyPixelsRGBA:"
- 		| targetIndex |
- 		tempBits := ByteArray new: thisScanline size * 4 // 3 withAll: 16rFF.
- 		tempForm := Form extent: width at 1 depth: 32 bits: tempBits.
- 		targetIndex := 1.
- 		1 to: thisScanline size by: 3 do: [ :index |
- 			tempBits
- 				at: targetIndex put: (thisScanline at: index);
- 				at: targetIndex + 1 put: (thisScanline at: index + 1);
- 				at: targetIndex + 2 put: (thisScanline at: index + 2).
- 			targetIndex := targetIndex + 4 ].
- 		cachedDecoderMap 
- 			ifNil:[cachedDecoderMap := self rgbaDecoderMapForDepth: depth].
- 		(BitBlt toForm: form)
- 			sourceForm: tempForm;
- 			destOrigin: 0 at y;
- 			combinationRule: Form over;
- 			colorMap: cachedDecoderMap;
- 			copyBits.
- 		^self ].
- 	tempForm := Form extent: width at 1 depth: 32.
- 	tempBits := tempForm bits.
- 	pixel := LargePositiveInteger new: 4.
- 	pixel at: 4 put: 16rFF.
- 	bitsPerChannel = 8
- 		ifTrue:
- 			[i := 1.
- 			1 to: width do:
- 				[ :x |
- 				pixel
- 					at: 3 put: (thisScanline at: i);
- 					at: 2 put: (thisScanline at: i+1);
- 					at: 1 put: (thisScanline at: i+2).
- 				tempBits at: x put: pixel normalize.
- 				i := i + 3].
- 			transparentPixelValue
- 				ifNotNil:
- 					[1 to: width do: [ :x |
- 						(tempBits at: x) = transparentPixelValue
- 							ifTrue: [tempBits at: x put: 0]]]]
- 		ifFalse:
- 			[i := 1.
- 			1 to: width do:
- 				[ :x |
- 				(transparentPixelValue == nil or: [(1 to: 6) anySatisfy: [:k | (transparentPixelValue digitAt: k) ~= (thisScanline at: i + 6 - k)]])
- 					ifTrue:
- 						[pixel
- 							at: 3 put: (thisScanline at: i);
- 							at: 2 put: (thisScanline at: i+2);
- 							at: 1 put: (thisScanline at: i+4).
- 						tempBits at: x put: pixel normalize]
- 					ifFalse:
- 						[tempBits at: x put: 0].
- 				i := i + 6]].
- 	
- 	tempForm displayOn: form at: 0 at y rule: Form over.
- !

Item was removed:
- ----- Method: PNGReadWriter>>copyPixelsRGB:at:by: (in category 'pixel copies') -----
- copyPixelsRGB: y at: startX by: incX
- 	"Handle interlaced RGB color mode (colorType = 2)"
- 
- 	| i pixel tempForm tempBits xx loopsToDo |
- 
- 	tempForm := Form extent: width at 1 depth: 32.
- 	tempBits := tempForm bits.
- 	pixel := LargePositiveInteger new: 4.
- 	pixel at: 4 put: 16rFF.
- 	loopsToDo := width - startX + incX - 1 // incX.
- 	bitsPerChannel = 8
- 		ifTrue:
- 			[i := (startX // incX * 3) + 1.
- 			xx := startX+1.
- 			1 to: loopsToDo do:
- 				[ :j |
- 				pixel
- 					at: 3 put: (thisScanline at: i);
- 					at: 2 put: (thisScanline at: i+1);
- 					at: 1 put: (thisScanline at: i+2).
- 				tempBits at: xx put: pixel normalize.
- 				i := i + 3.
- 				xx := xx + incX].
- 			transparentPixelValue
- 				ifNotNil: [startX to: width-1 by: incX do: [ :x |
- 					(tempBits at: x+1) = transparentPixelValue
- 						ifTrue: [	tempBits at: x+1 put: 0]]]]
- 		ifFalse:
- 			[i := (startX // incX * 6) + 1.
- 			xx := startX+1.
- 			1 to: loopsToDo do:
- 				[ :j |
- 				(transparentPixelValue == nil or: [(1 to: 6) anySatisfy: [:k | (transparentPixelValue digitAt: k) ~= (thisScanline at: i + 6 - k)]])
- 					ifTrue:
- 						[pixel
- 							at: 3 put: (thisScanline at: i);
- 							at: 2 put: (thisScanline at: i+2);
- 							at: 1 put: (thisScanline at: i+4).
- 						tempBits at: xx put: pixel normalize.]
- 					ifFalse:
- 						[tempBits at: xx put: 0].
- 				i := i + 6.
- 				xx := xx + incX]].
- 	tempForm displayOn: form at: 0 at y rule: Form over.
- 
- !

Item was removed:
- ----- Method: PNGReadWriter>>copyPixelsRGBA: (in category 'pixel copies') -----
- copyPixelsRGBA: y
- 	"Handle non-interlaced RGBA color modes (colorType = 6)"
- 
- 	| i pixel tempForm tempBits ff |
- 	bitsPerChannel = 8 ifTrue: [
- 		ff := Form extent: width at 1 depth: 32 bits: thisScanline.
- 		cachedDecoderMap 
- 			ifNil:[cachedDecoderMap := self rgbaDecoderMapForDepth: depth].
- 		(BitBlt toForm: form)
- 			sourceForm: ff;
- 			destOrigin: 0 at y;
- 			combinationRule: Form over;
- 			colorMap: cachedDecoderMap;
- 			copyBits.
- 		^self.
- 	].
- 	tempForm := Form extent: width at 1 depth: 32.
- 	tempBits := tempForm bits.
- 	pixel := LargePositiveInteger new: 4.
- 	i := -7.
- 	0 to: width-1 do: [ :x |
- 			i := i + 8.
- 			pixel at: 4 put: (thisScanline at: i+6);
- 				at: 3 put: (thisScanline at: i);
- 				at: 2 put: (thisScanline at: i+2);
- 				at: 1 put: (thisScanline at: i+4).
- 			tempBits at: x+1 put: pixel normalize.
- 	].
- 	tempForm displayOn: form at: 0 at y rule: Form over.
- !

Item was removed:
- ----- Method: PNGReadWriter>>copyPixelsRGBA:at:by: (in category 'pixel copies') -----
- copyPixelsRGBA: y at: startX by: incX
- 	"Handle interlaced RGBA color modes (colorType = 6)"
- 
- 	| i pixel tempForm tempBits |
- 
- 	tempForm := Form extent: width at 1 depth: 32.
- 	tempBits := tempForm bits.
- 	pixel := LargePositiveInteger new: 4.
- 	bitsPerChannel = 8 ifTrue: [
- 		i := (startX // incX << 2) + 1.
- 		startX to: width-1 by: incX do: [ :x |
- 			pixel at: 4 put: (thisScanline at: i+3);
- 				at: 3 put: (thisScanline at: i);
- 				at: 2 put: (thisScanline at: i+1);
- 				at: 1 put: (thisScanline at: i+2).
- 			tempBits at: x+1 put: pixel normalize.
- 			i := i + 4.
- 		]
- 	] ifFalse: [
- 		i := (startX // incX << 3) +1.
- 		startX to: width-1 by: incX do: [ :x |
- 			pixel at: 4 put: (thisScanline at: i+6);
- 				at: 3 put: (thisScanline at: i);
- 				at: 2 put: (thisScanline at: i+2);
- 				at: 1 put: (thisScanline at: i+4).
- 			tempBits at: x+1 put: pixel normalize.
- 			i := i + 8.
- 		].
- 	].
- 	tempForm displayOn: form at: 0 at y rule: Form paintAlpha.
- 
- !

Item was removed:
- ----- Method: PNGReadWriter>>debugging (in category 'accessing') -----
- debugging
- 
- 	^Debugging == true!

Item was removed:
- ----- Method: PNGReadWriter>>doPass: (in category 'miscellaneous') -----
- doPass: pass
- 	"Certain interlace passes are skipped with certain small image
- dimensions"
- 
- 	pass = 1 ifTrue: [ ^ true ].
- 	((width = 1) and: [height = 1]) ifTrue: [ ^ false ].
- 	pass = 2 ifTrue: [ ^ width >= 5 ].
- 	pass = 3 ifTrue: [ ^ height >= 5 ].
- 	pass = 4 ifTrue: [ ^ (width >=3 ) or: [height >= 5] ].
- 	pass = 5 ifTrue: [ ^ height >=3 ].
- 	pass = 6 ifTrue: [ ^ width >=2 ].
- 	pass = 7 ifTrue: [ ^ height >=2 ].
- 
- !

Item was removed:
- ----- Method: PNGReadWriter>>filterAverage: (in category 'filtering') -----
- filterAverage: count
- 	"Use the average of the pixel to the left and the pixel above as a predictor"
- 
- 	| delta |
- 	delta := bitsPerPixel // 8 max: 1.
- 	1 to: delta do: [:i |
- 		thisScanline at: i put: ((thisScanline at: i) + ((prevScanline at: i) // 2) bitAnd: 255)].
- 	delta + 1 to: count do: [:i |
- 		thisScanline at: i put:
- 			((thisScanline at: i)
- 			+ ((prevScanline at: i)
- 			+ (thisScanline at: i - delta) // 2) bitAnd: 255)]!

Item was removed:
- ----- Method: PNGReadWriter>>filterHorizontal: (in category 'filtering') -----
- filterHorizontal: count
- 	"Use the pixel to the left as a predictor"
- 
- 	| delta |
- 	delta := bitsPerPixel // 8 max: 1.
- 	delta+1 to: count do: [ :i |
- 		thisScanline at: i put: (((thisScanline at: i) +
- (thisScanline at: i-delta)) bitAnd: 255) ]
- 
- 
- !

Item was removed:
- ----- Method: PNGReadWriter>>filterNone: (in category 'filtering') -----
- filterNone: count
- !

Item was removed:
- ----- Method: PNGReadWriter>>filterPaeth: (in category 'filtering') -----
- filterPaeth: count
- 	"Select one of (the pixel to the left, the pixel above and the pixel to above left) to
- 	predict the value of this pixel"
- 
- 	| delta |
- 	delta := bitsPerPixel // 8 max: 1.
- 	1 to: delta do: [ :i |
- 		thisScanline at: i put:
- 			(((thisScanline at: i) + (prevScanline at: i)) bitAnd: 255)].
- 	delta+1 to: count do: [ :i |
- 		thisScanline
- 			at: i
- 			put: (((thisScanline at: i) + (self
- 				paethPredictLeft: (thisScanline at: i-delta)
- 				above: (prevScanline at: i)
- 				aboveLeft: (prevScanline at: i-delta)))
- 					bitAnd: 255)]
- 
- !

Item was removed:
- ----- Method: PNGReadWriter>>filterScanline:count: (in category 'filtering') -----
- filterScanline: filterType count: count
- 
- 	self
- 		perform: (
- 			#(filterNone: filterHorizontal: filterVertical: filterAverage: filterPaeth:)
- 				at: filterType+1)
- 		with: count.
- 
- !

Item was removed:
- ----- Method: PNGReadWriter>>filterVertical: (in category 'filtering') -----
- filterVertical: count
- 	"Use the pixel above as a predictor"
- 
- 	1 to: count do: [ :i |
- 		thisScanline at: i put: (((thisScanline at: i) +
- (prevScanline at: i)) bitAnd: 255) ]
- 
- !

Item was removed:
- ----- Method: PNGReadWriter>>grayColorsFor: (in category 'miscellaneous') -----
- grayColorsFor: d
- 	"return a color table for a gray image"
- 
- 	palette := Array new: 1<<d.
- 	d = 1 ifTrue: [
- 		palette at: 1 put: Color black.
- 		palette at: 2 put: Color white.
- 		^  palette
- 		].
- 	d = 2 ifTrue: [
- 		palette at: 1 put: Color black.
- 		palette at: 2 put: (Color gray: 85.0 / 255.0).
- 		palette at: 3 put: (Color gray: 170.0 / 255.0).
- 		palette at: 4 put: Color white.
- 		^ palette
- 		].
- 	d = 4 ifTrue: [
- 		0 to: 15 do: [ :g |
- 			palette at: g+1 put: (Color gray: (g/15) asFloat) ].
- 		^ palette
- 		].
- 	d = 8 ifTrue: [
- 		0 to: 255 do: [ :g |
- 			palette at: g+1 put: (Color gray: (g/255) asFloat) ].
- 		^ palette
- 		].
- !

Item was removed:
- ----- Method: PNGReadWriter>>nextImage (in category 'accessing') -----
- nextImage
- 	bigEndian := Smalltalk isBigEndian.
- 	filtersSeen := Bag new.
- 	idatChunkStream := nil.
- 	transparentPixelValue := nil.
- 	unknownChunks := Set new.
- 	stream reset.
- 	stream binary.
- 	stream skip: 8.
- 	[stream atEnd] whileFalse: [self processNextChunk].
- 	"Set up our form"
- 	palette ifNotNil: 
- 			["Dump the palette if it's the same as our standard palette"
- 
- 			palette = (StandardColors copyFrom: 1 to: palette size) 
- 				ifTrue: [palette := nil]].
- 	(depth <= 8 and: [palette notNil]) 
- 		ifTrue: 
- 			[form := ColorForm extent: width @ height depth: depth.
- 			form colors: palette]
- 		ifFalse: [form := Form extent: width @ height depth: depth].
- 	backColor ifNotNil: [form fillColor: backColor].
- 	idatChunkStream 
- 		ifNil: [ self error: 'image data is missing' translated ]
- 		ifNotNil: [ self processIDATChunk ].
- 	unknownChunks isEmpty 
- 		ifFalse: 
- 			["Transcript show: ' ',unknownChunks asSortedCollection asArray printString."
- 
- 			].
- 	self debugging 
- 		ifTrue: 
- 			[Transcript
- 				cr;
- 				show: 'form = ' , form printString.
- 			Transcript
- 				cr;
- 				show: 'colorType = ' , colorType printString.
- 			Transcript
- 				cr;
- 				show: 'interlaceMethod = ' , interlaceMethod printString.
- 			Transcript
- 				cr;
- 				show: 'filters = ' , filtersSeen sortedCounts asArray printString].
- 	^form!

Item was removed:
- ----- Method: PNGReadWriter>>nextPutImage: (in category 'writing') -----
- nextPutImage: aForm
- 	"Write out the given form. We're keeping it simple here, no interlacing, no filters."
- 	^self nextPutImage: aForm interlace: 0 filter: 0. "no filtering"!

Item was removed:
- ----- Method: PNGReadWriter>>nextPutImage:interlace:filter: (in category 'writing') -----
- nextPutImage: aForm interlace: aMethod filter: aFilterType 
- 	"Note: For now we keep it simple - interlace and filtering are simply ignored"
- 
- 	| crcStream |
- 	bigEndian := Smalltalk isBigEndian.
- 	form := aForm.
- 	width := aForm width.
- 	height := aForm height.
- 	aForm depth <= 8 
- 		ifTrue: 
- 			[bitsPerChannel := aForm depth.
- 			colorType := 3.
- 			bytesPerScanline := (width * aForm depth + 7) // 8]
- 		ifFalse: 
- 			[bitsPerChannel := 8.
- 			colorType := 6.
- 			bytesPerScanline := width * 4].
- 	self writeFileSignature.
- 	crcStream := WriteStream on: (ByteArray new: 1000).
- 	crcStream resetToStart.
- 	self writeIHDRChunkOn: crcStream.
- 	self writeChunk: crcStream.
- 	form depth <= 8 
- 		ifTrue: 
- 			[crcStream resetToStart.
- 			self writePLTEChunkOn: crcStream.
- 			self writeChunk: crcStream.
- 			form isColorForm 
- 				ifTrue: 
- 					[crcStream resetToStart.
- 					self writeTRNSChunkOn: crcStream.
- 					self writeChunk: crcStream]].
- 	form depth = 16 
- 		ifTrue: 
- 			[crcStream resetToStart.
- 			self writeSBITChunkOn: crcStream.
- 			self writeChunk: crcStream].
- 	crcStream resetToStart.
- 	self writeIDATChunkOn: crcStream.
- 	self writeChunk: crcStream.
- 	crcStream resetToStart.
- 	self writeIENDChunkOn: crcStream.
- 	self writeChunk: crcStream!

Item was removed:
- ----- Method: PNGReadWriter>>paethPredictLeft:above:aboveLeft: (in category 'filtering') -----
- paethPredictLeft: a above: b aboveLeft: c
- 	"Predicts the value of a pixel based on nearby pixels, based on
- Paeth (GG II, 1991)"
- 
- 	| pa pb pc |
- 	pa := b > c ifTrue: [b - c] ifFalse: [c - b].
- 	pb := a > c ifTrue: [a - c] ifFalse: [c - a].
- 	pc := a + b - c - c.
- 	pc < 0 ifTrue: [
- 		pc := pc * -1].
- 	((pa <= pb) and: [pa <= pc]) ifTrue: [^ a].
- 	(pb <= pc) ifTrue: [^ b].
- 	^ c
- !

Item was removed:
- ----- Method: PNGReadWriter>>processBackgroundChunk (in category 'chunks') -----
- processBackgroundChunk
- 
- 	| val red green blue max |
- 
- 	"Transcript show: '  BACKGROUND: ',chunk printString."
- 	colorType = 3 ifTrue: [
- 		backColor := palette at: chunk first + 1.
- 		^self
- 	].
- 	max := (2 raisedTo: bitsPerChannel) - 1.
- 	(colorType = 0 or: [colorType = 4]) ifTrue: [
- 		val := chunk unsignedShortAt: 1 bigEndian: true.
- 		backColor := Color gray: val / max.
- 		^self
- 	].
- 	(colorType = 2 or: [colorType = 6]) ifTrue: [
- 		red := chunk unsignedShortAt: 1 bigEndian: true.
- 		green := chunk unsignedShortAt: 3 bigEndian: true.
- 		blue := chunk unsignedShortAt: 5 bigEndian: true.
- 		backColor := Color r: red/max g: green/max b: blue/max.
- 		^self
- 	].
- "self halt."
- 
- "====
- The bKGD chunk specifies a default background color to present the image against. Note that viewers are not bound to honor this chunk; a viewer can choose to use a different background. 
- 
- For color type 3 (indexed color), the bKGD chunk contains: 
- 
- 
-    Palette index:  1 byte
- 
- The value is the palette index of the color to be used as background. 
- 
- For color types 0 and 4 (grayscale, with or without alpha), bKGD contains: 
- 
- 
-    Gray:  2 bytes, range 0 .. (2^bitdepth)-1
- 
- (For consistency, 2 bytes are used regardless of the image bit depth.) The value is the gray level to be used as background. 
- 
- For color types 2 and 6 (truecolor, with or without alpha), bKGD contains: 
- 
- 
-    Red:   2 bytes, range 0 .. (2^bitdepth)-1
-    Green: 2 bytes, range 0 .. (2^bitdepth)-1
-    Blue:  2 bytes, range 0 .. (2^bitdepth)-1
- 
- (For consistency, 2 bytes per sample are used regardless of the image bit depth.) This is the RGB color to be used as background. 
- 
- When present, the bKGD chunk must precede the first IDAT chunk, and must follow the PLTE chunk, if any. 
- ==="
- !

Item was removed:
- ----- Method: PNGReadWriter>>processIDATChunk (in category 'chunks') -----
- processIDATChunk
- 
- 	interlaceMethod = 0
- 		ifTrue: [ self processNonInterlaced ]
- 		ifFalse: [ self processInterlaced ]
- !

Item was removed:
- ----- Method: PNGReadWriter>>processIHDRChunk (in category 'chunks') -----
- processIHDRChunk
- 	width := chunk longAt: 1 bigEndian: true.
- 	height := chunk longAt: 5 bigEndian: true.
- 	bitsPerChannel := chunk at: 9.
- 	colorType := chunk at: 10.
- 	"compression := chunk at: 11." "TODO - validate compression"
- 	"filterMethod := chunk at: 12." "TODO - validate filterMethod"
- 	interlaceMethod := chunk at: 13. "TODO - validate interlace method"
- 	(#(2 4 6) includes: colorType)
- 		ifTrue: [depth := 32].
- 	(#(0 3) includes: colorType) ifTrue: [
- 		depth := bitsPerChannel min: 8.
- 		colorType = 0 ifTrue: [ "grayscale"
- 			palette := self grayColorsFor: depth.
- 		].
- 	].
- 	bitsPerPixel := (BPP at: colorType+1) at: bitsPerChannel highBit.
- 	bytesPerScanline := width * bitsPerPixel + 7 // 8.
- 	rowSize := width * depth + 31 >> 5.
- !

Item was removed:
- ----- Method: PNGReadWriter>>processInterlaced (in category 'chunks') -----
- processInterlaced
- 	| z startingCol colIncrement rowIncrement startingRow |
- 	startingCol := #(0 4 0 2 0 1 0 ).
- 	colIncrement := #(8 8 4 4 2 2 1 ).
- 	rowIncrement := #(8 8 8 4 4 2 2 ).
- 	startingRow := #(0 0 4 0 2 0 1 ).
- 	z := ZLibReadStream 
- 		on: idatChunkStream originalContents
- 		from: 1
- 		to: idatChunkStream position.
- 	1 to: 7 do: [:pass |
- 		| cx sc bytesPerPass |
- 		(self doPass: pass)
- 			ifTrue:
- 				[cx := colIncrement at: pass.
- 				sc := startingCol at: pass.
- 				bytesPerPass := width - sc + cx - 1 // cx * bitsPerPixel + 7 // 8.
- 				prevScanline := ByteArray new: bytesPerPass.
- 				thisScanline := ByteArray new: bytesPerScanline.
- 				(startingRow at: pass)
- 					to: height - 1
- 					by: (rowIncrement at: pass)
- 					do: [:y |
- 						| filter temp |
- 						filter := z next.
- 						filtersSeen add: filter.
- 						(filter isNil or: [(filter between: 0 and: 4) not])
- 							ifTrue: [^ self].
- 						thisScanline := z next: bytesPerPass into: thisScanline startingAt: 1.
- 						self filterScanline: filter count: bytesPerPass.
- 						self copyPixels: y at: sc by: cx.
- 						temp := prevScanline.
- 						prevScanline := thisScanline.
- 						thisScanline := temp.
- 					]
- 				]
- 	].
- 	z atEnd ifFalse:[self error: 'Unexpected data' translated].!

Item was removed:
- ----- Method: PNGReadWriter>>processNextChunk (in category 'chunks') -----
- processNextChunk
- 
- 	| length chunkType crc chunkCrc |
- 
- 	length := self nextLong.
- 
- 	chunkType := (self next: 4) asString.
- 	(chunk isNil or: [ chunk size ~= length ])
- 		ifTrue: [ chunk := self next: length ]
- 		ifFalse: [ stream next: length into: chunk startingAt: 1 ].
- 	chunkCrc := self nextLong bitXor: 16rFFFFFFFF.
- 	crc := self updateCrc: 16rFFFFFFFF from: 1 to: 4 in: chunkType.
- 	crc := self updateCrc: crc from: 1 to: length in: chunk.
- 	crc = chunkCrc ifFalse:[
- 		self error: ('PNGReadWriter crc error in chunk {1}' translated format: {chunkType}).
- 	].
- 
- 	chunkType = 'IEND' ifTrue: [stream setToEnd. ^self	"*should* be the last chunk"].
- 	chunkType = 'sBIT' ifTrue: [^self processSBITChunk "could indicate unusual sample depth in original"].
- 	chunkType = 'gAMA' ifTrue: [^self 	"indicates gamma correction value"].
- 	chunkType = 'bKGD' ifTrue: [^self processBackgroundChunk].
- 	chunkType = 'pHYs' ifTrue: [^self processPhysicalPixelChunk].
- 	chunkType = 'tRNS' ifTrue: [^self processTransparencyChunk].
- 
- 	chunkType = 'IHDR' ifTrue: [^self processIHDRChunk].
- 	chunkType = 'PLTE' ifTrue: [^self processPLTEChunk].
- 	chunkType = 'IDAT' ifTrue: [
- 		"---since the compressed data can span multiple
- 		chunks, stitch them all together first. later,
- 		if memory is an issue, we need to figure out how
- 		to do this on the fly---"
- 		idatChunkStream
- 			ifNil: [ idatChunkStream := WriteStream with: chunk copy ]
- 			ifNotNil: [ idatChunkStream nextPutAll: chunk ].
- 		^self
- 	].
- 	unknownChunks add: chunkType.
- !

Item was removed:
- ----- Method: PNGReadWriter>>processNonInterlaced (in category 'chunks') -----
- processNonInterlaced
- 	| z filter temp copyMethod debug |
- 	debug := self debugging.
- 	copyMethod := #(copyPixelsGray: nil copyPixelsRGB: copyPixelsIndexed:
- 		  copyPixelsGrayAlpha: nil copyPixelsRGBA:) at: colorType+1.
- 	debug ifTrue: [ Transcript cr; nextPutAll: 'NI chunk size='; print: idatChunkStream position ].
- 	z := ZLibReadStream 
- 		on: idatChunkStream originalContents
- 		from: 1
- 		to: idatChunkStream position.
- 	prevScanline := ByteArray new: bytesPerScanline.
- 	thisScanline := ByteArray new: bytesPerScanline.
- 	0 to: height-1 do: [ :y |
- 		filter := z next.
- 		debug ifTrue:[filtersSeen add: filter].
- 		thisScanline := z next: bytesPerScanline into: thisScanline startingAt: 1.
- 		(debug and: [ thisScanline size < bytesPerScanline ]) ifTrue: [ Transcript nextPutAll: ('wanted {1} but only got {2}' format: { bytesPerScanline. thisScanline size }); cr ].
- 		filter = 0 ifFalse:[self filterScanline: filter count: bytesPerScanline].
- 		self perform: copyMethod with: y.
- 		temp := prevScanline.
- 		prevScanline := thisScanline.
- 		thisScanline := temp.
- 		].
- 	z atEnd ifFalse:[self error:'Unexpected data'].
- 	debug ifTrue: [Transcript  nextPutAll: ' compressed size='; print: z position  ].
- !

Item was removed:
- ----- Method: PNGReadWriter>>processPLTEChunk (in category 'chunks') -----
- processPLTEChunk
- 
- 	| colorCount i |
- 
- 	colorCount := chunk size // 3.
- 	self flag: #todo. "validate colorCount against depth"
- 	palette := Array new: colorCount.
- 	0 to: colorCount-1 do: [ :index |
- 		i := index * 3 + 1.
- 		palette at: index+1 put:
- 			(Color r: (chunk at: i)/255.0 g: (chunk at: i+1)/255.0 b: (chunk at: i+2)/255.0)
- 		].!

Item was removed:
- ----- Method: PNGReadWriter>>processPhysicalPixelChunk (in category 'chunks') -----
- processPhysicalPixelChunk
- 
- 	"Transcript show: '  PHYSICAL: ',chunk printString."
- !

Item was removed:
- ----- Method: PNGReadWriter>>processSBITChunk (in category 'chunks') -----
- processSBITChunk
- 	| rBits gBits bBits aBits |
- 	colorType = 6 ifFalse:[^self].
- 	rBits := chunk at: 1.
- 	gBits := chunk at: 2.
- 	bBits := chunk at: 3.
- 	aBits := chunk at: 4.
- 	(rBits = 5 and:[gBits = 5 and:[bBits = 5 and:[aBits = 1]]]) ifTrue:[
- 		depth := 16.
- 	].!

Item was removed:
- ----- Method: PNGReadWriter>>processTransparencyChunk (in category 'chunks') -----
- processTransparencyChunk
- 
- 	"Transcript show: '  TRANSPARENCY ',chunk printString."
- 	colorType = 0
- 		ifTrue:
- 			[transparentPixelValue := chunk unsignedShortAt: 1 bigEndian: true.
- 			bitsPerChannel <= 8
- 				ifTrue: [palette at: transparentPixelValue + 1 put: Color transparent]
- 				ifFalse: [palette at: 1 put: Color transparent].
- 			^self].
- 	colorType = 2
- 		ifTrue:
- 			[| red green blue |
- 			red :=  chunk unsignedShortAt: 1 bigEndian: true.
- 			green :=  chunk unsignedShortAt: 3 bigEndian: true.
- 			blue :=  chunk unsignedShortAt: 5 bigEndian: true.
- 			transparentPixelValue := bitsPerChannel <= 8
- 				ifTrue: [16rFF00 + red << 8 + green << 8 + blue]
- 				ifFalse: [red << 16 + green << 16 + blue].
- 			^self].
- 	colorType = 3
- 		ifTrue:
- 			[chunk withIndexDo: [ :alpha :index |
- 				palette at: index put: ((palette at: index) alpha: alpha/255)].
- 			^self].
- !

Item was removed:
- ----- Method: PNGReadWriter>>rgbaDecoderMapForDepth: (in category 'pixel copies') -----
- rgbaDecoderMapForDepth: decoderDepth
- 	bigEndian ifTrue:[
- 		depth = 16 ifTrue:[
- 			"Big endian, 32 -> 16 color mapping."
- 			^ColorMap
- 				shifts: #(-17 -14 -11 0)
- 				masks: #(16rF8000000 16rF80000 16rF800 16r00)
- 		] ifFalse:[
- 			"Big endian, 32 -> 32 color mapping"
- 			^ColorMap 
- 				shifts: #(-8 -8 -8 24) 
- 				masks: #(16rFF000000 16rFF0000 16rFF00 16rFF).
- 		].
- 	].
- 	depth = 16 ifTrue:[
- 		"Little endian, 32 -> 16 color mapping."
- 		^ColorMap
- 			shifts: #(7 -6 -19 0)
- 			masks: #(16rF8 16rF800 16rF80000 0)
- 	] ifFalse:[
- 		"Little endian, 32 -> 32 color mapping"
- 		^ColorMap 
- 			shifts: #(-16 0 16 0) 
- 			masks: #(16rFF0000 16rFF00 16rFF 16rFF000000).
- 	].!

Item was removed:
- ----- Method: PNGReadWriter>>understandsImageFormat (in category 'accessing') -----
- understandsImageFormat
- 	#(137 80 78 71 13 10 26 10) do: [ :byte |
- 		stream next = byte ifFalse: [^ false]].
- 	^ true
- !

Item was removed:
- ----- Method: PNGReadWriter>>updateCrc:from:to:in: (in category 'writing') -----
- updateCrc: oldCrc from: start to: stop in: aCollection
- 	^ZipWriteStream updateCrc: oldCrc from: start to: stop in: aCollection!

Item was removed:
- ----- Method: PNGReadWriter>>writeChunk: (in category 'writing') -----
- writeChunk: crcStream
- 	| bytes length crc debug |
- 	debug := self debugging.
- 	bytes := crcStream originalContents.
- 	length := crcStream position.
- 	crc := self updateCrc: 16rFFFFFFFF from: 1 to: length in: bytes.
- 	crc := crc bitXor: 16rFFFFFFFF.
- 	debug ifTrue: [ Transcript cr;
- 		print: stream position; space;
- 		nextPutAll: (bytes copyFrom: 1 to: 4) asString;
- 		nextPutAll: ' len='; print: length;
- 		nextPutAll: ' crc=0x'; nextPutAll: crc printStringHex  ].
- 	stream nextNumber: 4 put: length-4. "exclude chunk name"
- 	stream next: length putAll: bytes startingAt: 1.
- 	stream nextNumber: 4 put: crc.
- 	debug ifTrue: [ Transcript nextPutAll: ' afterPos='; print: stream position ].
- 	crcStream resetToStart.!

Item was removed:
- ----- Method: PNGReadWriter>>writeFileSignature (in category 'writing') -----
- writeFileSignature
- 	stream nextPutAll: #[ 16r89 16r50 16r4E  16r47 16r0D 16r0A 16r1A 16r0A ]!

Item was removed:
- ----- Method: PNGReadWriter>>writeIDATChunkOn: (in category 'writing') -----
- writeIDATChunkOn: aStream
- 	"Write the IDAT chunk"
- 	| z |
- 	aStream nextPutAll: 'IDAT' asByteArray.
- 	z := ZLibWriteStream on: aStream.
- 	form depth <= 8 
- 		ifTrue:[self writeType3DataOn: z]
- 		ifFalse:[ self writeType6DataOn: z].
- 	self debugging ifTrue: [
- 		Transcript cr;
- 			nextPutAll: 'compressed size=';
- 			print: aStream position;
- 			nextPutAll: ' uncompressed size=';
- 			print: z position  ]
- !

Item was removed:
- ----- Method: PNGReadWriter>>writeIENDChunkOn: (in category 'writing') -----
- writeIENDChunkOn: aStream
- 	"Write the IEND chunk"
- 	aStream nextPutAll: 'IEND' asByteArray.!

Item was removed:
- ----- Method: PNGReadWriter>>writeIHDRChunkOn: (in category 'writing') -----
- writeIHDRChunkOn: aStream
- 	"Write the IHDR chunk"
- 	aStream nextPutAll: 'IHDR' asByteArray.
- 	aStream nextInt32Put: width.
- 	aStream nextInt32Put: height.
- 	aStream nextNumber: 1 put: bitsPerChannel.
- 	aStream nextNumber: 1 put: colorType.
- 	aStream nextNumber: 1 put: 0. "compression"
- 	aStream nextNumber: 1 put: 0. "filter method"
- 	aStream nextNumber: 1 put: 0. "interlace method"
- !

Item was removed:
- ----- Method: PNGReadWriter>>writePLTEChunkOn: (in category 'writing') -----
- writePLTEChunkOn: aStream
- 	"Write the PLTE chunk"
- 	| colors |
- 	aStream nextPutAll: 'PLTE' asByteArray.
- 	(form isColorForm) 
- 		ifTrue:[colors := form colors]
- 		ifFalse:[colors := Color indexedColors copyFrom: 1 to: (1 bitShift: form depth)].
- 	colors do:[:aColor|
- 		| r g b |
- 		r := (aColor red * 255) truncated.
- 		g := (aColor green * 255) truncated.
- 		b := (aColor blue * 255) truncated.
- 		aStream nextPut: r; nextPut: g; nextPut: b.
- 	].!

Item was removed:
- ----- Method: PNGReadWriter>>writeSBITChunkOn: (in category 'writing') -----
- writeSBITChunkOn: aStream
- 	"Write the IDAT chunk"
- 	aStream nextPutAll: 'sBIT' asByteArray.
- 	form depth = 16 ifFalse: [self notYetImplemented].
- 	aStream nextPut: 5.
- 	aStream nextPut: 5.
- 	aStream nextPut: 5.
- 	aStream nextPut: 1.!

Item was removed:
- ----- Method: PNGReadWriter>>writeTRNSChunkOn: (in category 'writing') -----
- writeTRNSChunkOn: aStream
- 	"Write out tRNS chunk"
- 	aStream nextPutAll: 'tRNS' asByteArray.
- 	form colors do:[:aColor|
- 		aStream nextPut: (aColor alpha * 255) truncated.
- 	].!

Item was removed:
- ----- Method: PNGReadWriter>>writeType3DataOn: (in category 'writing') -----
- writeType3DataOn: zStream
- 	"Write color indexed data."
- 	| scanline hack hackBlt swizzleBlt swizzleHack hackDepth |
- 	scanline := ByteArray new: bytesPerScanline + 3 // 4 * 4.
- 	hackDepth := bigEndian ifTrue:[form depth] ifFalse:[form depth negated].
- 	hack := Form extent: width at 1 depth: hackDepth bits: scanline.
- 	hackBlt := BitBlt toForm: hack.
- 	hackBlt sourceForm: form.
- 	hackBlt combinationRule: Form over.
- 	hackBlt destOrigin: 0 at 0.
- 	hackBlt width: width; height: 1.
- 	(form depth < 8 and:[bigEndian not]) ifTrue:[
- 		swizzleHack := Form new hackBits: scanline.
- 		swizzleBlt := BitBlt toForm: swizzleHack.
- 		swizzleBlt sourceForm: swizzleHack.
- 		swizzleBlt combinationRule: Form over.
- 		swizzleBlt colorMap: (StandardSwizzleMaps at: form depth).
- 	].
- 	0 to: height-1 do:[:i|
- 		hackBlt sourceOrigin: 0 at i; copyBits.
- 		swizzleBlt ifNotNil:[swizzleBlt copyBits].
- 		zStream nextPut: 0. "filterType"
- 		zStream next: bytesPerScanline putAll: scanline startingAt: 1.
- 	].
- 	zStream close.!

Item was removed:
- ----- Method: PNGReadWriter>>writeType6DataOn: (in category 'writing') -----
- writeType6DataOn: zStream
- 	"Write RGBA data."
- 	| scanline hack hackBlt cm miscBlt |
- 	scanline := ByteArray new: bytesPerScanline.
- 	hack := Form extent: width at 1 depth: 32 bits: scanline.
- 	form depth = 16 ifTrue:[
- 		"Expand 16 -> 32"
- 		miscBlt := BitBlt toForm: hack.
- 		miscBlt sourceForm: form.
- 		miscBlt combinationRule: Form over.
- 		miscBlt destOrigin: 0 at 0.
- 		miscBlt width: width; height: 1.
- 	].
- 	hackBlt := BitBlt toForm: hack.
- 	hackBlt sourceForm: (miscBlt ifNil:[form] ifNotNil:[hack]).
- 	hackBlt combinationRule: Form over.
- 	hackBlt destOrigin: 0 at 0.
- 	hackBlt width: width; height: 1.
- 	bigEndian ifTrue:[
- 		cm := ColorMap 
- 			shifts: #(8 8 8 -24) 
- 			masks: #(16rFF0000 16rFF00 16rFF 16rFF000000).
- 	] ifFalse:[
- 		cm := ColorMap 
- 			shifts: #(-16 0 16 0) 
- 			masks: #(16rFF0000 16rFF00 16rFF 16rFF000000).
- 	].
- 	hackBlt colorMap: cm.
- 	0 to: height-1 do:[:i|
- 		miscBlt ifNil:[
- 			hackBlt sourceOrigin: 0 at i; copyBits.
- 		] ifNotNil:[
- 			miscBlt sourceOrigin: 0 at i; copyBits.
- 			hack fixAlpha.
- 			hackBlt copyBits.
- 		].
- 		zStream nextPut: 0. "filterType"
- 		zStream nextPutAll: scanline.
- 	].
- 	zStream close.!

Item was removed:
- ImageReadWriter subclass: #PNMReadWriter
- 	instanceVariableNames: 'first type origin cols rows depth maxValue tupleType pragma'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Files'!
- 
- !PNMReadWriter commentStamp: 'nice 3/24/2010 07:37' prior: 0!
- I am a subclass of ImageReadWriter that decodes portable anymap file formats
- (pbm, pgm, ppm and  pam) images.
- 
- I accept the #origin pragma for SE files as described in:
- Algoritms For Image Processing And Computer Vision. J. R. Parker
- 
- Don't work with 2 bytes samples (16 bit grays, > 32 bits color, etc...), 
- pam files preliminary support.
- 
- f := ImageReadWriter formFromFileNamed: 'Tools:Squeak3.4:Carmen.ppm'.
- f morphEdit
- 
- Submitted by Javier Diaz Reinoso, Oct/2003!

Item was removed:
- ----- Method: PNMReadWriter class>>testToSEFile: (in category 'testing') -----
- testToSEFile: filename
- 	"write SE file with origin
- 		PNMReadWriter testToSEFile: 'Tools:Squeak3.4:outSE.pbm'.
- 	"
- 	| prw f |
- 	prw := self new.
- 	prw stream: ((FileStream newFileNamed: filename) binary).
- 	prw pragma: '#origin 10 10', String lf.
- 	f := Form fromUser.
- 	prw nextPutImage: f!

Item was removed:
- ----- Method: PNMReadWriter class>>typicalFileExtensions (in category 'image reading/writing') -----
- typicalFileExtensions
- 	"Answer a collection of file extensions (lowercase) which files that I can read might commonly have"
- 	^#('pbm' 'pgm' 'pnm' 'ppm' 'pam')!

Item was removed:
- ----- Method: PNMReadWriter>>cleanLine (in category 'reading') -----
- cleanLine
- 	"upTo LF or CR, tab as space"
- 
- 	^stream nextLine ifNotNil: [:line | line replaceAll: Character tab with: Character space]!

Item was removed:
- ----- Method: PNMReadWriter>>getTokenPbm: (in category 'reading') -----
- getTokenPbm: aCollection
- 	"get a number, return rest of collection"
- 	| line tokens token |
- 	tokens := aCollection.
- 	tokens size = 0 ifTrue:[
- 		[
- 			line := self pbmGetLine.
- 			line ifNil:[^{nil . nil}].
- 			tokens := line findTokens: ' '.
- 			tokens size = 0
- 		] whileTrue:[].
- 	].
- 	"Transcript cr; show: tokens asString."
- 	token := tokens removeFirst.
- 	^{token asInteger . tokens}
- !

Item was removed:
- ----- Method: PNMReadWriter>>nextImage (in category 'reading') -----
- nextImage
- 	"read one image"
- 	| data p |
- 	first ifNil:[
- 		first := false.
- 		data := stream contentsOfEntireFile.
- 		stream := (RWBinaryOrTextStream with: data) reset.
- 	]
- 	ifNotNil:[
- 		type < 4 ifTrue:[
- 			self error: 'Plain PBM, PGM or PPM have only one image' translated
- 		].
- 	].
- 	stream ascii.
- 	p := stream next.
- 	type := (stream next) asInteger - 48.
- 	(p = $P and:[type > 0 and:[type < 8]]) ifFalse:[
- 		self error: 'Not a PNM file' translated
- 	].
- 	type = 7 ifTrue:[
- 		self readHeaderPAM
- 	]
- 	ifFalse: [
- 		self readHeader
- 	].
- 	type caseOf: {
- 		[1] 	->	[^self readPlainBW].
- 		[2] 	->	[^self readPlainGray].
- 		[3] 	->	[^self readPlainRGB].
- 		[4] 	->	[^self readBWreverse: false].
- 		[5] 	->	[^self readGray].
- 		[6] 	->	[^self readRGB].
- 		[7] 	->	[	"PAM"
- 					(tupleType asUppercase) caseOf: {
- 						['BLACKANDWHITE'] 		-> [^self readBWreverse: true].
- 						['GRAYSCALE'] 			-> [^self readGray].
- 						['RGB'] 					-> [^self readRGB].
- 						['RGB_ALPHA'] 			-> [^self notYetImplemented].
- 						['GRAYSCALE_ALPHA'] 	-> [^self notYetImplemented].
- 					} otherwise: [^self readData].
- 				]
- 	}!

Item was removed:
- ----- Method: PNMReadWriter>>nextPutBW:reverse: (in category 'writing') -----
- nextPutBW: aForm reverse: flagXor
- 	| myType val nBytes bytesRow |
- 	cols := aForm width.
- 	rows := aForm height.
- 	depth := aForm depth.
- 	"stream position: 0."
- 	aForm depth = 1 ifTrue:[myType := $4] ifFalse:[myType := $5].
- 	self writeHeader: myType.
- 	stream binary.
- 	nBytes := (cols/8) ceiling.
- 	bytesRow := (cols/32) ceiling * 4.
- 	0 to: rows-1 do: [:y | | i |
- 		i := 1 + (bytesRow*y).
- 		0 to: nBytes-1 do: [:x |
- 			val := aForm bits byteAt: i.
- 			flagXor ifTrue:[val := val bitXor: 16rFF].
- 			stream nextPut: val.
- 			i := i+1.
- 		]
- 	].
- !

Item was removed:
- ----- Method: PNMReadWriter>>nextPutGray: (in category 'writing') -----
- nextPutGray: aForm
- 	| myType val |
- 	cols := aForm width.
- 	rows := aForm height.
- 	depth := aForm depth.
- 	"stream position: 0."
- 	aForm depth = 1 ifTrue:[myType := $4] ifFalse:[myType := $5].
- 	self writeHeader: myType.
- 	0 to: rows-1 do: [:y |
- 		0 to: cols-1 do: [:x |
- 			val := aForm pixelValueAt: x at y.
- 			stream nextPut: val.
- 		]
- 	].
- !

Item was removed:
- ----- Method: PNMReadWriter>>nextPutImage: (in category 'writing') -----
- nextPutImage: aForm
- 	aForm unhibernate.
- 	aForm depth	 caseOf: {
- 		[1] 		-> [self nextPutBW: aForm reverse: false].
- 		[16] 	-> [self nextPutRGB: aForm].
- 		[32] 	-> [self nextPutRGB: aForm].
- 	} otherwise: [
- 		(aForm respondsTo: #colors) ifTrue:[
- 			aForm colors ifNil: [
- 				self nextPutGray: aForm
- 			]
- 			ifNotNil: [
- 				self nextPutRGB: aForm
- 			]
- 		]
- 		ifFalse:[
- 			self nextPutGray: aForm
- 		]
- 	]!

Item was removed:
- ----- Method: PNMReadWriter>>nextPutRGB: (in category 'writing') -----
- nextPutRGB: aForm
- 	| myType f shift mask |
- 	cols := aForm width.
- 	rows := aForm height.
- 	depth := aForm depth.
- 	f := aForm.
- 	depth < 16 ifTrue:[
- 		f := aForm asFormOfDepth: 32.
- 		depth := 32.
- 	].
- 	myType := $6.
- 	"stream position: 0."
- 	self writeHeader: myType.
- 	depth = 32 ifTrue:[shift := 8. mask := 16rFF] ifFalse:[shift := 5. mask := 16r1F].
- 	0 to: rows-1 do: [:y |
- 		0 to: cols-1 do: [:x | | p r g b |
- 			p := f pixelValueAt: x at y.
- 			b := p bitAnd: mask. p := p >> shift.
- 			g := p bitAnd: mask. p := p >> shift.
- 			r := p bitAnd: mask.
- 			stream nextPut: r.
- 			stream nextPut: g.
- 			stream nextPut: b.
- 		]
- 	].
- !

Item was removed:
- ----- Method: PNMReadWriter>>origin (in category 'accessing') -----
- origin
- 	^origin!

Item was removed:
- ----- Method: PNMReadWriter>>pbmGetLine (in category 'reading') -----
- pbmGetLine
- 	"Get the next non-comment line from the PBM stream
- 	Look for 'pragmas' - commands hidden in the comments"
- 	
-  	| line |
- 	[
- 		line := self cleanLine.
- 		line ifNil: [^nil].
- 		(line size > 0 and:[(line at: 1) = $#]) ifTrue:[
- 			self pbmParam: line.
- 		].
- 		(line size = 0) or:[(line at: 1) = $#]
- 	]
-  	whileTrue: [].
- 	^line!

Item was removed:
- ----- Method: PNMReadWriter>>pbmParam: (in category 'reading') -----
- pbmParam: line
- 	"Look for a parameter hidden in a comment"
- 	| key tokens |
- 	tokens := line findTokens: ' '.
- 	key := (tokens at: 1) asLowercase.
- 	(key = '#origin' and:[tokens size = 3]) ifTrue:[	"ORIGIN key word"
- 		"This is for SE files as described in:
- 		Algoritms For Image Processing And Computer Vision. J. R. Parker"
- 		origin := ((tokens at: 2) asInteger) @ ((tokens at: 3) asInteger)
- 	].
- !

Item was removed:
- ----- Method: PNMReadWriter>>pragma: (in category 'accessing') -----
- pragma: s
- 	pragma := s!

Item was removed:
- ----- Method: PNMReadWriter>>r:g:b:for: (in category 'reading') -----
- r: r g: g b: b for: aDepth
- 	"integer value according depth"
- 	| val |
- 	aDepth = 16 ifTrue: [
- 		val := (1 << 15) + (r << 10) + (g << 5) + b.
- 	]
- 	ifFalse:[
- 		val := (16rFF << 24) + (r << 16) + (g << 8) + b.
- 	].
- 	^val
- !

Item was removed:
- ----- Method: PNMReadWriter>>readBWreverse: (in category 'reading') -----
- readBWreverse: flagXor
- 	"B&W for PAM"
- 	| val form bytesRow nBytes |
- 	stream binary.
- 	form := Form extent: cols at rows depth: 1.
- 	nBytes := (cols/8) ceiling.
- 	bytesRow := (cols/32) ceiling * 4.
- 	0 to: rows-1 do: [:y | | i |
- 		i := 1 + (bytesRow*y).
- 		0 to: nBytes-1 do: [:x |
- 			val := stream next.
- 			flagXor ifTrue:[val := val bitXor: 16rFF].
- 			form bits byteAt: i put: val.
- 			i := i+1.
- 		]
- 	].
- 	^form
- !

Item was removed:
- ----- Method: PNMReadWriter>>readData (in category 'reading') -----
- readData
- 	"generic data"
- 	| data nBits nBytes val sample |
- 	stream binary.
- 	data := OrderedCollection new.
- 	nBits := maxValue floorLog:2.
- 	nBytes := (nBits+1) >> 3.
- 	(nBits+1 rem: 8) > 0 ifTrue:[nBytes := nBytes+1].
- 
- 	0 to: rows-1 do: [:y |
- 		0 to: cols-1 do: [:x |
- 			val := 0.
- 			1 to: nBytes do: [:n |
- 				sample := stream next.
- 				val := val << 8 + sample.
- 			].
- 			data add: val.
- 		]
- 	].
- 	^data
- 
- !

Item was removed:
- ----- Method: PNMReadWriter>>readGray (in category 'reading') -----
- readGray
- 	"gray form, return ColorForm with gray ramp"
- 	| form poker |
- 	maxValue > 255 ifTrue:[self error: ('Gray value > {1} bits not supported in Squeak' translated format: {8})].
- 	stream binary.
- 	form := ColorForm extent: cols at rows depth: depth.
- 	form colors: nil.
- 	poker := BitBlt bitPokerToForm: form.
- 	0 to: rows-1 do: [:y |
- 		0 to: cols-1 do: [:x |
- 			|val|
- 			val := stream next.
- 			poker pixelAt: x at y put: val.
- 		]
- 	].
- 	"a better way is using a gamma corrected palette"
- 	form colors: ((0 to: 255) collect:[:c|
- 		c > maxValue
- 			ifTrue:[Color white]
- 			ifFalse:[Color gray: (c/maxValue) asFloat]]).
- 	form colors at: 1 put: (Color black).
- 	^form
- !

Item was removed:
- ----- Method: PNMReadWriter>>readHeader (in category 'reading') -----
- readHeader
- 	"read header for pbm, pgm or ppm"
- 	| tokens aux d c  |
- 	tokens := OrderedCollection new.
- 	aux := self getTokenPbm: tokens.
- 	cols := aux at: 1. tokens := aux at: 2.
- 	aux := self getTokenPbm: tokens.
- 	rows := aux at: 1. tokens := aux at: 2.
- 
- 	(type = 1 or:[type = 4]) ifTrue:[
- 		maxValue := 1
- 	]
- 	ifFalse: [
- 		aux := self getTokenPbm: tokens.
- 		maxValue := aux at: 1. tokens := aux at: 2.
- 	].
- 	d := {1 . 2 . 4 . 	8 . 		16 . 32}.
- 	c := {2 . 4 . 16 . 256 . 32768 . 16777216}. 
- 	(type = 3 or:[type = 6]) ifTrue: [
- 		maxValue >= 65536 ifTrue:[
- 			self error: ('Pixmap > {1} bits not supported in PPM' translated format: {48})
- 		].
- 		maxValue >= 256 ifTrue:[
- 			self error: ('Pixmap > {1} bits are not supported in Squeak' translated format: {32})
- 		].
- 		maxValue < 32 ifTrue:[depth := 16] ifFalse:[depth := 32].
- 	]
- 	ifFalse: [
- 		depth := nil.
- 		1 to: c size do:[:i| ((c at: i) > maxValue and:[depth = nil]) ifTrue:[depth:=d at: i]].
- 	].
- 	Transcript cr; show: 'PBM file class ', type asString, ' size ', cols asString, ' x ', 
- 		rows asString, ' maxValue =', maxValue asString, ' depth=', depth asString.
- !

Item was removed:
- ----- Method: PNMReadWriter>>readHeaderPAM (in category 'reading') -----
- readHeaderPAM
- 	"read pam header, not tested"
- 	| loop |
- 	tupleType := ''.
- 	loop := true.
- 	loop whileTrue:[ | key val tokens line |
- 		line := self pbmGetLine.
- 		tokens := line findTokens: ' '.
- 		tokens size = 2 ifTrue:[
- 			key := tokens at: 1 asUppercase.
- 			val := tokens at: 2.
- 			key caseOf: {
- 				['WIDTH'] 		-> [cols := val asInteger].
- 				['HEIGHT'] 		-> [rows := val asInteger].
- 				['DEPTH'] 		-> [depth := val asInteger].
- 				['MAXVAL']		-> [maxValue := val asInteger].
- 				['TUPLETYPE']	-> [tupleType := tupleType, ' ', val].
- 				['ENDHDR']		-> [loop := false].
- 			}
- 		]
- 	].
- 	Transcript cr; show: 'PAM file class ', type asString, ' size ', cols asString, ' x ', 
- 		rows asString, ' maxValue =', maxValue asString, ' depth=', depth asString.
- !

Item was removed:
- ----- Method: PNMReadWriter>>readPlainBW (in category 'reading') -----
- readPlainBW
- 	"plain BW"
- 	| val form poker |
- 	form := Form extent: cols at rows depth: depth.
- 	poker := BitBlt bitPokerToForm: form.
- 	0 to: rows-1 do: [:y |
- 		0 to: cols-1 do: [:x |
- 			[val := stream next. (val = $0 or:[val = $1])] whileFalse:[
- 				val ifNil: [self error: 'End of file reading PBM' translated].
- 			].
- 			poker pixelAt: x at y put: (val asInteger).
- 		]
- 	].
- 	^form
- !

Item was removed:
- ----- Method: PNMReadWriter>>readPlainGray (in category 'reading') -----
- readPlainGray
- 	"plain gray"
- 	| val form poker aux tokens |
- 	form := Form extent: cols at rows depth: depth.
- 	poker := BitBlt bitPokerToForm: form.
- 	tokens := OrderedCollection new.
- 	0 to: rows-1 do: [:y |
- 		0 to: cols-1 do: [:x |
- 			aux := self getTokenPbm: tokens.
- 			val := aux at: 1. tokens := aux at: 2.
- 			poker pixelAt: x at y put: val.
- 		]
- 	].
- 	^form
- !

Item was removed:
- ----- Method: PNMReadWriter>>readPlainRGB (in category 'reading') -----
- readPlainRGB
- 	"RGB form, use 32 bits"
- 	| val form poker tokens aux |
- 	maxValue > 255 ifTrue:[self error: ('RGB value > {1} bits not supported in Squeak' translated format: {32})].
- 	form := Form extent: cols at rows depth: 32.
- 	poker := BitBlt bitPokerToForm: form.
- 	tokens := OrderedCollection new.
- 	0 to: rows-1 do: [:y |
- 		0 to: cols-1 do: [:x | | r g b|
- 			aux := self getTokenPbm: tokens. r := aux at: 1. tokens := aux at: 2.
- 			aux := self getTokenPbm: tokens. g := aux at: 1. tokens := aux at: 2.
- 			aux := self getTokenPbm: tokens. b := aux at: 1. tokens := aux at: 2.
- 			val := self r: r g: g b: b for: depth.
- 			poker pixelAt: x at y put: val.
- 		]
- 	].
- 	^form
- !

Item was removed:
- ----- Method: PNMReadWriter>>readRGB (in category 'reading') -----
- readRGB
- 	"RGB form, use 16/32 bits"
- 	| val form poker sample shift |
- 	maxValue > 255 ifTrue:[self error: ('RGB value > {1} bits not supported in Squeak' translated format: {32})].
- 	stream binary.
- 	form := Form extent: cols at rows depth: depth.
- 	poker := BitBlt bitPokerToForm: form.
- 	depth = 32 ifTrue:[shift := 8] ifFalse:[shift := 5].
- 	0 to: rows-1 do: [:y |
- 		0 to: cols-1 do: [:x |
- 			val := 16rFF.	"no transparency"
- 			1 to: 3 do: [:i |
- 				sample := stream next.
- 				val := val << shift + sample.
- 			].
- 			poker pixelAt: x at y put: val.
- 		]
- 	].
- 	^form
- !

Item was removed:
- ----- Method: PNMReadWriter>>stream: (in category 'accessing') -----
- stream: s
- 	stream := s!

Item was removed:
- ----- Method: PNMReadWriter>>tupleType (in category 'accessing') -----
- tupleType
- 	^tupleType!

Item was removed:
- ----- Method: PNMReadWriter>>understandsImageFormat (in category 'testing') -----
- understandsImageFormat
- 	"P1 to P7"
- 	| p  |
- 	p := stream next asCharacter.
- 	type := stream next - 48.
- 	^(p = $P and:[type > 0 and:[type < 8]])
- 	!

Item was removed:
- ----- Method: PNMReadWriter>>writeHeader: (in category 'writing') -----
- writeHeader: myType
- 	"this is ascii"
- 	stream nextPut: ($P asciiValue).
- 	stream nextPut: (myType asciiValue).
- 	stream nextPut: 10.		"nl"
- 	pragma ifNotNil:[
- 		stream nextPutAll: (pragma asByteArray).
- 	].
- 	stream nextPutAll: (cols printString) asByteArray.
- 	stream nextPut: 32.		" "
- 	stream nextPutAll: (rows printString) asByteArray.
- 	stream nextPut: 10.		"nl"
- 	depth > 1 ifTrue: [| d c maxV |
- 		d := {1 . 2 . 4  . 8   . 16 . 32}.
- 		c := {1 . 3 . 15 . 255 . 31 . 255}. 
- 		maxV := nil.
- 		1 to: d size do:[:i| ((d at: i) = depth and:[maxV = nil]) ifTrue:[maxV := c at: i]].
- 		stream nextPutAll: (maxV printString) asByteArray.
- 		stream nextPut: 10.		"nl"
- 	]
- 	!

Item was removed:
- BitBlt subclass: #Pen
- 	instanceVariableNames: 'location direction penDown'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Primitives'!
- 
- !Pen commentStamp: '<historical>' prior: 0!
- My instances can scribble on the screen or some other Form, drawing and printing at any angle. Since I am a BitBlt, the drawing can be done with an arbitary source Form.
- !

Item was removed:
- ----- Method: Pen class>>example (in category 'examples') -----
- example
- 	"Draw a spiral with a pen that is 2 pixels wide."
- 	"Display restoreAfter: [Pen example]"
- 
- 	| bic |
- 	bic := self new.
- 	bic defaultNib: 2.
- 	bic color: Color blue.
- 	bic combinationRule: Form over.
- 	1 to: 100 do: [:i | bic go: i*4. bic turn: 89].
- !

Item was removed:
- ----- Method: Pen class>>feltTip:cellSize: (in category 'tablet drawing examples') -----
- feltTip: width cellSize: cellSize
- 	"Warning: This example potentially uses a large amount of memory--it creates a Form with cellSize squared bits for every Display pixel."
- 	"In this example, all drawing is done into a large, monochrome Form and then scaled down onto the Display using smoothing. The larger the cell size, the more possible shades of gray can be generated, and the smoother the resulting line appears. A cell size of 8 yields 64 possible grays, while a cell size of 16 gives 256 levels, which is about the maximum number of grays that the human visual system can distinguish. The width parameter determines the maximum line thickness. Requires the optional tablet support primitives which may not be supported on all platforms. Works best in full screen mode. Shift-mouse to exit." 
- 	"Pen feltTip: 2.7 cellSize: 8"
- 
- 	| tabletScale bitForm pen warp |
- 	tabletScale := self tabletScaleFactor.
- 	bitForm := Form extent: Display extent * cellSize depth: 1.
- 	pen := Pen newOnForm: bitForm.
- 	pen color: Color black.
- 	warp := (WarpBlt toForm: Display)
- 		sourceForm: bitForm;
- 		colorMap: (bitForm colormapIfNeededFor: Display);
- 		cellSize: cellSize;
- 		combinationRule: Form over.
- 	Display fillColor: Color white.
- 	Display restoreAfter: [ | p r nibSize srcR startP dstR |
- 		[Sensor shiftPressed and: [Sensor anyButtonPressed]] whileFalse: [
- 			p := (Sensor tabletPoint * cellSize * tabletScale) rounded.
- 			nibSize := (Sensor tabletPressure * (cellSize * width)) rounded.
- 		     nibSize > 0
- 				ifTrue: [
- 					pen squareNib: nibSize.
- 					startP := pen location.
- 					pen goto: p.
- 					r := startP rect: pen location.
- 					dstR := (r origin // cellSize) corner: ((r corner + nibSize + (cellSize - 1)) // cellSize).
- 					srcR := (dstR origin * cellSize) corner: (dstR corner * cellSize).
- 					warp copyQuad: srcR innerCorners toRect: dstR]
- 				ifFalse: [
- 					pen place: p]]].
- !

Item was removed:
- ----- Method: Pen class>>inkBrush (in category 'tablet drawing examples') -----
- inkBrush
- 	"Similar to simplePressurePen, but this example uses the average of the recent pen pressure values. The effect is that of a Japanese ink brush that comes up gradually off the paper as the brush is lifted, causing end (and beginning) of each stroke to taper. Requires the optional tablet support primitives which may not be supported on all platforms. Works best in full screen mode. Shift-mouse to exit." 
- 	"Pen inkBrush"
- 
- 	| tabletScale historyMSecs pressureHistory pen |
- 	tabletScale := self tabletScaleFactor.
- 	historyMSecs := 120.
- 	pressureHistory := OrderedCollection new.
- 	pen := Pen newOnForm: Display.
- 	pen color: Color black.
- 	Display fillColor: Color white.
- 	Display restoreAfter: [ | sum p averagePressure now currentPressure |
- 		[Sensor shiftPressed and: [Sensor anyButtonPressed]] whileFalse: [
- 			"compute the average pressure over last historyMSecs milliseconds"
- 			now := Time millisecondClockValue.
- 			currentPressure := (20.0 * Sensor tabletPressure) rounded.
- 			pressureHistory addLast: (Array with: now with: currentPressure).
- 			[pressureHistory size > 0 and:
- 			 [(pressureHistory first first + historyMSecs) < now]]
- 				whileTrue: [pressureHistory removeFirst].  "prune old entries"
- 			sum := pressureHistory inject: 0 into: [:t :e | t + e last].
- 			averagePressure := sum // pressureHistory size.
- 
- 			p := (Sensor tabletPoint * tabletScale) rounded.
- 		     averagePressure > 0
- 				ifTrue: [
- 					pen roundNib: averagePressure.
- 					pen goto: p]
- 				ifFalse: [
- 					pen place: p]]].
- !

Item was removed:
- ----- Method: Pen class>>new (in category 'instance creation') -----
- new
- 	^ self newOnForm: Display!

Item was removed:
- ----- Method: Pen class>>newOnForm: (in category 'instance creation') -----
- newOnForm: aForm
- 	| pen |
- 	pen := super new.
- 	pen setDestForm: aForm.
- 	pen sourceOrigin: 0 at 0.
- 	pen home.
- 	pen defaultNib: 1.
- 	pen north.
- 	pen down.
- 	^ pen!

Item was removed:
- ----- Method: Pen class>>simplePressurePen (in category 'tablet drawing examples') -----
- simplePressurePen
- 	"An example of using a pressure sensitive pen to control the thickness of the pen. This requires the optional tablet support primitives which may not be supported on all platforms. Works best in full screen mode. Shift-mouse to exit." 
- 	"Pen simplePressurePen"
- 
- 	| tabletScale pen |
- 	tabletScale := self tabletScaleFactor.
- 	pen := Pen newOnForm: Display.
- 	pen color: Color black.
- 	Display fillColor: Color white.
- 	Display restoreAfter: [ | p pressure |
- 		[Sensor shiftPressed and: [Sensor anyButtonPressed]] whileFalse: [
- 			p := (Sensor tabletPoint * tabletScale) rounded.
- 			pressure := (15.0 * Sensor tabletPressure) rounded.
- 		     pressure > 0
- 				ifTrue: [
- 					pen roundNib: pressure.
- 					pen goto: p]
- 				ifFalse: [
- 					pen place: p]]].
- !

Item was removed:
- ----- Method: Pen class>>tabletScaleFactor (in category 'tablet drawing examples') -----
- tabletScaleFactor
- 	"Answer a Point that scales tablet coordinates to Display coordinates, where the full extent of the tablet maps to the extent of the entire Display."
- 
- 	| tabletExtent |
- 	tabletExtent := Sensor tabletExtent.
- 	^ (Display width asFloat / tabletExtent x) @ (Display height asFloat / tabletExtent y)
- !

Item was removed:
- ----- Method: Pen class>>testMouseTracking (in category 'tablet drawing examples') -----
- testMouseTracking
- 	"A very simple example of drawing using the mouse. Compare the tracking speed of this example with that of testTabletTracking. Mouse down to draw a stroke, shift-mouse to exit." 
- 	"Pen testMouseTracking"
- 
- 	| pen |
- 	pen := Pen newOnForm: Display.
- 	pen roundNib: 8.
- 	pen color: Color black.
- 	Display fillColor: Color white.
- 	Display restoreAfter: [ | p |
- 		[Sensor shiftPressed and: [Sensor anyButtonPressed]] whileFalse: [
- 			p := Sensor cursorPoint.
- 		     Sensor anyButtonPressed
- 				ifTrue: [pen goto: p]
- 				ifFalse: [
- 					pen color: Color random.
- 					pen place: p]]].
- !

Item was removed:
- ----- Method: Pen class>>testTabletTracking (in category 'tablet drawing examples') -----
- testTabletTracking
- 	"A very simple example of drawing using the pen of a digitizing tablet such as a Wacom ArtZ tablet. This requires the optional tablet support primitives which may not be supported on all platforms. Compare the tracking speed of this example with that of testMouseTracking. On a Macintosh, the tablet primitives provide roughly 120 samples/second versus only 60 mouse samples/second, and the difference is noticable. Works best in full screen mode. Mouse down to draw a stroke, shift-mouse to exit." 
- 	"Pen testTabletTracking"
- 
- 	| tabletScale pen |
- 	tabletScale := self tabletScaleFactor.
- 	pen := Pen newOnForm: Display.
- 	pen roundNib: 8.
- 	pen color: Color black.
- 	Display fillColor: Color white.
- 	Display restoreAfter: [ | p |
- 		[Sensor shiftPressed and: [Sensor anyButtonPressed]] whileFalse: [
- 			p := (Sensor tabletPoint * tabletScale) rounded.
- 		     Sensor tabletPressure > 0
- 				ifTrue: [pen goto: p]
- 				ifFalse: [
- 					pen color: Color random.
- 					pen place: p]]].
- !

Item was removed:
- ----- Method: Pen>>color: (in category 'operations') -----
- color: aColorOrInteger
- 	"Set the pen to the given color or to a color chosen from a fixed set of colors."
- 
- 	| count c |
- 	aColorOrInteger isInteger
- 		ifTrue: [
- 			destForm depth = 1 ifTrue: [^ self fillColor: Color black].
- 			count := 19.  "number of colors in color wheel"
- 			c := (Color red wheel: count) at: ((aColorOrInteger * 7) \\ count) + 1]
- 		ifFalse: [c := aColorOrInteger].  "assume aColorOrInteger is a Color"
- 	self fillColor: c.
- !

Item was removed:
- ----- Method: Pen>>defaultNib: (in category 'initialize-release') -----
- defaultNib: widthInteger 
- 	"Nib is the tip of a pen. This sets up the pen, with a nib of width widthInteger. You can also set the shape of the pen nib using:
- 		roundNib: widthInteger, or
- 		squareNib: widthInteger, or
- 		sourceForm: aForm"
- "Example:
- 	| bic |
- 	bic := Pen new sourceForm: Cursor normal.
- 	bic combinationRule: Form paint; turn: 90.
- 	10 timesRepeat: [bic down; go: 3; up; go: 10]."
- 
- 	self color: Color black.
- 	self squareNib: widthInteger.
- !

Item was removed:
- ----- Method: Pen>>direction (in category 'accessing') -----
- direction
- 	"Answer the receiver's current direction. 0 is towards the top of the
- 	screen."
- 
- 	^direction!

Item was removed:
- ----- Method: Pen>>down (in category 'operations') -----
- down
- 	"Set the state of the receiver's pen to down (drawing)."
- 
- 	penDown := true!

Item was removed:
- ----- Method: Pen>>dragon: (in category 'geometric designs') -----
- dragon: n  "Display restoreAfter: [Display fillWhite. Pen new dragon: 10]."
- 	"Display restoreAfter: [Display fillWhite. 1 to: 4 do:
- 				[:i | Pen new color: i; turn: 90*i; dragon: 10]]"
- 	"Draw a dragon curve of order n in the center of the screen."
- 	n = 0
- 		ifTrue: [self go: 5]
- 		ifFalse: [n > 0
- 				ifTrue: [self dragon: n - 1; turn: 90; dragon: 1 - n]
- 				ifFalse: [self dragon: -1 - n; turn: -90; dragon: 1 + n]]
- !

Item was removed:
- ----- Method: Pen>>filberts:side: (in category 'geometric designs') -----
- filberts: n side: s   "Display restoreAfter: [Pen new filberts: 4 side: 5]"
- 	"Two Hilbert curve fragments form a Hilbert tile. Draw four interlocking 
- 	tiles of order n and sides length s."
- 	| n2 |
- 	Display fillWhite.
- 	n2 := 1 bitShift: n - 1.
- 	self up; go: 0 - n2 * s; down.
- 	1 to: 4 do: 
- 		[:i | 
- 		self fill: [:p |
- 				p hilbert: n side: s.
- 				p go: s.
- 				p hilbert: n side: s.
- 				p go: s.
- 				p up.
- 				p go: n2 - 1 * s.
- 				p turn: -90.
- 				p go: n2 * s.
- 				p turn: 180.
- 				p down]
- 			color: (Color perform: (#(yellow red green blue) at: i))]!

Item was removed:
- ----- Method: Pen>>fill:color: (in category 'operations') -----
- fill: drawBlock color: color
- 	| region tileForm tilePen shape saveColor recorder |
- 	drawBlock value: (recorder := self as: PenPointRecorder).
- 	region := Rectangle encompassing: recorder points.
- 	tileForm := Form extent: region extent+6.
- 	tilePen := Pen newOnForm: tileForm.
- 	tilePen location: location-(region origin-3)
- 		direction: direction
- 		penDown: penDown.
- 	drawBlock value: tilePen.  "Draw the shape in B/W"
- 	saveColor := halftoneForm.
- 	drawBlock value: self.
- 	halftoneForm := saveColor.
- 	shape := (tileForm findShapeAroundSeedBlock: [:f | f borderWidth: 1]) reverse.
- 	shape copy: shape boundingBox from: tileForm to: 0 at 0 rule: Form erase.
- 	destForm fillShape: shape fillColor: color at: region origin-3!

Item was removed:
- ----- Method: Pen>>go: (in category 'operations') -----
- go: distance 
- 	"Move the pen in its current direction a number of bits equal to the 
- 	argument, distance. If the pen is down, a line will be drawn using the 
- 	receiver's form source as the shape of the drawing brush."
- 
- 	self goto: (direction degreeCos @ direction degreeSin) * distance + location!

Item was removed:
- ----- Method: Pen>>goto: (in category 'operations') -----
- goto: aPoint 
- 	"Move the receiver to position aPoint. If the pen is down, a line will be 
- 	drawn from the current position to the new one using the receiver's 
- 	form source as the shape of the drawing brush. The receiver's set 
- 	direction does not change."
- 	| old |
- 	old := location.
- 	location := aPoint.
- 	penDown ifTrue: [self drawFrom: old rounded
- 								to: location rounded]
- 
- 	"NOTE:  This should be changed so it does NOT draw the first point, so as
- 	not to overstrike at line junctions.  At the same time, place should draw
- 	a single dot if the pen is down, as should down (put-pen-down) if it
- 	was not down before."!

Item was removed:
- ----- Method: Pen>>hilbert:side: (in category 'geometric designs') -----
- hilbert: n side: s 
- 	"Draw an nth level Hilbert curve with side length s in the center of the 
- 	screen. Write directly into the display's bitmap only. A Hilbert curve is 
- 	a space-filling curve."
- 
- 	| a m |
- 	n = 0 ifTrue: [^self turn: 180].
- 	n > 0
- 		ifTrue: 
- 			[a := 90.
- 			m := n - 1]
- 		ifFalse: 
- 			[a := -90.
- 			m := n + 1].
- 	self turn: a.
- 	self hilbert: 0 - m side: s.
- 	self turn: a; go: s.
- 	self hilbert: m side: s.
- 	self turn: 0 - a; go: s; turn: 0 - a.
- 	self hilbert: m side: s.
- 	self go: s; turn: a.
- 	self hilbert: 0 - m side: s.
- 	self turn: a
- 	" 
- 	(Pen new) hilbert: 3 side: 8. 
- 	(Pen new sourceForm: Cursor wait) combinationRule: Form under; 
- 	hilbert: 3 side: 25.
- 	"!

Item was removed:
- ----- Method: Pen>>hilberts: (in category 'geometric designs') -----
- hilberts: n   "Display restoreAfter: [Display fillWhite.  Pen new hilberts: 5]"
- 	"Draws n levels of nested Hilbert curves"
- 	| s |
- 	self up; turn: 90; go: 128; down.
- 	1 to: n do: 
- 		[:i | 
- 		s := 256 bitShift: 0 - i.
- 		self defaultNib: n - i * 2 + 1.
- 		self color: i+1.
- 		self up; go: 0 - s / 2; turn: -90; go: s / 2; turn: 90; down.
- 		self hilbert: i side: s.
- 		self go: s.
- 		self hilbert: i side: s.
- 		self go: s]!

Item was removed:
- ----- Method: Pen>>home (in category 'operations') -----
- home
- 	"Place the receiver at the center of its frame."
- 	location := destForm boundingBox center!

Item was removed:
- ----- Method: Pen>>location (in category 'accessing') -----
- location
- 	"Answer where the receiver is currently located."
- 
- 	^location!

Item was removed:
- ----- Method: Pen>>location:direction:penDown: (in category 'private') -----
- location: aPoint direction: aFloat penDown: aBoolean
- 	location := aPoint.
- 	direction := aFloat.
- 	penDown := aBoolean!

Item was removed:
- ----- Method: Pen>>mandala: (in category 'geometric designs') -----
- mandala: npoints
- 	"Display restoreAfter: [Pen new mandala: 30]"
- 	"On a circle of diameter d, place npoints number of points. Draw all 	possible connecting lines between the circumferential points."
- 	| l points d |
- 	Display fillWhite.
- 	d := Display height-50.
- 	l := 3.14 * d / npoints.
- 	self home; up; turn: -90; go: d // 2; turn: 90; go: 0 - l / 2; down.
- 	points := Array new: npoints.
- 	1 to: npoints do: 
- 		[:i | 
- 		points at: i put: location rounded.
- 		self go: l; turn: 360.0 / npoints].
- 	npoints // 2
- 		to: 1
- 		by: -1
- 		do: 
- 			[:i | 
- 			self color: i.
- 			1 to: npoints do: 
- 				[:j | 
- 				self place: (points at: j).
- 				self goto: (points at: j + i - 1 \\ npoints + 1)]]
- !

Item was removed:
- ----- Method: Pen>>north (in category 'operations') -----
- north
- 	"Set the receiver's direction to facing toward the top of the display screen."
- 
- 	direction := 270!

Item was removed:
- ----- Method: Pen>>place: (in category 'operations') -----
- place: aPoint 
- 	"Set the receiver at position aPoint. No lines are drawn."
- 
- 	location := aPoint!

Item was removed:
- ----- Method: Pen>>print:withFont: (in category 'operations') -----
- print: str withFont: font
- 	"Print the given string in the given font at the current heading"
- 	| lineStart scale wasDown |
- 	scale := sourceForm width.
- 	wasDown := penDown.
- 	lineStart := location.
- 	str do:
- 		[:char |
- 		char = Character cr ifTrue:
- 			[self place: lineStart; up; turn: 90; go: font height*scale; turn: -90; down]
- 		ifFalse:
- 			[ | charStart pix rowStart form backgroundCode |
- 			form := font characterFormAt: char.
- 			backgroundCode := 1<< (form depth // 3 * 3) - 1.
- 			charStart := location.
- wasDown ifTrue: [
- 			self up; turn: -90; go: font descent*scale; turn: 90; down.
- 			0 to: form height-1 do:
- 				[:y |
- 				rowStart := location.
- 				pix := RunArray newFrom:
- 					((0 to: form width-1) collect: [:x | form pixelValueAt: x at y]).
- 				pix runs with: pix values do:
- 					[:run :value |
- 					value = backgroundCode
- 						ifTrue: [self up; go: run*scale; down]
- 						ifFalse: [self go: run*scale]].
- 				self place: rowStart; up; turn: 90; go: scale; turn: -90; down].
- ].
- 			self place: charStart; up; go: form width*scale; down].
- 			].
- 	wasDown ifFalse: [self up]
- "
- Display restoreAfter:
- [Pen new squareNib: 2; color: Color red; turn: 45;
- 	print: 'The owl and the pussycat went to sea
- in a beautiful pea green boat.' withFont: TextStyle defaultFont]
- "!

Item was removed:
- ----- Method: Pen>>roundNib: (in category 'initialize-release') -----
- roundNib: diameter
- 	"Makes this pen draw with a round dot of the given diameter."
- 
- 	self sourceForm: (Form dotOfSize: diameter).
- 	combinationRule := Form paint.
- !

Item was removed:
- ----- Method: Pen>>sourceForm: (in category 'private') -----
- sourceForm: aForm
- 	(aForm depth = 1 and: [destForm depth > 1])
- 		ifTrue: ["Map 1-bit source to all ones for color mask"
- 				colorMap := Bitmap with: 0 with: 16rFFFFFFFF]
- 		ifFalse: [colorMap := nil].
- 	^ super sourceForm: aForm!

Item was removed:
- ----- Method: Pen>>spiral:angle: (in category 'geometric designs') -----
- spiral: n angle: a 
- 	"Draw a double squiral (see Papert, MindStorms), where each design is made
- 	by moving the receiver a distance of n after turning the amount + or -a."
- 
- 	1 to: n do: 
- 		[:i | 
- 		self color: i * 2.
- 		self go: i; turn: a]
- "
- 	Display restoreAfter: [
- 		Display fillWhite. Pen new spiral: 200 angle: 89; home; spiral: 200 angle: -89].
- "!

Item was removed:
- ----- Method: Pen>>squareNib: (in category 'initialize-release') -----
- squareNib: widthInteger 
- 	"Makes this pen draw with a square nib of the given width."
- 
- 	self sourceForm: (Form extent: widthInteger @widthInteger) fillBlack.
- 	self combinationRule: Form over.  "a bit faster than paint mode"
- !

Item was removed:
- ----- Method: Pen>>turn: (in category 'operations') -----
- turn: degrees 
- 	"Change the direction that the receiver faces by an amount equal to the 
- 	argument, degrees."
- 
- 	direction := direction + degrees!

Item was removed:
- ----- Method: Pen>>up (in category 'operations') -----
- up
- 	"Set the state of the receiver's pen to up (no drawing)."
- 
- 	penDown := false!

Item was removed:
- ----- Method: Pen>>web (in category 'geometric designs') -----
- web   "Display restoreAfter: [Pen new web]"
- 	"Draw pretty web-like patterns from the mouse movement on the screen.
- 	Press the mouse button to draw, option-click to exit.
- 	By Dan Ingalls and Mark Lentczner. "
- 	| history newPoint ancientPoint lastPoint filter color |
- 	"self erase."
- 	color := 1.
- 	[ history := OrderedCollection new.
- 	Sensor waitButton.
- 	Sensor yellowButtonPressed ifTrue: [^ self].
- 	filter := lastPoint := Sensor cursorPoint.
- 	20 timesRepeat: [ history addLast: lastPoint ].
- 	self color: (color := color + 1).
- 	[ Sensor redButtonPressed ] whileTrue: 
- 		[ newPoint := Sensor cursorPoint.
- 		(newPoint = lastPoint) ifFalse:
- 			[ ancientPoint := history removeFirst.
- 			filter := filter * 4 + newPoint // 5.
- 			self place: filter.
- 			self goto: ancientPoint.
- 			lastPoint := newPoint.
- 			history addLast: filter ] ] ] repeat!

Item was removed:
- Pen subclass: #PenPointRecorder
- 	instanceVariableNames: 'points'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Primitives'!
- 
- !PenPointRecorder commentStamp: 'nice 3/24/2010 07:38' prior: 0!
- This class is a special kind of Pen that instead of actually drawing lines records the destination points for those lines. These points can later be accessed through my accessing method #points.
- 
- This can be useful when determining the boundaries of a drawing session.
- 
- Example:
- 
- | pen |
- pen := PenPointRecorder new.
- pen up; goto: 100 at 100; down; goto: 120 at 120.
- Transcript cr;
- 	show: 'Bounding box for drawing: ';
- 	show: (Rectangle encompassing: pen points)
- 
- Implementation note: Shouldn't we override #drawFrom:to:withFirstPoint: instead, and what about #drawLoopX:Y:? Aren't we missing those calls?!

Item was removed:
- ----- Method: PenPointRecorder>>drawFrom:to: (in category 'line drawing') -----
- drawFrom: p1 to: p2
- 	"Overridden to skip drawing but track bounds of the region traversed."
- 
- 	points ifNil: [points := OrderedCollection with: p1].
- 	points addLast: p2!

Item was removed:
- ----- Method: PenPointRecorder>>points (in category 'accessing') -----
- points
- 	^ points!

Item was removed:
- Object subclass: #Point
- 	instanceVariableNames: 'x y'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'Graphics-Primitives'!
- 
- !Point commentStamp: '<historical>' prior: 0!
- I represent an x-y pair of numbers usually designating a location on the screen.!

Item was removed:
- ----- Method: Point class>>fromUser (in category 'instance creation') -----
- fromUser
- 	Sensor waitNoButton.
- 	Cursor crossHair show.
- 	Sensor waitButton.
- 	Cursor normal show.
- 	^ Sensor cursorPoint
- 
- "Point fromUser"!

Item was removed:
- ----- Method: Point class>>fromUserWithCursor: (in category 'instance creation') -----
- fromUserWithCursor: aCursor
- 	Sensor waitNoButton.
- 	aCursor showWhile:[Sensor waitButton].
- 	^ Sensor cursorPoint
- 
- "Point fromUserWithCursor: Cursor target"!

Item was removed:
- ----- Method: Point class>>r:degrees: (in category 'instance creation') -----
- r: rho degrees: degrees
- 	"Answer an instance of me with polar coordinates rho and theta."
- 
- 	^self basicNew setR: rho degrees: degrees!

Item was removed:
- ----- Method: Point class>>u:v: (in category 'instance creation') -----
- u: xInteger v: yInteger 
- 	"Answer an instance of me with coordinates xInteger and yInteger."
- 
- 	^self new setX: xInteger setY: yInteger!

Item was removed:
- ----- Method: Point class>>x:y: (in category 'instance creation') -----
- x: xInteger y: yInteger 
- 	"Answer an instance of me with coordinates xInteger and yInteger."
- 
- 	^self basicNew setX: xInteger setY: yInteger!

Item was removed:
- ----- Method: Point>>* (in category 'arithmetic') -----
- * arg 
- 	"Answer a Point that is the product of the receiver and arg."
- 
- 	arg isPoint ifTrue: [^ (x * arg x) @ (y * arg y)].
- 	^ arg adaptToPoint: self andSend: #*!

Item was removed:
- ----- Method: Point>>+ (in category 'arithmetic') -----
- + arg 
- 	"Answer a Point that is the sum of the receiver and arg."
- 
- 	arg isPoint ifTrue: [^ (x + arg x) @ (y + arg y)].
- 	^ arg adaptToPoint: self andSend: #+!

Item was removed:
- ----- Method: Point>>- (in category 'arithmetic') -----
- - arg 
- 	"Answer a Point that is the difference of the receiver and arg."
- 
- 	arg isPoint ifTrue: [^ (x - arg x) @ (y - arg y)].
- 	^ arg adaptToPoint: self andSend: #-!

Item was removed:
- ----- Method: Point>>/ (in category 'arithmetic') -----
- / arg 
- 	"Answer a Point that is the quotient of the receiver and arg."
- 
- 	arg isPoint ifTrue: [^ (x / arg x) @ (y / arg y)].
- 	^ arg adaptToPoint: self andSend: #/!

Item was removed:
- ----- Method: Point>>// (in category 'arithmetic') -----
- // arg 
- 	"Answer a Point that is the quotient of the receiver and arg."
- 
- 	arg isPoint ifTrue: [^ (x // arg x) @ (y // arg y)].
- 	^ arg adaptToPoint: self andSend: #//!

Item was removed:
- ----- Method: Point>>< (in category 'comparing') -----
- < aPoint 
- 	"Answer whether the receiver is above and to the left of aPoint."
- 
- 	^x < aPoint x and: [y < aPoint y]!

Item was removed:
- ----- Method: Point>><= (in category 'comparing') -----
- <= aPoint 
- 	"Answer whether the receiver is neither below nor to the right of aPoint."
- 
- 	^x <= aPoint x and: [y <= aPoint y]!

Item was removed:
- ----- Method