58 lines
1.6 KiB
Go
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)
|
|
}
|