package image_table import ( "image" "image/color" "image/draw" "golang.org/x/image/font" "golang.org/x/image/font/opentype" "golang.org/x/image/math/fixed" ) type TableBlock struct { Title string Header []string Rows []any } type Document struct { Blocks []TableBlock } var titleColor = color.RGBA{0x22, 0x22, 0x20, 255} // Высота заголовка блока const blockTitleHeight = 30 const blockSpacing = 20 // Рисуем текст заголовка func drawBigText(img *image.RGBA, x, y int, text string) { d := &font.Drawer{ Dst: img, Src: image.NewUniform(titleColor), Face: globalFaceBig, // увеличенный шрифт Dot: fixed.P(x, y), } d.DrawString(text) } // ---- Увеличенный шрифт для заголовков ---- var globalFaceBig font.Face func init() { f, err := opentype.Parse(jbTTF) if err != nil { panic(err) } globalFaceBig, err = opentype.NewFace(f, &opentype.FaceOptions{ Size: 12, DPI: 96, Hinting: font.HintingFull, }) if err != nil { panic(err) } } func RenderDocument(doc Document) image.Image { // Сначала считаем общие размеры width := 0 height := 0 blockImages := make([]image.Image, len(doc.Blocks)) for i, block := range doc.Blocks { tableImg := DrawTableWarm(block.Header, block.Rows) blockImages[i] = tableImg w := tableImg.Bounds().Dx() if w > width { width = w } height += blockTitleHeight + tableImg.Bounds().Dy() + blockSpacing } // Создаём документ img := image.NewRGBA(image.Rect(0, 0, width+40, height+40)) // общий фон draw.Draw(img, img.Bounds(), &image.Uniform{color.White}, image.Point{}, draw.Src) y := 20 // рендерим блоки for i, block := range doc.Blocks { // Заголовок блока drawBigText(img, 20, y+blockTitleHeight-10, block.Title) y += blockTitleHeight // Таблица tableImg := blockImages[i] draw.Draw( img, image.Rect(20, y, 20+tableImg.Bounds().Dx(), y+tableImg.Bounds().Dy()), tableImg, image.Point{}, draw.Over, ) y += tableImg.Bounds().Dy() + blockSpacing } return img }