mirror of https://github.com/liamg/aminal.git
finished sixel support
This commit is contained in:
parent
20c3c0cb14
commit
78d67302b4
38
README.md
38
README.md
|
@ -10,9 +10,14 @@ The project is experimental at the moment, so you probably won't want to rely on
|
|||
|
||||
Ensure you have your latest graphics card drivers installed before use.
|
||||
|
||||
Sixels are now supported.
|
||||
|
||||

|
||||
|
||||
|
||||
## Aims
|
||||
|
||||
- Full unicode support
|
||||
- Unicode support
|
||||
- OpenGL rendering
|
||||
- Full customisation options
|
||||
- True colour support
|
||||
|
@ -23,6 +28,7 @@ Ensure you have your latest graphics card drivers installed before use.
|
|||
- Resize logic that wraps/unwraps lines _correctly_
|
||||
- Bullshit graphical effects
|
||||
- Multi platform support
|
||||
- Sixel support
|
||||
|
||||
## What isn't supported?
|
||||
|
||||
|
@ -32,13 +38,6 @@ Ensure you have your latest graphics card drivers installed before use.
|
|||
<img alt="Overheating" src="https://imgs.xkcd.com/comics/workflow.png"/>
|
||||
</p>
|
||||
|
||||
## Build Dependencies
|
||||
|
||||
- Go 1.10.3+
|
||||
- On macOS, you need Xcode or Command Line Tools for Xcode (`xcode-select --install`) for required headers and libraries.
|
||||
- On Ubuntu/Debian-like Linux distributions, you need `libgl1-mesa-dev xorg-dev`.
|
||||
- On CentOS/Fedora-like Linux distributions, you need `libX11-devel libXcursor-devel libXrandr-devel libXinerama-devel mesa-libGL-devel libXi-devel`.
|
||||
|
||||
## Platform Support
|
||||
|
||||
| Platform | Supported |
|
||||
|
@ -47,25 +46,12 @@ Ensure you have your latest graphics card drivers installed before use.
|
|||
| MacOSX | ⏳ |
|
||||
| Windows | ⏳ |
|
||||
|
||||
## Planned Features
|
||||
## Build Dependencies
|
||||
|
||||
| Feature | Done | Notes |
|
||||
|-----------------------------|------|-------|
|
||||
| Pty allocation | ✔ |
|
||||
| OpenGL rendering | ✔ |
|
||||
| 8-bit (256) colour | ✔ |
|
||||
| 24-bit (true) colour | ✔ |
|
||||
| Resizing/content reordering | ✔ |
|
||||
| ANSI escape codes | ✔ |
|
||||
| UTF-8 input | ✔ |
|
||||
| UTF-8 output | ✔ |
|
||||
| Copy/paste | ✔ |
|
||||
| Customisable colour schemes | ✔ |
|
||||
| Config file | ✔ |
|
||||
| Scrolling | ✔ |
|
||||
| Mouse interaction | ✔ |
|
||||
| Clickable URLs | ✔ |
|
||||
| Sweet render effects | |
|
||||
- Go 1.10.3+
|
||||
- On macOS, you need Xcode or Command Line Tools for Xcode (`xcode-select --install`) for required headers and libraries.
|
||||
- On Ubuntu/Debian-like Linux distributions, you need `libgl1-mesa-dev xorg-dev`.
|
||||
- On CentOS/Fedora-like Linux distributions, you need `libX11-devel libXcursor-devel libXrandr-devel libXinerama-devel mesa-libGL-devel libXi-devel`.
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
|
|
|
@ -40,11 +40,11 @@ func (cell *Cell) DrawImage(x, y float32) {
|
|||
}
|
||||
|
||||
var tex uint32
|
||||
gl.Enable(gl.TEXTURE_2D)
|
||||
gl.GenTextures(1, &tex)
|
||||
gl.BindTexture(gl.TEXTURE_2D, tex)
|
||||
gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
|
||||
gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
|
||||
|
||||
gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
|
||||
gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
|
||||
|
||||
|
@ -60,6 +60,9 @@ func (cell *Cell) DrawImage(x, y float32) {
|
|||
gl.Ptr(cell.image.Pix),
|
||||
)
|
||||
gl.BindTexture(gl.TEXTURE_2D, 0)
|
||||
gl.Disable(gl.TEXTURE_2D)
|
||||
|
||||
gl.Disable(gl.BLEND)
|
||||
|
||||
var w float32 = float32(cell.image.Bounds().Size().X)
|
||||
var h float32 = float32(cell.image.Bounds().Size().Y)
|
||||
|
@ -67,6 +70,7 @@ func (cell *Cell) DrawImage(x, y float32) {
|
|||
var readFboId uint32
|
||||
gl.GenFramebuffers(1, &readFboId)
|
||||
gl.BindFramebuffer(gl.READ_FRAMEBUFFER, readFboId)
|
||||
|
||||
gl.FramebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
|
||||
gl.TEXTURE_2D, tex, 0)
|
||||
gl.BlitFramebuffer(0, 0, int32(w), int32(h),
|
||||
|
@ -74,6 +78,7 @@ func (cell *Cell) DrawImage(x, y float32) {
|
|||
gl.COLOR_BUFFER_BIT, gl.LINEAR)
|
||||
gl.BindFramebuffer(gl.READ_FRAMEBUFFER, 0)
|
||||
gl.DeleteFramebuffers(1, &readFboId)
|
||||
|
||||
}
|
||||
|
||||
func (cell *Cell) Attr() CellAttributes {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -6,8 +6,6 @@ import (
|
|||
"image/color"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-gl/gl/v2.1/gl"
|
||||
)
|
||||
|
||||
type Sixel struct {
|
||||
|
@ -32,7 +30,7 @@ func decompress(data string) string {
|
|||
inMarker = true
|
||||
countStr = ""
|
||||
} else {
|
||||
output = fmt.Sprintf("%s%c", output, r)
|
||||
output += string(r)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
@ -41,9 +39,7 @@ func decompress(data string) string {
|
|||
countStr = fmt.Sprintf("%s%c", countStr, r)
|
||||
} else {
|
||||
count, _ := strconv.Atoi(countStr)
|
||||
for i := 0; i < count; i++ {
|
||||
output = fmt.Sprintf("%s%c", output, r)
|
||||
}
|
||||
output += strings.Repeat(string(r), count)
|
||||
inMarker = false
|
||||
}
|
||||
}
|
||||
|
@ -85,9 +81,9 @@ func ParseString(data string) (*Sixel, error) {
|
|||
ratio = 5
|
||||
case "2":
|
||||
ratio = 3
|
||||
case "", "3", "4", "5", "6":
|
||||
case "3", "4", "5", "6":
|
||||
ratio = 2
|
||||
case "7", "8", "9":
|
||||
case "7", "8", "9", "":
|
||||
ratio = 1
|
||||
}
|
||||
if len(headers) > 1 {
|
||||
|
@ -165,37 +161,6 @@ func ParseString(data string) (*Sixel, error) {
|
|||
return &six, nil
|
||||
}
|
||||
|
||||
func (six *Sixel) Draw() error {
|
||||
rgba := six.RGBA()
|
||||
|
||||
var handle uint32
|
||||
gl.GenTextures(1, &handle)
|
||||
|
||||
target := uint32(gl.TEXTURE_2D)
|
||||
internalFmt := int32(gl.SRGB_ALPHA)
|
||||
format := uint32(gl.RGBA)
|
||||
width := int32(rgba.Rect.Size().X)
|
||||
height := int32(rgba.Rect.Size().Y)
|
||||
pixType := uint32(gl.UNSIGNED_BYTE)
|
||||
dataPtr := gl.Ptr(rgba.Pix)
|
||||
|
||||
gl.ActiveTexture(gl.TEXTURE0)
|
||||
gl.BindTexture(target, handle)
|
||||
|
||||
// set the texture wrapping/filtering options (applies to current bound texture obj)
|
||||
// TODO-cs
|
||||
//gl.TexParameteri(texture.target, gl.TEXTURE_WRAP_R, wrapR)
|
||||
//gl.TexParameteri(texture.target, gl.TEXTURE_WRAP_S, wrapS)
|
||||
gl.TexParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR) // minification filter
|
||||
gl.TexParameteri(target, gl.TEXTURE_MAG_FILTER, gl.LINEAR) // magnification filter
|
||||
|
||||
gl.TexImage2D(target, 0, internalFmt, width, height, 0, format, pixType, dataPtr)
|
||||
|
||||
// unbind
|
||||
gl.BindTexture(target, 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (six *Sixel) setPixel(x, y uint, c colour, vhRatio uint) {
|
||||
|
||||
if six.px == nil {
|
||||
|
@ -227,11 +192,11 @@ func (six *Sixel) RGBA() *image.RGBA {
|
|||
|
||||
for x, r := range six.px {
|
||||
for y, colour := range r {
|
||||
rgba.SetRGBA(int(x), int(six.height)-int(y), color.RGBA{
|
||||
colour[0],
|
||||
colour[1],
|
||||
colour[2],
|
||||
255,
|
||||
rgba.Set(int(x), int(six.height)-int(y), color.RGBA{
|
||||
R: colour[0],
|
||||
G: colour[1],
|
||||
B: colour[2],
|
||||
A: 255,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@ package terminal
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/draw"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/go-gl/gl/all-core/gl"
|
||||
"github.com/liamg/aminal/sixel"
|
||||
)
|
||||
|
||||
|
@ -18,7 +20,9 @@ func sixelHandler(pty chan rune, terminal *Terminal) error {
|
|||
_ = <-pty // swallow \ or bell
|
||||
break
|
||||
}
|
||||
data = append(data, b)
|
||||
if b >= 33 {
|
||||
data = append(data, b)
|
||||
}
|
||||
}
|
||||
|
||||
six, err := sixel.ParseString(string(data))
|
||||
|
@ -26,21 +30,43 @@ func sixelHandler(pty chan rune, terminal *Terminal) error {
|
|||
return fmt.Errorf("Failed to parse sixel data: %s", err)
|
||||
}
|
||||
|
||||
originalImage := six.RGBA()
|
||||
|
||||
w := originalImage.Bounds().Size().X
|
||||
h := originalImage.Bounds().Size().Y
|
||||
|
||||
x, y := terminal.ActiveBuffer().CursorColumn(), terminal.ActiveBuffer().CursorLine()
|
||||
terminal.ActiveBuffer().Write(' ')
|
||||
cell := terminal.ActiveBuffer().GetCell(x, y)
|
||||
if cell == nil {
|
||||
return fmt.Errorf("Missing cell for sixel")
|
||||
|
||||
fromBottom := int(terminal.ActiveBuffer().ViewHeight() - y)
|
||||
lines := int(math.Ceil(float64(h) / float64(terminal.charHeight)))
|
||||
if fromBottom < lines+2 {
|
||||
y -= (uint16(lines+2) - uint16(fromBottom))
|
||||
}
|
||||
|
||||
gl.UseProgram(terminal.program)
|
||||
cell.SetImage(six.RGBA())
|
||||
|
||||
imageHeight := float64(cell.Image().Bounds().Size().Y)
|
||||
lines := int(math.Ceil(imageHeight / float64(terminal.charHeight)))
|
||||
for l := 0; l <= int(lines+1); l++ {
|
||||
for l := 0; l <= int(lines); l++ {
|
||||
terminal.ActiveBuffer().Write([]rune(strings.Repeat(" ", int(terminal.ActiveBuffer().ViewWidth())))...)
|
||||
terminal.ActiveBuffer().NewLine()
|
||||
}
|
||||
cols := int(math.Ceil(float64(w) / float64(terminal.charWidth)))
|
||||
|
||||
for offsetY := 0; offsetY < lines-1; offsetY++ {
|
||||
for offsetX := 0; offsetX < cols-1; offsetX++ {
|
||||
|
||||
cell := terminal.ActiveBuffer().GetCell(x+uint16(offsetX), y+uint16((lines-2)-offsetY))
|
||||
if cell == nil {
|
||||
continue
|
||||
}
|
||||
img := originalImage.SubImage(image.Rect(
|
||||
offsetX*int(terminal.charWidth),
|
||||
offsetY*int(terminal.charHeight),
|
||||
(offsetX*int(terminal.charWidth))+int(terminal.charWidth),
|
||||
(offsetY*int(terminal.charHeight))+int(terminal.charHeight),
|
||||
))
|
||||
|
||||
rgba := image.NewRGBA(image.Rect(0, 0, int(terminal.charWidth), int(terminal.charHeight)))
|
||||
draw.Draw(rgba, rgba.Bounds(), img, img.Bounds().Min, draw.Src)
|
||||
cell.SetImage(rgba)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue