package d2raster

import (
	
	
	
	
	
	

	
)

type preparedFilterKind uint8

const (
	preparedGaussianBlur preparedFilterKind = iota
	preparedDropShadow
)

type blurAxis uint8

const (
	blurHorizontal blurAxis = iota
	blurVertical
)

type blurPass struct {
	axis   blurAxis
	radius int
	bounds image.Rectangle
}

type preparedFilter struct {
	kind        preparedFilterKind
	passes      []blurPass
	output      image.Rectangle
	offsetX     float64
	offsetY     float64
	shadowColor color.NRGBA
}

type normalizedFilter struct {
	kind        preparedFilterKind
	sigmaX      float64
	sigmaY      float64
	offsetX     float64
	offsetY     float64
	shadowColor color.NRGBA
	sourceIndex int
}

func normalizeNodeFilters( context.Context,  string,  []d2scene.Filter,  map[int]d2scene.DropShadow) ([]normalizedFilter, error) {
	if  == nil {
		 = context.Background()
	}
	if len() != 0 {
		 := make([]int, 0, len())
		for  := range  {
			 = append(, )
		}
		sort.Ints()
		for ,  := range  {
			if  < 0 ||  >= len() {
				return nil, fmt.Errorf("d2raster: node %q drop-shadow animation target index %d is outside %d filters", , , len())
			}
		}
	}

	 := make([]normalizedFilter, 0, len())
	for ,  := range  {
		if &255 == 0 {
			if  := .Err();  != nil {
				return nil, 
			}
		}
		var  normalizedFilter
		.sourceIndex = 
		switch value := .(type) {
		case d2scene.GaussianBlur:
			.kind, .sigmaX, .sigmaY = preparedGaussianBlur, .SigmaX, .SigmaY
		case *d2scene.GaussianBlur:
			if  == nil {
				return nil, fmt.Errorf("d2raster: node %q filter %d is a nil Gaussian blur", , )
			}
			.kind, .sigmaX, .sigmaY = preparedGaussianBlur, .SigmaX, .SigmaY
		case d2scene.DropShadow:
			.kind = preparedDropShadow
			.sigmaX, .sigmaY = .SigmaX, .SigmaY
			.offsetX, .offsetY, .shadowColor = .OffsetX, .OffsetY, .Color
		case *d2scene.DropShadow:
			if  == nil {
				return nil, fmt.Errorf("d2raster: node %q filter %d is a nil drop shadow", , )
			}
			.kind = preparedDropShadow
			.sigmaX, .sigmaY = .SigmaX, .SigmaY
			.offsetX, .offsetY, .shadowColor = .OffsetX, .OffsetY, .Color
		default:
			return nil, fmt.Errorf("d2raster: node %q filter %d has unsupported type %T", , , )
		}
		if  := validateNormalizedFilter(, , );  != nil {
			return nil, 
		}
		if ,  := [];  {
			if .kind != preparedDropShadow {
				return nil, fmt.Errorf("d2raster: node %q drop-shadow animation target index %d does not identify a drop shadow", , )
			}
			.sigmaX, .sigmaY = .SigmaX, .SigmaY
			.offsetX, .offsetY, .shadowColor = .OffsetX, .OffsetY, .Color
			if  := validateNormalizedFilter(, , );  != nil {
				return nil, 
			}
		}
		 = append(, )
	}
	if  := .Err();  != nil {
		return nil, 
	}
	return , nil
}

func validateNormalizedFilter( string,  int,  normalizedFilter) error {
	if .sigmaX < 0 || .sigmaY < 0 || !finite(.sigmaX) || !finite(.sigmaY) {
		return fmt.Errorf("d2raster: node %q filter %d has invalid Gaussian deviation", , )
	}
	if .kind == preparedDropShadow && (!finite(.offsetX) || !finite(.offsetY)) {
		return fmt.Errorf("d2raster: node %q filter %d has an invalid drop-shadow offset", , )
	}
	return nil
}

func ( *preflight) ( string,  []normalizedFilter,  d2scene.Matrix,  image.Rectangle) ([]preparedFilter, image.Rectangle, error) {
	 := 
	// Every supported filter maps transparent black to transparent black. The
	// normalized pass above has already validated all declared values, so an
	// empty subtree needs neither transformed-kernel arithmetic nor scratch.
	if .Empty() {
		return nil, , .ctx.Err()
	}
	 := make([]preparedFilter, 0, len())
	for ,  := range  {
		if  := .ctx.Err();  != nil {
			return nil, image.Rectangle{}, 
		}
		// A fully transparent shadow is an identity operation even when its
		// otherwise valid finite deviation would exceed the raster work domain.
		if .kind == preparedDropShadow && .shadowColor.A == 0 {
			continue
		}
		 := math.Hypot(.A*.sigmaX, .C*.sigmaY)
		 := math.Hypot(.B*.sigmaX, .D*.sigmaY)
		if !finite() || !finite() {
			return nil, image.Rectangle{}, fmt.Errorf("d2raster: node %q filter %d has non-finite transformed deviation", , .sourceIndex)
		}
		,  := blurSupportRadius()
		if  != nil {
			return nil, image.Rectangle{}, fmt.Errorf("d2raster: node %q filter %d horizontal deviation: %w", , .sourceIndex, )
		}
		,  := blurSupportRadius()
		if  != nil {
			return nil, image.Rectangle{}, fmt.Errorf("d2raster: node %q filter %d vertical deviation: %w", , .sourceIndex, )
		}

		 := preparedFilter{kind: .kind, shadowColor: .shadowColor}
		switch .kind {
		case preparedGaussianBlur:
			if .Empty() ||  == 0 &&  == 0 {
				continue
			}
			.passes, .output,  = prepareBlurPasses(, , )
			if  != nil {
				return nil, image.Rectangle{}, fmt.Errorf("d2raster: node %q filter %d: %w", , .sourceIndex, )
			}
			 = .output
		case preparedDropShadow:
			 := .Vector(d2scene.Point{X: .offsetX, Y: .offsetY})
			if !finitePoint() {
				return nil, image.Rectangle{}, fmt.Errorf("d2raster: node %q filter %d has a non-finite transformed shadow offset", , .sourceIndex)
			}
			.offsetX, .offsetY = .X, .Y
			 := 
			.passes, ,  = prepareBlurPasses(, , )
			if  != nil {
				return nil, image.Rectangle{}, fmt.Errorf("d2raster: node %q filter %d: %w", , .sourceIndex, )
			}
			,  := translatedFilterBoundsUnbounded(, .X, .Y)
			if  != nil {
				return nil, image.Rectangle{}, fmt.Errorf("d2raster: node %q filter %d: %w", , .sourceIndex, )
			}
			.output,  = unionFilterBounds(, )
			if  != nil {
				return nil, image.Rectangle{}, fmt.Errorf("d2raster: node %q filter %d: %w", , .sourceIndex, )
			}
			 = .output
		default:
			return nil, image.Rectangle{}, fmt.Errorf("d2raster: node %q filter %d has unknown prepared kind %d", , , .kind)
		}
		 = append(, )
	}
	return , , nil
}

const maxBlurSupportRadius = 1 << 30

func blurSupportRadius( float64) (int, error) {
	if  == 0 {
		return 0, nil
	}
	 := math.Ceil(3 * )
	if !finite() ||  > maxBlurSupportRadius {
		return 0, fmt.Errorf("three-sigma support exceeds the bounded raster domain")
	}
	return int(), nil
}

func prepareBlurPasses( image.Rectangle, ,  int) ([]blurPass, image.Rectangle, error) {
	 := splitBlurRadius()
	 := splitBlurRadius()
	 := 
	 := make([]blurPass, 0, 6)
	for  := range 3 {
		if [] != 0 {
			var  error
			,  = expandFilterBounds(, [], 0)
			if  != nil {
				return nil, image.Rectangle{}, 
			}
			 = append(, blurPass{axis: blurHorizontal, radius: [], bounds: })
		}
		if [] != 0 {
			var  error
			,  = expandFilterBounds(, 0, [])
			if  != nil {
				return nil, image.Rectangle{}, 
			}
			 = append(, blurPass{axis: blurVertical, radius: [], bounds: })
		}
	}
	return , , nil
}

func splitBlurRadius( int) [3]int {
	// Three successive boxes converge toward a Gaussian while retaining an
	// O(pixel-count) sliding-window implementation. Splitting the conservative
	// three-sigma support across the passes makes the actual finite support
	// exactly match the bounds charged during preflight.
	 := [3]int{ / 3,  / 3,  / 3}
	for  := 0;  < %3; ++ {
		[]++
	}
	return 
}

func expandFilterBounds( image.Rectangle, ,  int) (image.Rectangle, error) {
	if .Empty() {
		return image.Rectangle{}, nil
	}
	 := platformMaxInt()
	 := - - 1
	if int64(.Min.X) < +int64() || int64(.Min.Y) < +int64() ||
		int64(.Max.X) > -int64() || int64(.Max.Y) > -int64() {
		return image.Rectangle{}, fmt.Errorf("filter bounds exceed the platform integer domain")
	}
	,  := int64(.Min.X)-int64(), int64(.Min.Y)-int64()
	,  := int64(.Max.X)+int64(), int64(.Max.Y)+int64()
	if uint64()-uint64() > uint64() || uint64()-uint64() > uint64() {
		return image.Rectangle{}, fmt.Errorf("filter bounds exceed the platform integer domain")
	}
	return image.Rect(int(), int(), int(), int()), nil
}

func translatedFilterBoundsUnbounded( image.Rectangle, ,  float64) (image.Rectangle, error) {
	if .Empty() {
		return image.Rectangle{}, nil
	}
	 := math.Floor(float64(.Min.X) + )
	 := math.Floor(float64(.Min.Y) + )
	 := math.Ceil(float64(.Max.X) + )
	 := math.Ceil(float64(.Max.Y) + )
	 := platformMaxInt()
	 := - - 1
	 := float64()
	if  > 1<<53 {
		 = math.Nextafter(, 0)
	}
	if !finite() || !finite() || !finite() || !finite() ||
		 < float64() ||  < float64() ||
		 >  ||  >  ||  <=  ||  <=  {
		return image.Rectangle{}, fmt.Errorf("translated filter bounds exceed the platform integer domain")
	}
	 := image.Rect(int(), int(), int(), int())
	if uint64(int64(.Max.X))-uint64(int64(.Min.X)) > uint64() ||
		uint64(int64(.Max.Y))-uint64(int64(.Min.Y)) > uint64() {
		return image.Rectangle{}, fmt.Errorf("translated filter bounds exceed the platform integer domain")
	}
	return , nil
}

func unionFilterBounds(,  image.Rectangle) (image.Rectangle, error) {
	 := unionRect(, )
	if .Empty() {
		return , nil
	}
	 := uint64(platformMaxInt())
	if uint64(int64(.Max.X))-uint64(int64(.Min.X)) >  ||
		uint64(int64(.Max.Y))-uint64(int64(.Min.Y)) >  {
		return image.Rectangle{}, fmt.Errorf("filter bounds exceed the platform integer domain")
	}
	return , nil
}

// regionalFilters works backwards from the pixels a destination will consume.
// Each pass keeps its original kernel and transparent-outside-input semantics,
// but only allocates the output needed by its successor. The input rectangle
// includes every contributing sample, so the existing integer blur arithmetic
// and shadow interpolation produce the same pixels as the complete layers.
// Prepared filters are shared across bands and must remain immutable.
func regionalFilters( []preparedFilter, ,  image.Rectangle) ([]preparedFilter, image.Rectangle, error) {
	 := make([]preparedFilter, len())
	 := 
	for  := len() - 1;  >= 0; -- {
		 := []
		 := 
		if  > 0 {
			 = [-1].output
		}
		.output = .Intersect(.output)
		.passes = append([]blurPass(nil), .passes...)
		 := .output
		if .kind == preparedDropShadow {
			 := 
			if len(.passes) != 0 {
				 = .passes[len(.passes)-1].bounds
			}
			 = shadowSampleBounds(.output, , .offsetX, .offsetY)
		} else if .kind != preparedGaussianBlur {
			return nil, image.Rectangle{}, fmt.Errorf("d2raster: internal unknown prepared filter %d", .kind)
		}
		for  := len(.passes) - 1;  >= 0; -- {
			 := &.passes[]
			.bounds = .Intersect(.bounds)
			 := 
			if  > 0 {
				 = [].passes[-1].bounds
			}
			,  := .radius, 0
			if .axis == blurVertical {
				,  = 0, .radius
			}
			,  := expandFilterBounds(.bounds, , )
			if  != nil {
				// At the platform coordinate boundary, keeping the full previous
				// pass is conservative and avoids overflowing an intermediate ROI.
				 = 
			} else {
				 = .Intersect()
			}
		}
		 = .Intersect()
		if .kind == preparedDropShadow {
			// Source-over keeps the unshifted input in addition to its shadow.
			// A rectangle spans both regions; extreme offsets can still require
			// substantial storage and remain subject to MaxOffscreenBytes.
			 = unionRect(, .output.Intersect())
		}
		[] = 
	}
	return , .Intersect(), nil
}

func shadowSampleBounds(,  image.Rectangle, ,  float64) image.Rectangle {
	if .Empty() || .Empty() {
		return image.Rectangle{}
	}
	// Outside the exact float-integer domain the original sampler deliberately
	// uses floating-point coordinate arithmetic. Retain its source domain rather
	// than infer a cropped integer domain from rounded endpoints.
	const  = 1 << 53
	if !rectangleWithinExactFloatIntegerDomain() || !rectangleWithinExactFloatIntegerDomain() ||
		!finite() || !finite() || math.Abs() >  || math.Abs() >  {
		return 
	}
	 := 2.0 // floor(sample) and floor(sample)+1 for bilinear interpolation.
	if  == math.Trunc() &&  == math.Trunc() {
		 = 1
	}
	 := math.Max(math.Floor(float64(.Min.X)-), float64(.Min.X))
	 := math.Max(math.Floor(float64(.Min.Y)-), float64(.Min.Y))
	 := math.Min(math.Floor(float64(.Max.X-1)-)+, float64(.Max.X))
	 := math.Min(math.Floor(float64(.Max.Y-1)-)+, float64(.Max.Y))
	if  >=  ||  >=  {
		return image.Rectangle{}
	}
	return image.Rect(int(), int(), int(), int())
}

type ownedRGBA struct {
	image       *image.RGBA
	reservation int64
	scratch     *rasterScratch
}

func reserveRGBA( *rasterScratch,  image.Rectangle,  string) (ownedRGBA, error) {
	, ,  := .offscreen.newRGBA(, )
	if  != nil {
		return ownedRGBA{}, 
	}
	return ownedRGBA{image: , reservation: , scratch: }, nil
}

func ( *ownedRGBA) () {
	if  == nil || .reservation == 0 {
		return
	}
	.scratch.offscreen.recycleRGBA(.image, .reservation)
	.reservation = 0
	.image = nil
}

type ownedAlpha struct {
	image       *image.Alpha
	reservation int64
	scratch     *rasterScratch
}

func reserveAlpha( *rasterScratch,  image.Rectangle,  string) (ownedAlpha, error) {
	, ,  := .offscreen.newAlpha(, )
	if  != nil {
		return ownedAlpha{}, 
	}
	return ownedAlpha{image: , reservation: , scratch: }, nil
}

func ( *ownedAlpha) () {
	if  == nil || .reservation == 0 {
		return
	}
	.scratch.offscreen.recycleAlpha(.image, .reservation)
	.reservation = 0
	.image = nil
}

func applyPreparedFilter( context.Context,  *ownedRGBA,  preparedFilter,  *rasterScratch) error {
	switch .kind {
	case preparedGaussianBlur:
		return applyGaussianFilter(, , , )
	case preparedDropShadow:
		return applyDropShadowFilter(, , , )
	default:
		.release()
		return fmt.Errorf("d2raster: internal unknown prepared filter %d", .kind)
	}
}

func applyGaussianFilter( context.Context,  *ownedRGBA,  preparedFilter,  *rasterScratch) error {
	for ,  := range .passes {
		,  := reserveRGBA(, .bounds, "Gaussian blur pass")
		if  != nil {
			.release()
			return 
		}
		if  := boxBlurRGBA(, .image, .image, );  != nil {
			.release()
			.release()
			return fmt.Errorf("d2raster: Gaussian blur pass %d: %w", , )
		}
		.release()
		* = 
	}
	return nil
}

func applyDropShadowFilter( context.Context,  *ownedRGBA,  preparedFilter,  *rasterScratch) error {
	var  ownedAlpha
	for ,  := range .passes {
		,  := reserveAlpha(, .bounds, "drop-shadow blur pass")
		if  != nil {
			.release()
			.release()
			return 
		}
		if .image == nil {
			 = boxBlurAlphaFromRGBA(, .image, .image, )
		} else {
			 = boxBlurAlpha(, .image, .image, )
		}
		if  != nil {
			.release()
			.release()
			.release()
			return fmt.Errorf("d2raster: drop-shadow blur pass %d: %w", , )
		}
		.release()
		 = 
	}

	,  := reserveRGBA(, .output, "drop-shadow output layer")
	if  != nil {
		.release()
		.release()
		return 
	}
	if  := paintDropShadow(, .image, .image, alphaImage(&), .offsetX, .offsetY, .shadowColor);  != nil {
		.release()
		.release()
		.release()
		return 
	}
	if  := compositeLayerOver(, .image, .image, 1);  != nil {
		.release()
		.release()
		.release()
		return 
	}
	.release()
	.release()
	* = 
	return nil
}

func alphaImage( *ownedAlpha) *image.Alpha {
	if  == nil {
		return nil
	}
	return .image
}

func boxBlurRGBA( context.Context, ,  *image.RGBA,  blurPass) error {
	if expandedBlurPass(.Bounds(), .Bounds(), ) {
		return boxBlurRGBAExpanded(, , , )
	}
	return boxBlurRGBAGeneral(, , , )
}

// expandedBlurPass recognizes the layout produced by prepareBlurPasses. In
// that layout every row (horizontal pass) or column (vertical pass) has source
// pixels, and the moving window enters and leaves the source at fixed relative
// offsets. Keeping those facts out of the per-pixel loop materially reduces
// the cost of the six blur passes used by filters while the general kernel
// remains available for independently constructed images and tests.
func expandedBlurPass(,  image.Rectangle,  blurPass) bool {
	if .radius <= 0 || .Empty() || .Empty() {
		return false
	}
	 := int64(.radius)
	switch .axis {
	case blurHorizontal:
		return .Min.Y == .Min.Y && .Max.Y == .Max.Y &&
			int64(.Min.X) == int64(.Min.X)- &&
			int64(.Max.X) == int64(.Max.X)+
	case blurVertical:
		return .Min.X == .Min.X && .Max.X == .Max.X &&
			int64(.Min.Y) == int64(.Min.Y)- &&
			int64(.Max.Y) == int64(.Max.Y)+
	default:
		return false
	}
}

func boxBlurRGBAExpanded( context.Context, ,  *image.RGBA,  blurPass) error {
	 := int64(.radius)*2 + 1
	 :=  / 2
	 := .Bounds()
	 := .Bounds()
	 := .radius * 2
	if .axis == blurHorizontal {
		 := .Dx()
		 := .Dx()
		for  := 0;  < .Dy(); ++ {
			 := .PixOffset(.Min.X, .Min.Y+)
			 := .PixOffset(.Min.X, .Min.Y+)
			var  [4]int64
			[0] = int64(.Pix[])
			[1] = int64(.Pix[+1])
			[2] = int64(.Pix[+2])
			[3] = int64(.Pix[+3])
			for  := 0;  < ; ++ {
				if &255 == 0 {
					if  := .Err();  != nil {
						return 
					}
				}
				.Pix[] = uint8(([0] + ) / )
				.Pix[+1] = uint8(([1] + ) / )
				.Pix[+2] = uint8(([2] + ) / )
				.Pix[+3] = uint8(([3] + ) / )
				 += 4

				if  >=  {
					 :=  - 
					 :=  + *4
					[0] -= int64(.Pix[])
					[1] -= int64(.Pix[+1])
					[2] -= int64(.Pix[+2])
					[3] -= int64(.Pix[+3])
				}
				 :=  + 1
				if  <  {
					 :=  + *4
					[0] += int64(.Pix[])
					[1] += int64(.Pix[+1])
					[2] += int64(.Pix[+2])
					[3] += int64(.Pix[+3])
				}
			}
		}
		return .Err()
	}

	 := .Dy()
	 := .Dy()
	for  := 0;  < .Dx(); ++ {
		 := .PixOffset(.Min.X+, .Min.Y)
		 := .PixOffset(.Min.X+, .Min.Y)
		var  [4]int64
		[0] = int64(.Pix[])
		[1] = int64(.Pix[+1])
		[2] = int64(.Pix[+2])
		[3] = int64(.Pix[+3])
		for  := 0;  < ; ++ {
			if &255 == 0 {
				if  := .Err();  != nil {
					return 
				}
			}
			.Pix[] = uint8(([0] + ) / )
			.Pix[+1] = uint8(([1] + ) / )
			.Pix[+2] = uint8(([2] + ) / )
			.Pix[+3] = uint8(([3] + ) / )
			 += .Stride

			if  >=  {
				 :=  - 
				 :=  + *.Stride
				[0] -= int64(.Pix[])
				[1] -= int64(.Pix[+1])
				[2] -= int64(.Pix[+2])
				[3] -= int64(.Pix[+3])
			}
			 :=  + 1
			if  <  {
				 :=  + *.Stride
				[0] += int64(.Pix[])
				[1] += int64(.Pix[+1])
				[2] += int64(.Pix[+2])
				[3] += int64(.Pix[+3])
			}
		}
	}
	return .Err()
}

func boxBlurRGBAGeneral( context.Context, ,  *image.RGBA,  blurPass) error {
	 := int64(.radius)*2 + 1
	,  := .Bounds(), .Bounds()
	if .axis == blurHorizontal {
		for  := .Min.Y;  < .Max.Y; ++ {
			if (-.Min.Y)&15 == 0 {
				if  := .Err();  != nil {
					return 
				}
			}
			var  [4]int64
			 := .Min.X
			 := max(int64()-int64(.radius), int64(.Min.X))
			 := min(int64()+int64(.radius), int64(.Max.X)-1)
			 := -1
			if  >= .Min.Y &&  < .Max.Y {
				 = ( - .Min.Y) * .Stride
				for  := ;  <= ; ++ {
					 :=  + (int()-.Min.X)*4
					[0] += int64(.Pix[])
					[1] += int64(.Pix[+1])
					[2] += int64(.Pix[+2])
					[3] += int64(.Pix[+3])
				}
			}
			 := ( - .Min.Y) * .Stride
			for  := .Min.X;  < .Max.X; ++ {
				if (-.Min.X)&255 == 0 {
					if  := .Err();  != nil {
						return 
					}
				}
				 :=  + (-.Min.X)*4
				.Pix[] = uint8(([0] + /2) / )
				.Pix[+1] = uint8(([1] + /2) / )
				.Pix[+2] = uint8(([2] + /2) / )
				.Pix[+3] = uint8(([3] + /2) / )
				,  := int64()-int64(.radius), int64()+int64(.radius)+1
				if  >= 0 &&  >= int64(.Min.X) &&  < int64(.Max.X) {
					 :=  + (int()-.Min.X)*4
					[0] -= int64(.Pix[])
					[1] -= int64(.Pix[+1])
					[2] -= int64(.Pix[+2])
					[3] -= int64(.Pix[+3])
				}
				if  >= 0 &&  >= int64(.Min.X) &&  < int64(.Max.X) {
					 :=  + (int()-.Min.X)*4
					[0] += int64(.Pix[])
					[1] += int64(.Pix[+1])
					[2] += int64(.Pix[+2])
					[3] += int64(.Pix[+3])
				}
			}
		}
		return .Err()
	}

	for  := .Min.X;  < .Max.X; ++ {
		if (-.Min.X)&31 == 0 {
			if  := .Err();  != nil {
				return 
			}
		}
		var  [4]int64
		 := .Min.Y
		 := max(int64()-int64(.radius), int64(.Min.Y))
		 := min(int64()+int64(.radius), int64(.Max.Y)-1)
		 := -1
		if  >= .Min.X &&  < .Max.X {
			 = ( - .Min.X) * 4
			for  := ;  <= ; ++ {
				 := (int()-.Min.Y)*.Stride + 
				[0] += int64(.Pix[])
				[1] += int64(.Pix[+1])
				[2] += int64(.Pix[+2])
				[3] += int64(.Pix[+3])
			}
		}
		 := ( - .Min.X) * 4
		for  := .Min.Y;  < .Max.Y; ++ {
			if (-.Min.Y)&255 == 0 {
				if  := .Err();  != nil {
					return 
				}
			}
			 := (-.Min.Y)*.Stride + 
			.Pix[] = uint8(([0] + /2) / )
			.Pix[+1] = uint8(([1] + /2) / )
			.Pix[+2] = uint8(([2] + /2) / )
			.Pix[+3] = uint8(([3] + /2) / )
			,  := int64()-int64(.radius), int64()+int64(.radius)+1
			if  >= 0 &&  >= int64(.Min.Y) &&  < int64(.Max.Y) {
				 := (int()-.Min.Y)*.Stride + 
				[0] -= int64(.Pix[])
				[1] -= int64(.Pix[+1])
				[2] -= int64(.Pix[+2])
				[3] -= int64(.Pix[+3])
			}
			if  >= 0 &&  >= int64(.Min.Y) &&  < int64(.Max.Y) {
				 := (int()-.Min.Y)*.Stride + 
				[0] += int64(.Pix[])
				[1] += int64(.Pix[+1])
				[2] += int64(.Pix[+2])
				[3] += int64(.Pix[+3])
			}
		}
	}
	return .Err()
}

func boxBlurAlphaFromRGBA( context.Context,  *image.Alpha,  *image.RGBA,  blurPass) error {
	return boxBlurAlphaPixels(, , .Pix, .Stride, .Bounds(), 4, 3, )
}

func boxBlurAlpha( context.Context, ,  *image.Alpha,  blurPass) error {
	return boxBlurAlphaPixels(, , .Pix, .Stride, .Bounds(), 1, 0, )
}

func boxBlurAlphaPixels( context.Context,  *image.Alpha,  []uint8,  int,  image.Rectangle, ,  int,  blurPass) error {
	if expandedBlurPass(.Bounds(), , ) {
		return boxBlurAlphaPixelsExpanded(, , , , , , , )
	}
	return boxBlurAlphaPixelsGeneral(, , , , , , , )
}

func boxBlurAlphaPixelsExpanded( context.Context,  *image.Alpha,  []uint8,  int,  image.Rectangle, ,  int,  blurPass) error {
	 := int64(.radius)*2 + 1
	 :=  / 2
	 := .Bounds()
	 := .radius * 2
	if .axis == blurHorizontal {
		 := .Dx()
		 := .Dx()
		for  := 0;  < .Dy(); ++ {
			 := * + 
			 :=  * .Stride
			 := int64([])
			for  := 0;  < ; ++ {
				if &255 == 0 {
					if  := .Err();  != nil {
						return 
					}
				}
				.Pix[] = uint8(( + ) / )
				++
				if  >=  {
					 :=  - 
					 -= int64([+*])
				}
				 :=  + 1
				if  <  {
					 += int64([+*])
				}
			}
		}
		return .Err()
	}

	 := .Dy()
	 := .Dy()
	for  := 0;  < .Dx(); ++ {
		 := * + 
		 := 
		 := int64([])
		for  := 0;  < ; ++ {
			if &255 == 0 {
				if  := .Err();  != nil {
					return 
				}
			}
			.Pix[] = uint8(( + ) / )
			 += .Stride
			if  >=  {
				 :=  - 
				 -= int64([+*])
			}
			 :=  + 1
			if  <  {
				 += int64([+*])
			}
		}
	}
	return .Err()
}

func boxBlurAlphaPixelsGeneral( context.Context,  *image.Alpha,  []uint8,  int,  image.Rectangle, ,  int,  blurPass) error {
	 := int64(.radius)*2 + 1
	 := .Bounds()
	if .axis == blurHorizontal {
		for  := .Min.Y;  < .Max.Y; ++ {
			if (-.Min.Y)&15 == 0 {
				if  := .Err();  != nil {
					return 
				}
			}
			 := int64(0)
			 := .Min.X
			if  >= .Min.Y &&  < .Max.Y {
				 := max(int64()-int64(.radius), int64(.Min.X))
				 := min(int64()+int64(.radius), int64(.Max.X)-1)
				 := (-.Min.Y)* + 
				for  := ;  <= ; ++ {
					 += int64([+(int()-.Min.X)*])
				}
			}
			 := ( - .Min.Y) * .Stride
			for  := .Min.X;  < .Max.X; ++ {
				if (-.Min.X)&255 == 0 {
					if  := .Err();  != nil {
						return 
					}
				}
				.Pix[+-.Min.X] = uint8(( + /2) / )
				,  := int64()-int64(.radius), int64()+int64(.radius)+1
				if  >= .Min.Y &&  < .Max.Y &&  >= int64(.Min.X) &&  < int64(.Max.X) {
					 := (-.Min.Y)* + (int()-.Min.X)* + 
					 -= int64([])
				}
				if  >= .Min.Y &&  < .Max.Y &&  >= int64(.Min.X) &&  < int64(.Max.X) {
					 := (-.Min.Y)* + (int()-.Min.X)* + 
					 += int64([])
				}
			}
		}
		return .Err()
	}

	for  := .Min.X;  < .Max.X; ++ {
		if (-.Min.X)&31 == 0 {
			if  := .Err();  != nil {
				return 
			}
		}
		 := int64(0)
		 := .Min.Y
		if  >= .Min.X &&  < .Max.X {
			 := max(int64()-int64(.radius), int64(.Min.Y))
			 := min(int64()+int64(.radius), int64(.Max.Y)-1)
			 := (-.Min.X)* + 
			for  := ;  <= ; ++ {
				 += int64([(int()-.Min.Y)*+])
			}
		}
		 :=  - .Min.X
		for  := .Min.Y;  < .Max.Y; ++ {
			if (-.Min.Y)&255 == 0 {
				if  := .Err();  != nil {
					return 
				}
			}
			.Pix[(-.Min.Y)*.Stride+] = uint8(( + /2) / )
			,  := int64()-int64(.radius), int64()+int64(.radius)+1
			if  >= .Min.X &&  < .Max.X &&  >= int64(.Min.Y) &&  < int64(.Max.Y) {
				 := (int()-.Min.Y)* + (-.Min.X)* + 
				 -= int64([])
			}
			if  >= .Min.X &&  < .Max.X &&  >= int64(.Min.Y) &&  < int64(.Max.Y) {
				 := (int()-.Min.Y)* + (-.Min.X)* + 
				 += int64([])
			}
		}
	}
	return .Err()
}

func paintDropShadow( context.Context, ,  *image.RGBA,  *image.Alpha, ,  float64,  color.NRGBA) error {
	if finite() && finite() &&  == math.Trunc() &&  == math.Trunc() {
		return paintDropShadowInteger(, , , , , , )
	}
	for  := .Bounds().Min.Y;  < .Bounds().Max.Y; ++ {
		if (-.Bounds().Min.Y)&31 == 0 {
			if  := .Err();  != nil {
				return 
			}
		}
		 := float64() - 
		for  := .Bounds().Min.X;  < .Bounds().Max.X; ++ {
			if (-.Bounds().Min.X)&1023 == 0 {
				if  := .Err();  != nil {
					return 
				}
			}
			var  uint8
			if  == nil {
				 = sampleShadowAlphaRGBA(, float64()-, )
			} else {
				 = sampleShadowAlphaImage(, float64()-, )
			}
			if  == 0 {
				continue
			}
			 := premultipliedShadowPixel(, )
			 := .PixOffset(, )
			.Pix[] = [0]
			.Pix[+1] = [1]
			.Pix[+2] = [2]
			.Pix[+3] = [3]
		}
	}
	return .Err()
}

func paintDropShadowInteger( context.Context, ,  *image.RGBA,  *image.Alpha, ,  float64,  color.NRGBA) error {
	 := .Pix
	 := .Stride
	 := .Bounds()
	,  := 4, 3
	if  != nil {
		 = .Pix
		 = .Stride
		 = .Bounds()
		,  = 1, 0
	}
	// Computing translated integer bounds costs more than it saves for a single
	// destination pixel. Keep that degenerate case scalar while preserving the
	// same three cancellation checkpoints as the row kernel.
	 := .Bounds()
	if .Dx() == 1 && .Dy() == 1 {
		if  := .Err();  != nil {
			return 
		}
		if  := .Err();  != nil {
			return 
		}
		,  := .Min.X, .Min.Y
		,  := float64()-, float64()-
		if  >= float64(.Min.X) &&  < float64(.Max.X) &&
			 >= float64(.Min.Y) &&  < float64(.Max.Y) {
			,  := int(), int()
			 := [(-.Min.Y)*+(-.Min.X)*+]
			if  != 0 {
				 := premultipliedShadowPixel(, )
				 := .PixOffset(, )
				.Pix[] = [0]
				.Pix[+1] = [1]
				.Pix[+2] = [2]
				.Pix[+3] = [3]
			}
		}
		return .Err()
	}
	,  := exactIntegerTranslatedBounds(, , )
	if ! || !rectangleWithinExactFloatIntegerDomain() {
		return paintDropShadowIntegerGeneral(, , , , , , , , , )
	}
	for  := .Min.Y;  < .Max.Y; ++ {
		if (-.Min.Y)&31 == 0 {
			if  := .Err();  != nil {
				return 
			}
		}
		 :=  >= .Min.Y &&  < .Max.Y
		 := 0
		if  {
			 := .Min.Y +  - .Min.Y
			 = (-.Min.Y)* + 
		}
		 := .PixOffset(.Min.X, )
		for  := .Min.X;  < .Max.X; ++ {
			if (-.Min.X)&1023 == 0 {
				if  := .Err();  != nil {
					return 
				}
			}
			if ! ||  < .Min.X ||  >= .Max.X {
				 += 4
				continue
			}
			 := .Min.X +  - .Min.X
			 := [+(-.Min.X)*]
			if  != 0 {
				 := premultipliedShadowPixel(, )
				.Pix[] = [0]
				.Pix[+1] = [1]
				.Pix[+2] = [2]
				.Pix[+3] = [3]
			}
			 += 4
		}
	}
	return .Err()
}

func rectangleWithinExactFloatIntegerDomain( image.Rectangle) bool {
	const  = int64(1) << 53
	return int64(.Min.X) >= - && int64(.Min.X) <=  &&
		int64(.Min.Y) >= - && int64(.Min.Y) <=  &&
		int64(.Max.X) >= - && int64(.Max.X) <=  &&
		int64(.Max.Y) >= - && int64(.Max.Y) <= 
}

func exactIntegerTranslatedBounds( image.Rectangle, ,  float64) (image.Rectangle, bool) {
	// The general sampler converts each destination coordinate to float64 before
	// subtracting the offset. Outside float64's exact integer domain, adjacent
	// coordinates can alias even when translating the rectangle endpoints happens
	// to preserve its width. Only use the direct-index kernel when every operand
	// and translated endpoint is exactly representable, so it remains byte-for-byte
	// equivalent to that sampler.
	const  = int64(1) << 53
	if !rectangleWithinExactFloatIntegerDomain() ||
		 < -float64() ||  > float64() ||
		 < -float64() ||  > float64() {
		return image.Rectangle{}, false
	}
	 := float64(platformMaxInt())
	if platformMaxInt() > 1<<53 {
		 = math.Nextafter(, 0)
	}
	 := - - 1
	 := float64(.Min.X) + 
	 := float64(.Min.Y) + 
	 := float64(.Max.X) + 
	 := float64(.Max.Y) + 
	if  < -float64() ||  < -float64() ||
		 > float64() ||  > float64() ||
		 <  ||  <  ||  >  ||  >  ||
		 != math.Trunc() ||  != math.Trunc() ||  != math.Trunc() ||  != math.Trunc() {
		return image.Rectangle{}, false
	}
	 := image.Rect(int(), int(), int(), int())
	if .Dx() != .Dx() || .Dy() != .Dy() {
		return image.Rectangle{}, false
	}
	return , true
}

func paintDropShadowIntegerGeneral( context.Context,  *image.RGBA,  []byte,  int,  image.Rectangle, ,  int, ,  float64,  color.NRGBA) error {
	for  := .Bounds().Min.Y;  < .Bounds().Max.Y; ++ {
		if (-.Bounds().Min.Y)&31 == 0 {
			if  := .Err();  != nil {
				return 
			}
		}
		 := float64() - 
		 :=  >= float64(.Min.Y) &&  < float64(.Max.Y)
		 := 0
		if  {
			 = int()
		}
		for  := .Bounds().Min.X;  < .Bounds().Max.X; ++ {
			if (-.Bounds().Min.X)&1023 == 0 {
				if  := .Err();  != nil {
					return 
				}
			}
			if ! {
				continue
			}
			 := float64() - 
			if  < float64(.Min.X) ||  >= float64(.Max.X) {
				continue
			}
			 := int()
			 := [(-.Min.Y)*+(-.Min.X)*+]
			if  == 0 {
				continue
			}
			 := premultipliedShadowPixel(, )
			 := .PixOffset(, )
			.Pix[] = [0]
			.Pix[+1] = [1]
			.Pix[+2] = [2]
			.Pix[+3] = [3]
		}
	}
	return .Err()
}

func premultipliedShadowPixel( color.NRGBA,  uint8) [4]uint8 {
	 := uint8((uint32()*uint32(.A) + 127) / 255)
	return [4]uint8{
		uint8((uint32(.R)*uint32() + 127) / 255),
		uint8((uint32(.G)*uint32() + 127) / 255),
		uint8((uint32(.B)*uint32() + 127) / 255),
		,
	}
}

func sampleShadowAlphaRGBA( *image.RGBA, ,  float64) uint8 {
	 := .Bounds()
	// Reject non-contributing coordinates before float-to-int conversion. This
	// also makes finite but enormous offsets deterministic across architectures.
	if !finite() || !finite() ||
		 < float64(.Min.X)-1 ||  >= float64(.Max.X) ||
		 < float64(.Min.Y)-1 ||  >= float64(.Max.Y) {
		return 0
	}
	,  := int(math.Floor()), int(math.Floor())
	,  := -float64(), -float64()
	if  == 0 &&  == 0 {
		if  < .Min.X ||  >= .Max.X ||  < .Min.Y ||  >= .Max.Y {
			return 0
		}
		return .Pix[.PixOffset(, )+3]
	}
	if  >= .Min.X && +1 < .Max.X &&  >= .Min.Y && +1 < .Max.Y {
		 := .PixOffset(, ) + 3
		return interpolateShadowAlpha(
			.Pix[], .Pix[+4],
			.Pix[+.Stride], .Pix[+.Stride+4],
			, ,
		)
	}
	return interpolateShadowAlpha(
		rgbaAlphaAt(, , ), rgbaAlphaAt(, +1, ),
		rgbaAlphaAt(, , +1), rgbaAlphaAt(, +1, +1),
		, ,
	)
}

func sampleShadowAlphaImage( *image.Alpha, ,  float64) uint8 {
	 := .Bounds()
	// Keep the same pre-conversion guard as the RGBA path.
	if !finite() || !finite() ||
		 < float64(.Min.X)-1 ||  >= float64(.Max.X) ||
		 < float64(.Min.Y)-1 ||  >= float64(.Max.Y) {
		return 0
	}
	,  := int(math.Floor()), int(math.Floor())
	,  := -float64(), -float64()
	if  == 0 &&  == 0 {
		if  < .Min.X ||  >= .Max.X ||  < .Min.Y ||  >= .Max.Y {
			return 0
		}
		return .Pix[.PixOffset(, )]
	}
	if  >= .Min.X && +1 < .Max.X &&  >= .Min.Y && +1 < .Max.Y {
		 := .PixOffset(, )
		return interpolateShadowAlpha(
			.Pix[], .Pix[+1],
			.Pix[+.Stride], .Pix[+.Stride+1],
			, ,
		)
	}
	return interpolateShadowAlpha(
		alphaAt(, , ), alphaAt(, +1, ),
		alphaAt(, , +1), alphaAt(, +1, +1),
		, ,
	)
}

func interpolateShadowAlpha(, , ,  uint8, ,  float64) uint8 {
	 := float64() + (float64()-float64())*
	 := float64() + (float64()-float64())*
	return roundedByte( + (-)*)
}

func rgbaAlphaAt( *image.RGBA, ,  int) uint8 {
	if !image.Pt(, ).In(.Bounds()) {
		return 0
	}
	return .Pix[.PixOffset(, )+3]
}

func alphaAt( *image.Alpha, ,  int) uint8 {
	if !image.Pt(, ).In(.Bounds()) {
		return 0
	}
	return .Pix[.PixOffset(, )]
}

func planFilterResources( []preparedFilter,  image.Rectangle) (,  int64,  error) {
	,  := pixelStorageBytes(, 4)
	if  != nil {
		return 0, 0, fmt.Errorf("d2raster: filter input layer: %w", )
	}
	 = 
	for ,  := range  {
		switch .kind {
		case preparedGaussianBlur:
			for ,  := range .passes {
				,  := pixelStorageBytes(.bounds, 4)
				if  != nil {
					return 0, 0, fmt.Errorf("d2raster: Gaussian blur pass: %w", )
				}
				,  := checkedAdd(, )
				if ! {
					return 0, 0, fmt.Errorf("d2raster: peak offscreen pixel storage exceeds the int64 domain")
				}
				 = maxInt64(, )
				 = 
			}
		case preparedDropShadow:
			 := int64(0)
			for ,  := range .passes {
				,  := pixelStorageBytes(.bounds, 1)
				if  != nil {
					return 0, 0, fmt.Errorf("d2raster: drop-shadow blur pass: %w", )
				}
				,  := checkedAdd(, )
				if  {
					,  = checkedAdd(, )
				}
				if ! {
					return 0, 0, fmt.Errorf("d2raster: peak offscreen pixel storage exceeds the int64 domain")
				}
				 = maxInt64(, )
				 = 
			}
			,  := pixelStorageBytes(.output, 4)
			if  != nil {
				return 0, 0, fmt.Errorf("d2raster: drop-shadow output layer: %w", )
			}
			,  := checkedAdd(, )
			if  {
				,  = checkedAdd(, )
			}
			if ! {
				return 0, 0, fmt.Errorf("d2raster: peak offscreen pixel storage exceeds the int64 domain")
			}
			 = maxInt64(, )
			 = 
		default:
			return 0, 0, fmt.Errorf("d2raster: internal unknown prepared filter %d", .kind)
		}
	}
	return , , nil
}