Ubicación
racks/utils/visio_parser.py — función canónica de detección.
Propósito
Determinar si un SVG generado por libvisio-ng contiene ÚNICAMENTE un EMF incrustado sin ninguna geometría vectorial. Utilizado para identificar stencils de fabricante que requieren conversión a PNG.
Firma
def svg_is_emf_only(svg_text: str) -> bool:
Entrada
svg_text(str): contenido completo del SVG (puede tener errores de encoding, se ignoran).
Salida
True: el SVG tienedata:image/emf;base64,Y carece de cualquier etiqueta de geometría.False: el SVG es vectorial o está vacío.
Lógica
_EMF_DATA_RE = re.compile(r"data:image/emf;base64,([A-Za-z0-9+/=]+)")
_SVG_DRAW_TAGS = ("<path", "<rect", "<line", "<polyline", "<polygon", "<ellipse", "<circle", "<text")
def svg_is_emf_only(svg_text):
return bool(_EMF_DATA_RE.search(svg_text)) and not any(t in svg_text for t in _SVG_DRAW_TAGS)
Paso 1: regex busca patrón data:image/emf;base64, (se extrae el base64 pero no se valida aquí).
Paso 2: comprueba ausencia de TODAS las etiquetas vectoriales (búsqueda substring, case-sensitive).
Ambas condiciones deben ser True para retornar True.
Casos de uso
Detectar y agrupar
# En convert_emf_only_svgs()
for svg_name in svg_names:
with open(svg_path, encoding="utf-8", errors="ignore") as f:
text = f.read()
if svg_is_emf_only(text):
# → procesar este SVG (extraer EMF, convertir)
Validación post-conversión
# En tasks.py: verificar que no haya fallados
unconverted = [n for n in image_files
if n.endswith(".svg") and svg_is_emf_only(_read_svg(temp_dir, n))]
# Si len(unconverted) > 0, descartar esos masters
Tests
def test_emf_only_is_detected():
svg = '<svg xmlns="x"><image href="data:image/emf;base64,AQ=="/></svg>'
assert svg_is_emf_only(svg) is True
def test_vector_content_is_not_emf_only():
mixed = '<svg xmlns="x"><path d="M0 0"/><image href="data:image/emf;base64,AQ=="/></svg>'
assert svg_is_emf_only(mixed) is False
Falsos negativos (SVG que DEBERÍA detectarse pero no)
- EMF con geometría adicional (dibujado Visio + copiar-pegar de imagen):
.svg_is_emf_only()retornaFalse, se procesa como vectorial.- Impacto: bajo, el SVG es renderizable igualmente.
Falsos positivos (SVG que NO DEBERÍA detectarse pero sí)
- Improbables: requerirían un
data:image/emfen comentario o atributo sin etiquetas vectoriales.
Rendimiento
O(n) donde n = longitud del SVG:
- Una búsqueda regex (lineal).
- Hasta 8 búsquedas substring (lineal).
- Total: ~9 pasadas al texto sin compilación costosa.
Típicamente <1 ms incluso para SVGs de 1 MB.
Integración
- Punto de entrada:
convert_emf_only_svgs()(línea ~40). - Validación post-conversión:
racks/tasks.py(línea ~115). - Tests:
tests/api/test_visio_import_v2.py::TestEmfOnlyDetection. - QA real:
tests/qa/test_visio_real_vendor_files.py::test_real_vsdx_converts_and_imports.
Véase también
- [[entity—racks—service—emf-converter]]
- [[feature—stencils—visio-emf-to-png]]
- [[entity—racks—model—stencil]]