status-go/vendor/github.com/yeqown/go-qrcode/v2/matrix.go

168 lines
3.2 KiB
Go

package qrcode
import (
"errors"
"fmt"
)
var (
// ErrorOutRangeOfW x out of range of Width
ErrorOutRangeOfW = errors.New("out of range of width")
// ErrorOutRangeOfH y out of range of Height
ErrorOutRangeOfH = errors.New("out of range of height")
)
// newMatrix generate a matrix with map[][]qrbool
func newMatrix(width, height int) *Matrix {
mat := make([][]qrvalue, width)
for w := 0; w < width; w++ {
mat[w] = make([]qrvalue, height)
}
m := &Matrix{
mat: mat,
width: width,
height: height,
}
m.init()
return m
}
// Matrix is a matrix data type
// width:3 height: 4 for [3][4]int
type Matrix struct {
mat [][]qrvalue
width int
height int
}
// do some init work
func (m *Matrix) init() {
for w := 0; w < m.width; w++ {
for h := 0; h < m.height; h++ {
m.mat[w][h] = QRValue_INIT_V0
}
}
}
// print to stdout
func (m *Matrix) print() {
m.iter(IterDirection_ROW, func(x, y int, s qrvalue) {
fmt.Printf("%s ", s)
if (x + 1) == m.width {
fmt.Println()
}
})
}
// Copy matrix into a new Matrix
func (m *Matrix) Copy() *Matrix {
mat2 := make([][]qrvalue, m.width)
for w := 0; w < m.width; w++ {
mat2[w] = make([]qrvalue, m.height)
copy(mat2[w], m.mat[w])
}
m2 := &Matrix{
width: m.width,
height: m.height,
mat: mat2,
}
return m2
}
// Width ... width
func (m *Matrix) Width() int {
return m.width
}
// Height ... height
func (m *Matrix) Height() int {
return m.height
}
// set [w][h] as true
func (m *Matrix) set(w, h int, c qrvalue) error {
if w >= m.width || w < 0 {
return ErrorOutRangeOfW
}
if h >= m.height || h < 0 {
return ErrorOutRangeOfH
}
m.mat[w][h] = c
return nil
}
// at state qrvalue from matrix with position {x, y}
func (m *Matrix) at(w, h int) (qrvalue, error) {
if w >= m.width || w < 0 {
return QRValue_INIT_V0, ErrorOutRangeOfW
}
if h >= m.height || h < 0 {
return QRValue_INIT_V0, ErrorOutRangeOfH
}
return m.mat[w][h], nil
}
// iterDirection scan matrix direction
type iterDirection uint8
const (
// IterDirection_ROW for row first
IterDirection_ROW iterDirection = iota + 1
// IterDirection_COLUMN for column first
IterDirection_COLUMN
)
// Iterate the Matrix with loop direction IterDirection_ROW major or IterDirection_COLUMN major.
// IterDirection_COLUMN is recommended.
func (m *Matrix) Iterate(direction iterDirection, fn func(x, y int, s QRValue)) {
m.iter(direction, fn)
}
func (m *Matrix) iter(dir iterDirection, visitFn func(x int, y int, v qrvalue)) {
// row direction first
if dir == IterDirection_ROW {
for h := 0; h < m.height; h++ {
for w := 0; w < m.width; w++ {
visitFn(w, h, m.mat[w][h])
}
}
return
}
// column direction first
for w := 0; w < m.width; w++ {
for h := 0; h < m.height; h++ {
visitFn(w, h, m.mat[w][h])
}
}
return
}
// Row return a row of matrix, cur should be y dimension.
func (m *Matrix) Row(cur int) []qrvalue {
if cur >= m.height || cur < 0 {
return nil
}
col := make([]qrvalue, m.height)
for w := 0; w < m.width; w++ {
col[w] = m.mat[w][cur]
}
return col
}
// Col return a slice of column, cur should be x dimension.
func (m *Matrix) Col(cur int) []qrvalue {
if cur >= m.width || cur < 0 {
return nil
}
return m.mat[cur]
}