diff options
author | bptato <nincsnevem662@gmail.com> | 2024-09-05 18:55:25 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-09-05 19:14:40 +0200 |
commit | ef5d188e05d4895125ad059f5518f9c8ff83bef5 (patch) | |
tree | e57882c92366983491e9ba299e0366cba93c5a6a | |
parent | 3d40aced32d7c7ee1c98359ad98f43c11e72fd71 (diff) | |
download | chawan-ef5d188e05d4895125ad059f5518f9c8ff83bef5.tar.gz |
term: sixel sizing & output fixes
* round down to number divisible by 6 for height * make pager's dispw match term's dispw even after width clamping * make *BE procs actually emit/consume big-endian (lol) * fix borked sixel set raster attributes & control string I mixed up SRA with the device control string's parameters, so instead of toggling transparency in the DCS, I was setting the second SRA parameter to 0. Which, by the way, defines the aspect ratio's denominator, and has nothing to do with transparency. Whoops.
-rw-r--r-- | adapter/img/sixel.nim | 14 | ||||
-rw-r--r-- | src/local/pager.nim | 4 | ||||
-rw-r--r-- | src/local/term.nim | 31 |
3 files changed, 29 insertions, 20 deletions
diff --git a/adapter/img/sixel.nim b/adapter/img/sixel.nim index 7f2cdb5d..06a41a89 100644 --- a/adapter/img/sixel.nim +++ b/adapter/img/sixel.nim @@ -37,16 +37,16 @@ const DCSSTART = "\eP" const ST = "\e\\" proc setU32BE(s: var string; n: uint32; at: int) = - s[at] = char(n and 0xFF) - s[at + 1] = char((n shr 8) and 0xFF) - s[at + 2] = char((n shr 16) and 0xFF) - s[at + 3] = char((n shr 24) and 0xFF) + s[at] = char((n shr 24) and 0xFF) + s[at + 1] = char((n shr 16) and 0xFF) + s[at + 2] = char((n shr 8) and 0xFF) + s[at + 3] = char(n and 0xFF) proc putU32BE(s: var string; n: uint32) = - s &= char(n and 0xFF) - s &= char((n shr 8) and 0xFF) - s &= char((n shr 16) and 0xFF) s &= char((n shr 24) and 0xFF) + s &= char((n shr 16) and 0xFF) + s &= char((n shr 8) and 0xFF) + s &= char(n and 0xFF) type Node {.acyclic.} = ref object leaf: bool diff --git a/src/local/pager.nim b/src/local/pager.nim index c713d36a..035ec2d7 100644 --- a/src/local/pager.nim +++ b/src/local/pager.nim @@ -572,8 +572,8 @@ proc initImages(pager: Pager; container: Container) = let xpx = (image.x - container.fromx) * pager.attrs.ppc offx = -min(xpx, 0) let maxwpx = pager.bufWidth * pager.attrs.ppc - #TODO this is wrong if term caps sixel width - dispw = min(int(image.width) + xpx, maxwpx) - xpx + let width = min(image.width - offx, pager.term.sixelMaxWidth) + offx + dispw = min(width + xpx, maxwpx) - xpx let ypx = (image.y - container.fromy) * pager.attrs.ppl erry = -min(ypx, 0) mod 6 let cached = container.findCachedImage(image, offx, erry, dispw) diff --git a/src/local/term.nim b/src/local/term.nim index 29046ade..62f09ac9 100644 --- a/src/local/term.nim +++ b/src/local/term.nim @@ -105,7 +105,7 @@ type defaultForeground: RGBColor ibuf*: string # buffer for chars when we can't process them sixelRegisterNum*: int - sixelMaxWidth: int + sixelMaxWidth*: int sixelMaxHeight: int kittyId: int # counter for kitty image (*not* placement) ids. cursorx: int @@ -604,6 +604,9 @@ proc applyConfigDimensions(term: Terminal) = term.sixelMaxWidth = term.attrs.widthPx if term.sixelMaxHeight == 0: term.sixelMaxHeight = term.attrs.heightPx + # xterm acts weird even if I don't fill in the missing rows, so + # just round down instead. + term.sixelMaxHeight = (term.sixelMaxHeight div 6) * 6 proc applyConfig(term: Terminal) = # colors, formatting @@ -747,10 +750,10 @@ proc loadImage*(term: Terminal; data: Blob; pid, imageId, x, y, width, height, return nil func getU32BE(data: openArray[char]; i: int): uint32 = - return uint32(data[i]) or - (uint32(data[i + 1]) shl 8) or - (uint32(data[i + 2]) shl 16) or - (uint32(data[i + 3]) shl 24) + return uint32(data[i + 3]) or + (uint32(data[i + 2]) shl 8) or + (uint32(data[i + 1]) shl 16) or + (uint32(data[i]) shl 24) proc outputSixelImage(term: Terminal; x, y: int; image: CanvasImage; data: openArray[char]) = @@ -759,21 +762,27 @@ proc outputSixelImage(term: Terminal; x, y: int; image: CanvasImage; let dispw = image.dispw let disph = image.disph var outs = term.cursorGoto(x, y) - outs &= DCSSTART & 'q' - # set raster attributes let realw = dispw - offx let realh = disph - offy - # transparent if we want to draw a non-6-divisible number of rows + # set transparency if we want to draw a non-6-divisible number + # of rows; omit it otherwise, for then some terminals (e.g. foot) + # handle the image more efficiently let trans = realh mod 6 != 0 - outs &= "\"1;" & $int(trans) & ";" & $realw & ';' & $realh + outs &= DCSSTART & "0;" & $int(trans) & 'q' + # set raster attributes + outs &= "\"1;1;" & $realw & ';' & $realh if data.len < 4: # bounds check outs &= ST term.write(outs) return - term.write(outs) let sraLen = int(data.getU32BE(0)) let preludeLen = sraLen + 4 - term.write(data.toOpenArray(4, 4 + sraLen - 1)) + if preludeLen > data.len: + outs &= ST + term.write(outs) + return + term.write(outs) + term.write(data.toOpenArray(4, preludeLen - 1)) let lookupTableLen = int(data.getU32BE(data.len - 4)) let L = data.len - lookupTableLen - 4 # Note: we only crop images when it is possible to do so in near constant |