<commit_before>'From Squeak4.4 of 15 December 2012 [latest update: #12303] on 17 March 2013 at 4:20:53 pm'!
Object subclass: #BitBlt
	instanceVariableNames: 'destForm sourceForm halftoneForm combinationRule destX destY width height sourceX sourceY clipX clipY clipWidth clipHeight colorMap simW simH simSx simSy simDx simDy simDestBits simDestRaster simSourceBits simSourceRaster simHalftoneBits simSkew simMask1 simMask2 simSkewMask simNWords simHDir simVDir simPreload simSourceIndex simDestIndex simSourceDelta simDestDelta simInDebug '
	classVariableNames: 'AllOnes RightMasks WordSize0 WordSize '
	poolDictionaries: ''
	category: 'Graphics-Support'!
TestCase subclass: #BitBltSimTest
	instanceVariableNames: 'path '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'GraphicsTests-Primitives'!

!BitBlt methodsFor: 'private'!
clipRange
	destX >= clipX
		ifTrue:
			[simSx _ sourceX.
			simDx _ destX.
			simW _ width]
		ifFalse:
			[simSx _ sourceX + (clipX - destX).
			simW _ width - (clipX - destX).
			simDx _ clipX].
	simDx + simW > (clipX + clipWidth) ifTrue: [simW _ simW - (simDx + simW - (clipX + clipWidth))].
	destY >= clipY
		ifTrue:
			[simSy _ sourceY.
			simDy _ destY.
			simH _ height]
		ifFalse:
			[simSy _ sourceY + clipY - destY.
			simH _ height - (clipY - destY).
			simDy _ clipY].
	simDy + simH > (clipY + clipHeight) ifTrue: [simH _ simH - (simDy + simH - (clipY + clipHeight))].
	simSx < 0
		ifTrue:
			[simDx _ simDx - simSx.
			simW _ simW + simSx.
			simSx _ 0].
	simSx + simW > sourceForm width ifTrue: [simW _ simW - (simSx + simW - sourceForm width)].
	simSy < 0
		ifTrue:
			[simDy _ simDy - simSy.
			simH _ simH + simSy.
			simSy _ 0].
	simSy + simH > sourceForm height ifTrue: [simH _ simH - (simSy + simH - sourceForm height)]! !

!BitBlt methodsFor: 'private' stamp: 'tfel 3/13/2013 12:02'!
copyBitsAgain
	<primitive: 96>
	self simulateCopyBits.! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 3/15/2013 10:31'!
calculateOffsets
	"check if we need to preload buffer
	(i.e., two words of source needed for first word of destination)"
	simPreload _ (sourceForm notNil) and:
						[simSkew ~= 0 and: [simSkew <= (simSx bitAnd: WordSize0)]].
	simHDir < 0 ifTrue: [simPreload _ simPreload == false].
	"calculate starting offsets"
	simSourceIndex _ simSy * simSourceRaster + (simSx // WordSize).
	simDestIndex _ simDy * simDestRaster + (simDx // WordSize).
	"calculate increments from end of 1 line to start of next"
	simSourceDelta _
		(simSourceRaster * simVDir) -
			(simNWords + (simPreload ifTrue: [1] ifFalse: [0]) * simHDir).
	simDestDelta _ (simDestRaster * simVDir) - (simNWords * simHDir)! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 3/17/2013 16:16'!
checkOverlap
	| t |
	"check for possible overlap of source and destination"
	simHDir _ simVDir _ 1. "defaults for no overlap"
	(sourceForm == destForm and: [simDy >= simSy])
		ifTrue:
			[simDy > simSy "have to start at bottom"
				ifTrue: [simVDir _ -1. simSy _ simSy + simH - 1. simDy _ simDy + simH - 1]
				ifFalse: [simDx > simSx "y's are equal, but x's are backward"
							ifTrue: [simHDir _ -1.
									simSx _ simSx + simW - 1.
									"start at right"
									simDx _ simDx + simW - 1.
									"and fix up masks"
									simSkewMask _ simSkewMask bitInvert32.
									t _ simMask1.
									simMask1 _ simMask2.
									simMask2 _ t]]]! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 3/17/2013 16:16'!
computeMasks
	| startBits endBits |
	"calculate skeq and edge masks"
	simDestBits _ destForm bits.
	simDestRaster _ destForm width - 1 // WordSize + 1.
	sourceForm notNil
		ifTrue: [simSourceBits _ sourceForm bits.
				simSourceRaster _ sourceForm width - 1 // WordSize + 1]
		ifFalse: [simSourceRaster _ 0].
	halftoneForm notNil
		ifTrue: [simHalftoneBits _ halftoneForm bits].
	simSkew _ (simSx - simDx) bitAnd: WordSize0.
	"how many bits source gets skewed to right"
	startBits _ WordSize - (simDx bitAnd: WordSize0).
	"how many bits in first word"
	simMask1 _ RightMasks at: startBits + 1.
	endBits _ WordSize0 - ((simDx + simW - 1) bitAnd: WordSize0).
	"how many bits in last word"
	simMask2 _ (RightMasks at: endBits + 1) bitInvert32.
	simSkewMask _
		(simSkew = 0
			ifTrue: [0]
			ifFalse: [RightMasks at: WordSize - simSkew + 1]).
	"determine number of words stored per line; merge masks if necessary"
	simW < startBits
		ifTrue: [simMask1 _ simMask1 bitAnd: simMask2.
				simMask2 _ 0.
				simNWords _ 1]
		ifFalse: [simNWords _ (simW - startBits - 1) // WordSize + 2].! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 3/17/2013 16:17'!
copyLoop
	| prevWord thisWord skewWord mergeMask halftoneWord mergeWord noSimSkewMask |
	noSimSkewMask _ simSkewMask bitInvert32.
	1 to: simH do:
		[:i |
		halftoneForm notNil
			ifTrue:
				[halftoneWord _ simHalftoneBits at: 1 + (simDy \\ simHalftoneBits size).
				simDy _ simDy + simVDir]
			ifFalse: [halftoneWord _ AllOnes].
		skewWord _ halftoneWord.
		simPreload
			ifTrue:
				[prevWord _ simSourceBits at: simSourceIndex + 1.
				simSourceIndex _ simSourceIndex + simHDir]
			ifFalse: [prevWord _ 0].
		mergeMask _ simMask1.
		1 to: simNWords do:
			[:word |
			sourceForm notNil
				ifTrue:
					[prevWord _ prevWord bitAnd: simSkewMask.
						"XXX: Hack to work around out-of-bounds access"
					thisWord := (simSourceIndex < 0 or: [simSourceIndex >= simSourceBits size])
								ifTrue: [simSourceBits at: 1]
								ifFalse: [simSourceBits at: simSourceIndex + 1].
															"pick up next word"
					skewWord _
							prevWord bitOr: (thisWord bitAnd: simSkewMask bitInvert32).
					prevWord _ thisWord.
					"Change from BB: bitAnd: AllOnes to stay in word bounds"
					skewWord _ ((skewWord bitShift: simSkew) bitAnd: AllOnes) bitOr:
													(skewWord bitShift: simSkew - WordSize)].
			mergeWord _ self merge: (skewWord bitAnd: halftoneWord)
					with: (simDestBits at: simDestIndex + 1).
			simDestBits at: simDestIndex + 1 put: ((mergeMask bitAnd: mergeWord)
					bitOr: (mergeMask bitInvert32 bitAnd: (simDestBits at: simDestIndex + 1))).
			simSourceIndex _ simSourceIndex + simHDir.
			simDestIndex _ simDestIndex + simHDir.
			word = (simNWords - 1)
				ifTrue: [mergeMask _ simMask2]
				ifFalse: [mergeMask _ AllOnes]].
		simSourceIndex _ simSourceIndex + simSourceDelta.
		simDestIndex _ simDestIndex + simDestDelta]! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 3/17/2013 16:17'!
merge: srcWord with: dstWord

	combinationRule < 16
		ifTrue: [ "These are the 16 basic combination rules."
			combinationRule = 0 ifTrue: [^ 0].
			combinationRule = 1 ifTrue: [^ srcWord bitAnd: dstWord].
			combinationRule = 2 ifTrue: [^ srcWord bitAnd: dstWord bitInvert32].
			combinationRule = 3 ifTrue: [^ srcWord].
			combinationRule = 4 ifTrue: [^ srcWord bitInvert32 bitAnd: dstWord].
			combinationRule = 5 ifTrue: [^ dstWord].
			combinationRule = 6 ifTrue: [^ srcWord bitXor: dstWord].
			combinationRule = 7 ifTrue: [^ srcWord bitOr: dstWord].
			combinationRule = 8 ifTrue: [^ srcWord bitInvert32 bitAnd: dstWord bitInvert32].
			combinationRule = 9 ifTrue: [^ srcWord bitInvert32 bitXor: dstWord].
			combinationRule = 10 ifTrue: [^ dstWord bitInvert32].
			combinationRule = 11 ifTrue: [^ srcWord bitOr: dstWord bitInvert32].
			combinationRule = 12 ifTrue: [^ srcWord bitInvert32].
			combinationRule = 13 ifTrue: [^ srcWord bitInvert32 bitOr: dstWord].
			combinationRule = 14 ifTrue: [^ srcWord bitInvert32 bitOr: dstWord bitInvert32].
			combinationRule = 15 ifTrue: [^ dstWord].]
		ifFalse: [ "These are newer combination rules. (BitBltSimulation class>>#initializeRuleTable)"
			combinationRule = 16 ifTrue: [^ dstWord]. "unused - was old paint"
			combinationRule = 17 ifTrue: [^ dstWord]. "unused - was old mask"
			combinationRule = 18 ifTrue: [^ dstWord]. "addWord"
			combinationRule = 19 ifTrue: [^ dstWord]. "subWord"
			combinationRule = 20 ifTrue: [^ dstWord]. "rgbAdd"
			combinationRule = 21 ifTrue: [^ dstWord]. "rgbSub"
			combinationRule = 22 ifTrue: [^ dstWord]. "OLDrgbDiff"
			combinationRule = 23 ifTrue: [^ dstWord]. "OLDtallyIntoMap"
			combinationRule = 24 ifTrue: [^ dstWord]. "alphaBlend"
			combinationRule = 25 ifTrue: [^ dstWord]. "pixPaint"
			combinationRule = 26 ifTrue: [^ dstWord]. "pixMask"
			combinationRule = 27 ifTrue: [^ dstWord]. "rgbMax"
			combinationRule = 28 ifTrue: [^ dstWord]. "rgbMin"
			combinationRule = 29 ifTrue: [^ dstWord]. "rgbMinInvert"
			combinationRule = 30 ifTrue: [^ dstWord]. "alphaBlendConst"
			combinationRule = 31 ifTrue: [^ dstWord]. "alphaPaintConst"
			combinationRule = 32 ifTrue: [^ dstWord]. "rgbDiff"
			combinationRule = 33 ifTrue: [^ dstWord]. "tallyIntoMap"
			combinationRule = 34 ifTrue: [^ dstWord]. "alphaBlendScaled"
			combinationRule = 35 ifTrue: [^ dstWord]. "unused here - only used by FXBlt"
			combinationRule = 36 ifTrue: [^ dstWord]. "unused here - only used by FXBlt"
			combinationRule = 37 ifTrue: [^ dstWord]. "rgbMul"
			combinationRule = 38 ifTrue: [^ dstWord]. "pixSwap"
			combinationRule = 39 ifTrue: [^ dstWord]. "pixClear"
			combinationRule = 40 ifTrue: [^ dstWord]. "fixAlpha"
			combinationRule = 41 ifTrue: [^ dstWord]. "rgbComponentAlpha"].
	self error: 'Combination Rule is not supported.'! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 3/15/2013 14:49'!
sanitizeInput

	destForm unhibernate.
	sourceForm
		ifNotNil: [sourceForm unhibernate].
	halftoneForm ifNotNil: [
		(halftoneForm isKindOf: Form)
			ifFalse: [halftoneForm := Form new
										bits: halftoneForm;
										yourself].
		halftoneForm unhibernate].<commit_msg>added more concrete rule for pixPaint (combinationRule 25) the effect is still of though<commit_after>'From Squeak4.4 of 15 December 2012 [latest update: #12303] on 17 March 2013 at 4:20:53 pm'!
Object subclass: #BitBlt
	instanceVariableNames: 'destForm sourceForm halftoneForm combinationRule destX destY width height sourceX sourceY clipX clipY clipWidth clipHeight colorMap simW simH simSx simSy simDx simDy simDestBits simDestRaster simSourceBits simSourceRaster simHalftoneBits simSkew simMask1 simMask2 simSkewMask simNWords simHDir simVDir simPreload simSourceIndex simDestIndex simSourceDelta simDestDelta simInDebug '
	classVariableNames: 'AllOnes RightMasks WordSize0 WordSize '
	poolDictionaries: ''
	category: 'Graphics-Support'!
TestCase subclass: #BitBltSimTest
	instanceVariableNames: 'path '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'GraphicsTests-Primitives'!

!BitBlt methodsFor: 'private'!
clipRange
	destX >= clipX
		ifTrue:
			[simSx _ sourceX.
			simDx _ destX.
			simW _ width]
		ifFalse:
			[simSx _ sourceX + (clipX - destX).
			simW _ width - (clipX - destX).
			simDx _ clipX].
	simDx + simW > (clipX + clipWidth) ifTrue: [simW _ simW - (simDx + simW - (clipX + clipWidth))].
	destY >= clipY
		ifTrue:
			[simSy _ sourceY.
			simDy _ destY.
			simH _ height]
		ifFalse:
			[simSy _ sourceY + clipY - destY.
			simH _ height - (clipY - destY).
			simDy _ clipY].
	simDy + simH > (clipY + clipHeight) ifTrue: [simH _ simH - (simDy + simH - (clipY + clipHeight))].
	simSx < 0
		ifTrue:
			[simDx _ simDx - simSx.
			simW _ simW + simSx.
			simSx _ 0].
	simSx + simW > sourceForm width ifTrue: [simW _ simW - (simSx + simW - sourceForm width)].
	simSy < 0
		ifTrue:
			[simDy _ simDy - simSy.
			simH _ simH + simSy.
			simSy _ 0].
	simSy + simH > sourceForm height ifTrue: [simH _ simH - (simSy + simH - sourceForm height)]! !

!BitBlt methodsFor: 'private' stamp: 'tfel 3/13/2013 12:02'!
copyBitsAgain
	<primitive: 96>
	self simulateCopyBits.! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 3/15/2013 10:31'!
calculateOffsets
	"check if we need to preload buffer
	(i.e., two words of source needed for first word of destination)"
	simPreload _ (sourceForm notNil) and:
						[simSkew ~= 0 and: [simSkew <= (simSx bitAnd: WordSize0)]].
	simHDir < 0 ifTrue: [simPreload _ simPreload == false].
	"calculate starting offsets"
	simSourceIndex _ simSy * simSourceRaster + (simSx // WordSize).
	simDestIndex _ simDy * simDestRaster + (simDx // WordSize).
	"calculate increments from end of 1 line to start of next"
	simSourceDelta _
		(simSourceRaster * simVDir) -
			(simNWords + (simPreload ifTrue: [1] ifFalse: [0]) * simHDir).
	simDestDelta _ (simDestRaster * simVDir) - (simNWords * simHDir)! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 3/17/2013 16:16'!
checkOverlap
	| t |
	"check for possible overlap of source and destination"
	simHDir _ simVDir _ 1. "defaults for no overlap"
	(sourceForm == destForm and: [simDy >= simSy])
		ifTrue:
			[simDy > simSy "have to start at bottom"
				ifTrue: [simVDir _ -1. simSy _ simSy + simH - 1. simDy _ simDy + simH - 1]
				ifFalse: [simDx > simSx "y's are equal, but x's are backward"
							ifTrue: [simHDir _ -1.
									simSx _ simSx + simW - 1.
									"start at right"
									simDx _ simDx + simW - 1.
									"and fix up masks"
									simSkewMask _ simSkewMask bitInvert32.
									t _ simMask1.
									simMask1 _ simMask2.
									simMask2 _ t]]]! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 3/17/2013 16:16'!
computeMasks
	| startBits endBits |
	"calculate skeq and edge masks"
	simDestBits _ destForm bits.
	simDestRaster _ destForm width - 1 // WordSize + 1.
	sourceForm notNil
		ifTrue: [simSourceBits _ sourceForm bits.
				simSourceRaster _ sourceForm width - 1 // WordSize + 1]
		ifFalse: [simSourceRaster _ 0].
	halftoneForm notNil
		ifTrue: [simHalftoneBits _ halftoneForm bits].
	simSkew _ (simSx - simDx) bitAnd: WordSize0.
	"how many bits source gets skewed to right"
	startBits _ WordSize - (simDx bitAnd: WordSize0).
	"how many bits in first word"
	simMask1 _ RightMasks at: startBits + 1.
	endBits _ WordSize0 - ((simDx + simW - 1) bitAnd: WordSize0).
	"how many bits in last word"
	simMask2 _ (RightMasks at: endBits + 1) bitInvert32.
	simSkewMask _
		(simSkew = 0
			ifTrue: [0]
			ifFalse: [RightMasks at: WordSize - simSkew + 1]).
	"determine number of words stored per line; merge masks if necessary"
	simW < startBits
		ifTrue: [simMask1 _ simMask1 bitAnd: simMask2.
				simMask2 _ 0.
				simNWords _ 1]
		ifFalse: [simNWords _ (simW - startBits - 1) // WordSize + 2].! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 3/17/2013 16:17'!
copyLoop
	| prevWord thisWord skewWord mergeMask halftoneWord mergeWord noSimSkewMask |
	noSimSkewMask _ simSkewMask bitInvert32.
	1 to: simH do:
		[:i |
		halftoneForm notNil
			ifTrue:
				[halftoneWord _ simHalftoneBits at: 1 + (simDy \\ simHalftoneBits size).
				simDy _ simDy + simVDir]
			ifFalse: [halftoneWord _ AllOnes].
		skewWord _ halftoneWord.
		simPreload
			ifTrue:
				[prevWord _ simSourceBits at: simSourceIndex + 1.
				simSourceIndex _ simSourceIndex + simHDir]
			ifFalse: [prevWord _ 0].
		mergeMask _ simMask1.
		1 to: simNWords do:
			[:word |
			sourceForm notNil
				ifTrue:
					[prevWord _ prevWord bitAnd: simSkewMask.
						"XXX: Hack to work around out-of-bounds access"
					thisWord _ (simSourceIndex < 0 or: [simSourceIndex >= simSourceBits size])
								ifTrue: [simSourceBits at: 1]
								ifFalse: [simSourceBits at: simSourceIndex + 1].
															"pick up next word"
					skewWord _
							prevWord bitOr: (thisWord bitAnd: simSkewMask bitInvert32).
					prevWord _ thisWord.
					"Change from BB: bitAnd: AllOnes to stay in word bounds"
					skewWord _ ((skewWord bitShift: simSkew) bitAnd: AllOnes) bitOr:
													(skewWord bitShift: simSkew - WordSize)].
			mergeWord _ self merge: (skewWord bitAnd: halftoneWord)
					with: (simDestBits at: simDestIndex + 1).
			simDestBits at: simDestIndex + 1 put: ((mergeMask bitAnd: mergeWord)
					bitOr: (mergeMask bitInvert32 bitAnd: (simDestBits at: simDestIndex + 1))).
			simSourceIndex _ simSourceIndex + simHDir.
			simDestIndex _ simDestIndex + simHDir.
			word = (simNWords - 1)
				ifTrue: [mergeMask _ simMask2]
				ifFalse: [mergeMask _ AllOnes]].
		simSourceIndex _ simSourceIndex + simSourceDelta.
		simDestIndex _ simDestIndex + simDestDelta]! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 3/17/2013 16:17'!
merge: srcWord with: dstWord

	combinationRule < 16
		ifTrue: [ "These are the 16 basic combination rules."
			combinationRule = 0 ifTrue: [^ 0].
			combinationRule = 1 ifTrue: [^ srcWord bitAnd: dstWord].
			combinationRule = 2 ifTrue: [^ srcWord bitAnd: dstWord bitInvert32].
			combinationRule = 3 ifTrue: [^ srcWord].
			combinationRule = 4 ifTrue: [^ srcWord bitInvert32 bitAnd: dstWord].
			combinationRule = 5 ifTrue: [^ dstWord].
			combinationRule = 6 ifTrue: [^ srcWord bitXor: dstWord].
			combinationRule = 7 ifTrue: [^ srcWord bitOr: dstWord].
			combinationRule = 8 ifTrue: [^ srcWord bitInvert32 bitAnd: dstWord bitInvert32].
			combinationRule = 9 ifTrue: [^ srcWord bitInvert32 bitXor: dstWord].
			combinationRule = 10 ifTrue: [^ dstWord bitInvert32].
			combinationRule = 11 ifTrue: [^ srcWord bitOr: dstWord bitInvert32].
			combinationRule = 12 ifTrue: [^ srcWord bitInvert32].
			combinationRule = 13 ifTrue: [^ srcWord bitInvert32 bitOr: dstWord].
			combinationRule = 14 ifTrue: [^ srcWord bitInvert32 bitOr: dstWord bitInvert32].
			combinationRule = 15 ifTrue: [^ dstWord].]
		ifFalse: [ "These are newer combination rules. (BitBltSimulation class>>#initializeRuleTable)"
			combinationRule = 16 ifTrue: [^ dstWord]. "unused - was old paint"
			combinationRule = 17 ifTrue: [^ dstWord]. "unused - was old mask"
			combinationRule = 18 ifTrue: [^ dstWord]. "addWord"
			combinationRule = 19 ifTrue: [^ dstWord]. "subWord"
			combinationRule = 20 ifTrue: [^ dstWord]. "rgbAdd"
			combinationRule = 21 ifTrue: [^ dstWord]. "rgbSub"
			combinationRule = 22 ifTrue: [^ dstWord]. "OLDrgbDiff"
			combinationRule = 23 ifTrue: [^ dstWord]. "OLDtallyIntoMap"
			combinationRule = 24 ifTrue: [^ dstWord]. "alphaBlend"
			combinationRule = 25 ifTrue: [^ self pixPaint: srcWord with: dstWord].
			combinationRule = 26 ifTrue: [^ dstWord]. "pixMask"
			combinationRule = 27 ifTrue: [^ dstWord]. "rgbMax"
			combinationRule = 28 ifTrue: [^ dstWord]. "rgbMin"
			combinationRule = 29 ifTrue: [^ dstWord]. "rgbMinInvert"
			combinationRule = 30 ifTrue: [^ dstWord]. "alphaBlendConst"
			combinationRule = 31 ifTrue: [^ dstWord]. "alphaPaintConst"
			combinationRule = 32 ifTrue: [^ dstWord]. "rgbDiff"
			combinationRule = 33 ifTrue: [^ dstWord]. "tallyIntoMap"
			combinationRule = 34 ifTrue: [^ dstWord]. "alphaBlendScaled"
			combinationRule = 35 ifTrue: [^ dstWord]. "unused here - only used by FXBlt"
			combinationRule = 36 ifTrue: [^ dstWord]. "unused here - only used by FXBlt"
			combinationRule = 37 ifTrue: [^ dstWord]. "rgbMul"
			combinationRule = 38 ifTrue: [^ dstWord]. "pixSwap"
			combinationRule = 39 ifTrue: [^ dstWord]. "pixClear"
			combinationRule = 40 ifTrue: [^ dstWord]. "fixAlpha"
			combinationRule = 41 ifTrue: [^ dstWord]. "rgbComponentAlpha"].
	self error: 'Combination Rule is not supported.'! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 1/1/1981 00:00'!
pixPaint: srcWord with: dstWord
	srcWord = 0 ifTrue: [^ dstWord].
	^ srcWord bitOr: (dstWord bitAnd: srcWord bitInvert32)! !

!BitBlt methodsFor: 'simulation' stamp: 'tfel 3/15/2013 14:49'!
sanitizeInput

	destForm unhibernate.
	sourceForm
		ifNotNil: [sourceForm unhibernate].
	halftoneForm ifNotNil: [
		(halftoneForm isKindOf: Form)
			ifFalse: [halftoneForm := Form new
										bits: halftoneForm;
										yourself].
		halftoneForm unhibernate].
{'fraction_non_alphanumeric': 0.10305559849538826, 'fraction_numerical': 0.02931931777193796, 'mean_word_length': 3.6541966426858514, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7080099', 'n_tokens_mistral': 8169, 'n_tokens_neox': 6825, 'n_words': 1988}