package d2raster

import (
	
	
	

	
)

// maskRenderBounds omits the unchanged white area of a luminance mask whose
// first child is an opaque rectangular backdrop. D2's connection-label mask
// uses exactly this representation: a diagram-wide white rectangle followed by
// small label cutouts. Rendering that white area for every connection would
// otherwise scale with the connections' bounding-box areas.
//
// Reference-coordinate rendering is required because a smaller destination
// must not change the float32 rounding of antialiased mask geometry. Complete
// frames retain their existing path; band rendering already supplies stable
// reference origins for every node, including masks.
func maskRenderBounds( context.Context,  *preparedMask,  image.Rectangle,  bool) (image.Rectangle, error) {
	if  := .Err();  != nil {
		return image.Rectangle{}, 
	}
	if ! ||  == nil || .kind != d2scene.MaskLuminance || !plainMaskNode(.root) || .root.primitive != nil || len(.root.children) == 0 {
		return , nil
	}
	 := .root.children[0]
	if !plainMaskNode() || len(.children) != 0 || .primitive == nil {
		return , nil
	}
	 := .primitive
	if .fill == nil || .fill.kind != preparedSolidPaint || .fill.solid.R != 255 || .fill.solid.G != 255 || .fill.solid.B != 255 || .fill.solid.A != 255 || .stroke != nil || .image != nil || .vector != nil || len(.subpaths) != 1 {
		return , nil
	}
	// A large translation that cancels local coordinates can round differently
	// when the renderer subtracts its reference origin before transformation.
	if math.Abs(float64(.referenceBounds.Min.X)) > 1<<20 || math.Abs(float64(.referenceBounds.Min.Y)) > 1<<20 || !boundedRegionPoint(d2scene.Point{X: .transform.E, Y: .transform.F}) {
		return , nil
	}
	 := .subpaths[0].points
	if len() != 4 {
		return , nil
	}
	var  [4]d2scene.Point
	,  := math.Inf(1), math.Inf(1)
	,  := math.Inf(-1), math.Inf(-1)
	for ,  := range  {
		 = .transform.Point()
		// The one-pixel inset below is deliberately conservative. Within this
		// coordinate range float32 endpoint rounding cannot consume the inset.
		if !finitePoint() || math.Abs(.X) > 1<<20 || math.Abs(.Y) > 1<<20 {
			return , nil
		}
		[] = 
		,  = min(, .X), min(, .Y)
		,  = max(, .X), max(, .Y)
	}
	 := uint8(0)
	for ,  := range  {
		 := [(+1)%len()]
		if .X !=  && .X !=  || .Y !=  && .Y !=  ||  ==  || (.X == .X) == (.Y == .Y) {
			return , nil
		}
		 := uint8(0)
		if .X ==  {
			 |= 1
		}
		if .Y ==  {
			 |= 2
		}
		 |= 1 << 
	}
	if  != 0xf {
		return , nil
	}
	 := image.Rect(int(math.Ceil())+1, int(math.Ceil())+1, int(math.Floor())-1, int(math.Floor())-1)
	if !.In() {
		return , nil
	}
	var  image.Rectangle
	for ,  := range .root.children[1:] {
		if &255 == 0 {
			if  := .Err();  != nil {
				return image.Rectangle{}, 
			}
		}
		if  != nil && .opacity != 0 {
			 = unionRect(, .bounds.Intersect())
		}
	}
	return , nil
}

func plainMaskNode( *preparedNode) bool {
	return  != nil && .opacity == 1 && .blend == d2scene.BlendNormal && !.isolated && len(.filters) == 0 && .clip == nil && .mask == nil
}