mirror of https://github.com/mum4k/termdash.git
91 lines
3.3 KiB
Go
91 lines
3.3 KiB
Go
// Copyright 2019 Google Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Package segdisp provides utilities used by all segment display types.
|
|
package segdisp
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"math"
|
|
|
|
"github.com/mum4k/termdash/private/area"
|
|
"github.com/mum4k/termdash/private/canvas"
|
|
"github.com/mum4k/termdash/private/canvas/braille"
|
|
)
|
|
|
|
// Minimum valid size of a cell canvas in order to draw a segment display.
|
|
const (
|
|
// MinCols is the smallest valid amount of columns in a cell area.
|
|
MinCols = 6
|
|
// MinRowPixels is the smallest valid amount of rows in a cell area.
|
|
MinRows = 5
|
|
)
|
|
|
|
// aspectRatio is the desired aspect ratio of a single segment display.
|
|
var aspectRatio = image.Point{3, 5}
|
|
|
|
// Required when given an area of cells, returns either an area of the same
|
|
// size or a smaller area that is required to draw one segment display (i.e.
|
|
// one character).
|
|
// Returns a smaller area when the provided area didn't have the required
|
|
// aspect ratio.
|
|
// Returns an error if the area is too small to draw a segment display, i.e.
|
|
// smaller than MinCols x MinRows.
|
|
func Required(cellArea image.Rectangle) (image.Rectangle, error) {
|
|
if cols, rows := cellArea.Dx(), cellArea.Dy(); cols < MinCols || rows < MinRows {
|
|
return image.ZR, fmt.Errorf("cell area %v is too small to draw the segment display, has %dx%d cells, need at least %dx%d cells",
|
|
cellArea, cols, rows, MinCols, MinRows)
|
|
}
|
|
|
|
bcAr := image.Rect(cellArea.Min.X, cellArea.Min.Y, cellArea.Max.X*braille.ColMult, cellArea.Max.Y*braille.RowMult)
|
|
bcArAdj := area.WithRatio(bcAr, aspectRatio)
|
|
|
|
needCols := int(math.Ceil(float64(bcArAdj.Dx()) / braille.ColMult))
|
|
needRows := int(math.Ceil(float64(bcArAdj.Dy()) / braille.RowMult))
|
|
needAr := image.Rect(cellArea.Min.X, cellArea.Min.Y, cellArea.Min.X+needCols, cellArea.Min.Y+needRows)
|
|
return needAr, nil
|
|
}
|
|
|
|
// ToBraille converts the canvas into a braille canvas and returns a pixel area
|
|
// with aspect ratio adjusted for the segment display.
|
|
func ToBraille(cvs *canvas.Canvas) (*braille.Canvas, image.Rectangle, error) {
|
|
ar, err := Required(cvs.Area())
|
|
if err != nil {
|
|
return nil, image.ZR, fmt.Errorf("Required => %v", err)
|
|
}
|
|
|
|
bc, err := braille.New(ar)
|
|
if err != nil {
|
|
return nil, image.ZR, fmt.Errorf("braille.New => %v", err)
|
|
}
|
|
return bc, area.WithRatio(bc.Area(), aspectRatio), nil
|
|
}
|
|
|
|
// SegmentSize given an area for the display segment determines the size of
|
|
// individual segments, i.e. the width of a vertical or the height of a
|
|
// horizontal segment.
|
|
func SegmentSize(ar image.Rectangle) int {
|
|
// widthPerc is the relative width of a segment to the width of the canvas.
|
|
const widthPerc = 9
|
|
s := int(math.Round(float64(ar.Dx()) * widthPerc / 100))
|
|
if s > 3 && s%2 == 0 {
|
|
// Segments with odd number of pixels in their width/height look
|
|
// better, since the spike at the top of their slopes has only one
|
|
// pixel.
|
|
s++
|
|
}
|
|
return s
|
|
}
|