package d2isometricimg

import (
	
	
)

// A cover paints one continuous material silhouette. Each mesh facet keeps its
// own vector lighting inside the pattern, but antialiasing at internal facet
// edges cannot reveal the page behind it. The exact outer silhouette is filled
// once, so neither source opacity nor the authored outline gets thicker.
type svgPaintCover struct {
	batches  []*svgPaintBatch
	polygons [][]svgPoint
	first    int
	written  bool
}

func svgPreparePaintCovers( []*svgPaintBatch) map[*svgPaintBatch]*svgPaintCover {
	type  struct {
		 *Material
		    bool
		  bool
	}
	 := make(map[]*svgPaintCover)
	for ,  := range  {
		 := .triangle.Material
		if  == nil || len(.polygons) == 0 {
			continue
		}
		// Only a full, filled physical surface permits texture overdraw. Decals
		// and artwork with transparent margins must retain their separate clips.
		if .texture && (!.svgSolidTexture || .triangle.NoDepthWrite || .Multiply) {
			continue
		}
		 := {, .triangle.NoDepthWrite, .texture}
		 := []
		if  == nil {
			 = &svgPaintCover{first: .first}
			[] = 
		}
		.batches = append(.batches, )
		.polygons = append(.polygons, .polygons...)
	}
	 := make(map[*svgPaintBatch]*svgPaintCover)
	for ,  := range  {
		if len(.batches) < 2 {
			continue
		}
		for ,  := range .batches {
			[] = 
		}
	}
	return 
}

func writeSVGPaintCover( *nativeSVGWriter,  *svgPaintCover,  rasterCamera) {
	if .written || .err != nil {
		return
	}
	.written = true
	var  []svgPoint
	for ,  := range .polygons {
		 = append(, ...)
	}
	 := svgPolygonBox()
	// Keep the tile boundary away from the exact outer silhouette. Otherwise
	// the tile's own antialiasing would be multiplied by the final path edge.
	.minX, .minY, .maxX, .maxY = .minX-1, .minY-1, .maxX+1, .maxY+1
	 := fmt.Sprintf("paint-cover-%d", .first)
	 := make([]string, len(.batches))
	for ,  := range .batches {
		if .texture {
			continue
		}
		[] = .color
		if [] == "" {
			// The emitter numbers its regular batches positively. A separate
			// namespace prevents collision with a cover's original mesh indices.
			[] = writeSVGFaceGradient(, , -.first-1, )
		}
		if .err != nil {
			return
		}
	}
	.write(`<defs><pattern id="%s" patternUnits="userSpaceOnUse" x="%s" y="%s" width="%s" height="%s" viewBox="%s %s %s %s" preserveAspectRatio="none">`, , svgNumber(.minX), svgNumber(.minY), svgNumber(.maxX-.minX), svgNumber(.maxY-.minY), svgNumber(.minX), svgNumber(.minY), svgNumber(.maxX-.minX), svgNumber(.maxY-.minY))
	for ,  := range .batches {
		if .texture {
			// Keep the original UV transform and lighting, extending only its
			// internal clip. The final compound path applies silhouette and alpha
			// exactly once, so overlapping fragments cannot create darker seams.
			 := *
			 := *.triangle.Material
			.Color.A, .Multiply = 255, false
			.triangle.Material, .cover = &, nil
			.polygons = make([][]svgPoint, len(.polygons))
			for ,  := range .polygons {
				.polygons[] = svgExpandCoverPolygon(, .4)
			}
			writeSVGBatch(, &, -.first-1, )
			continue
		}
		// This is only substrate overdraw inside a single paint field. It is
		// clipped by the original compound silhouette below, never used as ink.
		.write(`<path d="%s" fill="%s" stroke="%s" stroke-width="0.8" stroke-linejoin="round"/>`, svgPolygonPath(.polygons), [], [])
	}
	.write(`</pattern></defs>`)
	 := .batches[0].triangle.Material
	 := ""
	if .Multiply {
		 = ` style="mix-blend-mode:multiply"`
	}
	.write(`<path d="%s" fill="url(#%s)" fill-opacity="%s"%s/>`, svgPolygonPath(.polygons), , svgNumber(float64(.Color.A)/255), )
}

// Offset a convex visible fragment's supporting edges by a fraction of a
// pixel. Bounding the result to the expanded box avoids long miters at acute
// projected corners. These points are only paint-field clips; they never
// replace the exact visible silhouette or any source geometry.
func svgExpandCoverPolygon( []svgPoint,  float64) []svgPoint {
	if len() < 3 ||  <= 0 {
		return 
	}
	 := svgPolygonBox()
	 := []svgPoint{
		{.minX - , .minY - , 0},
		{.maxX + , .minY - , 0},
		{.maxX + , .maxY + , 0},
		{.minX - , .maxY + , 0},
	}
	 := 1.
	if svgPolygonArea() < 0 {
		 = -1
	}
	for ,  := range  {
		 := [(+1)%len()]
		,  := .x-.x, .y-.y
		 := math.Hypot(, )
		if  < 1e-12 {
			continue
		}
		 := svgEdgeDistance(, )
		, _ = svgSplitPolygon(, func( svgPoint) float64 {
			return *()/ + 
		})
	}
	return 
}