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" ) // Document — документ, состоящий из нескольких таблиц с заголовками type Document struct { Blocks []TableBlock } // Цвет заголовка блока var titleColor = color.RGBA{0x22, 0x22, 0x20, 255} // Высота заголовка блока (над таблицей) const blockTitleHeight = 30 // Вертикальный отступ между блоками const blockSpacing = 20 // Шрифт для заголовков блоков (12pt) 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) } } // drawBigText рисует текст увеличенным шрифтом (для заголовков блоков) 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) } // RenderDocument рендерит документ — несколько именованных таблиц на одном изображении. // Каждый блок содержит заголовок и таблицу. Блоки располагаются вертикально с отступами. func RenderDocument(doc Document) image.Image { // Если нет блоков — возвращаем пустое изображение if len(doc.Blocks) == 0 { return image.NewRGBA(image.Rect(0, 0, 1, 1)) } // Рендерим каждую таблицу отдельно и считаем общие размеры 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 } // Внешние отступы документа margin := 20 // Создаём итоговое изображение img := image.NewRGBA(image.Rect(0, 0, width+margin*2, height+margin*2)) // Белый фон документа draw.Draw(img, img.Bounds(), &image.Uniform{color.White}, image.Point{}, draw.Src) y := margin // Отрисовка блоков for i, block := range doc.Blocks { // Заголовок блока drawBigText(img, margin, y+blockTitleHeight-10, block.Title) y += blockTitleHeight // Таблица блока tableImg := blockImages[i] draw.Draw( img, image.Rect(margin, y, margin+tableImg.Bounds().Dx(), y+tableImg.Bounds().Dy()), tableImg, image.Point{}, draw.Over, ) y += tableImg.Bounds().Dy() + blockSpacing } return img }