
793 pares confundibles que faltan en Unicode TR39, conjunto de datos pionero entre scripts, puntuación SSIM con conciencia de fuentes en 230 fuentes y más de 22,000+ caracteres
Puntuación empírica de similitud de glifos mediante raycasting de contornos vectoriales. Renderiza pares de caracteres confusables Unicode en 245 fuentes del sistema, mide la similitud estructural directamente a partir de los contornos de las fuentes (sin rasterización) y produce artefactos JSON con puntuaciones de distancia continua por fuente.
Resultados clave de 52,6 millones de comparaciones de un solo carácter y 190 millones de comparaciones de múltiples caracteres en 22.581 caracteres y 12 sistemas de escritura:
La salida se alimenta directamente en namespace-guard para la detección en tiempo real de confusables en nombres de paquetes, nombres de dominio e identificadores.
RaySpace proyecta rayos paralelos a través de los contornos de las fuentes en 36 ángulos y captura cinco capas de información por glifo: recuentos de cruces, posiciones de cruces, ángulos de cruce, distancias ping (ancho del trazo en cada cruce) y ping máximo (ancho del contador entre cruces). Esto produce una firma compacta por carácter y por fuente. Dos firmas se comparan con una distancia L1 ponderada en las cinco capas.
Un filtro en cascada de tres etapas hace factible la comparación exhaustiva:
El banco de firmas (294,646+ entradas en 245 fuentes; más con --include-uppercase) se precalcula una vez. El descubrimiento se ejecuta como aritmética de un solo hilo en el banco, completando 52,6 millones de comparaciones de pares en 31 minutos sin hilos de trabajo ni GPU.
npm install
# 1. Build the ray signature bank (prerequisite, ~24 min)
npx tsx scripts/build-signature-bank.ts
# 1b. Include uppercase Latin A-Z (optional)
# By default the bank only includes IDNA PVALID codepoints (lowercase,
# digits, symbols). Use --include-uppercase to add uppercase A-Z, useful
# for font identification and trademark visual comparison where uppercase
# glyph shapes matter. The builder is resumable, so this only computes
# the additional codepoints.
npx tsx scripts/build-signature-bank.ts --include-uppercase
# 1c. Include arbitrary codepoint ranges (optional)
npx tsx scripts/build-signature-bank.ts --extra-range=0041-005A
# 2. Single-char discovery (22,581 chars, 12 scripts, ~36 min)
npx tsx scripts/discover-singlechar-sdf.ts --scorer=ray
# 3. Multi-char (bigram) discovery (676 bigrams, ~63 min)
npx tsx scripts/discover-multichar-sdf.ts --scorer=ray
# 4. Score known TR39 multi-char confusables (~5 min)
npx tsx scripts/score-multichar-sdf.ts --scorer=ray
El pipeline original basado en SSIM puntuó 26,5 millones de comparaciones en 230 fuentes. Sigue siendo funcional pero está superado por RaySpace para todas las tareas de descubrimiento y puntuación.
# TR39 confusable pair scoring
npx tsx scripts/build-index.ts # Render index (~160s, 11,370 PNGs)
npx tsx scripts/score-all-pairs.ts # Score all pairs (~65s, 235K comparisons)
# Novel confusable discovery
npx tsx scripts/build-candidates.ts # Candidate set (~23K chars)
npx tsx scripts/build-index.ts --candidates # Render candidates (~40min, 89K PNGs)
npx tsx scripts/score-candidates.ts # Score against Latin targets (~15min, 2.9M comparisons)
# Extract high-scoring discoveries from both pipelines
npx tsx scripts/extract-discoveries.ts
"Ceros" = fuentes donde los contornos producen firmas de rayo bit-idénticas (distancia 0.000). La w latina/ԝ cirílica es idéntica en las 19 fuentes que contienen ambos glifos.
La Coda georgiana (U+10FF) forma un anillo confusable cuádruple con la o latina, la o cirílica y la ómicron griega, todas por debajo de la distancia 0.08.
El descubrimiento de oy/uk cirílico es el hallazgo novedoso más destacado: el bigrama latino "oy" es visualmente idéntico a la letra digráfica cirílica uk (ѹ) a distancia 0.000 en Helvetica y 0.0005 en Arial Unicode MS.
Tres niveles operativos recomendados:
Consulte qué pares confusables existen para una fuente específica. Útil para diseñadores de fuentes que lanzan un nuevo tipo de letra, proveedores de navegadores que evalúan un cambio de fuente del sistema, o cualquier persona que elija una fuente de visualización para contextos sensibles a la seguridad como dominios IDN.
npx tsx scripts/query-font.ts --list-fonts # 218 fonts in discovery data
npx tsx scripts/query-font.ts "Arial" # All pairs for Arial (SSIM >= 0.7)
npx tsx scripts/query-font.ts "Arial" --threshold 0.8 # High-confidence only
npx tsx scripts/query-font.ts "Arial" --compare "Georgia" # Diff two fonts by SSIM delta
npx tsx scripts/query-font.ts "Arial" --json # JSON for downstream processing
La coincidencia de nombres de fuentes es insensible a mayúsculas y subcadena, por lo que "arial" coincide con Arial, Arial Black y Arial Unicode MS. El modo de comparación ordena por las mayores diferencias de SSIM primero, mostrando exactamente qué pares mejoran o empeoran al cambiar de fuente.
Requiere los archivos de descubrimiento del pipeline de puntuación (gitignorados, regenerar localmente).
| Archivo | Descripción |
|---|---|
data/output/render-index/ |
confusable-weights-v2.json con registros distribucionales por par: media, p50, p90, recuento de fuentes, recuento de distancia cero, fracción cero y nivel recomendado (estricto/estándar/exploratorio). Las distancias RaySpace reemplazan SSIM. 4,174 pares en umbral estándar.confusable-weights.json para la puntuación de riesgo visual medida mediante confusableDistance({ weights })Artículos en paultendo.github.io que cubren los hallazgos y la metodología detrás de este proyecto:
Metodología y hallazgos de RaySpace:
Hallazgos del pipeline SSIM:
Artículos que cubren el espacio problemático más amplio que motivó este proyecto:
| Fuente | Destino | Escrituras | Media | Fuentes | Ceros |
|---|
| w U+0077 | ԝ U+051D | Latino-Cirílico | 0.000 | 19 | 19 |
| j U+006A | ϳ U+03F3 | Latino-Griego | 0.013 | 21 | 18 |
| i U+0069 | і U+0456 | Latino-Cirílico | 0.018 | 62 | 50 |
| s U+0073 | ѕ U+0455 | Latino-Cirílico | 0.018 | 62 | 46 |
| c U+0063 | с U+0441 | Latino-Cirílico | 0.019 | 61 | 45 |
| o U+006F | о U+043E | Latino-Cirílico | 0.020 | 61 | 44 |
| j U+006A | ј U+0458 | Latino-Cirílico | 0.021 | 60 | 48 |
| x U+0078 | х U+0445 | Latino-Cirílico | 0.023 | 59 | 50 |
| p U+0070 | р U+0440 | Latino-Cirílico | 0.024 | 61 | 46 |
| e U+0065 | е U+0435 | Latino-Cirílico | 0.032 | 61 | 44 |
| a U+0061 | а U+0430 | Latino-Cirílico | 0.042 | 61 | 45 |
| Fuente | Destino | Escrituras | Media | Fuentes |
|---|
| ο U+03BF | ჿ U+10FF | Griego-Georgiano | 0.057 | 2 |
| ヘ U+30D8 | へ U+3078 | Katakana-Hiragana | 0.122 | 11 |
| 丶 U+4E36 | ヽ U+30FD | Han-Katakana | 0.125 | 9 |
| 二 U+4E8C | ニ U+30CB | Han-Katakana | 0.249 | 11 |
| 口 U+53E3 | ロ U+30ED | Han-Katakana | 0.268 | 11 |
| Bigrama | Destino | Media | Fuentes | Notas |
|---|
| ll | ॥ U+0965 (doble danda devanagari) | 0.176 | 8 | Entre escrituras |
| oy | ѹ U+0479 (uk cirílico) | 0.322 | 16 | Confusable bigrama novedoso entre escrituras |
| rn | m U+006D | 0.531 | 95 | 33 fuentes por debajo de 0.40 |
| bl | ы U+044B (yeru cirílico) | 0.797 | 49 | Entre escrituras |
| Umbral medio | Pares únicos de un solo carácter | Pares únicos de múltiples caracteres |
|---|
| < 0.50 | 138 | 13 |
| < 1.00 | 4,174 | 1,631 |
| < 1.50 | 59,700 | (ruido) |
| < 2.00 | 249,976 | 2,524,275 |
| Archivo | Descripción |
|---|
data/output/confusable-discoveries.json | 110 pares TR39 con SSIM alta (>= 0.7) o idénticos en píxeles |
data/output/candidate-discoveries.json | 793 pares novedosos no en TR39, SSIM media >= 0.7 |
data/output/confusable-weights.json | 1,397 aristas ponderadas para integración con namespace-guard |
data/output/cross-script-discoveries.json | 563 pares confusables entre escrituras |
data/output/cross-script-summary.json | Resumen entre escrituras por par de escrituras |
data/output/multichar-discoveries.json | Descubrimientos confusables de múltiples caracteres |
| Renderizar PNGs + índice (pipeline SSIM) |
data/output/singlechar-sdf-scores.jsonl | Puntuaciones RaySpace de un solo carácter |
data/output/multichar-rayspace-scores.jsonl | Puntuaciones RaySpace de múltiples caracteres |
data/output/signature-bank/ | Banco de firmas de rayos (294,646 entradas, 7.9GB comprimido) |