mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-02-28 21:59:13 +00:00
terminados primeras modificaciones
This commit is contained in:
@ -6,6 +6,8 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Locale;
|
||||
|
||||
@ -42,6 +44,15 @@ import com.imprimelibros.erp.presupuesto.maquetacion.MaquetacionMatricesReposito
|
||||
import com.imprimelibros.erp.presupuesto.marcapaginas.MarcapaginasRepository;
|
||||
import com.imprimelibros.erp.users.UserDao;
|
||||
|
||||
import org.apache.batik.transcoder.TranscoderInput;
|
||||
import org.apache.batik.transcoder.TranscoderOutput;
|
||||
import org.apache.batik.transcoder.image.PNGTranscoder;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.imprimelibros.erp.externalApi.skApiClient;
|
||||
@ -1300,7 +1311,7 @@ public class PresupuestoService {
|
||||
public Map<String, Object> obtenerLomos(Presupuesto presupuesto) {
|
||||
try {
|
||||
Map<String, Object> response = apiClient.getLomos(this.toSkApiRequest(presupuesto));
|
||||
|
||||
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error obteniendo lomos: " + e.getMessage());
|
||||
@ -1308,6 +1319,65 @@ public class PresupuestoService {
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] obtenerPlantillaCubierta(
|
||||
Presupuesto.TipoEncuadernacion tipoLibro,
|
||||
Presupuesto.TipoCubierta tapa,
|
||||
Integer ancho,
|
||||
Integer alto,
|
||||
Integer lomo,
|
||||
Integer solapas,
|
||||
Locale locale) {
|
||||
|
||||
try {
|
||||
String plantillaName = "plantilla";
|
||||
if (tipoLibro == Presupuesto.TipoEncuadernacion.grapado) {
|
||||
plantillaName += "-grapado";
|
||||
}
|
||||
if (solapas > 0) {
|
||||
plantillaName += "-solapas";
|
||||
}
|
||||
plantillaName += ".svg";
|
||||
|
||||
Integer sangrado = 5; // mm,
|
||||
if (tapa != Presupuesto.TipoCubierta.tapaBlanda && tipoLibro != Presupuesto.TipoEncuadernacion.grapado) {
|
||||
sangrado = 20;
|
||||
}
|
||||
|
||||
Integer ancho_t = lomo + sangrado * 2 + ancho * 2 + solapas * 2;
|
||||
Integer alto_t = alto + sangrado * 2;
|
||||
|
||||
// 3) Leer SVG template como texto
|
||||
String basePath = "static/assets/images/imprimelibros/presupuestador/templates-cubierta/";
|
||||
String svg = readClasspathText(basePath + plantillaName);
|
||||
|
||||
// 4) Sustituciones {{...}}
|
||||
Map<String, String> vars = new HashMap<>();
|
||||
NumberFormat nf = NumberFormat.getIntegerInstance(locale);
|
||||
|
||||
vars.put("ancho", nf.format(ancho)); // mm o lo que representes
|
||||
vars.put("alto", nf.format(alto));
|
||||
vars.put("ancho_t", nf.format(ancho_t));
|
||||
vars.put("alto_t", nf.format(alto_t));
|
||||
vars.put("lomo_t", nf.format(lomo != null ? lomo : 0));
|
||||
vars.put("solapa_t", nf.format(solapas != null ? solapas : 0));
|
||||
vars.put("sangrado", nf.format(sangrado));
|
||||
vars.put("portada", messageSource.getMessage("presupuesto.plantilla-cubierta.portada", null, locale));
|
||||
vars.put("contraportada",
|
||||
messageSource.getMessage("presupuesto.plantilla-cubierta.contraportada", null, locale));
|
||||
vars.put("lomo", messageSource.getMessage("presupuesto.plantilla-cubierta.lomo", null, locale));
|
||||
vars.put("solapa", messageSource.getMessage("presupuesto.plantilla-cubierta.solapa", null, locale));
|
||||
svg = replaceMustache(svg, vars);
|
||||
|
||||
// 5) Render SVG -> PNG (Batik)
|
||||
svg = sanitizeForBatik(svg);
|
||||
return svgToPng(svg, /* dpi */ 300f);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error obteniendo plantilla de cubierta: " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PRIVADO (futuro botón "Guardar"): persiste el presupuesto como borrador.
|
||||
*/
|
||||
@ -1551,4 +1621,77 @@ public class PresupuestoService {
|
||||
return ip;
|
||||
}
|
||||
|
||||
private static String readClasspathText(String path) throws IOException {
|
||||
ClassPathResource res = new ClassPathResource(path);
|
||||
try (InputStream in = res.getInputStream()) {
|
||||
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
private static String replaceMustache(String svg, Map<String, String> vars) {
|
||||
String out = svg;
|
||||
for (var entry : vars.entrySet()) {
|
||||
out = out.replace("{{" + entry.getKey() + "}}", entry.getValue());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static byte[] svgToPng(String svgXml, float dpi) throws Exception {
|
||||
PNGTranscoder t = new PNGTranscoder();
|
||||
|
||||
// Esto SÍ es correcto (convierte unidades a mm según DPI)
|
||||
t.addTranscodingHint(PNGTranscoder.KEY_PIXEL_UNIT_TO_MILLIMETER, 25.4f / dpi);
|
||||
|
||||
// ❌ NO uses KEY_AOI con null (provoca tu error)
|
||||
// t.addTranscodingHint(PNGTranscoder.KEY_AOI, null);
|
||||
|
||||
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||
TranscoderInput input = new TranscoderInput(new StringReader(svgXml));
|
||||
TranscoderOutput output = new TranscoderOutput(out);
|
||||
t.transcode(input, output);
|
||||
return out.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static String sanitizeForBatik(String svg) {
|
||||
String out = svg;
|
||||
|
||||
// 1) Batik: context-stroke/context-fill
|
||||
out = out.replace("context-stroke", "#000");
|
||||
out = out.replace("context-fill", "none");
|
||||
|
||||
// 2) Batik: auto-start-reverse
|
||||
out = out.replace("auto-start-reverse", "auto");
|
||||
|
||||
// 3) Reemplazar markers Triangle*/marker6* -> Arrow2S*
|
||||
out = replaceMarkerAttr(out, "marker-start", "Arrow2Sstart");
|
||||
out = replaceMarkerAttr(out, "marker-end", "Arrow2Send");
|
||||
|
||||
// 4) Lo MISMO pero cuando viene dentro de style="...marker-start:url(#X);..."
|
||||
out = replaceMarkerInStyle(out, "marker-start", "Arrow2Sstart");
|
||||
out = replaceMarkerInStyle(out, "marker-end", "Arrow2Send");
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private static String replaceMarkerAttr(String svg, String attr, String newId) {
|
||||
// Soporta: marker-start="url(#Triangle-5)" o marker-start='url( #Triangle-5 )'
|
||||
Pattern p = Pattern.compile(
|
||||
"(" + attr
|
||||
+ "\\s*=\\s*)([\"'])\\s*url\\(\\s*#(Triangle[^\\s\\)\"']*|marker6[^\\s\\)\"']*)\\s*\\)\\s*\\2",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = p.matcher(svg);
|
||||
return m.replaceAll("$1$2url(#" + newId + ")$2");
|
||||
}
|
||||
|
||||
private static String replaceMarkerInStyle(String svg, String prop, String newId) {
|
||||
// Soporta dentro de style: marker-start:url(#Triangle-5) (con espacios
|
||||
// opcionales)
|
||||
Pattern p = Pattern.compile(
|
||||
"(" + prop + "\\s*:\\s*)url\\(\\s*#(Triangle[^\\s\\)\"';]*|marker6[^\\s\\)\"';]*)\\s*\\)",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = p.matcher(svg);
|
||||
return m.replaceAll("$1url(#" + newId + ")");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user