67 lines
2.2 KiB
Go
67 lines
2.2 KiB
Go
package platepdf
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
"fmt"
|
|
|
|
"printer.backend/internal/model"
|
|
)
|
|
|
|
const renderDPI = 300
|
|
|
|
// BuildCompositeSVG assembles a plate-sized SVG by embedding each item as a PNG
|
|
// rendered by rsvg-convert (identical to the standalone item file).
|
|
func BuildCompositeSVG(plate model.Plate, spec model.ItemSpec, itemSVG []byte, preview model.LayoutPreview) ([]byte, error) {
|
|
slotSVGs := make([][]byte, len(preview.Positions))
|
|
for i := range preview.Positions {
|
|
slotSVGs[i] = itemSVG
|
|
}
|
|
return BuildCompositeSVGSlots(plate, spec, slotSVGs, preview)
|
|
}
|
|
|
|
// BuildCompositeSVGSlots places one rendered item PNG per layout position.
|
|
// len(slotSVGs) must equal len(preview.Positions).
|
|
func BuildCompositeSVGSlots(plate model.Plate, spec model.ItemSpec, slotSVGs [][]byte, preview model.LayoutPreview) ([]byte, error) {
|
|
if len(slotSVGs) != len(preview.Positions) {
|
|
return nil, fmt.Errorf("slot svg count %d does not match positions %d", len(slotSVGs), len(preview.Positions))
|
|
}
|
|
|
|
canvasW := preview.CanvasWidthMM
|
|
canvasH := preview.CanvasHeightMM
|
|
if canvasW <= 0 || canvasH <= 0 {
|
|
canvasW = spec.CanvasWidthMM()
|
|
canvasH = spec.CanvasHeightMM()
|
|
}
|
|
|
|
slotPNGs := make([]string, len(slotSVGs))
|
|
for i, svg := range slotSVGs {
|
|
itemPNG, err := svgToPNGViaRsvg(svg, renderDPI)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("render item slot %d: %w", i, err)
|
|
}
|
|
slotPNGs[i] = base64.StdEncoding.EncodeToString(itemPNG)
|
|
}
|
|
|
|
var b bytes.Buffer
|
|
fmt.Fprintf(&b, `<?xml version="1.0" encoding="UTF-8"?>
|
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 %.4f %.4f" width="%.4fmm" height="%.4fmm">
|
|
<rect width="%.4f" height="%.4f" fill="#ffffff"/>
|
|
<rect x="%.4f" y="%.4f" width="%.4f" height="%.4f" fill="none" stroke="#cccccc" stroke-width="0.2"/>
|
|
`,
|
|
plate.WidthMM, plate.HeightMM, plate.WidthMM, plate.HeightMM,
|
|
plate.WidthMM, plate.HeightMM,
|
|
preview.PrintableXMM, preview.PrintableYMM, preview.PrintableWMM, preview.PrintableHMM,
|
|
)
|
|
|
|
for i, pos := range preview.Positions {
|
|
fmt.Fprintf(&b,
|
|
`<image x="%.4f" y="%.4f" width="%.4f" height="%.4f" href="data:image/png;base64,%s"/>`,
|
|
pos.XMM, pos.YMM, canvasW, canvasH, slotPNGs[i],
|
|
)
|
|
}
|
|
|
|
b.WriteString("\n</svg>")
|
|
return b.Bytes(), nil
|
|
}
|