mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-04 04:27:34 +00:00
103 lines
2.9 KiB
Go
103 lines
2.9 KiB
Go
// Copyright (c) 2022 Sam Blenny
|
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
//
|
|
package lib
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"strings"
|
|
)
|
|
|
|
// Holds packed XOR mask values of a blit pattern for character's glyph.
|
|
//
|
|
// Pixel order: row-major order traversal of px matrix; top-left pixel goes in
|
|
// least significant bit of of .Words[1]
|
|
// Mask values: bit=1 means foreground, bit=0 means background
|
|
//
|
|
// Patterns that need padding because their size is not a multiple of 32 bits
|
|
// (width*height % 32 != 0) get padded with zeros in the least significant bits
|
|
// of the last word.
|
|
type BlitPattern struct {
|
|
Words []uint32
|
|
Width uint8
|
|
CS CharSpec
|
|
}
|
|
|
|
// Extract matrix of pixels from an image containing grid of glyphs
|
|
// - img: image.Image from png file containing glyph grid
|
|
// - font: Glyph sheet specs (glyph size, border/gutter, etc)
|
|
// - cs: Character specs (source row and column in glyph grid)
|
|
func NewBlitPattern(img image.Image, font FontSpec, cs CharSpec, dbg bool) BlitPattern {
|
|
row := cs.Row
|
|
col := cs.Col
|
|
imgRect := img.Bounds()
|
|
rows := (imgRect.Max.Y - font.Border) / (font.Size + font.Gutter)
|
|
if row < 0 || row >= rows || col < 0 || col >= font.Cols {
|
|
panic("row or column out of range")
|
|
}
|
|
// Get pixels for grid cell, converting from RGBA to 1-bit
|
|
gridSize := font.Size + font.Gutter
|
|
border := font.Border
|
|
pxMatrix := Matrix{}
|
|
for y := border + (row * gridSize); y < (row+1)*gridSize; y++ {
|
|
var row MatrixRow
|
|
for x := border + (col * gridSize); x < (col+1)*gridSize; x++ {
|
|
r, _, _, _ := img.At(x, y).RGBA()
|
|
//fmt.Println(r, g, b, a)
|
|
if r == 0 {
|
|
row = append(row, 1)
|
|
} else {
|
|
row = append(row, 0)
|
|
}
|
|
}
|
|
pxMatrix = append(pxMatrix, row)
|
|
}
|
|
pxMatrix = pxMatrix.Trim(font, row, col)
|
|
width := uint8(len(pxMatrix[0]))
|
|
if font.Size <= 16 {
|
|
pxMatrix = pxMatrix.padTo16x16()
|
|
} else {
|
|
pxMatrix = pxMatrix.padTo32x32()
|
|
}
|
|
pxMatrix.Debug(cs, dbg)
|
|
if font.Size <= 16 {
|
|
patternBytes := pxMatrix.convertToPattern()
|
|
return BlitPattern{patternBytes, width, cs}
|
|
} else {
|
|
patternBytes := pxMatrix.convertToPattern32()
|
|
return BlitPattern{patternBytes, width, cs}
|
|
}
|
|
}
|
|
|
|
// Convert blit pattern to rust source code for part of an array of bytes
|
|
func ConvertPatternToRust(pattern BlitPattern) string {
|
|
patternStr := " "
|
|
wordsPerRow := uint32(8)
|
|
ceilRow := uint32(len(pattern.Words)) / wordsPerRow
|
|
if uint32(len(pattern.Words))%wordsPerRow > 0 {
|
|
ceilRow += 1
|
|
}
|
|
for i := uint32(0); i < ceilRow; i++ {
|
|
if i != 0 {
|
|
patternStr += " "
|
|
}
|
|
start := i * wordsPerRow
|
|
end := min(uint32(len(pattern.Words)), (i+1)*wordsPerRow)
|
|
line := pattern.Words[start:end]
|
|
var s []string
|
|
for _, word := range line {
|
|
s = append(s, fmt.Sprintf("0x%08x", word))
|
|
}
|
|
patternStr += strings.Join(s, ", ") + ",\n"
|
|
}
|
|
return patternStr
|
|
}
|
|
|
|
// Return lowest value among two integers
|
|
func min(a uint32, b uint32) uint32 {
|
|
if b > a {
|
|
return a
|
|
}
|
|
return b
|
|
}
|