'From Cuis 5.0 [latest update: #4171] on 24 May 2020 at 5:37:01 pm'!

!VectorEngineSmalltalk methodsFor: 'private - blend with mask' stamp: 'jmv 5/24/2020 17:10:32'!
blendFillOnlyAtX: x y: y pixelIndex: pixelIndex redIsInside: isRedInside greenIsInside: isGreenInside blueIsInside: isBlueInside

	"targetForm only contains opaque colors. Assume its alpha is always one. Don't ask for it. Set it to one when writing.
	Blends fill over background. Despite method selector, there might be a very thin stroke of the same color as the fill. Handle this by adjusting antiAliasAlphas.
	For blending, alphas are in [0 .. 1.0] and R, G, B color components are in [0 .. 255]"

	| targetWord resultR resultG resultB antiAliasAlphasWord antiAliasRedAlpha antiAliasGreenAlpha antiAliasBlueAlpha alpha resultAlpha targetAlpha |

	antiAliasAlphasWord _ alphaMask bytesAt: pixelIndex.

	antiAliasAlphasWord = "16r00000000" #[16r00 16r00 16r00 16r00] ifTrue: [	"Not in the stroke"
		(isRedInside or: [  isGreenInside or: [ isBlueInside ]]) ifFalse: [ 		"Not inside"
			^self]].	"Optimization: We are completely transparent at this point. Do nothing."

	"In this method, antiAliasAlphas are not used to blend stroke, but fill. This means that in the inside of the shape, and away from the stroke, they must be 1.0 (not 0.0)."
	antiAliasRedAlpha _ (antiAliasAlphasWord at: 3) / 127.0.
	isRedInside ifTrue: [ antiAliasRedAlpha _ 1.0 - antiAliasRedAlpha ].
	antiAliasGreenAlpha _ (antiAliasAlphasWord at: 2) / 127.0.
	isGreenInside ifTrue: [ antiAliasGreenAlpha _ 1.0 - antiAliasGreenAlpha ].
	antiAliasBlueAlpha _ (antiAliasAlphasWord at: 1) / 127.0.
	isBlueInside ifTrue: [ antiAliasBlueAlpha _ 1.0 - antiAliasBlueAlpha ].

	targetWord _ targetForm bits bytesAt: pixelIndex.
	targetAlpha _ (targetWord at: 4) / 255.0.

	antiAliasRedAlpha = 0.0 ifFalse: [
		alpha _ antiAliasRedAlpha * fillColor alpha.
		resultR _ alpha * fillColor red * 255 + ((1.0 - alpha) * (targetWord at: 3) * targetAlpha).
		resultAlpha _ targetAlpha + alpha - (targetAlpha*alpha).
		resultR _ resultR/resultAlpha.
		targetWord at: 3 put: resultR rounded ].

	antiAliasGreenAlpha = 0.0 ifFalse: [
		alpha _ antiAliasGreenAlpha * fillColor alpha.
		resultG _ alpha * fillColor green * 255 + ((1.0 - alpha) * (targetWord at: 2) * targetAlpha).
		resultAlpha _ targetAlpha + alpha - (targetAlpha*alpha).
		resultG _ resultG/resultAlpha.
		targetWord at: 2 put: resultG rounded.
		targetWord at: 4 put: (resultAlpha*255) rounded ].

	antiAliasBlueAlpha = 0.0 ifFalse: [
		alpha _ antiAliasBlueAlpha * fillColor alpha.
		resultB _ alpha * fillColor blue * 255 + ((1.0 - alpha) * (targetWord at: 1) * targetAlpha).
		resultAlpha _ targetAlpha + alpha - (targetAlpha*alpha).
		resultB _ resultB/resultAlpha.
		targetWord at: 1 put: resultB rounded ].

	targetForm bits bytesAt: pixelIndex put: targetWord.

	isGreenInside ifTrue: [
		morphIds at: pixelIndex put: currentMorphId ].! !

!VectorEngineSmalltalk methodsFor: 'private - blend with mask' stamp: 'jmv 5/24/2020 17:22:58'!
blendStrokeAndFillAtX: x y: y pixelIndex: pixelIndex redIsInside: isRedInside greenIsInside: isGreenInside blueIsInside: isBlueInside

	"targetForm only contains opaque colors. Assume its alpha is always one. Don't ask for it. Set it to one when writing.
	Do an appropriate (anti aliased) mix between stoke and fill (or pick just stroke or just fill). Blend this over background.
	For blending, alphas are in [0 .. 1.0] and R, G, B color components are in [0 .. 255]"

	| targetWord resultR resultG resultB antiAliasAlphasWord antiAliasRedAlpha antiAliasGreenAlpha antiAliasBlueAlpha alpha foreComponent targetAlpha resultAlpha |

	antiAliasAlphasWord _ alphaMask bytesAt: pixelIndex.
	antiAliasAlphasWord = "16r00000000" #[16r00 16r00 16r00 16r00] ifTrue: [
		(isRedInside or: [  isGreenInside or: [ isBlueInside ]]) ifFalse: [
			^self]].	"Optimization: We are completely transparent at this point. Do nothing."

	antiAliasRedAlpha _ (antiAliasAlphasWord at: 3) / 127.0.
	antiAliasGreenAlpha _ (antiAliasAlphasWord at: 2) / 127.0.
	antiAliasBlueAlpha _ (antiAliasAlphasWord at: 1) / 127.0.

	targetWord _ targetForm bits bytesAt: pixelIndex.
	targetAlpha _ (targetWord at: 4) / 255.0.

	isRedInside
		ifTrue: [ 							"Do gradient between stroke and fill. Blend the result over background"
			alpha _ antiAliasRedAlpha * strokeColor alpha + ((1-antiAliasRedAlpha) * fillColor alpha).
			foreComponent _ antiAliasRedAlpha * strokeColor red * 255 + ((1-antiAliasRedAlpha) * fillColor red * 255) ]
		ifFalse: [							"Blend stroke over background"
			alpha _ antiAliasRedAlpha * strokeColor alpha.
			foreComponent _ strokeColor red * 255 ].
	alpha = 0.0 ifFalse: [
		resultR _ alpha * foreComponent + ((1.0 - alpha) * (targetWord at: 3) * targetAlpha).
		resultAlpha _ targetAlpha + alpha - (targetAlpha*alpha).
		resultR _ resultR/resultAlpha.
		targetWord at: 3 put: resultR rounded ].

	isGreenInside
		ifTrue: [ 							"Do gradient between stroke and fill. Blend the result over background"
			alpha _ antiAliasGreenAlpha * strokeColor alpha + ((1-antiAliasGreenAlpha) * fillColor alpha).
			foreComponent _ antiAliasGreenAlpha * strokeColor green * 255 + ((1-antiAliasGreenAlpha) * fillColor green * 255).
			morphIds at: pixelIndex put: currentMorphId ]
		ifFalse: [							"Blend stroke over background"
			alpha _ antiAliasGreenAlpha * strokeColor alpha.
			foreComponent _ strokeColor green * 255.
			antiAliasGreenAlpha > 0.5 ifTrue: [
				morphIds at: pixelIndex put: currentMorphId ]. ].
	alpha = 0.0 ifFalse: [
		resultG _ alpha * foreComponent + ((1.0 - alpha) * (targetWord at: 2) * targetAlpha).
		resultAlpha _ targetAlpha + alpha - (targetAlpha*alpha).
		resultG _ resultG/resultAlpha.
		targetWord at: 2 put: resultG rounded.
		targetWord at: 4 put: (resultAlpha*255) rounded ].

	isBlueInside
		ifTrue: [ 							"Do gradient between stroke and fill. Blend the result over background"
			alpha _ antiAliasBlueAlpha * strokeColor alpha + ((1-antiAliasBlueAlpha) * fillColor alpha).
			foreComponent _ antiAliasBlueAlpha * strokeColor blue * 255 + ((1-antiAliasBlueAlpha) * fillColor blue * 255) ]
		ifFalse: [							"Blend stroke over background"
			alpha _ antiAliasBlueAlpha * strokeColor alpha.
			foreComponent _ strokeColor blue * 255 ].
	alpha = 0.0 ifFalse: [
		resultB _ alpha * foreComponent + ((1.0 - alpha) * (targetWord at: 1) * targetAlpha).
		resultAlpha _ targetAlpha + alpha - (targetAlpha*alpha).
		resultB _ resultB/resultAlpha.
		targetWord at: 1 put: resultB rounded ].

	targetForm bits bytesAt: pixelIndex put: targetWord.! !

!VectorEngineSmalltalk methodsFor: 'private - blend with mask' stamp: 'jmv 5/24/2020 17:18:46'!
blendStrokeOnlyAtX: x y: y pixelIndex: pixelIndex

	"targetForm only contains opaque colors. Assume its alpha is always one. Don't ask for it. Set it to one when writing.
	Blends stroke over background.
	For blending, alphas are in [0 .. 1.0] and R, G, B color components are in [0 .. 255]"

	| targetWord resultR resultG resultB antiAliasAlphasWord antiAliasRedAlpha antiAliasGreenAlpha antiAliasBlueAlpha alpha resultAlpha targetAlpha |

	antiAliasAlphasWord _ alphaMask bytesAt: pixelIndex.
	antiAliasAlphasWord = "16r00000000" #[16r00 16r00 16r00 16r00] ifTrue: [
		^self].	"Optimization: We are completely transparent at this point. Do nothing."

	antiAliasRedAlpha _ (antiAliasAlphasWord at: 3) / 127.0.
	antiAliasGreenAlpha _ (antiAliasAlphasWord at: 2) / 127.0.
	antiAliasBlueAlpha _ (antiAliasAlphasWord at: 1) / 127.0.

	targetWord _ targetForm bits bytesAt: pixelIndex.
	targetAlpha _ (targetWord at: 4) / 255.0.

	antiAliasRedAlpha = 0.0 ifFalse: [
		alpha _ antiAliasRedAlpha * strokeColor alpha.
		resultR _ alpha * strokeColor red * 255 + ((1.0 - alpha) * (targetWord at: 3) * targetAlpha).
		resultAlpha _ targetAlpha + alpha - (targetAlpha*alpha).
		resultR _ resultR/resultAlpha.
		targetWord at: 3 put: resultR rounded ].

	antiAliasGreenAlpha = 0.0 ifFalse: [
		alpha _ antiAliasGreenAlpha * strokeColor alpha.
		resultG _ alpha * strokeColor green * 255 + ((1.0 - alpha) * (targetWord at: 2) * targetAlpha).
		resultAlpha _ targetAlpha + alpha - (targetAlpha*alpha).
		resultG _ resultG/resultAlpha.
		targetWord at: 2 put: resultG rounded.
		targetWord at: 4 put: (resultAlpha*255) rounded ].

	antiAliasBlueAlpha = 0.0 ifFalse: [
		alpha _ antiAliasBlueAlpha * strokeColor alpha.
		resultB _ alpha * strokeColor blue * 255 + ((1.0 - alpha) * (targetWord at: 1) * targetAlpha).
		resultAlpha _ targetAlpha + alpha - (targetAlpha*alpha).
		resultB _ resultB/resultAlpha.
		targetWord at: 1 put: resultB rounded ].

	targetForm bits bytesAt: pixelIndex put: targetWord.

	antiAliasGreenAlpha > 0.5 ifTrue: [
		morphIds at: pixelIndex put: currentMorphId ].! !

