svg-playground

Escribir un dibujo
para entender la máquina

Un taller de 3 horas donde no se aprende SVG. Se aprende ciencias de la computación, y SVG es el bisturí porque un dibujo vectorial no es un blob de píxeles: es un documento XML que se escribe con printf, se versiona con git y se lee como cualquier otro texto. No hace falta ninguna herramienta de dibujo. El renderer es el navegador que ya tenés abierto.

Duración
3 horas
Nivel
Cero conocimiento de SVG. Terminal básica y un navegador.
Herramientas
printf, un navegador, un editor de texto
Te llevás
Un editor de SVG en vivo que entendés línea por línea, y la certeza de que dibujar es escribir
Un círculo cian sobre fondo negro, dibujado dentro de un cuadrado de coordenadas de 100 por 100 unidades
Esto es mano.svg: 116 bytes escritos con printf, sin ningún programa de dibujo. Es el archivo completo, no un recorte. El módulo 0 lo escribe de nuevo, a mano, en el editor de abajo.

01 La idea

El primer taller de esta serie rompía video para ver a un decodificador alucinar píxeles que nunca existieron. El segundo le mentía a la cabecera de una imagen para ver la misma clase de mentira fallar fuerte en una dirección y en silencio en la otra. Los dos trabajaban sobre formatos binarios: para leerlos hacía falta un programa que supiera dónde termina un campo y empieza el siguiente.

Este taller cambia el material, no el método. SVG es XML: texto plano, sin ningún campo binario, sin ningún byte que solo un programa especializado pueda interpretar. Eso cambia todo lo que se puede hacer con un dibujo. Se escribe con printf. Se versiona con git línea por línea. Y se diffea, en serio, no como curiosidad: el módulo 5 mide cuánto cuesta exactamente perder esa propiedad.

El módulo 7 cierra algo que viene de los dos talleres anteriores. En el taller de video, un fotograma clave faltante hacía que el decodificador alucinara píxeles. En el taller de imágenes, una cabecera mentirosa corría la imagen en silencio en una dirección y fallaba fuerte en la otra. Acá vas a romper el mismo byte de dos maneras — o mejor dicho, la misma manera, leída por dos parsers distintos — y uno se va a negar a leerlo con número de línea y columna, mientras el otro te lo arregla sin decir nada y dibuja igual. Tres talleres, tres filosofías de falla, y la diferencia nunca estuvo en el archivo. Siempre estuvo en quién lo lee.

02 Preparación

Antes de arrancar, cada persona necesita esto resuelto. No gastes tiempo del taller instalando cosas — de hecho, no hay nada que instalar.

Dos scripts, ya en el repo, hacen el trabajo mecánico para que el taller se dedique a leer y escribir, no a pelear con la terminal:

./scripts/gen-media.sh   # genera todos los .svg de media/ desde cero con printf y bucles de shell
./scripts/romper.sh media/mano.svg   # rompe un carácter y produce roto.svg + roto.html — el módulo 7

gen-media.sh no dibuja nada con un programa de dibujo: escribe cada .svg con printf o con un bucle for de shell, y al final imprime la tabla de bytes que este sitio cita. La única excepción es espiral-200.png, el raster de comparación del módulo 6: ese sí necesita un rasterizador, y como no hay ninguno instalado, el script prueba rsvg-convert, después inkscape, y si tampoco están usa un Chromium sin cabeza para sacarle una captura de pantalla al propio SVG. El renderer es el navegador incluso para generar el material del taller.

romper.sh le saca un solo carácter a un SVG con cierre propio (/>) y deja el mismo markup roto servido de dos maneras: como roto.svg y como roto.html. El módulo 7 abre los dos y compara cómo los lee cada parser.

04 El taller

Nueve módulos, 3 horas, terminal y un navegador. Cada módulo tiene la misma estructura: un concepto de ciencias de la computación, algo que hacés con las manos, y el momento en que las dos cosas encajan.

Módulo 0

Un dibujo de 116 bytes

15 min

Concepto Representación mínima de datos, XML como formato de dibujo

printf '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" fill="#4fd9e8"/></svg>\n' > mano.svg
wc -c mano.svg
116 mano.svg

mano.svg pesa 116 bytes y es un dibujo completo: un círculo cian de radio 40 dentro de un lienzo de 100 por 100 unidades. Ningún programa de dibujo estuvo involucrado. El navegador lo abre directo — probalo con doble clic o arrastrándolo a una pestaña.

El favicon de esta misma página es el mismo truco: favicon.svg pesa 192 bytes y se referencia así, sin conversión a ningún formato binario:

<link rel="icon" href="favicon.svg" type="image/svg+xml">

Ahora escribilo de nuevo, a mano, en el editor de abajo — es el mismo mano.svg, prellenado. Borrá algo, cambiá el radio, mirá qué pasa. La última línea de este módulo es el widget: escribís texto y aparece un dibujo, en vivo.

El momento Borrá el / antes del > de cierre del circle y mirá la línea de estado: el mismo parser estricto que va a protagonizar el módulo 7 ya está corriendo en este editor, en tiempo real, cada vez que tipeás.

Módulo 1

El viewBox es un sistema de coordenadas

20 min

Concepto Sistemas de coordenadas anidados, unidades de usuario

viewBox="0 0 100 100" no es un tamaño en píxeles: es una declaración de unidades de usuario, un sistema de coordenadas propio del dibujo. Sin width ni height, el SVG escala para llenar el contenedor donde lo pongas — por eso todos los dibujos de este sitio están escritos así a propósito: para que se incrusten de forma responsiva, sin media queries por dibujo.

Eso significa que hay al menos dos sistemas de coordenadas superpuestos: el interno, en unidades de usuario (los números que escribís en cx, r, d), y el externo, en píxeles de pantalla. La matriz que traduce uno al otro se llama CTMcurrent transformation matrix — y se puede leer, no solo intuir.

matriz.svg (374 bytes), incrustado directo como markup en esta página en vez de como <img>, para que puedas abrir la consola y llamar getCTM() sobre él de verdad. Su viewBox es 0 0 200 200. Medido con este mismo dibujo en un contenedor de 400 px de ancho (2× el viewBox, porque 400/200 = 2): la matriz que escribiste en el grupo amano, en unidades de usuario, es [0,8660254, 0,5, -0,5, 0,8660254, 34,641016, 20]. Lo que devuelve getCTM() ahí es [1,7321, 1, -1, 1,7321, 69,282, 40] — cada componente al doble, redondeando a cuatro decimales. Lo que pasa más allá del cuarto decimal lo mide el módulo 3, y no es lo que esperarías. Si tu ventana es angosta, abrí las devtools y forzá el ancho a 400 px para reproducir estos números dígito por dígito.

Ese factor 2 no es un redondeo ni una coincidencia de esta página: es la definición de viewBox funcionando. El navegador compone tu matriz con la suya — la que traduce las 200 unidades del viewBox al ancho real del contenedor — y getCTM() te devuelve el resultado ya multiplicado. Es la demostración más limpia que hay de que "sistema de coordenadas anidado" no es una frase abstracta: es un número que podés leer en la consola.

El momento Nunca hay un solo sistema de coordenadas en un SVG. Hay como mínimo dos, y getCTM() es la ventana a la matriz que los conecta. El módulo 3 va a mostrar que esa misma matriz también puede escribirse a mano, número por número.

Módulo 2

El atributo d es un lenguaje

25 min

Concepto DSL embebido, parsing declarativo, interpretación de una cadena

cat > camino.svg <<'EOF'
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 120">
  <path d="M 20 100 L 60 30 L 100 100 Z" fill="none" stroke="#4fd9e8" stroke-width="3"/>
  <path d="M 120 100 C 140 20, 180 20, 200 100" fill="none" stroke="#f26fc0" stroke-width="3"/>
  <path d="M 220 100 Q 250 10, 280 100" fill="none" stroke="#6fd88a" stroke-width="3"/>
</svg>
EOF
Tres trazos sobre fondo negro: un triángulo abierto cian a la izquierda, una curva de Bézier cúbica magenta en el medio, una curva cuadrática verde a la derecha
camino.svg, 343 bytes, tres path.

Cada letra de d es un comando de un lenguaje chico: M mueve el lápiz sin dibujar (moveto), L dibuja una recta (lineto), C dibuja una curva de Bézier cúbica con dos puntos de control, Q una cuadrática con uno solo, y Z cierra la figura volviendo al punto de partida. Medido con getTotalLength() sobre cada uno de los tres path de arriba:

pathdlargo
rectaM 20 100 L 60 30 L 100 100 Z241
cúbicaM 120 100 C 140 20, 180 20, 200 100153
cuadráticaM 220 100 Q 250 10, 280 100113

Ese número no está adivinado ni interpolado a ojo: getTotalLength() hace que el navegador mida, en unidades de usuario, la longitud real de una curva que parseó de una cadena de caracteres. La cadena "M 120 100 C 140 20, 180 20, 200 100" es un programa chico, con su propia sintaxis y su propio conjunto de comandos, y el navegador tiene un intérprete de ese programa integrado en el motor de renderizado. Un DSL completo, viviendo adentro de un atributo.

El momento No hay una "forma curva" guardada en algún lado: hay una cadena de texto que un intérprete lee, comando por comando, y convierte en geometría. El atributo d es la prueba más chica y más legible que existe de qué es un lenguaje de dominio específico con su propio parser.

Módulo 3

transform es una matriz

25 min

Concepto Álgebra lineal como sintaxis de atributo, composición de matrices

La sintaxis amigable de transformrotate, translate, scale— no es una capa por encima de algo más simple: es azúcar sintáctico sobre una matriz afín de 2×3, y el navegador la compila a esa matriz antes de dibujar nada. rotate(30) translate(40 0) compone, en unidades de usuario, exactamente a:

matrix(0.8660254 0.5 -0.5 0.8660254 34.641016 20)

La cuenta a mano: rotate(30) es la matriz [cos30, sin30, -sin30, cos30, 0, 0] = [0,866, 0,5, -0,5, 0,866, 0, 0]. Componer translate(40 0) encima multiplica esa traslación por la parte rotada de la matriz: e = 0,866 × 40 = 34,641 y f = 0,5 × 40 = 20. Nada de esto es magia del navegador — es la multiplicación de matrices de toda la vida, aplicada dos veces y sumada.

Volvé a mirar el dibujo incrustado en el módulo 1: el grupo compuesto usa la sintaxis amigable, el grupo amano usa los seis números crudos de arriba, y en pantalla se superponen sin que se vea un solo píxel de diferencia. Pero medilos con getCTM() y no son idénticos. Estos son los cuatro componentes de escala y rotación, medidos:

compuesto  1.7320508075688774   0.9999999999999999  -0.9999999999999999   1.7320508075688774
amano      1.732050895690918    1                   -1                    1.732050895690918
diferencia máxima: 0.000003524881620364795

Tres cosas para mirar de esa salida, y ninguna es un error del navegador:

  • El 1 que no es 1. rotate(30) debería dar sin 30 = 0,5 exacto. En aritmética de punto flotante sin(30°) vale 0,49999999999999994, y por eso el componente aparece como 0,9999999999999999 después de escalar. No es el SVG: probá Math.sin(30 * Math.PI / 180) en cualquier consola y en Python te da lo mismo.
  • Se separan en el sexto decimal. La diferencia máxima es 3,52 × 10⁻⁶ de unidad de usuario. Componer dos matrices y multiplicarlas en el momento no acumula el mismo redondeo que escribir el producto ya hecho. Son dos caminos aritméticos al mismo lugar.
  • Escribir más decimales no cambia nada. Verificado: matrix(0.8660254 ...) y matrix(0.8660254037844387 ...) devuelven resultados byte a byte iguales. Los números de los atributos se guardan con precisión reducida, así que a partir del séptimo dígito estás escribiendo decoración.

Y aun así: 3,5 millonésimas de unidad de usuario, en un dibujo de 200 unidades de lado, es una fracción invisible de un píxel. Se superponen perfectamente a la vista porque el error es del orden del redondeo, no de la geometría. La conclusión sigue en pie y ahora está medida en vez de afirmada.

Esta misma matriz de 2×3 ya la usaste en otra forma, en el taller anterior de esta serie. En pixel-playground escribiste un kernel de convolución de 3×3: una matriz chica que se desliza sobre una imagen. Son la misma clase de objeto matemático haciendo trabajos distintos. El kernel de convolución combina los valores de los píxeles vecinos — multiplica y suma intensidades. La matriz afín de transform reubica coordenadas — multiplica y suma posiciones. Una opera sobre qué tan brillante es un punto; la otra, sobre dónde está. Multiplicar-y-sumar es el núcleo de las dos, y es el núcleo de casi toda la computación gráfica.

El momento rotate(), translate() y scale() no son primitivas independientes: son nombres legibles para casos particulares de una única matriz de 2×3. Escribirla a mano, número por número, y verla caer encima de la versión legible con un error de una millonésima es la prueba de que no hay dos sistemas — hay uno solo, con dos formas de nombrarlo y dos caminos de redondeo para llegar.

Módulo 4

Dibujar con un for

20 min

Concepto Generación procedural, programa como dibujo

for i in $(seq 1 60); do
  printf '  <circle cx="100" cy="100" r="%d" fill="none" stroke="#4fd9e8" stroke-opacity="0.35" transform="rotate(%d 100 100) translate(%d 0)"/>\n' \
    "$((100 - i))" "$((i * 6))" "$((i / 2))"
done >> espiral.svg
Espiral formada por 60 círculos concéntricos sin relleno, cada uno rotado y desplazado un poco más que el anterior, en trazo cian translúcido sobre fondo negro
espiral.svg, 8.194 bytes, 60 elementos circle. Cada uno con un radio, una rotación y una traslación un poco distintas de la del anterior — el bucle de shell de arriba, ejecutado una vez por cada i de 1 a 60.

Ningún programa de dibujo estuvo involucrado en ningún paso. El bucle no generó una imagen que después se convirtió a SVG: generó directamente el texto del SVG, línea por línea, con la misma herramienta con la que un script genera cualquier otro archivo de texto. path del módulo 2 y transform del módulo 3 son lo único que hizo falta aprender para que esto sea posible.

El momento Un dibujo generativo no necesita un lenguaje de shaders ni un motor de partículas. Necesita una forma, un atributo que varíe con el índice del bucle, y printf. La distancia entre "escribir un archivo de texto" y "escribir un programa que dibuja" es más chica de lo que parece.

Módulo 5

Versionar un dibujo

25 min — el módulo central

Concepto Control de versiones, granularidad de diff, formato como decisión funcional

El mismo dibujo, ocho círculos, escrito de dos formas. Un elemento por línea:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
  <circle cx="22" cy="100" r="12" fill="#4fd9e8"/>
  <circle cx="44" cy="100" r="12" fill="#4fd9e8"/>
  ...
</svg>

Y la misma información, minificada a una sola línea. El contenido es idéntico; lo único que cambia es dónde caen los saltos:

Ocho círculos cian del mismo tamaño en fila horizontal sobre fondo negro
multi.svg 482 bytes, 10 líneas — un elemento por línea.
Los mismos ocho círculos cian del mismo tamaño en fila horizontal sobre fondo negro, geométricamente idénticos al anterior
multi-min.svg 465 bytes, 1 línea — mismo dibujo, minificado.

Geométricamente son el mismo dibujo: los mismos ocho círculos, en los mismos cx, con el mismo r. Ahora cambiá el radio del cuarto círculo de 12 a 30. En multi.svg, ese es 1 línea cambiada de 10, y el diff muestra exactamente eso:

@@ -5 +5 @@
-  <circle cx="88" cy="100" r="12" fill="#4fd9e8"/>
+  <circle cx="88" cy="100" r="30" fill="#4fd9e8"/>

El mismo cambio en la versión de una sola línea es 1 línea cambiada de 1 — porque solo hay una línea. git diff no tiene ninguna línea más chica en la que fijarse: reimprime el dibujo entero dos veces, una como borrado y una como agregado, y revisar ese diff a ojo es imposible. No hay forma de ver, mirando el diff, que el único cambio real fue un 12 que pasó a 30.

Minificar ahorró 17 bytes, un 3,5 %, y a cambio costó la capacidad entera de revisar un cambio. Ese no es un argumento de gusto ni de estilo de código: es un número medido, y dice que en este caso el ahorro de espacio no vale ni de cerca lo que cuesta.

El momento git diffea líneas, no dibujos ni significado. Si el formato pone un elemento por línea, un cambio quirúrgico se ve quirúrgico. Si lo aplasta todo a una línea, el mismo cambio se ve como si se hubiera reescrito todo. El salto de línea no es un detalle cosmético: es una decisión funcional sobre si el control de versiones te va a servir de algo. Ningún taller de este tipo sobre imágenes raster puede correr este módulo — un PPM o un PNG no tienen líneas que diffear, tienen bytes de una grilla. Esto es exclusivo de que el dibujo sea texto.

Módulo 6

Receta contra resultado

20 min

Concepto Representación por regla vs. representación por muestra, independencia de resolución

El mismo dibujo de 60 círculos del módulo 4, exportado a raster a tres tamaños distintos, contra el peso del propio SVG:

renderPNGSVGPNG/SVG
200×20049.7948.1946,08×
800×800415.1168.19450,66×
2000×20001.390.5228.194169,70×

El SVG pesa 8.194 bytes en las tres filas. No cambia. El PNG crece aproximadamente con el área — de 200×200 a 2000×2000 el área se multiplica por 100, y el PNG por casi 28. La razón de la diferencia no es un detalle de compresión: es que el SVG no guarda una imagen, guarda una receta — 60 elementos circle con sus atributos — y esa receta se ejecuta en el momento de dibujar, a cualquier resolución que pida el dispositivo. El PNG, en cambio, guarda el resultado de ejecutar esa receta una vez, congelado en una grilla de píxeles de un tamaño fijo.

La espiral de 60 círculos como SVG, trazo nítido a cualquier tamaño
SVG 8.194 bytes, a cualquier tamaño.
La misma espiral de 60 círculos como PNG de 200 por 200, generada con un rasterizador headless
PNG 49.794 bytes, fijo a 200×200.

Mostrados al mismo tamaño en CSS, escalá la página del navegador hacia arriba y mirá los dos: el SVG se mantiene nítido, el PNG empieza a mostrar sus píxeles.

Esto es la misma familia de idea que pixel-playground, módulo 5, donde cuantizar una imagen a 2 colores no le sacaba un solo byte al PPM crudo — el formato reserva espacio fijo por píxel sin importar cuánta información real hay adentro. Ahí la lección era que menos información no es menos bytes. Acá es la otra cara de la misma moneda: lo que un archivo guarda y lo que representa son preguntas distintas, y la independencia de resolución del SVG es la versión más extrema y más medible de esa distinción que vas a ver en todo el taller.

El momento Guardar una receta en vez de un resultado no es una optimización de espacio que a veces funciona: es una propiedad estructural que se sostiene siempre, y la tabla de arriba la vuelve un número concreto en vez de una promesa de marketing sobre "gráficos vectoriales".

Módulo 7

El mismo error, dos parsers

15 min — el cierre de la serie

Concepto Parsing estricto vs. permisivo, ley de Postel, modelos de amenaza distintos

./scripts/romper.sh media/mano.svg

El script le saca exactamente un carácter a mano.svg — el / del cierre propio de <circle ... />. 116 bytes se convierten en 115 bytes. Con eso escribe dos archivos, roto.svg y roto.html, con el mismo markup inválido adentro, servido de dos maneras distintas.

Abrí roto.svg. El parser de XML es estricto y lo rechaza: document.documentElement.tagName pasa a ser html — el documento SVG fue reemplazado por una página de error — aparece un elemento parsererror, y el mensaje dice, con línea y columna exactas:

This page contains the following errors: error on line 1 at column 114: Unexpected closing tag: {http://www.w3.org/2000/svg}svg != ...

Abrí roto.html, el mismo markup exacto, servido como HTML. Ahí no hay parsererror: el círculo está en el DOM, r="40" se lee de vuelta correctamente, y pinta 599 px de ancho. El parser de HTML cerró el tag por vos, en silencio, y dibujó.

Nótese la precisión de la afirmación: no es que la versión XML "no dibuje nada". La página de error de Chromium sí muestra un árbol con el código fuente. Lo verificado y defendible es esto: en un caso, el elemento raíz pasa a ser html, aparece parsererror, y se reporta línea y columna. En el otro, no hay error y el círculo se renderiza.

Esto es la ley de Postel en 115 bytes: sé liberal en lo que aceptás. HTML eligió ser liberal porque la primera web estaba llena de páginas escritas a mano, con errores, por gente que nunca leyó una especificación. XML eligió ser estricto porque se diseñó para que máquinas intercambiaran datos entre sí, sin un humano mirando en el medio. Ninguna de las dos decisiones está mal — tienen modelos de amenaza distintos. ffmpeg-playground hizo exactamente este argumento sobre decodificadores de video: un decodificador tolera un paquete perdido porque cortar una videollamada es peor que degradarla, mientras que un handshake de TLS aborta ante el primer byte inesperado porque ahí la permisividad es la vulnerabilidad. La pregunta es siempre la misma — cuánta permisividad tolerar — y la respuesta correcta depende de quién está leyendo y para qué.

El momento Esto cierra la serie. En ffmpeg-playground, un fotograma clave faltante hizo que el decodificador alucinara — dibujó algo, pero no lo que había. En pixel-playground, una cabecera mentirosa corrió la imagen en silencio en una dirección y falló fuerte en la otra. Acá, el mismo byte roto se rechaza con línea y columna por un parser y se repara en silencio por el otro. Tres talleres, tres formas distintas de fallar, y en ningún caso la diferencia estuvo en el archivo. Siempre estuvo en el programa que lo lee.

Módulo 8

Exportar y nombrar

5 min

Concepto Cierre y evaluación

Cada persona guarda el dibujo que más le gustó de todo el taller. No hace falta convertirlo a nada: ya es el archivo final, el mismo que se puede abrir, leer y editar con un editor de texto común.

Y antes de mostrarlo, dice una sola frase: qué parte de su dibujo es receta y no resultado — un transform, un bucle, un path que reutilizó. Esa frase es toda la evaluación del taller. Si puede decirla, entendió que el dibujo es texto y que eso no es un detalle técnico sino la razón por la que todo lo anterior funcionó. Si no puede, el dibujo queda igual de lindo — pero volvemos 10 minutos al módulo 3.

El momento El que aparece cuando alguien mira el archivo de otro y dice, sin que se lo pidan, "esto lo podés versionar". Ahí dejaron de ver una imagen y empezaron a ver un documento.

05 Para seguir

Ordenado por dificultad. El primero es el que más enseña.

  1. Animar el mismo SVG con SMIL y con CSS, comparar

    Tomá cualquier dibujo del taller y animalo dos veces: una con animate/animateTransform declarados adentro del propio SVG (SMIL), y otra con @keyframes en una hoja de estilos aparte (CSS). Mismo resultado visual, mecanismos completamente distintos — uno vive en el documento del dibujo, el otro en la hoja de estilos que lo rodea.

  2. potrace: el puente de vuelta a pixel-playground

    potrace convierte un bitmap en curvas vectoriales — el camino inverso al de todo este taller, que escribió el vector directamente. Tomá una imagen tramada a un bit del taller de netpbm de esta serie y pasala por potrace: es el gancho de vuelta a la parada anterior.

  3. Un gráfico desde datos reales con awk y printf

    Tomá una columna de números de cualquier archivo real y generá un path o una serie de rect con awk, calculando posiciones, y printf, escribiendo el SVG. Es el módulo 4 de este taller aplicado a datos que te importan, en vez de a una espiral decorativa.

  4. Filtros SVG como puente a los shaders

    Una cadena de feGaussianBlur, feColorMatrix y feDisplacementMap dentro de un filter es un grafo de operaciones sobre píxeles, muy parecido en estructura a un fragment shader. Escribir el mismo efecto en los dos lenguajes es la puerta de entrada a por qué existe WebGL.

  5. Escribir a mano el glifo de una letra como path

    Elegí una letra de tu nombre y escribí su contorno como un único path, a mano, con los comandos del módulo 2. Es el ejercicio más lento de esta lista y el que más deja: una fuente tipográfica es, literalmente, una colección de path con metadatos encima.

06 Glosario

Estas son las traducciones que usamos, con el término original al lado para que puedan googlear.

Vectorial vector graphics
Una imagen descrita como formas y coordenadas, no como una grilla de píxeles. Se recalcula al dibujar, a cualquier tamaño.
Raster raster
Una imagen descrita como una grilla fija de píxeles. El resultado congelado de dibujar algo una vez, a un tamaño.
viewBox
La declaración del sistema de coordenadas interno de un SVG: qué región, en qué unidades, se va a mostrar.
Unidades de usuario user units
Las unidades del sistema de coordenadas interno declarado por viewBox. No son píxeles de pantalla hasta que algo las traduce.
Sistema de coordenadas coordinate system
El acuerdo sobre qué significa cada número de posición. Un SVG tiene al menos dos anidados: el interno y el de pantalla.
Matriz afín affine matrix
Una matriz de 2×3 que combina rotación, escala y traslación en una sola operación. Lo que hay detrás de cada transform.
CTM current transformation matrix
La matriz acumulada que traduce las coordenadas de un elemento a coordenadas de pantalla. Se lee con getCTM().
path
El elemento que dibuja cualquier forma arbitraria a partir de una secuencia de comandos en su atributo d.
Comando de path path command
Cada letra del lenguaje de d: M moveto, L lineto, C cúbica, Q cuadrática, Z cerrar.
Bézier
Familia de curvas definidas por puntos de control. C es cúbica (dos puntos de control), Q es cuadrática (uno).
XML extensible markup language
El lenguaje de marcado del que SVG es un dialecto. Reglas estrictas de sintaxis: todo tag que abre, cierra.
Buen formato / well-formed
Un documento XML que respeta todas las reglas de sintaxis: tags balanceados, atributos entre comillas, un solo elemento raíz. Sin eso, el parser de XML se niega.
Parser estricto strict parser
Un parser que aborta ante la primera violación de sintaxis, en vez de intentar adivinar qué quiso decir el archivo. El parser de XML del módulo 7.
Parser permisivo lenient parser
Un parser que repara errores comunes en silencio para producir un resultado igual. El parser de HTML del módulo 7.
Ley de Postel Postel's law, robustness principle
"Sé liberal en lo que aceptás, conservador en lo que enviás". Explica por qué HTML perdona y XML no — no es un error de diseño, es un modelo de amenaza distinto.
Minificar minify
Sacarle espacios y saltos de línea a un archivo de texto sin cambiar lo que significa. Ahorra bytes; el módulo 5 mide qué cuesta.
Granularidad de diff diff granularity
Qué tan chica es la unidad mínima que un sistema de control de versiones puede mostrar como cambiada. En git, esa unidad es la línea.
Independencia de resolución resolution independence
La propiedad de un formato de representar lo mismo sin importar a qué tamaño se dibuje. El SVG la tiene; el PNG no.