Spaces:
Sleeping
Sleeping
Alessandro Tomassini
deploy(hf): overlay README/Dockerfile da huggingface/, senza docs/binari/model
c42a5a1 | """Metodo B — rendering SVG server-side con rettangoli di redazione.""" | |
| from __future__ import annotations | |
| from xml.sax.saxutils import escape as xml_escape | |
| from pdf.rendering.base import ( | |
| MethodInfo, | |
| RenderKind, | |
| RenderMethod, | |
| RenderOutput, | |
| RenderParams, | |
| boxes_on_page, | |
| ) | |
| from pdf.rendering.styles import severity_rgb255 | |
| class SvgRenderMethod(RenderMethod): | |
| info = MethodInfo( | |
| key="svg", | |
| label="B · SVG", | |
| kind=RenderKind.VIEW, | |
| media_type="image/svg+xml", | |
| styles=("fill", "outline", "label"), | |
| default_style="fill", | |
| description=( | |
| "SVG vettoriale generato dal server con i riquadri incorporati. " | |
| "Geometria precisa, nessuna dipendenza client, testo selezionabile." | |
| ), | |
| ) | |
| def render(self, params: RenderParams) -> RenderOutput: | |
| import fitz | |
| doc = fitz.open(stream=params.pdf_bytes, filetype="pdf") | |
| page = doc.load_page(params.page) | |
| mat = fitz.Matrix(params.scale, params.scale) | |
| svg_text = page.get_svg_image(matrix=mat) | |
| page_w = page.rect.width * params.scale | |
| page_h = page.rect.height * params.scale | |
| doc.close() | |
| elements = self._build_elements(params) | |
| svg = svg_text.replace("</svg>", "\n".join(elements) + "\n</svg>") | |
| return RenderOutput( | |
| data=svg.encode("utf-8"), | |
| media_type=self.info.media_type, | |
| headers={ | |
| "X-Page-Width": f"{page_w:.1f}", | |
| "X-Page-Height": f"{page_h:.1f}", | |
| "Cache-Control": "private, max-age=300", | |
| }, | |
| ) | |
| def _build_elements(self, params: RenderParams) -> list[str]: | |
| out: list[str] = [] | |
| s = params.scale | |
| for b in boxes_on_page(params): | |
| r, g, bl = severity_rgb255(b.get("severity", "media")) | |
| color = f"rgb({r},{g},{bl})" | |
| x0, y0 = b["x0"] * s, b["y0"] * s | |
| w, h = (b["x1"] - b["x0"]) * s, (b["y1"] - b["y0"]) * s | |
| label = xml_escape(str(b.get("label", ""))) | |
| rect = f'x="{x0:.1f}" y="{y0:.1f}" width="{w:.1f}" height="{h:.1f}"' | |
| if params.style == "outline": | |
| out.append( | |
| f'<rect {rect} fill="none" stroke="{color}" stroke-width="2" ' | |
| f'rx="2" ry="2"><title>{label}</title></rect>' | |
| ) | |
| elif params.style == "label": | |
| fs = max(7.0, min(h * 0.7, 14.0)) | |
| out.append( | |
| f'<rect {rect} fill="{color}" opacity="{params.opacity}" rx="2" ry="2">' | |
| f'<title>{label}</title></rect>' | |
| f'<text x="{x0 + w / 2:.1f}" y="{y0 + h / 2 + fs / 3:.1f}" ' | |
| f'font-size="{fs:.1f}" fill="white" text-anchor="middle" ' | |
| f'font-family="sans-serif" font-weight="bold" ' | |
| f'pointer-events="none">{label}</text>' | |
| ) | |
| else: # fill | |
| out.append( | |
| f'<rect {rect} fill="{color}" opacity="{params.opacity}" ' | |
| f'rx="2" ry="2"><title>{label}</title></rect>' | |
| ) | |
| return out | |