[{"data":1,"prerenderedAt":1296},["ShallowReactive",2],{"blog-es-tofu-boxes-japanese":3},{"id":4,"title":5,"author":6,"body":9,"date":1260,"description":1261,"draft":1262,"extension":1263,"howTo":1264,"image":1286,"meta":1287,"navigation":131,"path":1288,"seo":1289,"stem":1290,"tags":1291,"updated":1286,"__hash__":1295},"blogEs/es/blog/008.tofu-boxes-japanese.md","¿Por qué mi PDF muestra rectángulos (tofu) en lugar de japonés?",{"name":7,"url":8},"gpdf team","https://gpdf.dev",{"type":10,"value":11,"toc":1248},"minimark",[12,17,21,25,33,36,97,101,104,707,721,734,738,741,761,781,787,791,798,943,977,981,988,991,994,1024,1027,1031,1037,1102,1117,1120,1152,1156,1173,1177,1207,1211,1214,1231,1244],[13,14,16],"h2",{"id":15},"la-pregunta-en-otras-palabras","La pregunta, en otras palabras",[18,19,20],"p",{},"Escribí texto japonés con gpdf y el PDF resultante muestra rectángulos vacíos donde deberían estar los caracteres. ¿Qué es eso y cómo logro que los glifos japoneses reales aparezcan en el archivo?",[13,22,24],{"id":23},"la-respuesta-rápida","La respuesta rápida",[18,26,27,28,32],{},"Eso es ",[29,30,31],"em",{},"tofu"," — el visor de PDF dibuja un rectángulo como marcador porque la fuente embebida en el PDF no tiene glifo para el code point Unicode que pediste. Cuatro cosas lo causan, y una es mucho más frecuente que las otras.",[18,34,35],{},"Por orden de frecuencia:",[37,38,39,56,73,87],"ol",{},[40,41,42,46,47,51,52,55],"li",{},[43,44,45],"strong",{},"Ninguna fuente CJK registrada."," ",[48,49,50],"code",{},"gpdf.NewDocument"," no tiene ninguna llamada a ",[48,53,54],{},"WithFont",", así que el documento cae en las fuentes Base-14 del PDF (Helvetica, Times, Courier). Ninguna cubre U+3040–U+9FFF.",[40,57,58,46,65,68,69,72],{},[43,59,60,61,64],{},"Fuente CJK registrada, pero el nombre de familia en ",[48,62,63],{},"c.Text"," es otro.",[48,66,67],{},"WithFont(\"NotoSansJP\", ...)"," está puesto, pero ",[48,70,71],{},"template.FontFamily(\"Arial\")"," en el texto fuerza a gpdf a buscar japonés en una fuente latina.",[40,74,75,78,79,82,83,86],{},[43,76,77],{},"El archivo de fuente no contiene glifos CJK."," El TTF en disco es un subset latino (",[48,80,81],{},"NotoSans-Regular.ttf"," en lugar de ",[48,84,85],{},"NotoSansJP-Regular.ttf","). El nombre parece correcto, la cobertura está vacía.",[40,88,89,92,93,96],{},[43,90,91],{},"Los bytes estaban rotos antes de llegar a gpdf."," La cadena se decodificó como Shift-JIS o Latin-1 aguas arriba y los code points ya no son japoneses. Si ves ",[48,94,95],{},"縺ゅ→縺"," en vez de rectángulos, es esta.",[13,98,100],{"id":99},"la-corrección-canónica-para-la-causa-1","La corrección canónica para la causa #1",[18,102,103],{},"Nueve de cada diez veces es esto:",[105,106,111],"pre",{"className":107,"code":108,"language":109,"meta":110,"style":110},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","package main\n\nimport (\n    \"log\"\n    \"os\"\n\n    \"github.com/gpdf-dev/gpdf\"\n    \"github.com/gpdf-dev/gpdf/document\"\n    \"github.com/gpdf-dev/gpdf/template\"\n)\n\nfunc main() {\n    font, err := os.ReadFile(\"NotoSansJP-Regular.ttf\")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    doc := gpdf.NewDocument(\n        gpdf.WithPageSize(gpdf.A4),\n        gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n        gpdf.WithFont(\"NotoSansJP\", font),\n        gpdf.WithDefaultFont(\"NotoSansJP\", 12),\n    )\n\n    page := doc.AddPage()\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(\"こんにちは、世界。\")\n        })\n    })\n\n    data, err := doc.Generate()\n    if err != nil {\n        log.Fatal(err)\n    }\n    if err := os.WriteFile(\"hello.pdf\", data, 0o644); err != nil {\n        log.Fatal(err)\n    }\n}\n","go","",[48,112,113,126,133,143,155,165,170,180,190,200,206,211,227,265,281,299,305,310,329,353,391,416,441,447,452,471,505,542,564,570,576,581,602,615,630,635,681,696,701],{"__ignoreMap":110},[114,115,118,122],"span",{"class":116,"line":117},"line",1,[114,119,121],{"class":120},"sMK4o","package",[114,123,125],{"class":124},"sBMFI"," main\n",[114,127,129],{"class":116,"line":128},2,[114,130,132],{"emptyLinePlaceholder":131},true,"\n",[114,134,136,140],{"class":116,"line":135},3,[114,137,139],{"class":138},"s7zQu","import",[114,141,142],{"class":120}," (\n",[114,144,146,149,152],{"class":116,"line":145},4,[114,147,148],{"class":120},"    \"",[114,150,151],{"class":124},"log",[114,153,154],{"class":120},"\"\n",[114,156,158,160,163],{"class":116,"line":157},5,[114,159,148],{"class":120},[114,161,162],{"class":124},"os",[114,164,154],{"class":120},[114,166,168],{"class":116,"line":167},6,[114,169,132],{"emptyLinePlaceholder":131},[114,171,173,175,178],{"class":116,"line":172},7,[114,174,148],{"class":120},[114,176,177],{"class":124},"github.com/gpdf-dev/gpdf",[114,179,154],{"class":120},[114,181,183,185,188],{"class":116,"line":182},8,[114,184,148],{"class":120},[114,186,187],{"class":124},"github.com/gpdf-dev/gpdf/document",[114,189,154],{"class":120},[114,191,193,195,198],{"class":116,"line":192},9,[114,194,148],{"class":120},[114,196,197],{"class":124},"github.com/gpdf-dev/gpdf/template",[114,199,154],{"class":120},[114,201,203],{"class":116,"line":202},10,[114,204,205],{"class":120},")\n",[114,207,209],{"class":116,"line":208},11,[114,210,132],{"emptyLinePlaceholder":131},[114,212,214,217,221,224],{"class":116,"line":213},12,[114,215,216],{"class":120},"func",[114,218,220],{"class":219},"s2Zo4"," main",[114,222,223],{"class":120},"()",[114,225,226],{"class":120}," {\n",[114,228,230,234,237,240,243,246,249,252,255,258,261,263],{"class":116,"line":229},13,[114,231,233],{"class":232},"sTEyZ","    font",[114,235,236],{"class":120},",",[114,238,239],{"class":232}," err ",[114,241,242],{"class":120},":=",[114,244,245],{"class":232}," os",[114,247,248],{"class":120},".",[114,250,251],{"class":219},"ReadFile",[114,253,254],{"class":120},"(",[114,256,257],{"class":120},"\"",[114,259,85],{"class":260},"sfazB",[114,262,257],{"class":120},[114,264,205],{"class":120},[114,266,268,271,273,276,279],{"class":116,"line":267},14,[114,269,270],{"class":138},"    if",[114,272,239],{"class":232},[114,274,275],{"class":120},"!=",[114,277,278],{"class":120}," nil",[114,280,226],{"class":120},[114,282,284,287,289,292,294,297],{"class":116,"line":283},15,[114,285,286],{"class":232},"        log",[114,288,248],{"class":120},[114,290,291],{"class":219},"Fatal",[114,293,254],{"class":120},[114,295,296],{"class":232},"err",[114,298,205],{"class":120},[114,300,302],{"class":116,"line":301},16,[114,303,304],{"class":120},"    }\n",[114,306,308],{"class":116,"line":307},17,[114,309,132],{"emptyLinePlaceholder":131},[114,311,313,316,318,321,323,326],{"class":116,"line":312},18,[114,314,315],{"class":232},"    doc ",[114,317,242],{"class":120},[114,319,320],{"class":232}," gpdf",[114,322,248],{"class":120},[114,324,325],{"class":219},"NewDocument",[114,327,328],{"class":120},"(\n",[114,330,332,335,337,340,342,345,347,350],{"class":116,"line":331},19,[114,333,334],{"class":232},"        gpdf",[114,336,248],{"class":120},[114,338,339],{"class":219},"WithPageSize",[114,341,254],{"class":120},[114,343,344],{"class":232},"gpdf",[114,346,248],{"class":120},[114,348,349],{"class":232},"A4",[114,351,352],{"class":120},"),\n",[114,354,356,358,360,363,365,368,370,373,375,377,379,382,384,388],{"class":116,"line":355},20,[114,357,334],{"class":232},[114,359,248],{"class":120},[114,361,362],{"class":219},"WithMargins",[114,364,254],{"class":120},[114,366,367],{"class":232},"document",[114,369,248],{"class":120},[114,371,372],{"class":219},"UniformEdges",[114,374,254],{"class":120},[114,376,367],{"class":232},[114,378,248],{"class":120},[114,380,381],{"class":219},"Mm",[114,383,254],{"class":120},[114,385,387],{"class":386},"sbssI","20",[114,389,390],{"class":120},"))),\n",[114,392,394,396,398,400,402,404,407,409,411,414],{"class":116,"line":393},21,[114,395,334],{"class":232},[114,397,248],{"class":120},[114,399,54],{"class":219},[114,401,254],{"class":120},[114,403,257],{"class":120},[114,405,406],{"class":260},"NotoSansJP",[114,408,257],{"class":120},[114,410,236],{"class":120},[114,412,413],{"class":232}," font",[114,415,352],{"class":120},[114,417,419,421,423,426,428,430,432,434,436,439],{"class":116,"line":418},22,[114,420,334],{"class":232},[114,422,248],{"class":120},[114,424,425],{"class":219},"WithDefaultFont",[114,427,254],{"class":120},[114,429,257],{"class":120},[114,431,406],{"class":260},[114,433,257],{"class":120},[114,435,236],{"class":120},[114,437,438],{"class":386}," 12",[114,440,352],{"class":120},[114,442,444],{"class":116,"line":443},23,[114,445,446],{"class":120},"    )\n",[114,448,450],{"class":116,"line":449},24,[114,451,132],{"emptyLinePlaceholder":131},[114,453,455,458,460,463,465,468],{"class":116,"line":454},25,[114,456,457],{"class":232},"    page ",[114,459,242],{"class":120},[114,461,462],{"class":232}," doc",[114,464,248],{"class":120},[114,466,467],{"class":219},"AddPage",[114,469,470],{"class":120},"()\n",[114,472,474,477,479,482,485,489,492,495,497,500,503],{"class":116,"line":473},26,[114,475,476],{"class":232},"    page",[114,478,248],{"class":120},[114,480,481],{"class":219},"AutoRow",[114,483,484],{"class":120},"(func(",[114,486,488],{"class":487},"sHdIc","r",[114,490,491],{"class":120}," *",[114,493,494],{"class":124},"template",[114,496,248],{"class":120},[114,498,499],{"class":124},"RowBuilder",[114,501,502],{"class":120},")",[114,504,226],{"class":120},[114,506,508,511,513,516,518,521,523,526,529,531,533,535,538,540],{"class":116,"line":507},27,[114,509,510],{"class":232},"        r",[114,512,248],{"class":120},[114,514,515],{"class":219},"Col",[114,517,254],{"class":120},[114,519,520],{"class":386},"12",[114,522,236],{"class":120},[114,524,525],{"class":120}," func(",[114,527,528],{"class":487},"c",[114,530,491],{"class":120},[114,532,494],{"class":124},[114,534,248],{"class":120},[114,536,537],{"class":124},"ColBuilder",[114,539,502],{"class":120},[114,541,226],{"class":120},[114,543,545,548,550,553,555,557,560,562],{"class":116,"line":544},28,[114,546,547],{"class":232},"            c",[114,549,248],{"class":120},[114,551,552],{"class":219},"Text",[114,554,254],{"class":120},[114,556,257],{"class":120},[114,558,559],{"class":260},"こんにちは、世界。",[114,561,257],{"class":120},[114,563,205],{"class":120},[114,565,567],{"class":116,"line":566},29,[114,568,569],{"class":120},"        })\n",[114,571,573],{"class":116,"line":572},30,[114,574,575],{"class":120},"    })\n",[114,577,579],{"class":116,"line":578},31,[114,580,132],{"emptyLinePlaceholder":131},[114,582,584,587,589,591,593,595,597,600],{"class":116,"line":583},32,[114,585,586],{"class":232},"    data",[114,588,236],{"class":120},[114,590,239],{"class":232},[114,592,242],{"class":120},[114,594,462],{"class":232},[114,596,248],{"class":120},[114,598,599],{"class":219},"Generate",[114,601,470],{"class":120},[114,603,605,607,609,611,613],{"class":116,"line":604},33,[114,606,270],{"class":138},[114,608,239],{"class":232},[114,610,275],{"class":120},[114,612,278],{"class":120},[114,614,226],{"class":120},[114,616,618,620,622,624,626,628],{"class":116,"line":617},34,[114,619,286],{"class":232},[114,621,248],{"class":120},[114,623,291],{"class":219},[114,625,254],{"class":120},[114,627,296],{"class":232},[114,629,205],{"class":120},[114,631,633],{"class":116,"line":632},35,[114,634,304],{"class":120},[114,636,638,640,642,644,646,648,651,653,655,658,660,662,665,667,670,673,675,677,679],{"class":116,"line":637},36,[114,639,270],{"class":138},[114,641,239],{"class":232},[114,643,242],{"class":120},[114,645,245],{"class":232},[114,647,248],{"class":120},[114,649,650],{"class":219},"WriteFile",[114,652,254],{"class":120},[114,654,257],{"class":120},[114,656,657],{"class":260},"hello.pdf",[114,659,257],{"class":120},[114,661,236],{"class":120},[114,663,664],{"class":232}," data",[114,666,236],{"class":120},[114,668,669],{"class":386}," 0o644",[114,671,672],{"class":120},");",[114,674,239],{"class":232},[114,676,275],{"class":120},[114,678,278],{"class":120},[114,680,226],{"class":120},[114,682,684,686,688,690,692,694],{"class":116,"line":683},37,[114,685,286],{"class":232},[114,687,248],{"class":120},[114,689,291],{"class":219},[114,691,254],{"class":120},[114,693,296],{"class":232},[114,695,205],{"class":120},[114,697,699],{"class":116,"line":698},38,[114,700,304],{"class":120},[114,702,704],{"class":116,"line":703},39,[114,705,706],{"class":120},"}\n",[18,708,709,710,713,714,717,718,720],{},"Dos líneas registran la fuente y la ponen por defecto. Sin CGO. Sin la contabilidad de ",[48,711,712],{},"AddUTF8Font",". Si antes veías ",[48,715,716],{},"□□□□□、□□。"," y corres este programa con un ",[48,719,85],{}," real al lado, obtienes los glifos reales.",[18,722,723,724,726,727,248],{},"Descarga ",[48,725,85],{}," desde ",[728,729,733],"a",{"href":730,"rel":731},"https://fonts.google.com/noto/specimen/Noto+Sans+JP",[732],"nofollow","Google Fonts",[13,735,737],{"id":736},"cómo-saber-qué-causa-tienes","Cómo saber qué causa tienes",[18,739,740],{},"La mayor parte consiste en mirar tres sitios: dónde construyes el documento, dónde escribes el texto, y el archivo TTF mismo.",[18,742,743,749,750,753,754,757,758,760],{},[43,744,745,746],{},"Si la salida son ",[48,747,748],{},"□□□"," (rectángulos idénticos), es causa 1, 2 o 3. El PDF embebió ",[29,751,752],{},"una"," fuente, pero no tiene los glifos. Abre el PDF en Acrobat, ve a ",[48,755,756],{},"Archivo → Propiedades → Fuentes"," y mira qué fuentes se embebieron. Si solo aparecen Helvetica / Times / Courier, causa 1. Si ",[48,759,406],{}," aparece pero siguen los rectángulos, causa 2 o 3.",[18,762,763,772,773,776,777,780],{},[43,764,765,766,768,769],{},"Si la salida es ",[48,767,95],{}," o ",[48,770,771],{},"ã\"ã‚\"ã«ã¡ã¯"," (latín revuelto), es causa 4. La cadena japonesa se re-codificó antes de que gpdf la recibiera. Culpable más común: un CSV guardado como Shift-JIS por Excel y leído con ",[48,774,775],{},"os.ReadFile"," como si fuera UTF-8, o un endpoint HTTP que no declaró ",[48,778,779],{},"charset=utf-8",". Arregla el decodificador, no el PDF.",[18,782,783,786],{},[43,784,785],{},"Salida mixta"," — algunos caracteres se ven, otros son rectángulos — significa cobertura parcial. Una fuente etiquetada \"japonesa\" puede incluir hiragana y katakana pero saltarse kanji poco comunes como 鬱 o 龠. Cambia a Noto Sans JP (cubre JIS X 0213) o Source Han Sans JP si caes en esto.",[13,788,790],{"id":789},"causa-2-al-detalle-fuente-correcta-familia-mal-escrita","Causa 2 al detalle: fuente correcta, familia mal escrita",[18,792,793,794,797],{},"Esta es traicionera porque la fuente ",[29,795,796],{},"sí"," está embebida — solo que no se usa. Reproducción mínima:",[105,799,801],{"className":107,"code":800,"language":109,"meta":110,"style":110},"doc := gpdf.NewDocument(\n    gpdf.WithFont(\"NotoSansJP\", font),\n    // Sin WithDefaultFont.\n)\n\npage.AutoRow(func(r *template.RowBuilder) {\n    r.Col(12, func(c *template.ColBuilder) {\n        c.Text(\"こんにちは\") // Usa la fuente por defecto: Helvetica.\n    })\n})\n",[48,802,803,818,841,847,851,855,880,911,934,938],{"__ignoreMap":110},[114,804,805,808,810,812,814,816],{"class":116,"line":117},[114,806,807],{"class":232},"doc ",[114,809,242],{"class":120},[114,811,320],{"class":232},[114,813,248],{"class":120},[114,815,325],{"class":219},[114,817,328],{"class":120},[114,819,820,823,825,827,829,831,833,835,837,839],{"class":116,"line":128},[114,821,822],{"class":232},"    gpdf",[114,824,248],{"class":120},[114,826,54],{"class":219},[114,828,254],{"class":120},[114,830,257],{"class":120},[114,832,406],{"class":260},[114,834,257],{"class":120},[114,836,236],{"class":120},[114,838,413],{"class":232},[114,840,352],{"class":120},[114,842,843],{"class":116,"line":135},[114,844,846],{"class":845},"sHwdD","    // Sin WithDefaultFont.\n",[114,848,849],{"class":116,"line":145},[114,850,205],{"class":120},[114,852,853],{"class":116,"line":157},[114,854,132],{"emptyLinePlaceholder":131},[114,856,857,860,862,864,866,868,870,872,874,876,878],{"class":116,"line":167},[114,858,859],{"class":232},"page",[114,861,248],{"class":120},[114,863,481],{"class":219},[114,865,484],{"class":120},[114,867,488],{"class":487},[114,869,491],{"class":120},[114,871,494],{"class":124},[114,873,248],{"class":120},[114,875,499],{"class":124},[114,877,502],{"class":120},[114,879,226],{"class":120},[114,881,882,885,887,889,891,893,895,897,899,901,903,905,907,909],{"class":116,"line":172},[114,883,884],{"class":232},"    r",[114,886,248],{"class":120},[114,888,515],{"class":219},[114,890,254],{"class":120},[114,892,520],{"class":386},[114,894,236],{"class":120},[114,896,525],{"class":120},[114,898,528],{"class":487},[114,900,491],{"class":120},[114,902,494],{"class":124},[114,904,248],{"class":120},[114,906,537],{"class":124},[114,908,502],{"class":120},[114,910,226],{"class":120},[114,912,913,916,918,920,922,924,927,929,931],{"class":116,"line":182},[114,914,915],{"class":232},"        c",[114,917,248],{"class":120},[114,919,552],{"class":219},[114,921,254],{"class":120},[114,923,257],{"class":120},[114,925,926],{"class":260},"こんにちは",[114,928,257],{"class":120},[114,930,502],{"class":120},[114,932,933],{"class":845}," // Usa la fuente por defecto: Helvetica.\n",[114,935,936],{"class":116,"line":192},[114,937,575],{"class":120},[114,939,940],{"class":116,"line":202},[114,941,942],{"class":120},"})\n",[18,944,945,946,949,950,952,953,956,957,959,960,962,963,965,966,969,970,972,973,976],{},"Solución: añade ",[48,947,948],{},"gpdf.WithDefaultFont(\"NotoSansJP\", 12)"," a ",[48,951,325],{},", o pasa ",[48,954,955],{},"template.FontFamily(\"NotoSansJP\")"," en cada ",[48,958,63],{}," que necesite japonés. El nombre de familia en ",[48,961,54],{}," y el de ",[48,964,63],{}," deben coincidir ",[43,967,968],{},"exactamente",", incluyendo mayúsculas y minúsculas. Para gpdf, ",[48,971,406],{}," y ",[48,974,975],{},"notosansjp"," son dos fuentes distintas.",[13,978,980],{"id":979},"causa-3-al-detalle-el-ttf-equivocado","Causa 3 al detalle: el TTF equivocado",[18,982,983,972,985,987],{},[48,984,81],{},[48,986,85],{}," son dos archivos distintos. El primero es una fuente latina sin ninguna cobertura CJK. El segundo es la versión japonesa, con unos 17.000 glifos. Se ven casi idénticos en un listado de directorio, y el autocompletado fácilmente te pasa el equivocado.",[18,989,990],{},"gpdf no valida la cobertura de glifos al registrar. Si le das bytes, confía. El fallo aparece como tofu en tiempo de render.",[18,992,993],{},"Manera rápida de comprobar:",[995,996,997,1004,1011],"ul",{},[40,998,999,1000,1003],{},"macOS: ",[48,1001,1002],{},"Font Book"," → doble clic en el archivo → previsualización muestra una cuadrícula de glifos",[40,1005,1006,1007,1010],{},"Linux: ",[48,1008,1009],{},"otfinfo -u NotoSans-Regular.ttf"," vuelca la cobertura Unicode",[40,1012,1013,1014,1019,1020,1023],{},"Multiplataforma: ",[728,1015,1018],{"href":1016,"rel":1017},"https://github.com/fonttools/fonttools",[732],"fontTools"," — ",[48,1021,1022],{},"ttx -t cmap NotoSans-Regular.ttf"," exporta la tabla cmap como XML",[18,1025,1026],{},"Si U+3042 (あ) no está en la lista, tienes el subset latino.",[13,1028,1030],{"id":1029},"causa-4-al-detalle-corrupción-de-codificación","Causa 4 al detalle: corrupción de codificación",[18,1032,1033,1034,1036],{},"Esta en realidad no involucra a gpdf. La cadena que le diste a ",[48,1035,63],{}," ya traía los bytes mal. Imprímela antes de renderizar:",[105,1038,1040],{"className":107,"code":1039,"language":109,"meta":110,"style":110},"text := loadLabelFromSomewhere()\nfmt.Printf(\"%q\\n\", text) // Muestra las runas reales\nc.Text(text)\n",[48,1041,1042,1054,1087],{"__ignoreMap":110},[114,1043,1044,1047,1049,1052],{"class":116,"line":117},[114,1045,1046],{"class":232},"text ",[114,1048,242],{"class":120},[114,1050,1051],{"class":219}," loadLabelFromSomewhere",[114,1053,470],{"class":120},[114,1055,1056,1059,1061,1064,1066,1068,1072,1075,1077,1079,1082,1084],{"class":116,"line":128},[114,1057,1058],{"class":232},"fmt",[114,1060,248],{"class":120},[114,1062,1063],{"class":219},"Printf",[114,1065,254],{"class":120},[114,1067,257],{"class":120},[114,1069,1071],{"class":1070},"swJcz","%q",[114,1073,1074],{"class":232},"\\n",[114,1076,257],{"class":120},[114,1078,236],{"class":120},[114,1080,1081],{"class":232}," text",[114,1083,502],{"class":120},[114,1085,1086],{"class":845}," // Muestra las runas reales\n",[114,1088,1089,1091,1093,1095,1097,1100],{"class":116,"line":135},[114,1090,528],{"class":232},[114,1092,248],{"class":120},[114,1094,552],{"class":219},[114,1096,254],{"class":120},[114,1098,1099],{"class":232},"text",[114,1101,205],{"class":120},[18,1103,1104,1105,1108,1109,1112,1113,1116],{},"Si ",[48,1106,1107],{},"fmt.Printf(\"%q\\n\", text)"," imprime ",[48,1110,1111],{},"\"縺ゅ→縺\""," en vez de ",[48,1114,1115],{},"\"あいうえ\"",", la corrupción ocurrió aguas arriba. gpdf no puede repararlo — encuentra el punto donde UTF-8 se decodificó mal.",[18,1118,1119],{},"Culpables habituales aguas arriba:",[995,1121,1122,1131,1145],{},[40,1123,1124,1125,1127,1128],{},"Leer un CSV exportado desde Excel (Windows Shift-JIS) con ",[48,1126,775],{}," y castearlo directo a ",[48,1129,1130],{},"string",[40,1132,1133,1134,768,1137,1140,1141,1144],{},"Una columna de base de datos declarada ",[48,1135,1136],{},"latin1",[48,1138,1139],{},"utf8mb3"," (no ",[48,1142,1143],{},"utf8mb4",") que ya guarda mojibake",[40,1146,1147,1148,1151],{},"Una respuesta HTTP sin ",[48,1149,1150],{},"Content-Type: application/json; charset=utf-8"," y un cliente que adivinó Latin-1",[13,1153,1155],{"id":1154},"un-caso-límite-que-conviene-nombrar","Un caso límite que conviene nombrar",[18,1157,1158,1159,1162,1163,1165,1166,1169,1170,1172],{},"gpdf hace subset silenciosamente. El subset se congela en el momento de ",[48,1160,1161],{},"Generate()",". Si durante la construcción del documento renderizas ",[48,1164,926],{}," y luego ",[48,1167,1168],{},"鬱陶しい",", el segundo también se añade al subset correctamente. Pero si generas el PDF, lo abres en Acrobat y escribes un kanji que no estaba en el texto original, ahí tendrás tofu — ese glifo nunca entró en el subset. No pospongas la edición al PDF; vuelve a ejecutar el programa en Go y llama a ",[48,1171,1161],{}," de nuevo.",[13,1174,1176],{"id":1175},"recetas-relacionadas","Recetas relacionadas",[995,1178,1179,1189,1200],{},[40,1180,1181,1185,1186,1188],{},[728,1182,1184],{"href":1183},"/es/blog/embed-japanese-font","¿Cómo incrusto una fuente japonesa en gpdf?"," — recorrido completo de ",[48,1187,54],{}," con variantes bold/italic y documentos multi-CJK",[40,1190,1191,1195,1196,1199],{},[728,1192,1194],{"href":1193},"/es/blog/noto-sans-jp-with-gpdf","¿Cómo uso Noto Sans JP con gpdf?"," — qué archivo de Noto elegir y cómo ",[48,1197,1198],{},"go:embed"," simplifica la distribución",[40,1201,1202,1206],{},[728,1203,1205],{"href":1204},"/es/blog/japanese-pdf-in-go","La guía definitiva para PDFs en japonés con Go (2026)"," — guía extensa que cubre fuentes, texto vertical, ruby y layout específico de JP",[13,1208,1210],{"id":1209},"prueba-gpdf","Prueba gpdf",[18,1212,1213],{},"gpdf es una librería Go para generar PDFs. Licencia MIT, cero dependencias externas, soporte CJK nativo.",[105,1215,1219],{"className":1216,"code":1217,"language":1218,"meta":110,"style":110},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com/gpdf-dev/gpdf\n","bash",[48,1220,1221],{"__ignoreMap":110},[114,1222,1223,1225,1228],{"class":116,"line":117},[114,1224,109],{"class":124},[114,1226,1227],{"class":260}," get",[114,1229,1230],{"class":260}," github.com/gpdf-dev/gpdf\n",[18,1232,1233,1238,1239],{},[728,1234,1237],{"href":1235,"rel":1236},"https://github.com/gpdf-dev/gpdf",[732],"⭐ Star en GitHub"," · ",[728,1240,1243],{"href":1241,"rel":1242},"https://gpdf.dev/es/docs/quickstart",[732],"Leer los docs",[1245,1246,1247],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":110,"searchDepth":128,"depth":128,"links":1249},[1250,1251,1252,1253,1254,1255,1256,1257,1258,1259],{"id":15,"depth":128,"text":16},{"id":23,"depth":128,"text":24},{"id":99,"depth":128,"text":100},{"id":736,"depth":128,"text":737},{"id":789,"depth":128,"text":790},{"id":979,"depth":128,"text":980},{"id":1029,"depth":128,"text":1030},{"id":1154,"depth":128,"text":1155},{"id":1175,"depth":128,"text":1176},{"id":1209,"depth":128,"text":1210},"2026-04-17","Los rectángulos vacíos en lugar de caracteres japoneses significan que el PDF no encontró glifos para esos code points. Cuatro causas y sus soluciones.",false,"md",{"name":1265,"totalTime":1266,"tools":1267,"steps":1270},"Diagnosticar y corregir los rectángulos tofu en un documento gpdf","PT15M",[1268,1269],"Go 1.22+","Un TTF con soporte CJK como NotoSansJP-Regular.ttf",[1271,1274,1277,1280,1283],{"name":1272,"text":1273},"Confirma si el síntoma es tofu o mojibake","Abre el PDF. Caracteres japoneses como rectángulos vacíos (□) indican que no se encontró el glifo. Texto latino incomprensible como 縺ゅ→縺 indica que el UTF-8 se decodificó mal antes de llegar a gpdf.",{"name":1275,"text":1276},"Verifica que haya una fuente CJK registrada","Busca gpdf.WithFont en la construcción del documento. Si no hay TTF CJK registrado, gpdf recurre a las fuentes Base-14 del PDF, ninguna de las cuales cubre los code points CJK.",{"name":1278,"text":1279},"Valida el nombre de familia en cada c.Text","Si no usas WithDefaultFont, cada c.Text que renderice japonés necesita template.FontFamily(\"NotoSansJP\") explícito. Un nombre mal escrito silenciosamente vuelve a la fuente por defecto.",{"name":1281,"text":1282},"Confirma que el TTF contenga glifos CJK","NotoSans-Regular.ttf (subset Latin) y NotoSansJP-Regular.ttf son archivos distintos. gpdf no valida la cobertura de glifos en el momento del registro.",{"name":1284,"text":1285},"Regenera y verifica en dos visores","Abre el PDF en Adobe Acrobat y en Chrome. Ambos deberían renderizar japonés. Si solo uno funciona, los glifos están embebidos pero el subset registrado no coincide para ese code point.",null,{},"/es/blog/tofu-boxes-japanese",{"title":5,"description":1261},"es/blog/008.tofu-boxes-japanese",[1292,1293,1294],"recipe","troubleshooting","cjk","YWDfUvfpgiQQHiamvKjsb1HqJZ9N_VNBsfpgfsevCXw",1776529274196]