[{"data":1,"prerenderedAt":5361},["ShallowReactive",2],{"blog-pt-signintech-gopdf-migration":3},{"id":4,"title":5,"author":6,"body":10,"date":5320,"description":5321,"draft":5322,"extension":5323,"howTo":5324,"image":5351,"meta":5352,"navigation":548,"path":5353,"seo":5354,"stem":5355,"tags":5356,"updated":5351,"__hash__":5360},"blogPt/pt/blog/021.signintech-gopdf-migration.md","De signintech/gopdf para gpdf: menos cálculo de coordenadas",{"name":7,"url":8,"avatar":9},"Taiki Noda","https://nadai.dev/en/about","https://nadai.dev/og-default.png",{"type":11,"value":12,"toc":5303},"minimark",[13,18,39,59,62,65,69,72,75,84,87,91,94,104,126,129,133,136,485,509,513,516,521,1000,1005,1439,1446,1450,1453,1457,1916,1926,1930,2212,2229,2233,2239,2243,3034,3040,3044,3302,3308,3319,3323,3326,3330,3732,3739,3743,4000,4010,4014,4017,4021,4296,4299,4303,4655,4663,4667,4670,4930,4933,4937,4940,5035,5041,5048,5052,5055,5111,5118,5122,5128,5134,5148,5170,5192,5207,5224,5228,5231,5248,5263,5267,5299],[14,15,17],"h2",{"id":16},"tldr","TL;DR",[19,20,21,25,26,29,30,34,35,38],"p",{},[22,23,24],"strong",{},"gpdf"," é uma biblioteca PDF em Go puro com motor de layout de 12 colunas. ",[22,27,28],{},"signintech/gopdf"," é um binding de baixo nível sobre o sistema de coordenadas PDF. Se você já usa gopdf há algum tempo e a base de código é hoje em sua maioria ",[31,32,33],"code",{},"SetXY",", ",[31,36,37],{},"Cell"," e aritmética de larguras, este guia mostra em que essas chamadas colapsam quando há um motor de layout abaixo.",[19,40,41,42,44,45,44,47,50,51,54,55,58],{},"Semana passada estava com alguém refatorando um gerador de notas fiscais sobre signintech/gopdf. Cinco anos de acúmulo. A função que desenhava a tabela de itens tinha 280 linhas. Cerca de 40 faziam trabalho real: formatar valor, formatar data, repetir por linha. As outras 240 calculavam posições x, rastreavam y, chamavam ",[31,43,33],{},", chamavam ",[31,46,37],{},[31,48,49],{},"Br",", desenhavam linhas de borda com ",[31,52,53],{},"Line(x1, y1, x2, y2)",", decidiam se a linha cabia na página ou se era preciso ",[31,56,57],{},"AddPage"," manual e reimprimir o cabeçalho.",[19,60,61],{},"Essa é a experiência gopdf em produção. Não é uma biblioteca ruim. É um binding fino, rápido, sem CGO sobre o modelo de imaging do PDF — exatamente o que o nome promete. Há um cursor, há coordenadas, e o engenheiro faz papel de motor de layout.",[19,63,64],{},"Este artigo mapeia a API do gopdf para gpdf, função por função. A tese está no título: a maioria das linhas desaparece porque faziam matemática de layout que o runtime pode fazer por você.",[14,66,68],{"id":67},"o-que-signintechgopdf-é-e-o-que-não-é","O que signintech/gopdf é — e o que não é",[19,70,71],{},"Vale deixar claro antes de qualquer narrativa de \"migre já\", porque o gopdf tem virtudes reais.",[19,73,74],{},"É mantido ativamente. É Go puro (sem CGO), então cross-compilation e imagens Alpine simplesmente funcionam. Suporta fontes TrueType incluindo CJK. A saída é rápida — gopdf está na mesma faixa que gpdf nas primitivas de imaging porque ambos escrevem o wire format PDF diretamente, sem motor pesado na frente. A API mapeia diretamente para o modelo PDF subjacente: há um ponto atual, você o move, você desenha nele. Se você já pensa em coordenadas PDF, gopdf é confortável.",[19,76,77,78,80,81,83],{},"O que não é, é um sistema de layout. Não há noção de linha, coluna, container flex ou grade. Não há quebra de página automática: quando seu conteúdo passa da margem inferior, o conteúdo passa da margem inferior (ou sai da página) até você chamar ",[31,79,57],{}," por conta própria. Tabelas não existem como primitiva — são um padrão que você reimplementa em cada projeto, com chamadas ",[31,82,37],{}," célula a célula, linhas de borda manuais e sua própria lógica de quebra de página.",[19,85,86],{},"Para um certificado de uma página ou um formulário fixo muito controlado, o modelo de cursor está ok. Para notas fiscais, relatórios, extratos, qualquer coisa com conteúdo de tamanho variável — a matemática de coordenadas cresce com a área do documento. Essa é a carga de trabalho para a qual gpdf foi feito.",[14,88,90],{"id":89},"a-mudança-de-modelo-mental","A mudança de modelo mental",[19,92,93],{},"Esta é a parte que muda de fato como o código é lido. gpdf tem duas ideias que gopdf não tem:",[19,95,96,99,100,103],{},[22,97,98],{},"Árvore declarativa."," Você não diz ao renderer onde colocar as coisas. Você descreve uma árvore de páginas → linhas → colunas → conteúdo, e o motor de layout resolve as posições em uma única passagem. Não há cursor a avançar. Duas chamadas ",[31,101,102],{},"r.Col(...)"," consecutivas não precisam saber uma da outra.",[19,105,106,109,110,113,114,117,118,121,122,125],{},[22,107,108],{},"Grade de 12 colunas."," Cada linha tem implicitamente 12 unidades de largura. Você as gasta entre as colunas: ",[31,111,112],{},"r.Col(8, ...)"," toma dois terços, ",[31,115,116],{},"r.Col(4, ...)"," toma um terço. A grade é a mesma ideia que Bootstrap e Tailwind usam para HTML, aplicada a PDF. Você para de calcular ",[31,119,120],{},"pageWidth - leftMargin - rightMargin"," dividido por 4. Você escreve ",[31,123,124],{},"r.Col(3, ...)"," quatro vezes.",[19,127,128],{},"Essas duas ideias removem a maior parte da matemática. Os pares before/after a seguir colapsam todos da mesma forma: um loop imperativo que avança um cursor vira uma pequena árvore declarativa.",[14,130,132],{"id":131},"a-tabela-de-mapeamento-da-api","A tabela de mapeamento da API",[19,134,135],{},"Cola primeiro. As seções depois percorrem cinco pares concretos.",[137,138,139,153],"table",{},[140,141,142],"thead",{},[143,144,145,149,151],"tr",{},[146,147,148],"th",{},"O que você quer fazer",[146,150,28],{},[146,152,24],{},[154,155,156,172,187,202,222,240,258,277,295,311,326,341,356,371,392,414,437,452,467],"tbody",{},[143,157,158,162,167],{},[159,160,161],"td",{},"Construir",[159,163,164],{},[31,165,166],{},"pdf := gopdf.GoPdf{}; pdf.Start(gopdf.Config{...})",[159,168,169],{},[31,170,171],{},"doc := gpdf.NewDocument(gpdf.WithPageSize(document.A4), ...)",[143,173,174,177,182],{},[159,175,176],{},"Tamanho de página",[159,178,179],{},[31,180,181],{},"Config{PageSize: gopdf.PageSizeA4}",[159,183,184],{},[31,185,186],{},"gpdf.WithPageSize(document.A4)",[143,188,189,192,197],{},[159,190,191],{},"Adicionar página",[159,193,194],{},[31,195,196],{},"pdf.AddPage()",[159,198,199],{},[31,200,201],{},"page := doc.AddPage()",[143,203,204,207,217],{},[159,205,206],{},"Mover cursor",[159,208,209,212,213],{},[31,210,211],{},"pdf.SetX(40); pdf.SetY(80)"," ",[214,215,216],"em",{},"(em todo lugar)",[159,218,219],{},[214,220,221],{},"(sem cursor)",[143,223,224,227,232],{},[159,225,226],{},"Texto de uma linha",[159,228,229],{},[31,230,231],{},"pdf.SetXY(x, y); pdf.Cell(nil, \"hi\")",[159,233,234,212,237],{},[31,235,236],{},"c.Text(\"hi\")",[214,238,239],{},"(dentro de uma coluna)",[143,241,242,245,250],{},[159,243,244],{},"Texto com quebra",[159,246,247],{},[31,248,249],{},"pdf.MultiCell(&gopdf.Rect{W: 200, H: 100}, body)",[159,251,252,212,255],{},[31,253,254],{},"c.Text(body)",[214,256,257],{},"(quebra automática)",[143,259,260,263,268],{},[159,261,262],{},"Quebra de linha",[159,264,265],{},[31,266,267],{},"pdf.Br(20)",[159,269,270],{},[214,271,272,273,276],{},"(implícito entre linhas; ",[31,274,275],{},"c.Spacer(document.Mm(4))"," se preciso)",[143,278,279,282,287],{},[159,280,281],{},"Registro de fonte",[159,283,284],{},[31,285,286],{},"pdf.AddTTFFont(\"noto\", \"fonts/Noto.ttf\")",[159,288,289,212,292],{},[31,290,291],{},"gpdf.WithFont(\"Noto\", ttfBytes)",[214,293,294],{},"(na construção)",[143,296,297,300,305],{},[159,298,299],{},"Fonte ativa",[159,301,302],{},[31,303,304],{},"pdf.SetFont(\"noto\", \"\", 14)",[159,306,307,308],{},"por texto: ",[31,309,310],{},"template.FontFamily(\"Noto\"), template.FontSize(14)",[143,312,313,316,321],{},[159,314,315],{},"Cor",[159,317,318],{},[31,319,320],{},"pdf.SetTextColor(26, 35, 126)",[159,322,323],{},[31,324,325],{},"template.TextColor(pdf.RGBHex(0x1A237E))",[143,327,328,331,336],{},[159,329,330],{},"Linha horizontal",[159,332,333],{},[31,334,335],{},"pdf.Line(40, 100, 555, 100)",[159,337,338],{},[31,339,340],{},"c.Line(template.LineColor(pdf.Gray(0.7)))",[143,342,343,346,351],{},[159,344,345],{},"Retângulo",[159,347,348],{},[31,349,350],{},"pdf.RectFromUpperLeftWithStyle(x, y, w, h, \"FD\")",[159,352,353],{},[31,354,355],{},"c.Box(template.BgColor(...), template.Border(...))",[143,357,358,361,366],{},[159,359,360],{},"Imagem",[159,362,363],{},[31,364,365],{},"pdf.Image(\"logo.png\", x, y, &gopdf.Rect{W: 100, H: 50})",[159,367,368],{},[31,369,370],{},"c.Image(imgBytes, template.FitWidth(document.Mm(35)))",[143,372,373,376,387],{},[159,374,375],{},"Tabela manual",[159,377,378,379,381,382,381,385],{},"dezenas de ",[31,380,37],{}," + ",[31,383,384],{},"Line",[31,386,33],{},[159,388,389],{},[31,390,391],{},"c.Table(headers, rows, template.ColumnWidths(...))",[143,393,394,397,406],{},[159,395,396],{},"Cabeçalho / rodapé",[159,398,399,402,403],{},[31,400,401],{},"pdf.AddHeader(fn)"," / ",[31,404,405],{},"pdf.AddFooter(fn)",[159,407,408,402,411],{},[31,409,410],{},"doc.Header(fn)",[31,412,413],{},"doc.Footer(fn)",[143,415,416,419,426],{},[159,417,418],{},"Número de página",[159,420,421,422,425],{},"formatar ",[31,423,424],{},"\"Page %d of %d\""," de um contador próprio",[159,427,428,402,431,212,434],{},[31,429,430],{},"c.PageNumber()",[31,432,433],{},"c.TotalPages()",[214,435,436],{},"(placeholders)",[143,438,439,442,447],{},[159,440,441],{},"Criptografar",[159,443,444],{},[31,445,446],{},"Config{Protection: PDFProtectionConfig{...}}",[159,448,449],{},[31,450,451],{},"gpdf.WithEncryption(gpdf.AES256, \"user\", \"owner\", perms)",[143,453,454,457,462],{},[159,455,456],{},"Saída",[159,458,459],{},[31,460,461],{},"pdf.WritePdf(\"out.pdf\")",[159,463,464],{},[31,465,466],{},"data, _ := doc.Generate(); os.WriteFile(\"out.pdf\", data, 0o644)",[143,468,469,472,480],{},[159,470,471],{},"Saída para writer",[159,473,474,402,477],{},[31,475,476],{},"pdf.Write(w)",[31,478,479],{},"pdf.ToBuffer()",[159,481,482],{},[31,483,484],{},"doc.Render(w)",[19,486,487,488,491,492,494,495,497,498,500,501,504,505,508],{},"Duas mudanças estruturais. Primeiro, ",[22,489,490],{},"o cursor desaparece",". As linhas marcadas ",[214,493,216],{}," na tabela não são exagero — em uma base gopdf real, chamadas ",[31,496,33],{}," superam em número as ",[31,499,37],{},". Todas colapsam para nada em gpdf. Segundo, ",[22,502,503],{},"pixels viram porcentagens",". ",[31,506,507],{},"Rect{W: 200, H: 100}"," vira \"esta coluna toma 4 das 12 unidades do container em que está\". Coloque a mesma coluna dentro de uma linha com metade da largura e ela escala sem mudanças.",[14,510,512],{"id":511},"before-after-1-hello-world","Before / After 1: hello world",[19,514,515],{},"A diferença mais curta possível. Veja o que falta à direita.",[19,517,518],{},[22,519,520],{},"Before — signintech/gopdf:",[522,523,528],"pre",{"className":524,"code":525,"language":526,"meta":527,"style":527},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","package main\n\nimport (\n    \"log\"\n\n    \"github.com/signintech/gopdf\"\n)\n\nfunc main() {\n    pdf := gopdf.GoPdf{}\n    pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})\n    pdf.AddPage()\n\n    if err := pdf.AddTTFFont(\"helvetica\", \"fonts/Helvetica.ttf\"); err != nil {\n        log.Fatal(err)\n    }\n    if err := pdf.SetFont(\"helvetica\", \"\", 24); err != nil {\n        log.Fatal(err)\n    }\n\n    pdf.SetX(40)\n    pdf.SetY(80)\n    if err := pdf.Cell(nil, \"Olá, mundo!\"); err != nil {\n        log.Fatal(err)\n    }\n\n    if err := pdf.WritePdf(\"hello.pdf\"); err != nil {\n        log.Fatal(err)\n    }\n}\n","go","",[31,529,530,543,550,560,572,577,587,593,598,614,636,680,692,697,751,769,775,820,835,840,845,862,879,914,929,934,939,974,989,994],{"__ignoreMap":527},[531,532,535,539],"span",{"class":533,"line":534},"line",1,[531,536,538],{"class":537},"sMK4o","package",[531,540,542],{"class":541},"sBMFI"," main\n",[531,544,546],{"class":533,"line":545},2,[531,547,549],{"emptyLinePlaceholder":548},true,"\n",[531,551,553,557],{"class":533,"line":552},3,[531,554,556],{"class":555},"s7zQu","import",[531,558,559],{"class":537}," (\n",[531,561,563,566,569],{"class":533,"line":562},4,[531,564,565],{"class":537},"    \"",[531,567,568],{"class":541},"log",[531,570,571],{"class":537},"\"\n",[531,573,575],{"class":533,"line":574},5,[531,576,549],{"emptyLinePlaceholder":548},[531,578,580,582,585],{"class":533,"line":579},6,[531,581,565],{"class":537},[531,583,584],{"class":541},"github.com/signintech/gopdf",[531,586,571],{"class":537},[531,588,590],{"class":533,"line":589},7,[531,591,592],{"class":537},")\n",[531,594,596],{"class":533,"line":595},8,[531,597,549],{"emptyLinePlaceholder":548},[531,599,601,604,608,611],{"class":533,"line":600},9,[531,602,603],{"class":537},"func",[531,605,607],{"class":606},"s2Zo4"," main",[531,609,610],{"class":537},"()",[531,612,613],{"class":537}," {\n",[531,615,617,621,624,627,630,633],{"class":533,"line":616},10,[531,618,620],{"class":619},"sTEyZ","    pdf ",[531,622,623],{"class":537},":=",[531,625,626],{"class":541}," gopdf",[531,628,629],{"class":537},".",[531,631,632],{"class":541},"GoPdf",[531,634,635],{"class":537},"{}\n",[531,637,639,642,644,647,650,653,655,658,661,664,667,670,672,674,677],{"class":533,"line":638},11,[531,640,641],{"class":619},"    pdf",[531,643,629],{"class":537},[531,645,646],{"class":606},"Start",[531,648,649],{"class":537},"(",[531,651,652],{"class":541},"gopdf",[531,654,629],{"class":537},[531,656,657],{"class":541},"Config",[531,659,660],{"class":537},"{",[531,662,663],{"class":619},"PageSize",[531,665,666],{"class":537},":",[531,668,669],{"class":537}," *",[531,671,652],{"class":619},[531,673,629],{"class":537},[531,675,676],{"class":619},"PageSizeA4",[531,678,679],{"class":537},"})\n",[531,681,683,685,687,689],{"class":533,"line":682},12,[531,684,641],{"class":619},[531,686,629],{"class":537},[531,688,57],{"class":606},[531,690,691],{"class":537},"()\n",[531,693,695],{"class":533,"line":694},13,[531,696,549],{"emptyLinePlaceholder":548},[531,698,700,703,706,708,711,713,716,718,721,725,727,730,733,736,738,741,743,746,749],{"class":533,"line":699},14,[531,701,702],{"class":555},"    if",[531,704,705],{"class":619}," err ",[531,707,623],{"class":537},[531,709,710],{"class":619}," pdf",[531,712,629],{"class":537},[531,714,715],{"class":606},"AddTTFFont",[531,717,649],{"class":537},[531,719,720],{"class":537},"\"",[531,722,724],{"class":723},"sfazB","helvetica",[531,726,720],{"class":537},[531,728,729],{"class":537},",",[531,731,732],{"class":537}," \"",[531,734,735],{"class":723},"fonts/Helvetica.ttf",[531,737,720],{"class":537},[531,739,740],{"class":537},");",[531,742,705],{"class":619},[531,744,745],{"class":537},"!=",[531,747,748],{"class":537}," nil",[531,750,613],{"class":537},[531,752,754,757,759,762,764,767],{"class":533,"line":753},15,[531,755,756],{"class":619},"        log",[531,758,629],{"class":537},[531,760,761],{"class":606},"Fatal",[531,763,649],{"class":537},[531,765,766],{"class":619},"err",[531,768,592],{"class":537},[531,770,772],{"class":533,"line":771},16,[531,773,774],{"class":537},"    }\n",[531,776,778,780,782,784,786,788,791,793,795,797,799,801,804,806,810,812,814,816,818],{"class":533,"line":777},17,[531,779,702],{"class":555},[531,781,705],{"class":619},[531,783,623],{"class":537},[531,785,710],{"class":619},[531,787,629],{"class":537},[531,789,790],{"class":606},"SetFont",[531,792,649],{"class":537},[531,794,720],{"class":537},[531,796,724],{"class":723},[531,798,720],{"class":537},[531,800,729],{"class":537},[531,802,803],{"class":537}," \"\"",[531,805,729],{"class":537},[531,807,809],{"class":808},"sbssI"," 24",[531,811,740],{"class":537},[531,813,705],{"class":619},[531,815,745],{"class":537},[531,817,748],{"class":537},[531,819,613],{"class":537},[531,821,823,825,827,829,831,833],{"class":533,"line":822},18,[531,824,756],{"class":619},[531,826,629],{"class":537},[531,828,761],{"class":606},[531,830,649],{"class":537},[531,832,766],{"class":619},[531,834,592],{"class":537},[531,836,838],{"class":533,"line":837},19,[531,839,774],{"class":537},[531,841,843],{"class":533,"line":842},20,[531,844,549],{"emptyLinePlaceholder":548},[531,846,848,850,852,855,857,860],{"class":533,"line":847},21,[531,849,641],{"class":619},[531,851,629],{"class":537},[531,853,854],{"class":606},"SetX",[531,856,649],{"class":537},[531,858,859],{"class":808},"40",[531,861,592],{"class":537},[531,863,865,867,869,872,874,877],{"class":533,"line":864},22,[531,866,641],{"class":619},[531,868,629],{"class":537},[531,870,871],{"class":606},"SetY",[531,873,649],{"class":537},[531,875,876],{"class":808},"80",[531,878,592],{"class":537},[531,880,882,884,886,888,890,892,894,897,899,902,904,906,908,910,912],{"class":533,"line":881},23,[531,883,702],{"class":555},[531,885,705],{"class":619},[531,887,623],{"class":537},[531,889,710],{"class":619},[531,891,629],{"class":537},[531,893,37],{"class":606},[531,895,896],{"class":537},"(nil,",[531,898,732],{"class":537},[531,900,901],{"class":723},"Olá, mundo!",[531,903,720],{"class":537},[531,905,740],{"class":537},[531,907,705],{"class":619},[531,909,745],{"class":537},[531,911,748],{"class":537},[531,913,613],{"class":537},[531,915,917,919,921,923,925,927],{"class":533,"line":916},24,[531,918,756],{"class":619},[531,920,629],{"class":537},[531,922,761],{"class":606},[531,924,649],{"class":537},[531,926,766],{"class":619},[531,928,592],{"class":537},[531,930,932],{"class":533,"line":931},25,[531,933,774],{"class":537},[531,935,937],{"class":533,"line":936},26,[531,938,549],{"emptyLinePlaceholder":548},[531,940,942,944,946,948,950,952,955,957,959,962,964,966,968,970,972],{"class":533,"line":941},27,[531,943,702],{"class":555},[531,945,705],{"class":619},[531,947,623],{"class":537},[531,949,710],{"class":619},[531,951,629],{"class":537},[531,953,954],{"class":606},"WritePdf",[531,956,649],{"class":537},[531,958,720],{"class":537},[531,960,961],{"class":723},"hello.pdf",[531,963,720],{"class":537},[531,965,740],{"class":537},[531,967,705],{"class":619},[531,969,745],{"class":537},[531,971,748],{"class":537},[531,973,613],{"class":537},[531,975,977,979,981,983,985,987],{"class":533,"line":976},28,[531,978,756],{"class":619},[531,980,629],{"class":537},[531,982,761],{"class":606},[531,984,649],{"class":537},[531,986,766],{"class":619},[531,988,592],{"class":537},[531,990,992],{"class":533,"line":991},29,[531,993,774],{"class":537},[531,995,997],{"class":533,"line":996},30,[531,998,999],{"class":537},"}\n",[19,1001,1002],{},[22,1003,1004],{},"After — gpdf:",[522,1006,1008],{"className":524,"code":1007,"language":526,"meta":527,"style":527},"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    doc := gpdf.NewDocument(\n        gpdf.WithPageSize(document.A4),\n        gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n    )\n\n    page := doc.AddPage()\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(\"Olá, mundo!\", template.FontSize(24), template.Bold())\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",[31,1009,1010,1016,1020,1026,1034,1043,1047,1056,1065,1074,1078,1082,1092,1110,1133,1168,1173,1177,1193,1225,1261,1307,1312,1317,1321,1341,1353,1367,1371,1415,1429,1434],{"__ignoreMap":527},[531,1011,1012,1014],{"class":533,"line":534},[531,1013,538],{"class":537},[531,1015,542],{"class":541},[531,1017,1018],{"class":533,"line":545},[531,1019,549],{"emptyLinePlaceholder":548},[531,1021,1022,1024],{"class":533,"line":552},[531,1023,556],{"class":555},[531,1025,559],{"class":537},[531,1027,1028,1030,1032],{"class":533,"line":562},[531,1029,565],{"class":537},[531,1031,568],{"class":541},[531,1033,571],{"class":537},[531,1035,1036,1038,1041],{"class":533,"line":574},[531,1037,565],{"class":537},[531,1039,1040],{"class":541},"os",[531,1042,571],{"class":537},[531,1044,1045],{"class":533,"line":579},[531,1046,549],{"emptyLinePlaceholder":548},[531,1048,1049,1051,1054],{"class":533,"line":589},[531,1050,565],{"class":537},[531,1052,1053],{"class":541},"github.com/gpdf-dev/gpdf",[531,1055,571],{"class":537},[531,1057,1058,1060,1063],{"class":533,"line":595},[531,1059,565],{"class":537},[531,1061,1062],{"class":541},"github.com/gpdf-dev/gpdf/document",[531,1064,571],{"class":537},[531,1066,1067,1069,1072],{"class":533,"line":600},[531,1068,565],{"class":537},[531,1070,1071],{"class":541},"github.com/gpdf-dev/gpdf/template",[531,1073,571],{"class":537},[531,1075,1076],{"class":533,"line":616},[531,1077,592],{"class":537},[531,1079,1080],{"class":533,"line":638},[531,1081,549],{"emptyLinePlaceholder":548},[531,1083,1084,1086,1088,1090],{"class":533,"line":682},[531,1085,603],{"class":537},[531,1087,607],{"class":606},[531,1089,610],{"class":537},[531,1091,613],{"class":537},[531,1093,1094,1097,1099,1102,1104,1107],{"class":533,"line":694},[531,1095,1096],{"class":619},"    doc ",[531,1098,623],{"class":537},[531,1100,1101],{"class":619}," gpdf",[531,1103,629],{"class":537},[531,1105,1106],{"class":606},"NewDocument",[531,1108,1109],{"class":537},"(\n",[531,1111,1112,1115,1117,1120,1122,1125,1127,1130],{"class":533,"line":699},[531,1113,1114],{"class":619},"        gpdf",[531,1116,629],{"class":537},[531,1118,1119],{"class":606},"WithPageSize",[531,1121,649],{"class":537},[531,1123,1124],{"class":619},"document",[531,1126,629],{"class":537},[531,1128,1129],{"class":619},"A4",[531,1131,1132],{"class":537},"),\n",[531,1134,1135,1137,1139,1142,1144,1146,1148,1151,1153,1155,1157,1160,1162,1165],{"class":533,"line":753},[531,1136,1114],{"class":619},[531,1138,629],{"class":537},[531,1140,1141],{"class":606},"WithMargins",[531,1143,649],{"class":537},[531,1145,1124],{"class":619},[531,1147,629],{"class":537},[531,1149,1150],{"class":606},"UniformEdges",[531,1152,649],{"class":537},[531,1154,1124],{"class":619},[531,1156,629],{"class":537},[531,1158,1159],{"class":606},"Mm",[531,1161,649],{"class":537},[531,1163,1164],{"class":808},"20",[531,1166,1167],{"class":537},"))),\n",[531,1169,1170],{"class":533,"line":771},[531,1171,1172],{"class":537},"    )\n",[531,1174,1175],{"class":533,"line":777},[531,1176,549],{"emptyLinePlaceholder":548},[531,1178,1179,1182,1184,1187,1189,1191],{"class":533,"line":822},[531,1180,1181],{"class":619},"    page ",[531,1183,623],{"class":537},[531,1185,1186],{"class":619}," doc",[531,1188,629],{"class":537},[531,1190,57],{"class":606},[531,1192,691],{"class":537},[531,1194,1195,1198,1200,1203,1206,1210,1212,1215,1217,1220,1223],{"class":533,"line":837},[531,1196,1197],{"class":619},"    page",[531,1199,629],{"class":537},[531,1201,1202],{"class":606},"AutoRow",[531,1204,1205],{"class":537},"(func(",[531,1207,1209],{"class":1208},"sHdIc","r",[531,1211,669],{"class":537},[531,1213,1214],{"class":541},"template",[531,1216,629],{"class":537},[531,1218,1219],{"class":541},"RowBuilder",[531,1221,1222],{"class":537},")",[531,1224,613],{"class":537},[531,1226,1227,1230,1232,1235,1237,1240,1242,1245,1248,1250,1252,1254,1257,1259],{"class":533,"line":842},[531,1228,1229],{"class":619},"        r",[531,1231,629],{"class":537},[531,1233,1234],{"class":606},"Col",[531,1236,649],{"class":537},[531,1238,1239],{"class":808},"12",[531,1241,729],{"class":537},[531,1243,1244],{"class":537}," func(",[531,1246,1247],{"class":1208},"c",[531,1249,669],{"class":537},[531,1251,1214],{"class":541},[531,1253,629],{"class":537},[531,1255,1256],{"class":541},"ColBuilder",[531,1258,1222],{"class":537},[531,1260,613],{"class":537},[531,1262,1263,1266,1268,1271,1273,1275,1277,1279,1281,1284,1286,1289,1291,1294,1297,1299,1301,1304],{"class":533,"line":847},[531,1264,1265],{"class":619},"            c",[531,1267,629],{"class":537},[531,1269,1270],{"class":606},"Text",[531,1272,649],{"class":537},[531,1274,720],{"class":537},[531,1276,901],{"class":723},[531,1278,720],{"class":537},[531,1280,729],{"class":537},[531,1282,1283],{"class":619}," template",[531,1285,629],{"class":537},[531,1287,1288],{"class":606},"FontSize",[531,1290,649],{"class":537},[531,1292,1293],{"class":808},"24",[531,1295,1296],{"class":537},"),",[531,1298,1283],{"class":619},[531,1300,629],{"class":537},[531,1302,1303],{"class":606},"Bold",[531,1305,1306],{"class":537},"())\n",[531,1308,1309],{"class":533,"line":864},[531,1310,1311],{"class":537},"        })\n",[531,1313,1314],{"class":533,"line":881},[531,1315,1316],{"class":537},"    })\n",[531,1318,1319],{"class":533,"line":916},[531,1320,549],{"emptyLinePlaceholder":548},[531,1322,1323,1326,1328,1330,1332,1334,1336,1339],{"class":533,"line":931},[531,1324,1325],{"class":619},"    data",[531,1327,729],{"class":537},[531,1329,705],{"class":619},[531,1331,623],{"class":537},[531,1333,1186],{"class":619},[531,1335,629],{"class":537},[531,1337,1338],{"class":606},"Generate",[531,1340,691],{"class":537},[531,1342,1343,1345,1347,1349,1351],{"class":533,"line":936},[531,1344,702],{"class":555},[531,1346,705],{"class":619},[531,1348,745],{"class":537},[531,1350,748],{"class":537},[531,1352,613],{"class":537},[531,1354,1355,1357,1359,1361,1363,1365],{"class":533,"line":941},[531,1356,756],{"class":619},[531,1358,629],{"class":537},[531,1360,761],{"class":606},[531,1362,649],{"class":537},[531,1364,766],{"class":619},[531,1366,592],{"class":537},[531,1368,1369],{"class":533,"line":976},[531,1370,774],{"class":537},[531,1372,1373,1375,1377,1379,1382,1384,1387,1389,1391,1393,1395,1397,1400,1402,1405,1407,1409,1411,1413],{"class":533,"line":991},[531,1374,702],{"class":555},[531,1376,705],{"class":619},[531,1378,623],{"class":537},[531,1380,1381],{"class":619}," os",[531,1383,629],{"class":537},[531,1385,1386],{"class":606},"WriteFile",[531,1388,649],{"class":537},[531,1390,720],{"class":537},[531,1392,961],{"class":723},[531,1394,720],{"class":537},[531,1396,729],{"class":537},[531,1398,1399],{"class":619}," data",[531,1401,729],{"class":537},[531,1403,1404],{"class":808}," 0o644",[531,1406,740],{"class":537},[531,1408,705],{"class":619},[531,1410,745],{"class":537},[531,1412,748],{"class":537},[531,1414,613],{"class":537},[531,1416,1417,1419,1421,1423,1425,1427],{"class":533,"line":996},[531,1418,756],{"class":619},[531,1420,629],{"class":537},[531,1422,761],{"class":606},[531,1424,649],{"class":537},[531,1426,766],{"class":619},[531,1428,592],{"class":537},[531,1430,1432],{"class":533,"line":1431},31,[531,1433,774],{"class":537},[531,1435,1437],{"class":533,"line":1436},32,[531,1438,999],{"class":537},[19,1440,1441,1442,1445],{},"Duas coisas sumiram. O arquivo TTF não é mais exigido em runtime — Helvetica é parte das 14 fontes padrão e gpdf as embute. O ",[31,1443,1444],{},"SetX(40); SetY(80)"," foi embora — a linha se acomoda dentro das margens automaticamente. O que foi adicionado: uma linha com uma coluna ocupando todas as 12 unidades. Esse andaime parece pesado para \"Olá, mundo!\", mas é o mesmo que sustenta um relatório de 100 páginas — esse é o ponto.",[14,1447,1449],{"id":1448},"before-after-2-uma-linha-de-cabeçalho-de-4-colunas","Before / After 2: uma linha de cabeçalho de 4 colunas",[19,1451,1452],{},"Aqui é onde a matemática de coordenadas mais aparece. Você quer uma faixa de cabeçalho atravessando a página com quatro células iguais: largura da página menos margens, dividida por 4. No gopdf, você faz essa divisão. No gpdf, você gasta 12 unidades em quatro maneiras.",[19,1454,1455],{},[22,1456,520],{},[522,1458,1460],{"className":524,"code":1459,"language":526,"meta":527,"style":527},"const (\n    pageWidth   = 595.28 // A4 (pt)\n    leftMargin  = 40.0\n    rightMargin = 40.0\n    rowY        = 100.0\n    rowH        = 24.0\n)\n\ncontentWidth := pageWidth - leftMargin - rightMargin // 515.28\ncolW := contentWidth / 4                              // 128.82\n\npdf.SetFont(\"helvetica-bold\", \"\", 11)\npdf.SetFillColor(26, 35, 126)\npdf.SetTextColor(255, 255, 255)\n\nheaders := []string{\"Descrição\", \"Qtd\", \"Unitário\", \"Valor\"}\nfor i, h := range headers {\n    x := leftMargin + colW*float64(i)\n    pdf.RectFromUpperLeftWithStyle(x, rowY, colW, rowH, \"F\")\n\n    pdf.SetXY(x+6, rowY+7)\n    if err := pdf.Cell(nil, h); err != nil {\n        log.Fatal(err)\n    }\n}\n\npdf.SetTextColor(0, 0, 0)\n",[31,1461,1462,1469,1484,1494,1503,1513,1523,1527,1531,1555,1574,1578,1607,1633,1658,1662,1714,1738,1766,1805,1809,1837,1866,1880,1884,1888,1892],{"__ignoreMap":527},[531,1463,1464,1467],{"class":533,"line":534},[531,1465,1466],{"class":537},"const",[531,1468,559],{"class":537},[531,1470,1471,1474,1477,1480],{"class":533,"line":545},[531,1472,1473],{"class":619},"    pageWidth   ",[531,1475,1476],{"class":537},"=",[531,1478,1479],{"class":808}," 595.28",[531,1481,1483],{"class":1482},"sHwdD"," // A4 (pt)\n",[531,1485,1486,1489,1491],{"class":533,"line":552},[531,1487,1488],{"class":619},"    leftMargin  ",[531,1490,1476],{"class":537},[531,1492,1493],{"class":808}," 40.0\n",[531,1495,1496,1499,1501],{"class":533,"line":562},[531,1497,1498],{"class":619},"    rightMargin ",[531,1500,1476],{"class":537},[531,1502,1493],{"class":808},[531,1504,1505,1508,1510],{"class":533,"line":574},[531,1506,1507],{"class":619},"    rowY        ",[531,1509,1476],{"class":537},[531,1511,1512],{"class":808}," 100.0\n",[531,1514,1515,1518,1520],{"class":533,"line":579},[531,1516,1517],{"class":619},"    rowH        ",[531,1519,1476],{"class":537},[531,1521,1522],{"class":808}," 24.0\n",[531,1524,1525],{"class":533,"line":589},[531,1526,592],{"class":537},[531,1528,1529],{"class":533,"line":595},[531,1530,549],{"emptyLinePlaceholder":548},[531,1532,1533,1536,1538,1541,1544,1547,1549,1552],{"class":533,"line":600},[531,1534,1535],{"class":619},"contentWidth ",[531,1537,623],{"class":537},[531,1539,1540],{"class":619}," pageWidth ",[531,1542,1543],{"class":537},"-",[531,1545,1546],{"class":619}," leftMargin ",[531,1548,1543],{"class":537},[531,1550,1551],{"class":619}," rightMargin ",[531,1553,1554],{"class":1482},"// 515.28\n",[531,1556,1557,1560,1562,1565,1568,1571],{"class":533,"line":616},[531,1558,1559],{"class":619},"colW ",[531,1561,623],{"class":537},[531,1563,1564],{"class":619}," contentWidth ",[531,1566,1567],{"class":537},"/",[531,1569,1570],{"class":808}," 4",[531,1572,1573],{"class":1482},"                              // 128.82\n",[531,1575,1576],{"class":533,"line":638},[531,1577,549],{"emptyLinePlaceholder":548},[531,1579,1580,1583,1585,1587,1589,1591,1594,1596,1598,1600,1602,1605],{"class":533,"line":682},[531,1581,1582],{"class":619},"pdf",[531,1584,629],{"class":537},[531,1586,790],{"class":606},[531,1588,649],{"class":537},[531,1590,720],{"class":537},[531,1592,1593],{"class":723},"helvetica-bold",[531,1595,720],{"class":537},[531,1597,729],{"class":537},[531,1599,803],{"class":537},[531,1601,729],{"class":537},[531,1603,1604],{"class":808}," 11",[531,1606,592],{"class":537},[531,1608,1609,1611,1613,1616,1618,1621,1623,1626,1628,1631],{"class":533,"line":694},[531,1610,1582],{"class":619},[531,1612,629],{"class":537},[531,1614,1615],{"class":606},"SetFillColor",[531,1617,649],{"class":537},[531,1619,1620],{"class":808},"26",[531,1622,729],{"class":537},[531,1624,1625],{"class":808}," 35",[531,1627,729],{"class":537},[531,1629,1630],{"class":808}," 126",[531,1632,592],{"class":537},[531,1634,1635,1637,1639,1642,1644,1647,1649,1652,1654,1656],{"class":533,"line":699},[531,1636,1582],{"class":619},[531,1638,629],{"class":537},[531,1640,1641],{"class":606},"SetTextColor",[531,1643,649],{"class":537},[531,1645,1646],{"class":808},"255",[531,1648,729],{"class":537},[531,1650,1651],{"class":808}," 255",[531,1653,729],{"class":537},[531,1655,1651],{"class":808},[531,1657,592],{"class":537},[531,1659,1660],{"class":533,"line":753},[531,1661,549],{"emptyLinePlaceholder":548},[531,1663,1664,1667,1669,1672,1676,1678,1680,1683,1685,1687,1689,1692,1694,1696,1698,1701,1703,1705,1707,1710,1712],{"class":533,"line":771},[531,1665,1666],{"class":619},"headers ",[531,1668,623],{"class":537},[531,1670,1671],{"class":537}," []",[531,1673,1675],{"class":1674},"spNyl","string",[531,1677,660],{"class":537},[531,1679,720],{"class":537},[531,1681,1682],{"class":723},"Descrição",[531,1684,720],{"class":537},[531,1686,729],{"class":537},[531,1688,732],{"class":537},[531,1690,1691],{"class":723},"Qtd",[531,1693,720],{"class":537},[531,1695,729],{"class":537},[531,1697,732],{"class":537},[531,1699,1700],{"class":723},"Unitário",[531,1702,720],{"class":537},[531,1704,729],{"class":537},[531,1706,732],{"class":537},[531,1708,1709],{"class":723},"Valor",[531,1711,720],{"class":537},[531,1713,999],{"class":537},[531,1715,1716,1719,1722,1724,1727,1729,1732,1735],{"class":533,"line":777},[531,1717,1718],{"class":555},"for",[531,1720,1721],{"class":619}," i",[531,1723,729],{"class":537},[531,1725,1726],{"class":619}," h ",[531,1728,623],{"class":537},[531,1730,1731],{"class":555}," range",[531,1733,1734],{"class":619}," headers ",[531,1736,1737],{"class":537},"{\n",[531,1739,1740,1743,1745,1747,1750,1753,1756,1759,1761,1764],{"class":533,"line":822},[531,1741,1742],{"class":619},"    x ",[531,1744,623],{"class":537},[531,1746,1546],{"class":619},[531,1748,1749],{"class":537},"+",[531,1751,1752],{"class":619}," colW",[531,1754,1755],{"class":537},"*",[531,1757,1758],{"class":1674},"float64",[531,1760,649],{"class":537},[531,1762,1763],{"class":619},"i",[531,1765,592],{"class":537},[531,1767,1768,1770,1772,1775,1777,1780,1782,1785,1787,1789,1791,1794,1796,1798,1801,1803],{"class":533,"line":837},[531,1769,641],{"class":619},[531,1771,629],{"class":537},[531,1773,1774],{"class":606},"RectFromUpperLeftWithStyle",[531,1776,649],{"class":537},[531,1778,1779],{"class":619},"x",[531,1781,729],{"class":537},[531,1783,1784],{"class":619}," rowY",[531,1786,729],{"class":537},[531,1788,1752],{"class":619},[531,1790,729],{"class":537},[531,1792,1793],{"class":619}," rowH",[531,1795,729],{"class":537},[531,1797,732],{"class":537},[531,1799,1800],{"class":723},"F",[531,1802,720],{"class":537},[531,1804,592],{"class":537},[531,1806,1807],{"class":533,"line":842},[531,1808,549],{"emptyLinePlaceholder":548},[531,1810,1811,1813,1815,1817,1819,1821,1823,1826,1828,1830,1832,1835],{"class":533,"line":847},[531,1812,641],{"class":619},[531,1814,629],{"class":537},[531,1816,33],{"class":606},[531,1818,649],{"class":537},[531,1820,1779],{"class":619},[531,1822,1749],{"class":537},[531,1824,1825],{"class":808},"6",[531,1827,729],{"class":537},[531,1829,1784],{"class":619},[531,1831,1749],{"class":537},[531,1833,1834],{"class":808},"7",[531,1836,592],{"class":537},[531,1838,1839,1841,1843,1845,1847,1849,1851,1853,1856,1858,1860,1862,1864],{"class":533,"line":864},[531,1840,702],{"class":555},[531,1842,705],{"class":619},[531,1844,623],{"class":537},[531,1846,710],{"class":619},[531,1848,629],{"class":537},[531,1850,37],{"class":606},[531,1852,896],{"class":537},[531,1854,1855],{"class":619}," h",[531,1857,740],{"class":537},[531,1859,705],{"class":619},[531,1861,745],{"class":537},[531,1863,748],{"class":537},[531,1865,613],{"class":537},[531,1867,1868,1870,1872,1874,1876,1878],{"class":533,"line":881},[531,1869,756],{"class":619},[531,1871,629],{"class":537},[531,1873,761],{"class":606},[531,1875,649],{"class":537},[531,1877,766],{"class":619},[531,1879,592],{"class":537},[531,1881,1882],{"class":533,"line":916},[531,1883,774],{"class":537},[531,1885,1886],{"class":533,"line":931},[531,1887,999],{"class":537},[531,1889,1890],{"class":533,"line":936},[531,1891,549],{"emptyLinePlaceholder":548},[531,1893,1894,1896,1898,1900,1902,1905,1907,1910,1912,1914],{"class":533,"line":941},[531,1895,1582],{"class":619},[531,1897,629],{"class":537},[531,1899,1641],{"class":606},[531,1901,649],{"class":537},[531,1903,1904],{"class":808},"0",[531,1906,729],{"class":537},[531,1908,1909],{"class":808}," 0",[531,1911,729],{"class":537},[531,1913,1909],{"class":808},[531,1915,592],{"class":537},[19,1917,1918,1919,1922,1923,1925],{},"Quatro constantes. Uma subtração de larguras. Uma divisão. Um loop com ",[31,1920,1921],{},"colW*float64(i)"," — e aquele cast para float só está ali porque o ",[31,1924,1755],{}," de Go não promove int para float64. Nada disso existe na versão gpdf.",[19,1927,1928],{},[22,1929,1004],{},[522,1931,1933],{"className":524,"code":1932,"language":526,"meta":527,"style":527},"page.AutoRow(func(r *template.RowBuilder) {\n    headers := []string{\"Descrição\", \"Qtd\", \"Unitário\", \"Valor\"}\n    for _, h := range headers {\n        r.Col(3, func(c *template.ColBuilder) {\n            c.Box(\n                template.BgColor(pdf.RGBHex(0x1A237E)),\n                template.Padding(document.Mm(2), document.Mm(3)),\n            )\n            c.Text(h,\n                template.Bold(), template.FontSize(11),\n                template.TextColor(pdf.White),\n            )\n        })\n    }\n})\n",[31,1934,1935,1960,2005,2025,2056,2067,2094,2131,2136,2152,2176,2196,2200,2204,2208],{"__ignoreMap":527},[531,1936,1937,1940,1942,1944,1946,1948,1950,1952,1954,1956,1958],{"class":533,"line":534},[531,1938,1939],{"class":619},"page",[531,1941,629],{"class":537},[531,1943,1202],{"class":606},[531,1945,1205],{"class":537},[531,1947,1209],{"class":1208},[531,1949,669],{"class":537},[531,1951,1214],{"class":541},[531,1953,629],{"class":537},[531,1955,1219],{"class":541},[531,1957,1222],{"class":537},[531,1959,613],{"class":537},[531,1961,1962,1965,1967,1969,1971,1973,1975,1977,1979,1981,1983,1985,1987,1989,1991,1993,1995,1997,1999,2001,2003],{"class":533,"line":545},[531,1963,1964],{"class":619},"    headers ",[531,1966,623],{"class":537},[531,1968,1671],{"class":537},[531,1970,1675],{"class":1674},[531,1972,660],{"class":537},[531,1974,720],{"class":537},[531,1976,1682],{"class":723},[531,1978,720],{"class":537},[531,1980,729],{"class":537},[531,1982,732],{"class":537},[531,1984,1691],{"class":723},[531,1986,720],{"class":537},[531,1988,729],{"class":537},[531,1990,732],{"class":537},[531,1992,1700],{"class":723},[531,1994,720],{"class":537},[531,1996,729],{"class":537},[531,1998,732],{"class":537},[531,2000,1709],{"class":723},[531,2002,720],{"class":537},[531,2004,999],{"class":537},[531,2006,2007,2010,2013,2015,2017,2019,2021,2023],{"class":533,"line":552},[531,2008,2009],{"class":555},"    for",[531,2011,2012],{"class":619}," _",[531,2014,729],{"class":537},[531,2016,1726],{"class":619},[531,2018,623],{"class":537},[531,2020,1731],{"class":555},[531,2022,1734],{"class":619},[531,2024,1737],{"class":537},[531,2026,2027,2029,2031,2033,2035,2038,2040,2042,2044,2046,2048,2050,2052,2054],{"class":533,"line":562},[531,2028,1229],{"class":619},[531,2030,629],{"class":537},[531,2032,1234],{"class":606},[531,2034,649],{"class":537},[531,2036,2037],{"class":808},"3",[531,2039,729],{"class":537},[531,2041,1244],{"class":537},[531,2043,1247],{"class":1208},[531,2045,669],{"class":537},[531,2047,1214],{"class":541},[531,2049,629],{"class":537},[531,2051,1256],{"class":541},[531,2053,1222],{"class":537},[531,2055,613],{"class":537},[531,2057,2058,2060,2062,2065],{"class":533,"line":574},[531,2059,1265],{"class":619},[531,2061,629],{"class":537},[531,2063,2064],{"class":606},"Box",[531,2066,1109],{"class":537},[531,2068,2069,2072,2074,2077,2079,2081,2083,2086,2088,2091],{"class":533,"line":579},[531,2070,2071],{"class":619},"                template",[531,2073,629],{"class":537},[531,2075,2076],{"class":606},"BgColor",[531,2078,649],{"class":537},[531,2080,1582],{"class":619},[531,2082,629],{"class":537},[531,2084,2085],{"class":606},"RGBHex",[531,2087,649],{"class":537},[531,2089,2090],{"class":808},"0x1A237E",[531,2092,2093],{"class":537},")),\n",[531,2095,2096,2098,2100,2103,2105,2107,2109,2111,2113,2116,2118,2121,2123,2125,2127,2129],{"class":533,"line":589},[531,2097,2071],{"class":619},[531,2099,629],{"class":537},[531,2101,2102],{"class":606},"Padding",[531,2104,649],{"class":537},[531,2106,1124],{"class":619},[531,2108,629],{"class":537},[531,2110,1159],{"class":606},[531,2112,649],{"class":537},[531,2114,2115],{"class":808},"2",[531,2117,1296],{"class":537},[531,2119,2120],{"class":619}," document",[531,2122,629],{"class":537},[531,2124,1159],{"class":606},[531,2126,649],{"class":537},[531,2128,2037],{"class":808},[531,2130,2093],{"class":537},[531,2132,2133],{"class":533,"line":595},[531,2134,2135],{"class":537},"            )\n",[531,2137,2138,2140,2142,2144,2146,2149],{"class":533,"line":600},[531,2139,1265],{"class":619},[531,2141,629],{"class":537},[531,2143,1270],{"class":606},[531,2145,649],{"class":537},[531,2147,2148],{"class":619},"h",[531,2150,2151],{"class":537},",\n",[531,2153,2154,2156,2158,2160,2163,2165,2167,2169,2171,2174],{"class":533,"line":616},[531,2155,2071],{"class":619},[531,2157,629],{"class":537},[531,2159,1303],{"class":606},[531,2161,2162],{"class":537},"(),",[531,2164,1283],{"class":619},[531,2166,629],{"class":537},[531,2168,1288],{"class":606},[531,2170,649],{"class":537},[531,2172,2173],{"class":808},"11",[531,2175,1132],{"class":537},[531,2177,2178,2180,2182,2185,2187,2189,2191,2194],{"class":533,"line":638},[531,2179,2071],{"class":619},[531,2181,629],{"class":537},[531,2183,2184],{"class":606},"TextColor",[531,2186,649],{"class":537},[531,2188,1582],{"class":619},[531,2190,629],{"class":537},[531,2192,2193],{"class":619},"White",[531,2195,1132],{"class":537},[531,2197,2198],{"class":533,"line":682},[531,2199,2135],{"class":537},[531,2201,2202],{"class":533,"line":694},[531,2203,1311],{"class":537},[531,2205,2206],{"class":533,"line":699},[531,2207,774],{"class":537},[531,2209,2210],{"class":533,"line":753},[531,2211,679],{"class":537},[19,2213,2214,2216,2217,2220,2221,2224,2225,2228],{},[31,2215,124],{}," quatro vezes soma 12. A grade cuida das larguras. Trocar A4 por Letter, ou diminuir margens, e o cabeçalho continua alinhado porque nada aqui depende de ",[31,2218,2219],{},"pageWidth",". Para que a coluna 1 seja o dobro da largura das outras três, mude-a para ",[31,2222,2223],{},"r.Col(6, ...)"," e uma das outras para ",[31,2226,2227],{},"r.Col(2, ...)",". Sem aritmética.",[14,2230,2232],{"id":2231},"before-after-3-uma-tabela-de-nf-que-atravessa-páginas","Before / After 3: uma tabela de NF que atravessa páginas",[19,2234,2235,2236,2238],{},"A grande. No gopdf, desenhar uma tabela que flui por várias páginas é quase totalmente bookkeeping: você rastreia a y atual, desenha cada linha, verifica se a próxima cabe e, se não, chama ",[31,2237,57],{}," e reimprime o cabeçalho. A máquina de estados está no seu código.",[19,2240,2241],{},[22,2242,520],{},[522,2244,2246],{"className":524,"code":2245,"language":526,"meta":527,"style":527},"func drawInvoiceTable(pdf *gopdf.GoPdf, items [][4]string) error {\n    const (\n        pageH       = 841.89 // altura A4\n        bottomLimit = pageH - 40\n        rowH        = 22.0\n        leftX       = 40.0\n    )\n    cols := []float64{260, 80, 80, 95}\n\n    drawHeader := func(y float64) float64 {\n        pdf.SetFont(\"helvetica-bold\", \"\", 11)\n        pdf.SetFillColor(26, 35, 126)\n        pdf.SetTextColor(255, 255, 255)\n        x := leftX\n        for i, h := range []string{\"Descrição\", \"Qtd\", \"Unitário\", \"Valor\"} {\n            pdf.RectFromUpperLeftWithStyle(x, y, cols[i], rowH, \"F\")\n            pdf.SetXY(x+6, y+7)\n            if err := pdf.Cell(nil, h); err != nil {\n                log.Println(err)\n            }\n            x += cols[i]\n        }\n        pdf.SetTextColor(0, 0, 0)\n        pdf.SetFont(\"helvetica\", \"\", 11)\n        return y + rowH\n    }\n\n    y := drawHeader(100)\n    for _, row := range items {\n        if y+rowH > bottomLimit {\n            pdf.AddPage()\n            y = drawHeader(60)\n        }\n\n        x := leftX\n        for i, cell := range row {\n            pdf.RectFromUpperLeftWithStyle(x, y, cols[i], rowH, \"D\")\n            pdf.SetXY(x+6, y+7)\n            if err := pdf.Cell(nil, cell); err != nil {\n                return err\n            }\n            x += cols[i]\n        }\n        y += rowH\n    }\n    return nil\n}\n",[31,2247,2248,2290,2297,2310,2325,2335,2344,2348,2380,2384,2405,2432,2454,2476,2486,2542,2585,2611,2640,2656,2661,2678,2683,2705,2731,2744,2748,2752,2769,2789,2809,2819,2835,2840,2845,2854,2874,2914,2941,2971,2980,2985,3000,3005,3015,3020,3029],{"__ignoreMap":527},[531,2249,2250,2252,2255,2257,2259,2261,2263,2265,2267,2269,2272,2275,2278,2281,2283,2285,2288],{"class":533,"line":534},[531,2251,603],{"class":537},[531,2253,2254],{"class":606}," drawInvoiceTable",[531,2256,649],{"class":537},[531,2258,1582],{"class":1208},[531,2260,669],{"class":537},[531,2262,652],{"class":541},[531,2264,629],{"class":537},[531,2266,632],{"class":541},[531,2268,729],{"class":537},[531,2270,2271],{"class":1208}," items",[531,2273,2274],{"class":537}," [][",[531,2276,2277],{"class":808},"4",[531,2279,2280],{"class":537},"]",[531,2282,1675],{"class":1674},[531,2284,1222],{"class":537},[531,2286,2287],{"class":1674}," error",[531,2289,613],{"class":537},[531,2291,2292,2295],{"class":533,"line":545},[531,2293,2294],{"class":537},"    const",[531,2296,559],{"class":537},[531,2298,2299,2302,2304,2307],{"class":533,"line":552},[531,2300,2301],{"class":619},"        pageH       ",[531,2303,1476],{"class":537},[531,2305,2306],{"class":808}," 841.89",[531,2308,2309],{"class":1482}," // altura A4\n",[531,2311,2312,2315,2317,2320,2322],{"class":533,"line":562},[531,2313,2314],{"class":619},"        bottomLimit ",[531,2316,1476],{"class":537},[531,2318,2319],{"class":619}," pageH ",[531,2321,1543],{"class":537},[531,2323,2324],{"class":808}," 40\n",[531,2326,2327,2330,2332],{"class":533,"line":574},[531,2328,2329],{"class":619},"        rowH        ",[531,2331,1476],{"class":537},[531,2333,2334],{"class":808}," 22.0\n",[531,2336,2337,2340,2342],{"class":533,"line":579},[531,2338,2339],{"class":619},"        leftX       ",[531,2341,1476],{"class":537},[531,2343,1493],{"class":808},[531,2345,2346],{"class":533,"line":589},[531,2347,1172],{"class":537},[531,2349,2350,2353,2355,2357,2359,2361,2364,2366,2369,2371,2373,2375,2378],{"class":533,"line":595},[531,2351,2352],{"class":619},"    cols ",[531,2354,623],{"class":537},[531,2356,1671],{"class":537},[531,2358,1758],{"class":1674},[531,2360,660],{"class":537},[531,2362,2363],{"class":808},"260",[531,2365,729],{"class":537},[531,2367,2368],{"class":808}," 80",[531,2370,729],{"class":537},[531,2372,2368],{"class":808},[531,2374,729],{"class":537},[531,2376,2377],{"class":808}," 95",[531,2379,999],{"class":537},[531,2381,2382],{"class":533,"line":600},[531,2383,549],{"emptyLinePlaceholder":548},[531,2385,2386,2389,2391,2393,2396,2399,2401,2403],{"class":533,"line":616},[531,2387,2388],{"class":619},"    drawHeader ",[531,2390,623],{"class":537},[531,2392,1244],{"class":537},[531,2394,2395],{"class":1208},"y",[531,2397,2398],{"class":1674}," float64",[531,2400,1222],{"class":537},[531,2402,2398],{"class":1674},[531,2404,613],{"class":537},[531,2406,2407,2410,2412,2414,2416,2418,2420,2422,2424,2426,2428,2430],{"class":533,"line":638},[531,2408,2409],{"class":619},"        pdf",[531,2411,629],{"class":537},[531,2413,790],{"class":606},[531,2415,649],{"class":537},[531,2417,720],{"class":537},[531,2419,1593],{"class":723},[531,2421,720],{"class":537},[531,2423,729],{"class":537},[531,2425,803],{"class":537},[531,2427,729],{"class":537},[531,2429,1604],{"class":808},[531,2431,592],{"class":537},[531,2433,2434,2436,2438,2440,2442,2444,2446,2448,2450,2452],{"class":533,"line":682},[531,2435,2409],{"class":619},[531,2437,629],{"class":537},[531,2439,1615],{"class":606},[531,2441,649],{"class":537},[531,2443,1620],{"class":808},[531,2445,729],{"class":537},[531,2447,1625],{"class":808},[531,2449,729],{"class":537},[531,2451,1630],{"class":808},[531,2453,592],{"class":537},[531,2455,2456,2458,2460,2462,2464,2466,2468,2470,2472,2474],{"class":533,"line":694},[531,2457,2409],{"class":619},[531,2459,629],{"class":537},[531,2461,1641],{"class":606},[531,2463,649],{"class":537},[531,2465,1646],{"class":808},[531,2467,729],{"class":537},[531,2469,1651],{"class":808},[531,2471,729],{"class":537},[531,2473,1651],{"class":808},[531,2475,592],{"class":537},[531,2477,2478,2481,2483],{"class":533,"line":699},[531,2479,2480],{"class":619},"        x ",[531,2482,623],{"class":537},[531,2484,2485],{"class":619}," leftX\n",[531,2487,2488,2491,2493,2495,2497,2499,2501,2503,2505,2507,2509,2511,2513,2515,2517,2519,2521,2523,2525,2527,2529,2531,2533,2535,2537,2540],{"class":533,"line":753},[531,2489,2490],{"class":555},"        for",[531,2492,1721],{"class":619},[531,2494,729],{"class":537},[531,2496,1726],{"class":619},[531,2498,623],{"class":537},[531,2500,1731],{"class":555},[531,2502,1671],{"class":537},[531,2504,1675],{"class":1674},[531,2506,660],{"class":537},[531,2508,720],{"class":537},[531,2510,1682],{"class":723},[531,2512,720],{"class":537},[531,2514,729],{"class":537},[531,2516,732],{"class":537},[531,2518,1691],{"class":723},[531,2520,720],{"class":537},[531,2522,729],{"class":537},[531,2524,732],{"class":537},[531,2526,1700],{"class":723},[531,2528,720],{"class":537},[531,2530,729],{"class":537},[531,2532,732],{"class":537},[531,2534,1709],{"class":723},[531,2536,720],{"class":537},[531,2538,2539],{"class":537},"}",[531,2541,613],{"class":537},[531,2543,2544,2547,2549,2551,2553,2555,2557,2560,2562,2565,2568,2570,2573,2575,2577,2579,2581,2583],{"class":533,"line":771},[531,2545,2546],{"class":619},"            pdf",[531,2548,629],{"class":537},[531,2550,1774],{"class":606},[531,2552,649],{"class":537},[531,2554,1779],{"class":619},[531,2556,729],{"class":537},[531,2558,2559],{"class":619}," y",[531,2561,729],{"class":537},[531,2563,2564],{"class":619}," cols",[531,2566,2567],{"class":537},"[",[531,2569,1763],{"class":619},[531,2571,2572],{"class":537},"],",[531,2574,1793],{"class":619},[531,2576,729],{"class":537},[531,2578,732],{"class":537},[531,2580,1800],{"class":723},[531,2582,720],{"class":537},[531,2584,592],{"class":537},[531,2586,2587,2589,2591,2593,2595,2597,2599,2601,2603,2605,2607,2609],{"class":533,"line":777},[531,2588,2546],{"class":619},[531,2590,629],{"class":537},[531,2592,33],{"class":606},[531,2594,649],{"class":537},[531,2596,1779],{"class":619},[531,2598,1749],{"class":537},[531,2600,1825],{"class":808},[531,2602,729],{"class":537},[531,2604,2559],{"class":619},[531,2606,1749],{"class":537},[531,2608,1834],{"class":808},[531,2610,592],{"class":537},[531,2612,2613,2616,2618,2620,2622,2624,2626,2628,2630,2632,2634,2636,2638],{"class":533,"line":822},[531,2614,2615],{"class":555},"            if",[531,2617,705],{"class":619},[531,2619,623],{"class":537},[531,2621,710],{"class":619},[531,2623,629],{"class":537},[531,2625,37],{"class":606},[531,2627,896],{"class":537},[531,2629,1855],{"class":619},[531,2631,740],{"class":537},[531,2633,705],{"class":619},[531,2635,745],{"class":537},[531,2637,748],{"class":537},[531,2639,613],{"class":537},[531,2641,2642,2645,2647,2650,2652,2654],{"class":533,"line":837},[531,2643,2644],{"class":619},"                log",[531,2646,629],{"class":537},[531,2648,2649],{"class":606},"Println",[531,2651,649],{"class":537},[531,2653,766],{"class":619},[531,2655,592],{"class":537},[531,2657,2658],{"class":533,"line":842},[531,2659,2660],{"class":537},"            }\n",[531,2662,2663,2666,2669,2671,2673,2675],{"class":533,"line":847},[531,2664,2665],{"class":619},"            x ",[531,2667,2668],{"class":537},"+=",[531,2670,2564],{"class":619},[531,2672,2567],{"class":537},[531,2674,1763],{"class":619},[531,2676,2677],{"class":537},"]\n",[531,2679,2680],{"class":533,"line":864},[531,2681,2682],{"class":537},"        }\n",[531,2684,2685,2687,2689,2691,2693,2695,2697,2699,2701,2703],{"class":533,"line":881},[531,2686,2409],{"class":619},[531,2688,629],{"class":537},[531,2690,1641],{"class":606},[531,2692,649],{"class":537},[531,2694,1904],{"class":808},[531,2696,729],{"class":537},[531,2698,1909],{"class":808},[531,2700,729],{"class":537},[531,2702,1909],{"class":808},[531,2704,592],{"class":537},[531,2706,2707,2709,2711,2713,2715,2717,2719,2721,2723,2725,2727,2729],{"class":533,"line":916},[531,2708,2409],{"class":619},[531,2710,629],{"class":537},[531,2712,790],{"class":606},[531,2714,649],{"class":537},[531,2716,720],{"class":537},[531,2718,724],{"class":723},[531,2720,720],{"class":537},[531,2722,729],{"class":537},[531,2724,803],{"class":537},[531,2726,729],{"class":537},[531,2728,1604],{"class":808},[531,2730,592],{"class":537},[531,2732,2733,2736,2739,2741],{"class":533,"line":931},[531,2734,2735],{"class":555},"        return",[531,2737,2738],{"class":619}," y ",[531,2740,1749],{"class":537},[531,2742,2743],{"class":619}," rowH\n",[531,2745,2746],{"class":533,"line":936},[531,2747,774],{"class":537},[531,2749,2750],{"class":533,"line":941},[531,2751,549],{"emptyLinePlaceholder":548},[531,2753,2754,2757,2759,2762,2764,2767],{"class":533,"line":976},[531,2755,2756],{"class":619},"    y ",[531,2758,623],{"class":537},[531,2760,2761],{"class":606}," drawHeader",[531,2763,649],{"class":537},[531,2765,2766],{"class":808},"100",[531,2768,592],{"class":537},[531,2770,2771,2773,2775,2777,2780,2782,2784,2787],{"class":533,"line":991},[531,2772,2009],{"class":555},[531,2774,2012],{"class":619},[531,2776,729],{"class":537},[531,2778,2779],{"class":619}," row ",[531,2781,623],{"class":537},[531,2783,1731],{"class":555},[531,2785,2786],{"class":619}," items ",[531,2788,1737],{"class":537},[531,2790,2791,2794,2796,2798,2801,2804,2807],{"class":533,"line":996},[531,2792,2793],{"class":555},"        if",[531,2795,2559],{"class":619},[531,2797,1749],{"class":537},[531,2799,2800],{"class":619},"rowH ",[531,2802,2803],{"class":537},">",[531,2805,2806],{"class":619}," bottomLimit ",[531,2808,1737],{"class":537},[531,2810,2811,2813,2815,2817],{"class":533,"line":1431},[531,2812,2546],{"class":619},[531,2814,629],{"class":537},[531,2816,57],{"class":606},[531,2818,691],{"class":537},[531,2820,2821,2824,2826,2828,2830,2833],{"class":533,"line":1436},[531,2822,2823],{"class":619},"            y ",[531,2825,1476],{"class":537},[531,2827,2761],{"class":606},[531,2829,649],{"class":537},[531,2831,2832],{"class":808},"60",[531,2834,592],{"class":537},[531,2836,2838],{"class":533,"line":2837},33,[531,2839,2682],{"class":537},[531,2841,2843],{"class":533,"line":2842},34,[531,2844,549],{"emptyLinePlaceholder":548},[531,2846,2848,2850,2852],{"class":533,"line":2847},35,[531,2849,2480],{"class":619},[531,2851,623],{"class":537},[531,2853,2485],{"class":619},[531,2855,2857,2859,2861,2863,2866,2868,2870,2872],{"class":533,"line":2856},36,[531,2858,2490],{"class":555},[531,2860,1721],{"class":619},[531,2862,729],{"class":537},[531,2864,2865],{"class":619}," cell ",[531,2867,623],{"class":537},[531,2869,1731],{"class":555},[531,2871,2779],{"class":619},[531,2873,1737],{"class":537},[531,2875,2877,2879,2881,2883,2885,2887,2889,2891,2893,2895,2897,2899,2901,2903,2905,2907,2910,2912],{"class":533,"line":2876},37,[531,2878,2546],{"class":619},[531,2880,629],{"class":537},[531,2882,1774],{"class":606},[531,2884,649],{"class":537},[531,2886,1779],{"class":619},[531,2888,729],{"class":537},[531,2890,2559],{"class":619},[531,2892,729],{"class":537},[531,2894,2564],{"class":619},[531,2896,2567],{"class":537},[531,2898,1763],{"class":619},[531,2900,2572],{"class":537},[531,2902,1793],{"class":619},[531,2904,729],{"class":537},[531,2906,732],{"class":537},[531,2908,2909],{"class":723},"D",[531,2911,720],{"class":537},[531,2913,592],{"class":537},[531,2915,2917,2919,2921,2923,2925,2927,2929,2931,2933,2935,2937,2939],{"class":533,"line":2916},38,[531,2918,2546],{"class":619},[531,2920,629],{"class":537},[531,2922,33],{"class":606},[531,2924,649],{"class":537},[531,2926,1779],{"class":619},[531,2928,1749],{"class":537},[531,2930,1825],{"class":808},[531,2932,729],{"class":537},[531,2934,2559],{"class":619},[531,2936,1749],{"class":537},[531,2938,1834],{"class":808},[531,2940,592],{"class":537},[531,2942,2944,2946,2948,2950,2952,2954,2956,2958,2961,2963,2965,2967,2969],{"class":533,"line":2943},39,[531,2945,2615],{"class":555},[531,2947,705],{"class":619},[531,2949,623],{"class":537},[531,2951,710],{"class":619},[531,2953,629],{"class":537},[531,2955,37],{"class":606},[531,2957,896],{"class":537},[531,2959,2960],{"class":619}," cell",[531,2962,740],{"class":537},[531,2964,705],{"class":619},[531,2966,745],{"class":537},[531,2968,748],{"class":537},[531,2970,613],{"class":537},[531,2972,2974,2977],{"class":533,"line":2973},40,[531,2975,2976],{"class":555},"                return",[531,2978,2979],{"class":619}," err\n",[531,2981,2983],{"class":533,"line":2982},41,[531,2984,2660],{"class":537},[531,2986,2988,2990,2992,2994,2996,2998],{"class":533,"line":2987},42,[531,2989,2665],{"class":619},[531,2991,2668],{"class":537},[531,2993,2564],{"class":619},[531,2995,2567],{"class":537},[531,2997,1763],{"class":619},[531,2999,2677],{"class":537},[531,3001,3003],{"class":533,"line":3002},43,[531,3004,2682],{"class":537},[531,3006,3008,3011,3013],{"class":533,"line":3007},44,[531,3009,3010],{"class":619},"        y ",[531,3012,2668],{"class":537},[531,3014,2743],{"class":619},[531,3016,3018],{"class":533,"line":3017},45,[531,3019,774],{"class":537},[531,3021,3023,3026],{"class":533,"line":3022},46,[531,3024,3025],{"class":555},"    return",[531,3027,3028],{"class":537}," nil\n",[531,3030,3032],{"class":533,"line":3031},47,[531,3033,999],{"class":537},[19,3035,3036,3037,3039],{},"A função de tabela tem 30 linhas, das quais só 5 são sobre os dados. O resto é layout: alturas fixas, limite inferior fixo, uma closure para redesenhar o cabeçalho após quebras, dois ",[31,3038,1718],{},", dois avanços de cursor por célula. Essa é a mediana das tabelas gopdf.",[19,3041,3042],{},[22,3043,1004],{},[522,3045,3047],{"className":524,"code":3046,"language":526,"meta":527,"style":527},"page.AutoRow(func(r *template.RowBuilder) {\n    r.Col(12, func(c *template.ColBuilder) {\n        c.Table(\n            []string{\"Descrição\", \"Qtd\", \"Unitário\", \"Valor\"},\n            items, // [][]string\n            template.ColumnWidths(55, 15, 15, 15),\n            template.TableHeaderStyle(\n                template.Bold(),\n                template.TextColor(pdf.White),\n                template.BgColor(pdf.RGBHex(0x1A237E)),\n            ),\n            template.TableStripe(pdf.RGBHex(0xF5F5F5)),\n        )\n    })\n})\n",[31,3048,3049,3073,3104,3116,3158,3168,3198,3209,3220,3238,3260,3265,3289,3294,3298],{"__ignoreMap":527},[531,3050,3051,3053,3055,3057,3059,3061,3063,3065,3067,3069,3071],{"class":533,"line":534},[531,3052,1939],{"class":619},[531,3054,629],{"class":537},[531,3056,1202],{"class":606},[531,3058,1205],{"class":537},[531,3060,1209],{"class":1208},[531,3062,669],{"class":537},[531,3064,1214],{"class":541},[531,3066,629],{"class":537},[531,3068,1219],{"class":541},[531,3070,1222],{"class":537},[531,3072,613],{"class":537},[531,3074,3075,3078,3080,3082,3084,3086,3088,3090,3092,3094,3096,3098,3100,3102],{"class":533,"line":545},[531,3076,3077],{"class":619},"    r",[531,3079,629],{"class":537},[531,3081,1234],{"class":606},[531,3083,649],{"class":537},[531,3085,1239],{"class":808},[531,3087,729],{"class":537},[531,3089,1244],{"class":537},[531,3091,1247],{"class":1208},[531,3093,669],{"class":537},[531,3095,1214],{"class":541},[531,3097,629],{"class":537},[531,3099,1256],{"class":541},[531,3101,1222],{"class":537},[531,3103,613],{"class":537},[531,3105,3106,3109,3111,3114],{"class":533,"line":552},[531,3107,3108],{"class":619},"        c",[531,3110,629],{"class":537},[531,3112,3113],{"class":606},"Table",[531,3115,1109],{"class":537},[531,3117,3118,3121,3123,3125,3127,3129,3131,3133,3135,3137,3139,3141,3143,3145,3147,3149,3151,3153,3155],{"class":533,"line":562},[531,3119,3120],{"class":537},"            []",[531,3122,1675],{"class":1674},[531,3124,660],{"class":537},[531,3126,720],{"class":537},[531,3128,1682],{"class":723},[531,3130,720],{"class":537},[531,3132,729],{"class":537},[531,3134,732],{"class":537},[531,3136,1691],{"class":723},[531,3138,720],{"class":537},[531,3140,729],{"class":537},[531,3142,732],{"class":537},[531,3144,1700],{"class":723},[531,3146,720],{"class":537},[531,3148,729],{"class":537},[531,3150,732],{"class":537},[531,3152,1709],{"class":723},[531,3154,720],{"class":537},[531,3156,3157],{"class":537},"},\n",[531,3159,3160,3163,3165],{"class":533,"line":574},[531,3161,3162],{"class":619},"            items",[531,3164,729],{"class":537},[531,3166,3167],{"class":1482}," // [][]string\n",[531,3169,3170,3173,3175,3178,3180,3183,3185,3188,3190,3192,3194,3196],{"class":533,"line":579},[531,3171,3172],{"class":619},"            template",[531,3174,629],{"class":537},[531,3176,3177],{"class":606},"ColumnWidths",[531,3179,649],{"class":537},[531,3181,3182],{"class":808},"55",[531,3184,729],{"class":537},[531,3186,3187],{"class":808}," 15",[531,3189,729],{"class":537},[531,3191,3187],{"class":808},[531,3193,729],{"class":537},[531,3195,3187],{"class":808},[531,3197,1132],{"class":537},[531,3199,3200,3202,3204,3207],{"class":533,"line":589},[531,3201,3172],{"class":619},[531,3203,629],{"class":537},[531,3205,3206],{"class":606},"TableHeaderStyle",[531,3208,1109],{"class":537},[531,3210,3211,3213,3215,3217],{"class":533,"line":595},[531,3212,2071],{"class":619},[531,3214,629],{"class":537},[531,3216,1303],{"class":606},[531,3218,3219],{"class":537},"(),\n",[531,3221,3222,3224,3226,3228,3230,3232,3234,3236],{"class":533,"line":600},[531,3223,2071],{"class":619},[531,3225,629],{"class":537},[531,3227,2184],{"class":606},[531,3229,649],{"class":537},[531,3231,1582],{"class":619},[531,3233,629],{"class":537},[531,3235,2193],{"class":619},[531,3237,1132],{"class":537},[531,3239,3240,3242,3244,3246,3248,3250,3252,3254,3256,3258],{"class":533,"line":616},[531,3241,2071],{"class":619},[531,3243,629],{"class":537},[531,3245,2076],{"class":606},[531,3247,649],{"class":537},[531,3249,1582],{"class":619},[531,3251,629],{"class":537},[531,3253,2085],{"class":606},[531,3255,649],{"class":537},[531,3257,2090],{"class":808},[531,3259,2093],{"class":537},[531,3261,3262],{"class":533,"line":638},[531,3263,3264],{"class":537},"            ),\n",[531,3266,3267,3269,3271,3274,3276,3278,3280,3282,3284,3287],{"class":533,"line":682},[531,3268,3172],{"class":619},[531,3270,629],{"class":537},[531,3272,3273],{"class":606},"TableStripe",[531,3275,649],{"class":537},[531,3277,1582],{"class":619},[531,3279,629],{"class":537},[531,3281,2085],{"class":606},[531,3283,649],{"class":537},[531,3285,3286],{"class":808},"0xF5F5F5",[531,3288,2093],{"class":537},[531,3290,3291],{"class":533,"line":694},[531,3292,3293],{"class":537},"        )\n",[531,3295,3296],{"class":533,"line":699},[531,3297,1316],{"class":537},[531,3299,3300],{"class":533,"line":753},[531,3301,679],{"class":537},[19,3303,3304,3305,3307],{},"É só isso. Quebras de página automáticas. Cabeçalho repetido em toda página onde o corpo continua. Linhas zebradas por uma opção. Larguras de coluna são porcentagens do container, então a mesma tabela dentro de ",[31,3306,2223],{}," renderiza em metade da largura com as mesmas proporções, sem reescrita. A função de bookkeeping de 25 linhas do gopdf desaparece.",[19,3309,3310,3311,3314,3315,3318],{},"Um número concreto. A renderização da NF de 100 linhas faz benchmark em ",[22,3312,3313],{},"108 µs"," no gpdf e cerca de ",[22,3316,3317],{},"2.4 ms"," no signintech/gopdf — o número do gopdf depende do padrão célula a célula que você escreveu. O fator não é a manchete; o sumiço da função é.",[14,3320,3322],{"id":3321},"before-after-4-imagem-ao-lado-de-um-parágrafo","Before / After 4: imagem ao lado de um parágrafo",[19,3324,3325],{},"Padrão comum: logo à esquerda, bloco de endereço à direita.",[19,3327,3328],{},[22,3329,520],{},[522,3331,3333],{"className":524,"code":3332,"language":526,"meta":527,"style":527},"const (\n    leftX  = 40.0\n    rightX = 380.0\n    blockY = 50.0\n)\n\nif err := pdf.Image(\"logo.png\", leftX, blockY, &gopdf.Rect{W: 100, H: 60}); err != nil {\n    log.Fatal(err)\n}\n\npdf.SetFont(\"helvetica-bold\", \"\", 14)\npdf.SetXY(rightX, blockY)\nif err := pdf.Cell(nil, \"ACME Ltda.\"); err != nil {\n    log.Fatal(err)\n}\n\npdf.SetFont(\"helvetica\", \"\", 10)\npdf.SetXY(rightX, blockY+20)\npdf.Cell(nil, \"Av. Paulista 1000\")\npdf.SetXY(rightX, blockY+34)\npdf.Cell(nil, \"São Paulo, SP — 01310-100\")\npdf.SetXY(rightX, blockY+48)\npdf.Cell(nil, \"billing@acme.example\")\n",[31,3334,3335,3341,3350,3360,3370,3374,3378,3456,3471,3475,3479,3506,3525,3558,3572,3576,3580,3607,3629,3648,3671,3690,3713],{"__ignoreMap":527},[531,3336,3337,3339],{"class":533,"line":534},[531,3338,1466],{"class":537},[531,3340,559],{"class":537},[531,3342,3343,3346,3348],{"class":533,"line":545},[531,3344,3345],{"class":619},"    leftX  ",[531,3347,1476],{"class":537},[531,3349,1493],{"class":808},[531,3351,3352,3355,3357],{"class":533,"line":552},[531,3353,3354],{"class":619},"    rightX ",[531,3356,1476],{"class":537},[531,3358,3359],{"class":808}," 380.0\n",[531,3361,3362,3365,3367],{"class":533,"line":562},[531,3363,3364],{"class":619},"    blockY ",[531,3366,1476],{"class":537},[531,3368,3369],{"class":808}," 50.0\n",[531,3371,3372],{"class":533,"line":574},[531,3373,592],{"class":537},[531,3375,3376],{"class":533,"line":579},[531,3377,549],{"emptyLinePlaceholder":548},[531,3379,3380,3383,3385,3387,3389,3391,3394,3396,3398,3401,3403,3405,3408,3410,3413,3415,3418,3420,3422,3425,3427,3430,3432,3435,3437,3440,3442,3445,3448,3450,3452,3454],{"class":533,"line":589},[531,3381,3382],{"class":555},"if",[531,3384,705],{"class":619},[531,3386,623],{"class":537},[531,3388,710],{"class":619},[531,3390,629],{"class":537},[531,3392,3393],{"class":606},"Image",[531,3395,649],{"class":537},[531,3397,720],{"class":537},[531,3399,3400],{"class":723},"logo.png",[531,3402,720],{"class":537},[531,3404,729],{"class":537},[531,3406,3407],{"class":619}," leftX",[531,3409,729],{"class":537},[531,3411,3412],{"class":619}," blockY",[531,3414,729],{"class":537},[531,3416,3417],{"class":537}," &",[531,3419,652],{"class":541},[531,3421,629],{"class":537},[531,3423,3424],{"class":541},"Rect",[531,3426,660],{"class":537},[531,3428,3429],{"class":619},"W",[531,3431,666],{"class":537},[531,3433,3434],{"class":808}," 100",[531,3436,729],{"class":537},[531,3438,3439],{"class":619}," H",[531,3441,666],{"class":537},[531,3443,3444],{"class":808}," 60",[531,3446,3447],{"class":537},"});",[531,3449,705],{"class":619},[531,3451,745],{"class":537},[531,3453,748],{"class":537},[531,3455,613],{"class":537},[531,3457,3458,3461,3463,3465,3467,3469],{"class":533,"line":595},[531,3459,3460],{"class":619},"    log",[531,3462,629],{"class":537},[531,3464,761],{"class":606},[531,3466,649],{"class":537},[531,3468,766],{"class":619},[531,3470,592],{"class":537},[531,3472,3473],{"class":533,"line":600},[531,3474,999],{"class":537},[531,3476,3477],{"class":533,"line":616},[531,3478,549],{"emptyLinePlaceholder":548},[531,3480,3481,3483,3485,3487,3489,3491,3493,3495,3497,3499,3501,3504],{"class":533,"line":638},[531,3482,1582],{"class":619},[531,3484,629],{"class":537},[531,3486,790],{"class":606},[531,3488,649],{"class":537},[531,3490,720],{"class":537},[531,3492,1593],{"class":723},[531,3494,720],{"class":537},[531,3496,729],{"class":537},[531,3498,803],{"class":537},[531,3500,729],{"class":537},[531,3502,3503],{"class":808}," 14",[531,3505,592],{"class":537},[531,3507,3508,3510,3512,3514,3516,3519,3521,3523],{"class":533,"line":682},[531,3509,1582],{"class":619},[531,3511,629],{"class":537},[531,3513,33],{"class":606},[531,3515,649],{"class":537},[531,3517,3518],{"class":619},"rightX",[531,3520,729],{"class":537},[531,3522,3412],{"class":619},[531,3524,592],{"class":537},[531,3526,3527,3529,3531,3533,3535,3537,3539,3541,3543,3546,3548,3550,3552,3554,3556],{"class":533,"line":694},[531,3528,3382],{"class":555},[531,3530,705],{"class":619},[531,3532,623],{"class":537},[531,3534,710],{"class":619},[531,3536,629],{"class":537},[531,3538,37],{"class":606},[531,3540,896],{"class":537},[531,3542,732],{"class":537},[531,3544,3545],{"class":723},"ACME Ltda.",[531,3547,720],{"class":537},[531,3549,740],{"class":537},[531,3551,705],{"class":619},[531,3553,745],{"class":537},[531,3555,748],{"class":537},[531,3557,613],{"class":537},[531,3559,3560,3562,3564,3566,3568,3570],{"class":533,"line":699},[531,3561,3460],{"class":619},[531,3563,629],{"class":537},[531,3565,761],{"class":606},[531,3567,649],{"class":537},[531,3569,766],{"class":619},[531,3571,592],{"class":537},[531,3573,3574],{"class":533,"line":753},[531,3575,999],{"class":537},[531,3577,3578],{"class":533,"line":771},[531,3579,549],{"emptyLinePlaceholder":548},[531,3581,3582,3584,3586,3588,3590,3592,3594,3596,3598,3600,3602,3605],{"class":533,"line":777},[531,3583,1582],{"class":619},[531,3585,629],{"class":537},[531,3587,790],{"class":606},[531,3589,649],{"class":537},[531,3591,720],{"class":537},[531,3593,724],{"class":723},[531,3595,720],{"class":537},[531,3597,729],{"class":537},[531,3599,803],{"class":537},[531,3601,729],{"class":537},[531,3603,3604],{"class":808}," 10",[531,3606,592],{"class":537},[531,3608,3609,3611,3613,3615,3617,3619,3621,3623,3625,3627],{"class":533,"line":822},[531,3610,1582],{"class":619},[531,3612,629],{"class":537},[531,3614,33],{"class":606},[531,3616,649],{"class":537},[531,3618,3518],{"class":619},[531,3620,729],{"class":537},[531,3622,3412],{"class":619},[531,3624,1749],{"class":537},[531,3626,1164],{"class":808},[531,3628,592],{"class":537},[531,3630,3631,3633,3635,3637,3639,3641,3644,3646],{"class":533,"line":837},[531,3632,1582],{"class":619},[531,3634,629],{"class":537},[531,3636,37],{"class":606},[531,3638,896],{"class":537},[531,3640,732],{"class":537},[531,3642,3643],{"class":723},"Av. Paulista 1000",[531,3645,720],{"class":537},[531,3647,592],{"class":537},[531,3649,3650,3652,3654,3656,3658,3660,3662,3664,3666,3669],{"class":533,"line":842},[531,3651,1582],{"class":619},[531,3653,629],{"class":537},[531,3655,33],{"class":606},[531,3657,649],{"class":537},[531,3659,3518],{"class":619},[531,3661,729],{"class":537},[531,3663,3412],{"class":619},[531,3665,1749],{"class":537},[531,3667,3668],{"class":808},"34",[531,3670,592],{"class":537},[531,3672,3673,3675,3677,3679,3681,3683,3686,3688],{"class":533,"line":847},[531,3674,1582],{"class":619},[531,3676,629],{"class":537},[531,3678,37],{"class":606},[531,3680,896],{"class":537},[531,3682,732],{"class":537},[531,3684,3685],{"class":723},"São Paulo, SP — 01310-100",[531,3687,720],{"class":537},[531,3689,592],{"class":537},[531,3691,3692,3694,3696,3698,3700,3702,3704,3706,3708,3711],{"class":533,"line":864},[531,3693,1582],{"class":619},[531,3695,629],{"class":537},[531,3697,33],{"class":606},[531,3699,649],{"class":537},[531,3701,3518],{"class":619},[531,3703,729],{"class":537},[531,3705,3412],{"class":619},[531,3707,1749],{"class":537},[531,3709,3710],{"class":808},"48",[531,3712,592],{"class":537},[531,3714,3715,3717,3719,3721,3723,3725,3728,3730],{"class":533,"line":881},[531,3716,1582],{"class":619},[531,3718,629],{"class":537},[531,3720,37],{"class":606},[531,3722,896],{"class":537},[531,3724,732],{"class":537},[531,3726,3727],{"class":723},"billing@acme.example",[531,3729,720],{"class":537},[531,3731,592],{"class":537},[19,3733,3734,3735,3738],{},"São seis coordenadas y explícitas, e a coluna direita começa em ",[31,3736,3737],{},"rightX = 380"," porque alguém decidiu que o logo tem 100 e o bloco direito precisa de 240 pixels de gap. Mova o logo para a direita e todos os números mudam.",[19,3740,3741],{},[22,3742,1004],{},[522,3744,3746],{"className":524,"code":3745,"language":526,"meta":527,"style":527},"//go:embed logo.png\nvar logoData []byte\n\npage.AutoRow(func(r *template.RowBuilder) {\n    r.Col(4, func(c *template.ColBuilder) {\n        c.Image(logoData, template.FitWidth(document.Mm(35)))\n    })\n    r.Col(8, func(c *template.ColBuilder) {\n        c.Text(\"ACME Ltda.\", template.Bold(), template.FontSize(14))\n        c.Text(\"Av. Paulista 1000\")\n        c.Text(\"São Paulo, SP — 01310-100\")\n        c.Text(\"billing@acme.example\")\n    })\n})\n",[31,3747,3748,3753,3767,3771,3795,3825,3863,3867,3898,3938,3956,3974,3992,3996],{"__ignoreMap":527},[531,3749,3750],{"class":533,"line":534},[531,3751,3752],{"class":1482},"//go:embed logo.png\n",[531,3754,3755,3758,3761,3764],{"class":533,"line":545},[531,3756,3757],{"class":537},"var",[531,3759,3760],{"class":619}," logoData ",[531,3762,3763],{"class":537},"[]",[531,3765,3766],{"class":1674},"byte\n",[531,3768,3769],{"class":533,"line":552},[531,3770,549],{"emptyLinePlaceholder":548},[531,3772,3773,3775,3777,3779,3781,3783,3785,3787,3789,3791,3793],{"class":533,"line":562},[531,3774,1939],{"class":619},[531,3776,629],{"class":537},[531,3778,1202],{"class":606},[531,3780,1205],{"class":537},[531,3782,1209],{"class":1208},[531,3784,669],{"class":537},[531,3786,1214],{"class":541},[531,3788,629],{"class":537},[531,3790,1219],{"class":541},[531,3792,1222],{"class":537},[531,3794,613],{"class":537},[531,3796,3797,3799,3801,3803,3805,3807,3809,3811,3813,3815,3817,3819,3821,3823],{"class":533,"line":574},[531,3798,3077],{"class":619},[531,3800,629],{"class":537},[531,3802,1234],{"class":606},[531,3804,649],{"class":537},[531,3806,2277],{"class":808},[531,3808,729],{"class":537},[531,3810,1244],{"class":537},[531,3812,1247],{"class":1208},[531,3814,669],{"class":537},[531,3816,1214],{"class":541},[531,3818,629],{"class":537},[531,3820,1256],{"class":541},[531,3822,1222],{"class":537},[531,3824,613],{"class":537},[531,3826,3827,3829,3831,3833,3835,3838,3840,3842,3844,3847,3849,3851,3853,3855,3857,3860],{"class":533,"line":579},[531,3828,3108],{"class":619},[531,3830,629],{"class":537},[531,3832,3393],{"class":606},[531,3834,649],{"class":537},[531,3836,3837],{"class":619},"logoData",[531,3839,729],{"class":537},[531,3841,1283],{"class":619},[531,3843,629],{"class":537},[531,3845,3846],{"class":606},"FitWidth",[531,3848,649],{"class":537},[531,3850,1124],{"class":619},[531,3852,629],{"class":537},[531,3854,1159],{"class":606},[531,3856,649],{"class":537},[531,3858,3859],{"class":808},"35",[531,3861,3862],{"class":537},")))\n",[531,3864,3865],{"class":533,"line":589},[531,3866,1316],{"class":537},[531,3868,3869,3871,3873,3875,3877,3880,3882,3884,3886,3888,3890,3892,3894,3896],{"class":533,"line":595},[531,3870,3077],{"class":619},[531,3872,629],{"class":537},[531,3874,1234],{"class":606},[531,3876,649],{"class":537},[531,3878,3879],{"class":808},"8",[531,3881,729],{"class":537},[531,3883,1244],{"class":537},[531,3885,1247],{"class":1208},[531,3887,669],{"class":537},[531,3889,1214],{"class":541},[531,3891,629],{"class":537},[531,3893,1256],{"class":541},[531,3895,1222],{"class":537},[531,3897,613],{"class":537},[531,3899,3900,3902,3904,3906,3908,3910,3912,3914,3916,3918,3920,3922,3924,3926,3928,3930,3932,3935],{"class":533,"line":600},[531,3901,3108],{"class":619},[531,3903,629],{"class":537},[531,3905,1270],{"class":606},[531,3907,649],{"class":537},[531,3909,720],{"class":537},[531,3911,3545],{"class":723},[531,3913,720],{"class":537},[531,3915,729],{"class":537},[531,3917,1283],{"class":619},[531,3919,629],{"class":537},[531,3921,1303],{"class":606},[531,3923,2162],{"class":537},[531,3925,1283],{"class":619},[531,3927,629],{"class":537},[531,3929,1288],{"class":606},[531,3931,649],{"class":537},[531,3933,3934],{"class":808},"14",[531,3936,3937],{"class":537},"))\n",[531,3939,3940,3942,3944,3946,3948,3950,3952,3954],{"class":533,"line":616},[531,3941,3108],{"class":619},[531,3943,629],{"class":537},[531,3945,1270],{"class":606},[531,3947,649],{"class":537},[531,3949,720],{"class":537},[531,3951,3643],{"class":723},[531,3953,720],{"class":537},[531,3955,592],{"class":537},[531,3957,3958,3960,3962,3964,3966,3968,3970,3972],{"class":533,"line":638},[531,3959,3108],{"class":619},[531,3961,629],{"class":537},[531,3963,1270],{"class":606},[531,3965,649],{"class":537},[531,3967,720],{"class":537},[531,3969,3685],{"class":723},[531,3971,720],{"class":537},[531,3973,592],{"class":537},[531,3975,3976,3978,3980,3982,3984,3986,3988,3990],{"class":533,"line":682},[531,3977,3108],{"class":619},[531,3979,629],{"class":537},[531,3981,1270],{"class":606},[531,3983,649],{"class":537},[531,3985,720],{"class":537},[531,3987,3727],{"class":723},[531,3989,720],{"class":537},[531,3991,592],{"class":537},[531,3993,3994],{"class":533,"line":694},[531,3995,1316],{"class":537},[531,3997,3998],{"class":533,"line":699},[531,3999,679],{"class":537},[19,4001,4002,4003,4006,4007,4009],{},"Duas colunas, 4 + 8 = 12. A imagem se ajusta a uma largura fixa e gpdf calcula a altura pela razão de aspecto. Cada ",[31,4004,4005],{},"c.Text"," flui abaixo do anterior — sem ",[31,4008,49],{},", sem aritmética y. Inverta a ordem das colunas se quiser o logo à direita.",[14,4011,4013],{"id":4012},"before-after-5-numeração-de-página-no-rodapé","Before / After 5: numeração de página no rodapé",[19,4015,4016],{},"No gopdf, você mantém a contagem manualmente, porque o render é em uma passagem e o total não é conhecido quando você desenha o primeiro rodapé. A maioria das bases faz um workaround de duas passagens: renderizar uma vez para contar, renderizar de novo com o total já assado.",[19,4018,4019],{},[22,4020,520],{},[522,4022,4024],{"className":524,"code":4023,"language":526,"meta":527,"style":527},"totalPages := 0\npdf.AddFooter(func() {\n    totalPages++\n})\n\nbuildContent(&pdf)\nfinalTotal := totalPages\n\npdf2 := gopdf.GoPdf{}\npdf2.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})\npageNum := 0\npdf2.AddFooter(func() {\n    pageNum++\n    pdf2.SetFont(\"helvetica\", \"\", 8)\n    pdf2.SetXY(40, 800)\n    pdf2.Cell(nil, fmt.Sprintf(\"Página %d de %d\", pageNum, finalTotal))\n})\nbuildContent(&pdf2)\npdf2.WritePdf(\"report.pdf\")\n",[31,4025,4026,4036,4050,4058,4062,4066,4078,4088,4092,4107,4140,4149,4161,4168,4196,4215,4263,4267,4277],{"__ignoreMap":527},[531,4027,4028,4031,4033],{"class":533,"line":534},[531,4029,4030],{"class":619},"totalPages ",[531,4032,623],{"class":537},[531,4034,4035],{"class":808}," 0\n",[531,4037,4038,4040,4042,4045,4048],{"class":533,"line":545},[531,4039,1582],{"class":619},[531,4041,629],{"class":537},[531,4043,4044],{"class":606},"AddFooter",[531,4046,4047],{"class":537},"(func()",[531,4049,613],{"class":537},[531,4051,4052,4055],{"class":533,"line":552},[531,4053,4054],{"class":619},"    totalPages",[531,4056,4057],{"class":537},"++\n",[531,4059,4060],{"class":533,"line":562},[531,4061,679],{"class":537},[531,4063,4064],{"class":533,"line":574},[531,4065,549],{"emptyLinePlaceholder":548},[531,4067,4068,4071,4074,4076],{"class":533,"line":579},[531,4069,4070],{"class":606},"buildContent",[531,4072,4073],{"class":537},"(&",[531,4075,1582],{"class":619},[531,4077,592],{"class":537},[531,4079,4080,4083,4085],{"class":533,"line":589},[531,4081,4082],{"class":619},"finalTotal ",[531,4084,623],{"class":537},[531,4086,4087],{"class":619}," totalPages\n",[531,4089,4090],{"class":533,"line":595},[531,4091,549],{"emptyLinePlaceholder":548},[531,4093,4094,4097,4099,4101,4103,4105],{"class":533,"line":600},[531,4095,4096],{"class":619},"pdf2 ",[531,4098,623],{"class":537},[531,4100,626],{"class":541},[531,4102,629],{"class":537},[531,4104,632],{"class":541},[531,4106,635],{"class":537},[531,4108,4109,4112,4114,4116,4118,4120,4122,4124,4126,4128,4130,4132,4134,4136,4138],{"class":533,"line":616},[531,4110,4111],{"class":619},"pdf2",[531,4113,629],{"class":537},[531,4115,646],{"class":606},[531,4117,649],{"class":537},[531,4119,652],{"class":541},[531,4121,629],{"class":537},[531,4123,657],{"class":541},[531,4125,660],{"class":537},[531,4127,663],{"class":619},[531,4129,666],{"class":537},[531,4131,669],{"class":537},[531,4133,652],{"class":619},[531,4135,629],{"class":537},[531,4137,676],{"class":619},[531,4139,679],{"class":537},[531,4141,4142,4145,4147],{"class":533,"line":638},[531,4143,4144],{"class":619},"pageNum ",[531,4146,623],{"class":537},[531,4148,4035],{"class":808},[531,4150,4151,4153,4155,4157,4159],{"class":533,"line":682},[531,4152,4111],{"class":619},[531,4154,629],{"class":537},[531,4156,4044],{"class":606},[531,4158,4047],{"class":537},[531,4160,613],{"class":537},[531,4162,4163,4166],{"class":533,"line":694},[531,4164,4165],{"class":619},"    pageNum",[531,4167,4057],{"class":537},[531,4169,4170,4173,4175,4177,4179,4181,4183,4185,4187,4189,4191,4194],{"class":533,"line":699},[531,4171,4172],{"class":619},"    pdf2",[531,4174,629],{"class":537},[531,4176,790],{"class":606},[531,4178,649],{"class":537},[531,4180,720],{"class":537},[531,4182,724],{"class":723},[531,4184,720],{"class":537},[531,4186,729],{"class":537},[531,4188,803],{"class":537},[531,4190,729],{"class":537},[531,4192,4193],{"class":808}," 8",[531,4195,592],{"class":537},[531,4197,4198,4200,4202,4204,4206,4208,4210,4213],{"class":533,"line":753},[531,4199,4172],{"class":619},[531,4201,629],{"class":537},[531,4203,33],{"class":606},[531,4205,649],{"class":537},[531,4207,859],{"class":808},[531,4209,729],{"class":537},[531,4211,4212],{"class":808}," 800",[531,4214,592],{"class":537},[531,4216,4217,4219,4221,4223,4225,4228,4230,4233,4235,4237,4240,4244,4247,4249,4251,4253,4256,4258,4261],{"class":533,"line":771},[531,4218,4172],{"class":619},[531,4220,629],{"class":537},[531,4222,37],{"class":606},[531,4224,896],{"class":537},[531,4226,4227],{"class":619}," fmt",[531,4229,629],{"class":537},[531,4231,4232],{"class":606},"Sprintf",[531,4234,649],{"class":537},[531,4236,720],{"class":537},[531,4238,4239],{"class":723},"Página ",[531,4241,4243],{"class":4242},"swJcz","%d",[531,4245,4246],{"class":723}," de ",[531,4248,4243],{"class":4242},[531,4250,720],{"class":537},[531,4252,729],{"class":537},[531,4254,4255],{"class":619}," pageNum",[531,4257,729],{"class":537},[531,4259,4260],{"class":619}," finalTotal",[531,4262,3937],{"class":537},[531,4264,4265],{"class":533,"line":777},[531,4266,679],{"class":537},[531,4268,4269,4271,4273,4275],{"class":533,"line":822},[531,4270,4070],{"class":606},[531,4272,4073],{"class":537},[531,4274,4111],{"class":619},[531,4276,592],{"class":537},[531,4278,4279,4281,4283,4285,4287,4289,4292,4294],{"class":533,"line":837},[531,4280,4111],{"class":619},[531,4282,629],{"class":537},[531,4284,954],{"class":606},[531,4286,649],{"class":537},[531,4288,720],{"class":537},[531,4290,4291],{"class":723},"report.pdf",[531,4293,720],{"class":537},[531,4295,592],{"class":537},[19,4297,4298],{},"Se você manteve código gopdf, escreveu isto. Não está em FAQ algum, mas é a única forma de obter um rodapé honesto \"Página X de Y\" sem fazer parsing da saída.",[19,4300,4301],{},[22,4302,1004],{},[522,4304,4306],{"className":524,"code":4305,"language":526,"meta":527,"style":527},"doc.Footer(func(p *template.PageBuilder) {\n    p.AutoRow(func(r *template.RowBuilder) {\n        r.Col(6, func(c *template.ColBuilder) {\n            c.Text(\"ACME Ltda.\",\n                template.FontSize(8), template.TextColor(pdf.Gray(0.5)))\n        })\n        r.Col(6, func(c *template.ColBuilder) {\n            c.Stack(template.AlignRight(), func(c *template.ColBuilder) {\n                c.Text(\"Página \", template.Inline())\n                c.PageNumber(template.Inline())\n                c.Text(\" de \", template.Inline())\n                c.TotalPages(template.Inline())\n            }, template.FontSize(8), template.TextColor(pdf.Gray(0.5)))\n        })\n    })\n})\n",[31,4307,4308,4335,4360,4390,4408,4444,4448,4478,4514,4542,4561,4587,4606,4643,4647,4651],{"__ignoreMap":527},[531,4309,4310,4313,4315,4318,4320,4322,4324,4326,4328,4331,4333],{"class":533,"line":534},[531,4311,4312],{"class":619},"doc",[531,4314,629],{"class":537},[531,4316,4317],{"class":606},"Footer",[531,4319,1205],{"class":537},[531,4321,19],{"class":1208},[531,4323,669],{"class":537},[531,4325,1214],{"class":541},[531,4327,629],{"class":537},[531,4329,4330],{"class":541},"PageBuilder",[531,4332,1222],{"class":537},[531,4334,613],{"class":537},[531,4336,4337,4340,4342,4344,4346,4348,4350,4352,4354,4356,4358],{"class":533,"line":545},[531,4338,4339],{"class":619},"    p",[531,4341,629],{"class":537},[531,4343,1202],{"class":606},[531,4345,1205],{"class":537},[531,4347,1209],{"class":1208},[531,4349,669],{"class":537},[531,4351,1214],{"class":541},[531,4353,629],{"class":537},[531,4355,1219],{"class":541},[531,4357,1222],{"class":537},[531,4359,613],{"class":537},[531,4361,4362,4364,4366,4368,4370,4372,4374,4376,4378,4380,4382,4384,4386,4388],{"class":533,"line":552},[531,4363,1229],{"class":619},[531,4365,629],{"class":537},[531,4367,1234],{"class":606},[531,4369,649],{"class":537},[531,4371,1825],{"class":808},[531,4373,729],{"class":537},[531,4375,1244],{"class":537},[531,4377,1247],{"class":1208},[531,4379,669],{"class":537},[531,4381,1214],{"class":541},[531,4383,629],{"class":537},[531,4385,1256],{"class":541},[531,4387,1222],{"class":537},[531,4389,613],{"class":537},[531,4391,4392,4394,4396,4398,4400,4402,4404,4406],{"class":533,"line":562},[531,4393,1265],{"class":619},[531,4395,629],{"class":537},[531,4397,1270],{"class":606},[531,4399,649],{"class":537},[531,4401,720],{"class":537},[531,4403,3545],{"class":723},[531,4405,720],{"class":537},[531,4407,2151],{"class":537},[531,4409,4410,4412,4414,4416,4418,4420,4422,4424,4426,4428,4430,4432,4434,4437,4439,4442],{"class":533,"line":574},[531,4411,2071],{"class":619},[531,4413,629],{"class":537},[531,4415,1288],{"class":606},[531,4417,649],{"class":537},[531,4419,3879],{"class":808},[531,4421,1296],{"class":537},[531,4423,1283],{"class":619},[531,4425,629],{"class":537},[531,4427,2184],{"class":606},[531,4429,649],{"class":537},[531,4431,1582],{"class":619},[531,4433,629],{"class":537},[531,4435,4436],{"class":606},"Gray",[531,4438,649],{"class":537},[531,4440,4441],{"class":808},"0.5",[531,4443,3862],{"class":537},[531,4445,4446],{"class":533,"line":579},[531,4447,1311],{"class":537},[531,4449,4450,4452,4454,4456,4458,4460,4462,4464,4466,4468,4470,4472,4474,4476],{"class":533,"line":589},[531,4451,1229],{"class":619},[531,4453,629],{"class":537},[531,4455,1234],{"class":606},[531,4457,649],{"class":537},[531,4459,1825],{"class":808},[531,4461,729],{"class":537},[531,4463,1244],{"class":537},[531,4465,1247],{"class":1208},[531,4467,669],{"class":537},[531,4469,1214],{"class":541},[531,4471,629],{"class":537},[531,4473,1256],{"class":541},[531,4475,1222],{"class":537},[531,4477,613],{"class":537},[531,4479,4480,4482,4484,4487,4489,4491,4493,4496,4498,4500,4502,4504,4506,4508,4510,4512],{"class":533,"line":595},[531,4481,1265],{"class":619},[531,4483,629],{"class":537},[531,4485,4486],{"class":606},"Stack",[531,4488,649],{"class":537},[531,4490,1214],{"class":619},[531,4492,629],{"class":537},[531,4494,4495],{"class":606},"AlignRight",[531,4497,2162],{"class":537},[531,4499,1244],{"class":537},[531,4501,1247],{"class":1208},[531,4503,669],{"class":537},[531,4505,1214],{"class":541},[531,4507,629],{"class":537},[531,4509,1256],{"class":541},[531,4511,1222],{"class":537},[531,4513,613],{"class":537},[531,4515,4516,4519,4521,4523,4525,4527,4529,4531,4533,4535,4537,4540],{"class":533,"line":600},[531,4517,4518],{"class":619},"                c",[531,4520,629],{"class":537},[531,4522,1270],{"class":606},[531,4524,649],{"class":537},[531,4526,720],{"class":537},[531,4528,4239],{"class":723},[531,4530,720],{"class":537},[531,4532,729],{"class":537},[531,4534,1283],{"class":619},[531,4536,629],{"class":537},[531,4538,4539],{"class":606},"Inline",[531,4541,1306],{"class":537},[531,4543,4544,4546,4548,4551,4553,4555,4557,4559],{"class":533,"line":616},[531,4545,4518],{"class":619},[531,4547,629],{"class":537},[531,4549,4550],{"class":606},"PageNumber",[531,4552,649],{"class":537},[531,4554,1214],{"class":619},[531,4556,629],{"class":537},[531,4558,4539],{"class":606},[531,4560,1306],{"class":537},[531,4562,4563,4565,4567,4569,4571,4573,4575,4577,4579,4581,4583,4585],{"class":533,"line":638},[531,4564,4518],{"class":619},[531,4566,629],{"class":537},[531,4568,1270],{"class":606},[531,4570,649],{"class":537},[531,4572,720],{"class":537},[531,4574,4246],{"class":723},[531,4576,720],{"class":537},[531,4578,729],{"class":537},[531,4580,1283],{"class":619},[531,4582,629],{"class":537},[531,4584,4539],{"class":606},[531,4586,1306],{"class":537},[531,4588,4589,4591,4593,4596,4598,4600,4602,4604],{"class":533,"line":682},[531,4590,4518],{"class":619},[531,4592,629],{"class":537},[531,4594,4595],{"class":606},"TotalPages",[531,4597,649],{"class":537},[531,4599,1214],{"class":619},[531,4601,629],{"class":537},[531,4603,4539],{"class":606},[531,4605,1306],{"class":537},[531,4607,4608,4611,4613,4615,4617,4619,4621,4623,4625,4627,4629,4631,4633,4635,4637,4639,4641],{"class":533,"line":694},[531,4609,4610],{"class":537},"            },",[531,4612,1283],{"class":619},[531,4614,629],{"class":537},[531,4616,1288],{"class":606},[531,4618,649],{"class":537},[531,4620,3879],{"class":808},[531,4622,1296],{"class":537},[531,4624,1283],{"class":619},[531,4626,629],{"class":537},[531,4628,2184],{"class":606},[531,4630,649],{"class":537},[531,4632,1582],{"class":619},[531,4634,629],{"class":537},[531,4636,4436],{"class":606},[531,4638,649],{"class":537},[531,4640,4441],{"class":808},[531,4642,3862],{"class":537},[531,4644,4645],{"class":533,"line":699},[531,4646,1311],{"class":537},[531,4648,4649],{"class":533,"line":753},[531,4650,1316],{"class":537},[531,4652,4653],{"class":533,"line":771},[531,4654,679],{"class":537},[19,4656,4657,4659,4660,4662],{},[31,4658,4550],{}," e ",[31,4661,4595],{}," são placeholders. O motor de layout pagina primeiro, resolve os totais e depois escreve. Uma passagem, sem contagem manual, sem render duplo.",[14,4664,4666],{"id":4665},"texto-cjk-sem-o-subset-manual","Texto CJK sem o subset manual",[19,4668,4669],{},"signintech/gopdf suporta CJK, mas o caminho é bookkeeping de conjunto de caracteres feito à mão. Você adiciona o TTF, define o mapa de caracteres e, se o texto contém um glifo fora do subset que registrou, sai tofu. O subseter TrueType do gpdf percorre o cmap (formatos 4, 6, 12) e embute exatamente os glifos que você usou — sem lista manual de subset.",[522,4671,4673],{"className":524,"code":4672,"language":526,"meta":527,"style":527},"//go:embed NotoSansJP-Regular.ttf\nvar notoJP []byte\n\ndoc := gpdf.NewDocument(\n    gpdf.WithPageSize(document.A4),\n    gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n    gpdf.WithFont(\"NotoSansJP\", notoJP),\n    gpdf.WithDefaultFont(\"NotoSansJP\", 14),\n)\n\npage := doc.AddPage()\npage.AutoRow(func(r *template.RowBuilder) {\n    r.Col(12, func(c *template.ColBuilder) {\n        c.Text(\"こんにちは、世界。\")\n        c.Text(\"吾輩は猫である。名前はまだ無い。\")\n    })\n})\n",[31,4674,4675,4680,4691,4695,4710,4729,4759,4784,4807,4811,4815,4830,4854,4884,4903,4922,4926],{"__ignoreMap":527},[531,4676,4677],{"class":533,"line":534},[531,4678,4679],{"class":1482},"//go:embed NotoSansJP-Regular.ttf\n",[531,4681,4682,4684,4687,4689],{"class":533,"line":545},[531,4683,3757],{"class":537},[531,4685,4686],{"class":619}," notoJP ",[531,4688,3763],{"class":537},[531,4690,3766],{"class":1674},[531,4692,4693],{"class":533,"line":552},[531,4694,549],{"emptyLinePlaceholder":548},[531,4696,4697,4700,4702,4704,4706,4708],{"class":533,"line":562},[531,4698,4699],{"class":619},"doc ",[531,4701,623],{"class":537},[531,4703,1101],{"class":619},[531,4705,629],{"class":537},[531,4707,1106],{"class":606},[531,4709,1109],{"class":537},[531,4711,4712,4715,4717,4719,4721,4723,4725,4727],{"class":533,"line":574},[531,4713,4714],{"class":619},"    gpdf",[531,4716,629],{"class":537},[531,4718,1119],{"class":606},[531,4720,649],{"class":537},[531,4722,1124],{"class":619},[531,4724,629],{"class":537},[531,4726,1129],{"class":619},[531,4728,1132],{"class":537},[531,4730,4731,4733,4735,4737,4739,4741,4743,4745,4747,4749,4751,4753,4755,4757],{"class":533,"line":579},[531,4732,4714],{"class":619},[531,4734,629],{"class":537},[531,4736,1141],{"class":606},[531,4738,649],{"class":537},[531,4740,1124],{"class":619},[531,4742,629],{"class":537},[531,4744,1150],{"class":606},[531,4746,649],{"class":537},[531,4748,1124],{"class":619},[531,4750,629],{"class":537},[531,4752,1159],{"class":606},[531,4754,649],{"class":537},[531,4756,1164],{"class":808},[531,4758,1167],{"class":537},[531,4760,4761,4763,4765,4768,4770,4772,4775,4777,4779,4782],{"class":533,"line":589},[531,4762,4714],{"class":619},[531,4764,629],{"class":537},[531,4766,4767],{"class":606},"WithFont",[531,4769,649],{"class":537},[531,4771,720],{"class":537},[531,4773,4774],{"class":723},"NotoSansJP",[531,4776,720],{"class":537},[531,4778,729],{"class":537},[531,4780,4781],{"class":619}," notoJP",[531,4783,1132],{"class":537},[531,4785,4786,4788,4790,4793,4795,4797,4799,4801,4803,4805],{"class":533,"line":595},[531,4787,4714],{"class":619},[531,4789,629],{"class":537},[531,4791,4792],{"class":606},"WithDefaultFont",[531,4794,649],{"class":537},[531,4796,720],{"class":537},[531,4798,4774],{"class":723},[531,4800,720],{"class":537},[531,4802,729],{"class":537},[531,4804,3503],{"class":808},[531,4806,1132],{"class":537},[531,4808,4809],{"class":533,"line":600},[531,4810,592],{"class":537},[531,4812,4813],{"class":533,"line":616},[531,4814,549],{"emptyLinePlaceholder":548},[531,4816,4817,4820,4822,4824,4826,4828],{"class":533,"line":638},[531,4818,4819],{"class":619},"page ",[531,4821,623],{"class":537},[531,4823,1186],{"class":619},[531,4825,629],{"class":537},[531,4827,57],{"class":606},[531,4829,691],{"class":537},[531,4831,4832,4834,4836,4838,4840,4842,4844,4846,4848,4850,4852],{"class":533,"line":682},[531,4833,1939],{"class":619},[531,4835,629],{"class":537},[531,4837,1202],{"class":606},[531,4839,1205],{"class":537},[531,4841,1209],{"class":1208},[531,4843,669],{"class":537},[531,4845,1214],{"class":541},[531,4847,629],{"class":537},[531,4849,1219],{"class":541},[531,4851,1222],{"class":537},[531,4853,613],{"class":537},[531,4855,4856,4858,4860,4862,4864,4866,4868,4870,4872,4874,4876,4878,4880,4882],{"class":533,"line":694},[531,4857,3077],{"class":619},[531,4859,629],{"class":537},[531,4861,1234],{"class":606},[531,4863,649],{"class":537},[531,4865,1239],{"class":808},[531,4867,729],{"class":537},[531,4869,1244],{"class":537},[531,4871,1247],{"class":1208},[531,4873,669],{"class":537},[531,4875,1214],{"class":541},[531,4877,629],{"class":537},[531,4879,1256],{"class":541},[531,4881,1222],{"class":537},[531,4883,613],{"class":537},[531,4885,4886,4888,4890,4892,4894,4896,4899,4901],{"class":533,"line":699},[531,4887,3108],{"class":619},[531,4889,629],{"class":537},[531,4891,1270],{"class":606},[531,4893,649],{"class":537},[531,4895,720],{"class":537},[531,4897,4898],{"class":723},"こんにちは、世界。",[531,4900,720],{"class":537},[531,4902,592],{"class":537},[531,4904,4905,4907,4909,4911,4913,4915,4918,4920],{"class":533,"line":753},[531,4906,3108],{"class":619},[531,4908,629],{"class":537},[531,4910,1270],{"class":606},[531,4912,649],{"class":537},[531,4914,720],{"class":537},[531,4916,4917],{"class":723},"吾輩は猫である。名前はまだ無い。",[531,4919,720],{"class":537},[531,4921,592],{"class":537},[531,4923,4924],{"class":533,"line":771},[531,4925,1316],{"class":537},[531,4927,4928],{"class":533,"line":777},[531,4929,679],{"class":537},[19,4931,4932],{},"Uma fatura japonesa de 200 caracteres produz um subset de fonte de ~30 KB em vez de um embed completo de 4 MB.",[14,4934,4936],{"id":4935},"benchmarks","Benchmarks",[19,4938,4939],{},"Mesmo hardware, mesmas cargas, Apple M1 com Go 1.25.",[137,4941,4942,4959],{},[140,4943,4944],{},[143,4945,4946,4949,4951,4953,4956],{},[146,4947,4948],{},"Benchmark",[146,4950,24],{},[146,4952,28],{},[146,4954,4955],{},"gofpdf",[146,4957,4958],{},"Maroto v2",[154,4960,4961,4980,4998,5016],{},[143,4962,4963,4966,4971,4974,4977],{},[159,4964,4965],{},"Página única",[159,4967,4968],{},[22,4969,4970],{},"13 µs",[159,4972,4973],{},"423 µs",[159,4975,4976],{},"132 µs",[159,4978,4979],{},"237 µs",[143,4981,4982,4985,4989,4992,4995],{},[159,4983,4984],{},"Tabela 4×10",[159,4986,4987],{},[22,4988,3313],{},[159,4990,4991],{},"835 µs",[159,4993,4994],{},"241 µs",[159,4996,4997],{},"8.6 ms",[143,4999,5000,5003,5008,5010,5013],{},[159,5001,5002],{},"Relatório 100 páginas",[159,5004,5005],{},[22,5006,5007],{},"683 µs",[159,5009,4997],{},[159,5011,5012],{},"11.7 ms",[159,5014,5015],{},"19.8 ms",[143,5017,5018,5021,5026,5029,5032],{},[159,5019,5020],{},"NF CJK complexa",[159,5022,5023],{},[22,5024,5025],{},"133 µs",[159,5027,5028],{},"997 µs",[159,5030,5031],{},"254 µs",[159,5033,5034],{},"10.4 ms",[19,5036,5037,5038,629],{},"Números de ",[31,5039,5040],{},"gpdf/_benchmark/benchmark_test.go",[19,5042,5043,5044,5047],{},"A ",[22,5045,5046],{},"108 µs por página com tabela"," em um único core dá ~9.000 NF por segundo. Para a maioria das cargas, geração de PDF pode ficar no caminho da request.",[14,5049,5051],{"id":5050},"o-que-gopdf-tem-e-gpdf-não","O que gopdf tem e gpdf não",[19,5053,5054],{},"Seção honesta. Se seu uso de gopdf depende disto, a migração não cobre tudo só com este artigo.",[5056,5057,5058,5075,5081,5095],"ul",{},[5059,5060,5061,5066,5067,5070,5071,5074],"li",{},[22,5062,5063,629],{},[31,5064,5065],{},"ImportPage"," Importar uma página de um PDF existente e estampar conteúdo por cima. O overlay do gpdf (",[31,5068,5069],{},"gpdf.Overlay",") cobre o caso comum, mas não expõe a primitiva ",[31,5072,5073],{},"UseImportedTemplate"," igual.",[5059,5076,5077,5080],{},[22,5078,5079],{},"Polígonos e ovais como primitivas."," O conjunto primitivo do gpdf é retângulos, linhas, imagens, texto e tabelas; desenho de path arbitrário não é de primeira classe. Para visualização, use uma lib de charts para gerar PNG/SVG e embuta.",[5059,5082,5083,5086,5087,5090,5091,5094],{},[22,5084,5085],{},"Posicionamento direto de cursor."," Para colocação pixel-perfect (um carimbo exatamente em ",[31,5088,5089],{},"(420, 240)","), ",[31,5092,5093],{},"page.Absolute(x, y, fn)"," existe, mas é a saída de emergência.",[5059,5096,5097,5105,5106,402,5108,5110],{},[22,5098,5099,402,5102,629],{},[31,5100,5101],{},"PlaceHolderText",[31,5103,5104],{},"FillInPlaceHoldText"," Mecanismo geral de \"preencher este slot depois\" ainda não existe; placeholders ",[31,5107,4550],{},[31,5109,4595],{}," cobrem o caso de numeração.",[19,5112,5113,5114,5117],{},"Para ",[22,5115,5116],{},"NFs, extratos, relatórios, certificados, contratos, recibos, etiquetas de envio, romaneios e documentos CJK"," — o que a maior parte das contas gopdf realmente gera — a troca é completa.",[14,5119,5121],{"id":5120},"faq","FAQ",[19,5123,5124,5127],{},[22,5125,5126],{},"gpdf é um fork de signintech/gopdf?","\nNão. gpdf é uma reimplementação limpa em Go puro. Sem código compartilhado nem linhagem.",[19,5129,5130,5133],{},[22,5131,5132],{},"Os dois são Go puro e sem CGO. Qual o ganho real de trocar?","\nO motor de layout. As seções de migração acima são 80% sobre remover matemática de coordenadas, e essa é a diferença do dia a dia. Benchmarks são vitória secundária. Licença MIT é idêntica à MIT do gopdf, então licença não é fator.",[19,5135,5136,5139,5140,5143,5144,5147],{},[22,5137,5138],{},"Posso migrar incrementalmente?","\nPosso. As duas libs não conflitam. Cada uma produz ",[31,5141,5142],{},"[]byte"," independente. Renderize uma seção com gpdf, outra com gopdf e ",[31,5145,5146],{},"gpdf.Merge(a, b)"," cola. Na prática, a maioria acha mais fácil migrar um documento por vez.",[19,5149,5150,5157,5158,5161,5162,5165,5166,5169],{},[22,5151,5152,5153,5156],{},"Meu código existente usa ",[31,5154,5155],{},"pdf.Image(path, ...)"," para carregar logos do disco. Preciso embutir?","\nNão precisa. ",[31,5159,5160],{},"c.Image(imageBytes, ...)"," aceita bytes — use ",[31,5163,5164],{},"os.ReadFile"," para carregar em runtime. Mas ",[31,5167,5168],{},"//go:embed"," é o melhor default.",[19,5171,5172,5179,34,5182,34,5185,5188,5189,629],{},[22,5173,5174,5175,5178],{},"E ",[31,5176,5177],{},"gopdf.PageSizeA4"," e outras constantes de tamanho?",[31,5180,5181],{},"document.A4",[31,5183,5184],{},"document.Letter",[31,5186,5187],{},"document.Legal"," cobrem o mesmo conjunto. Tamanho custom: ",[31,5190,5191],{},"document.PageSize(document.Mm(210), document.Mm(297))",[19,5193,5194,5201,5203,5204,629],{},[22,5195,5196,5197,5200],{},"Meu gerador usa ",[31,5198,5199],{},"pdf.Rotate"," para carimbos diagonais. Tem equivalente?",[31,5202,5093],{}," aceita opção de rotação; o típico \"marca-d'água diagonal\" é uma chamada ",[31,5205,5206],{},"page.Absolute",[19,5208,5209,5212,5213,1567,5215,5217,5218,1567,5221,5223],{},[22,5210,5211],{},"Tem ferramenta que reescreva meu código automaticamente?","\nAinda não. Mapeamento das partes simples (",[31,5214,33],{},[31,5216,37],{}," → ",[31,5219,5220],{},"r.Col",[31,5222,4005],{},") é mecânico, mas a reescrita de tabelas é estrutural — você apaga o bookkeeping em vez de traduzir. Migração manual de um gerador típico leva algumas horas por tipo de documento.",[14,5225,5227],{"id":5226},"experimente-gpdf","Experimente gpdf",[19,5229,5230],{},"gpdf é uma biblioteca Go para gerar PDFs. Licença MIT, zero dependências externas, suporte CJK nativo, layout em grade de 12 colunas.",[522,5232,5236],{"className":5233,"code":5234,"language":5235,"meta":527,"style":527},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com/gpdf-dev/gpdf\n","bash",[31,5237,5238],{"__ignoreMap":527},[531,5239,5240,5242,5245],{"class":533,"line":534},[531,5241,526],{"class":541},[531,5243,5244],{"class":723}," get",[531,5246,5247],{"class":723}," github.com/gpdf-dev/gpdf\n",[19,5249,5250,5257,5258],{},[5251,5252,5256],"a",{"href":5253,"rel":5254},"https://github.com/gpdf-dev/gpdf",[5255],"nofollow","⭐ Star no GitHub"," · ",[5251,5259,5262],{"href":5260,"rel":5261},"https://gpdf.dev/pt/docs/quickstart",[5255],"Leia a documentação",[14,5264,5266],{"id":5265},"próximas-leituras","Próximas leituras",[5056,5268,5269,5275,5281,5287,5293],{},[5059,5270,5271],{},[5251,5272,5274],{"href":5273},"/pt/blog/12-column-grid","A grade de 12 colunas: pensamento Bootstrap para layout PDF",[5059,5276,5277],{},[5251,5278,5280],{"href":5279},"/pt/blog/bootstrap-grid-thinking-for-pdf","Pensamento de grade Bootstrap para PDF",[5059,5282,5283],{},[5251,5284,5286],{"href":5285},"/pt/blog/gofpdf-migration","gofpdf foi arquivado. Como migrar para gpdf.",[5059,5288,5289],{},[5251,5290,5292],{"href":5291},"/pt/blog/unidoc-migration","unipdf é AGPL ou pago. Como migrar para gpdf.",[5059,5294,5295],{},[5251,5296,5298],{"href":5297},"/pt/blog/invoice-pdf-go-under-50-lines","Gerar uma NF em PDF em Go com menos de 50 linhas",[5300,5301,5302],"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 .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 .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 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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":527,"searchDepth":545,"depth":545,"links":5304},[5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319],{"id":16,"depth":545,"text":17},{"id":67,"depth":545,"text":68},{"id":89,"depth":545,"text":90},{"id":131,"depth":545,"text":132},{"id":511,"depth":545,"text":512},{"id":1448,"depth":545,"text":1449},{"id":2231,"depth":545,"text":2232},{"id":3321,"depth":545,"text":3322},{"id":4012,"depth":545,"text":4013},{"id":4665,"depth":545,"text":4666},{"id":4935,"depth":545,"text":4936},{"id":5050,"depth":545,"text":5051},{"id":5120,"depth":545,"text":5121},{"id":5226,"depth":545,"text":5227},{"id":5265,"depth":545,"text":5266},"2026-05-06","signintech/gopdf funciona, mas cada célula, linha e cabeçalho é um cálculo (x, y). Este guia mapeia a API do gopdf para gpdf — mesmo Go, sem coordenadas.",false,"md",{"name":5325,"totalTime":5326,"tools":5327,"steps":5329},"Migrar um projeto Go de signintech/gopdf para gpdf","PT40M",[5328],"Go 1.22+",[5330,5333,5336,5339,5342,5345,5348],{"name":5331,"text":5332},"Substituir o caminho de import","Trocar github.com/signintech/gopdf por github.com/gpdf-dev/gpdf, github.com/gpdf-dev/gpdf/document e github.com/gpdf-dev/gpdf/template. A struct gopdf.GoPdf{} com cursor mutável compartilhado deixa de existir — não há tipo equivalente em gpdf.",{"name":5334,"text":5335},"Substituir pdf.Start e pdf.AddPage por gpdf.NewDocument","Construir o documento com gpdf.NewDocument(WithPageSize(document.A4), WithMargins(...)). doc.AddPage() retorna um PageBuilder, não um cursor. Você para de rastrear a posição y manualmente.",{"name":5337,"text":5338},"Remover todas as chamadas SetX, SetY e SetXY","Apagar todas as chamadas de cursor. Envolver o conteúdo em page.AutoRow(func(r *RowBuilder)) e r.Col(span, func(c *ColBuilder)). A grade de 12 colunas cuida do posicionamento horizontal; AutoRow empilha verticalmente sem matemática manual de y.",{"name":5340,"text":5341},"Substituir Cell e MultiCell por c.Text","Dentro de uma coluna, chamar c.Text(string, options...) em vez de calcular um Rect e chamar Cell ou MultiCell. A quebra de linha é automática — a coluna conhece sua própria largura.",{"name":5343,"text":5344},"Reescrever loops manuais de tabela com c.Table","Substituir os loops SetXY/Cell que desenham cada linha de cabeçalho e corpo por c.Table(headers, rows, template.ColumnWidths(...)). Bordas, quebras de página e repetição de cabeçalho são tratadas pelo motor de layout.",{"name":5346,"text":5347},"Mudar o registro de fontes para bytes","Substituir pdf.AddTTFFont(name, path) por gpdf.WithFont(name, ttfBytes) na construção. Embutir o TTF via //go:embed para que o binário deixe de precisar de um caminho de fonte em runtime.",{"name":5349,"text":5350},"Substituir WritePdf por doc.Generate mais os.WriteFile","Trocar pdf.WritePdf(path) por data, _ := doc.Generate() seguido de os.WriteFile(path, data, 0o644). Use doc.Render(w) quando quiser fazer streaming direto para um http.ResponseWriter ou S3 PutObject.",null,{},"/pt/blog/signintech-gopdf-migration",{"title":5,"description":5321},"pt/blog/021.signintech-gopdf-migration",[5357,5358,5359],"migration","comparison","tutorial","4-aM4PQek_MflIhDIvetPZsrVPs3_IgS0Ce7klzWarI",1779199037344]