clone

fifteen puzzle games for the terminal, with daily puzzles, weekly ladders and xp, built on bubble tea

feat/app-decomposition
puzzletea / games / hitori / print_adapter.go
print_adapter.go 2.7K
1package hitori23import (4 "strings"5 "unicode/utf8"67 "codeberg.org/go-pdf/fpdf"8 "github.com/FelineStateMachine/puzzletea/export/pdf"9)1011type printAdapter struct{}1213var PDFPrintAdapter = printAdapter{}1415func (printAdapter) CanonicalGameType() string { return "Hitori" }16func (printAdapter) Aliases() []string { return []string{"hitori"} }1718func (printAdapter) BuildPDFPayload(save []byte) (any, error) {19 return pdfexport.ParseHitoriPrintData(save)20}2122func (printAdapter) RenderPDFBody(pdf *fpdf.Fpdf, payload any) error {23 switch data := payload.(type) {24 case *pdfexport.HitoriData:25 renderHitoriPage(pdf, data)26 }27 return nil28}2930func renderHitoriPage(pdf *fpdf.Fpdf, data *pdfexport.HitoriData) {31 if data == nil || data.Size <= 0 {32 return33 }3435 size := data.Size36 pageW, pageH := pdf.GetPageSize()37 pageNo := pdf.PageNo()38 body := pdfexport.PuzzleBodyRect(pageW, pageH, pageNo)39 rules := []string{"Shade duplicates; shaded cells cannot touch orthogonally; unshaded cells stay connected."}40 ruleLines := pdfexport.InstructionLineCount(pdf, body.W, rules)41 area := pdfexport.PuzzleBoardRect(pageW, pageH, pageNo, ruleLines)42 cellSize := pdfexport.FitCompactCellSize(size, size, area)43 if cellSize <= 0 {44 return45 }4647 blockW := float64(size) * cellSize48 blockH := float64(size) * cellSize49 startX, startY := pdfexport.CenteredOrigin(area, size, size, cellSize)5051 pdf.SetDrawColor(55, 55, 55)52 pdf.SetLineWidth(pdfexport.ThinGridLineMM)53 for y := range size {54 for x := range size {55 cellX := startX + float64(x)*cellSize56 cellY := startY + float64(y)*cellSize57 pdf.Rect(cellX, cellY, cellSize, cellSize, "D")5859 text := ""60 if y < len(data.Numbers) && x < len(data.Numbers[y]) {61 text = strings.TrimSpace(data.Numbers[y][x])62 }63 if text == "" || text == "." {64 continue65 }66 drawHitoriCellNumber(pdf, cellX, cellY, cellSize, text)67 }68 }6970 pdf.SetDrawColor(35, 35, 35)71 pdf.SetLineWidth(pdfexport.OuterBorderLineMM)72 pdf.Rect(startX, startY, blockW, blockH, "D")7374 ruleY := pdfexport.InstructionY(startY+blockH, pageH, ruleLines)75 pdfexport.RenderInstructions(pdf, body.X, ruleY, body.W, rules)76}7778func drawHitoriCellNumber(pdf *fpdf.Fpdf, x, y, cellSize float64, text string) {79 fontSize := pdfexport.StandardCellFontSize(cellSize, 0.58)80 runeCount := utf8.RuneCountInString(text)81 switch {82 case runeCount >= 3:83 fontSize *= 0.784 case runeCount == 2:85 fontSize *= 0.8286 }87 fontSize = pdfexport.ClampStandardCellFontSize(fontSize)8889 pdf.SetTextColor(pdfexport.PrimaryTextGray, pdfexport.PrimaryTextGray, pdfexport.PrimaryTextGray)90 pdf.SetFont(pdfexport.SansFontFamily, "B", fontSize)91 lineH := fontSize * 0.9292 pdf.SetXY(x, y+(cellSize-lineH)/2)93 pdf.CellFormat(cellSize, lineH, text, "", 0, "C", false, 0, "")94}