CreaRack-SL

Función: svg_is_emf_only() — Detectar SVGs con solo arte EMF

Entidadactivecreado Mon Jul 13#racks#stencils#detection#regex#emf#svg

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 tiene data: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() retorna False, 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/emf en 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]]