107 lines
2.1 KiB
Go
107 lines
2.1 KiB
Go
|
package termutil
|
||
|
|
||
|
import (
|
||
|
"image"
|
||
|
"math"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/liamg/darktile/internal/app/darktile/sixel"
|
||
|
)
|
||
|
|
||
|
type Sixel struct {
|
||
|
X uint16
|
||
|
Y uint64 // raw line
|
||
|
Width uint64
|
||
|
Height uint64
|
||
|
Image image.Image
|
||
|
}
|
||
|
|
||
|
type VisibleSixel struct {
|
||
|
ViewLineOffset int
|
||
|
Sixel Sixel
|
||
|
}
|
||
|
|
||
|
func (b *Buffer) addSixel(img image.Image, widthCells int, heightCells int) {
|
||
|
b.sixels = append(b.sixels, Sixel{
|
||
|
X: b.CursorColumn(),
|
||
|
Y: b.cursorPosition.Line,
|
||
|
Width: uint64(widthCells),
|
||
|
Height: uint64(heightCells),
|
||
|
Image: img,
|
||
|
})
|
||
|
if b.modes.SixelScrolling {
|
||
|
b.cursorPosition.Line += uint64(heightCells)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (b *Buffer) clearSixelsAtRawLine(rawLine uint64) {
|
||
|
var filtered []Sixel
|
||
|
|
||
|
for _, sixelImage := range b.sixels {
|
||
|
if sixelImage.Y+sixelImage.Height-1 >= rawLine && sixelImage.Y <= rawLine {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
filtered = append(filtered, sixelImage)
|
||
|
}
|
||
|
|
||
|
b.sixels = filtered
|
||
|
}
|
||
|
|
||
|
func (b *Buffer) GetVisibleSixels() []VisibleSixel {
|
||
|
|
||
|
firstLine := b.convertViewLineToRawLine(0)
|
||
|
lastLine := b.convertViewLineToRawLine(b.viewHeight - 1)
|
||
|
|
||
|
var visible []VisibleSixel
|
||
|
|
||
|
for _, sixelImage := range b.sixels {
|
||
|
if sixelImage.Y+sixelImage.Height-1 < firstLine {
|
||
|
continue
|
||
|
}
|
||
|
if sixelImage.Y > lastLine {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
visible = append(visible, VisibleSixel{
|
||
|
ViewLineOffset: int(sixelImage.Y) - int(firstLine),
|
||
|
Sixel: sixelImage,
|
||
|
})
|
||
|
}
|
||
|
|
||
|
return visible
|
||
|
}
|
||
|
|
||
|
func (t *Terminal) handleSixel(readChan chan MeasuredRune) (renderRequired bool) {
|
||
|
|
||
|
var data []rune
|
||
|
|
||
|
var inEscape bool
|
||
|
|
||
|
for {
|
||
|
r := <-readChan
|
||
|
|
||
|
switch r.Rune {
|
||
|
case 0x1b:
|
||
|
inEscape = true
|
||
|
continue
|
||
|
case 0x5c:
|
||
|
if inEscape {
|
||
|
img, err := sixel.Decode(strings.NewReader(string(data)), t.theme.DefaultBackground())
|
||
|
if err != nil {
|
||
|
return false
|
||
|
}
|
||
|
w, h := t.windowManipulator.CellSizeInPixels()
|
||
|
cw := int(math.Ceil(float64(img.Bounds().Dx()) / float64(w)))
|
||
|
ch := int(math.Ceil(float64(img.Bounds().Dy()) / float64(h)))
|
||
|
t.activeBuffer.addSixel(img, cw, ch)
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inEscape = false
|
||
|
|
||
|
data = append(data, r.Rune)
|
||
|
}
|
||
|
}
|