2026-05-26 18:27:37 +02:00

58 lines
1.6 KiB
Go

package itemimage
import (
"encoding/base64"
"fmt"
"net/http"
"regexp"
"strings"
"printer.backend/internal/model"
"printer.backend/internal/svgtemplate"
)
var maskGroupRE = regexp.MustCompile(`(?s)(<g clip-path="url\(#item-mask\)">).*?(</g>)`)
// Embed replaces the green placeholder in an item SVG with the given raster image,
// clipped to the product mask (same area as the green preview rect).
func Embed(itemSVG []byte, spec model.ItemSpec, imageData []byte, contentType string) ([]byte, error) {
if len(imageData) == 0 {
return nil, fmt.Errorf("empty image data")
}
if err := spec.Normalize(); err != nil {
return nil, err
}
d := svgtemplate.Build(
spec.WidthMM, spec.HeightMM,
spec.BleedMM, spec.MarginMM, spec.PaddingMM,
spec.CornerRadiusMM,
)
prepared, mime, err := prepareRaster(imageData, d)
if err != nil {
return nil, err
}
if mime == "" {
mime = normalizeMIME(contentType, prepared)
}
href := fmt.Sprintf("data:%s;base64,%s", mime, base64.StdEncoding.EncodeToString(prepared))
inner := fmt.Sprintf(
`<image x="%.4f" y="%.4f" width="%.4f" height="%.4f" preserveAspectRatio="xMidYMid slice" href="%s"/>`,
d.OuterOffsetX, d.OuterOffsetY, d.OuterWidth, d.OuterHeight, href,
)
out := maskGroupRE.ReplaceAll(itemSVG, []byte("${1}"+inner+"${2}"))
if string(out) == string(itemSVG) {
return nil, fmt.Errorf("item svg has no printable mask group")
}
return out, nil
}
func normalizeMIME(contentType string, data []byte) string {
if ct := strings.TrimSpace(strings.Split(contentType, ";")[0]); ct != "" {
return ct
}
return http.DetectContentType(data)
}