Added Printjobs
This commit is contained in:
@@ -13,6 +13,20 @@ 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 {
|
||||
@@ -20,11 +34,14 @@ func BuildCompositeSVG(plate model.Plate, spec model.ItemSpec, itemSVG []byte, p
|
||||
canvasH = spec.CanvasHeightMM()
|
||||
}
|
||||
|
||||
itemPNG, err := svgToPNGViaRsvg(itemSVG, renderDPI)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("render item: %w", err)
|
||||
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)
|
||||
}
|
||||
itemB64 := base64.StdEncoding.EncodeToString(itemPNG)
|
||||
|
||||
var b bytes.Buffer
|
||||
fmt.Fprintf(&b, `<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -37,10 +54,10 @@ func BuildCompositeSVG(plate model.Plate, spec model.ItemSpec, itemSVG []byte, p
|
||||
preview.PrintableXMM, preview.PrintableYMM, preview.PrintableWMM, preview.PrintableHMM,
|
||||
)
|
||||
|
||||
for _, pos := range preview.Positions {
|
||||
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, itemB64,
|
||||
pos.XMM, pos.YMM, canvasW, canvasH, slotPNGs[i],
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -30,3 +30,20 @@ func Generate(plate model.Plate, spec model.ItemSpec, itemSVGPath string, previe
|
||||
}
|
||||
return pdf, nil
|
||||
}
|
||||
|
||||
// GenerateWithSlots builds a PDF with a distinct item SVG per layout slot.
|
||||
// Requires rsvg-convert on PATH.
|
||||
func GenerateWithSlots(plate model.Plate, spec model.ItemSpec, slotSVGs [][]byte, preview model.LayoutPreview) ([]byte, error) {
|
||||
if !rsvgAvailable() {
|
||||
return nil, fmt.Errorf("rsvg-convert not found in PATH (required for PDF export)")
|
||||
}
|
||||
composite, err := BuildCompositeSVGSlots(plate, spec, slotSVGs, preview)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pdf, err := svgToPDFViaRsvg(composite, plate.WidthMM, plate.HeightMM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("render plate pdf: %w", err)
|
||||
}
|
||||
return pdf, nil
|
||||
}
|
||||
|
||||
@@ -64,7 +64,12 @@ func TestBuildCompositeSVG(t *testing.T) {
|
||||
func TestBuildCompositeSVGInvalid(t *testing.T) {
|
||||
requireRsvg(t)
|
||||
|
||||
_, err := BuildCompositeSVG(model.Plate{}, model.ItemSpec{}, []byte("not svg"), model.LayoutPreview{})
|
||||
preview := model.LayoutPreview{
|
||||
Positions: []model.LayoutPosition{{XMM: 0, YMM: 0}},
|
||||
CanvasWidthMM: 10,
|
||||
CanvasHeightMM: 10,
|
||||
}
|
||||
_, err := BuildCompositeSVG(model.Plate{}, model.ItemSpec{WidthMM: 10, HeightMM: 10}, []byte("not svg"), preview)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for invalid svg")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user