diff options
author | bptato <nincsnevem662@gmail.com> | 2024-10-04 16:44:29 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-10-04 16:58:42 +0200 |
commit | 62586dc23790732e66add5b27d4d37f1a56b41e0 (patch) | |
tree | ed33d758156658b93f81de6b71449a70ef69d32b /src/local | |
parent | faa97429d651c76d86ad0c2ab530d9f666fb6927 (diff) | |
download | chawan-62586dc23790732e66add5b27d4d37f1a56b41e0.tar.gz |
sixel, term: reduce half-dump special casing
Makes it slightly easier to debug image output. Also, we stop sending dimension headers, and no longer check for the scheme env var to make CLI invocation a bit less annoying.
Diffstat (limited to 'src/local')
-rw-r--r-- | src/local/container.nim | 2 | ||||
-rw-r--r-- | src/local/pager.nim | 10 | ||||
-rw-r--r-- | src/local/term.nim | 47 |
3 files changed, 37 insertions, 22 deletions
diff --git a/src/local/container.nim b/src/local/container.nim index bbd90f1e..88becc71 100644 --- a/src/local/container.nim +++ b/src/local/container.nim @@ -124,6 +124,8 @@ type erry*: int # same as CanvasImage.offy % 6 # whether the image has transparency, *disregarding the last row* transparent*: bool + # length of introducer, raster, palette data before pixel data + preludeLen*: int Container* = ref object of RootObj # note: this is not the same as source.request.url (but should be synced diff --git a/src/local/pager.nim b/src/local/pager.nim index 09951082..d3b4d860 100644 --- a/src/local/pager.nim +++ b/src/local/pager.nim @@ -632,8 +632,11 @@ proc loadCachedImage(pager: Pager; container: Container; image: PosBitmap; cachedImage.data = blob cachedImage.state = cisLoaded cachedImage.cacheId = cacheId - let trns = response.headers.getOrDefault("Cha-Image-Sixel-Transparent", "0") - cachedImage.transparent = trns == "1" + cachedImage.transparent = + response.headers.getOrDefault("Cha-Image-Sixel-Transparent", "0") == "1" + let plens = response.headers.getOrDefault("Cha-Image-Sixel-Prelude-Len") + if (let plen = parseInt64(plens).get(0); plen <= int64(int.high)): + cachedImage.preludeLen = plen ) ) container.cachedImages.add(cachedImage) @@ -665,7 +668,8 @@ proc initImages(pager: Pager; container: Container) = let canvasImage = pager.term.loadImage(cached.data, container.process, imageId, image.x - container.fromx, image.y - container.fromy, image.width, image.height, image.x, image.y, pager.bufWidth, - pager.bufHeight, erry, offx, dispw, cached.transparent, redrawNext) + pager.bufHeight, erry, offx, dispw, cached.preludeLen, cached.transparent, + redrawNext) if canvasImage != nil: newImages.add(canvasImage) pager.term.clearImages(pager.bufHeight) diff --git a/src/local/term.nim b/src/local/term.nim index 2550ca69..c984e9d8 100644 --- a/src/local/term.nim +++ b/src/local/term.nim @@ -73,7 +73,8 @@ type damaged: bool marked*: bool dead: bool - transparent: bool # note: this is only set in outputSixelImage + transparent: bool + preludeLen: int kittyId: int # 0 if kitty erry: int @@ -760,7 +761,7 @@ proc checkImageDamage*(term: Terminal; maxw, maxh: int) = term.lineDamage[y] = mx proc loadImage*(term: Terminal; data: Blob; pid, imageId, x, y, width, height, - rx, ry, maxw, maxh, erry, offx, dispw: int; transparent: bool; + rx, ry, maxw, maxh, erry, offx, dispw, preludeLen: int; transparent: bool; redrawNext: var bool): CanvasImage = if (let image = term.findImage(pid, imageId, rx, ry, width, height, erry, offx, dispw); image != nil): @@ -787,7 +788,8 @@ proc loadImage*(term: Terminal; data: Blob; pid, imageId, x, y, width, height, width: width, height: height, erry: erry, - transparent: transparent + transparent: transparent, + preludeLen: preludeLen ) if term.positionImage(image, x, y, maxw, maxh): redrawNext = true @@ -801,6 +803,23 @@ func getU32BE(data: openArray[char]; i: int): uint32 = (uint32(data[i + 1]) shl 16) or (uint32(data[i]) shl 24) +proc appendSixelAttrs(outs: var string; data: openArray[char]; + realw, realh: int) = + var i = 0 + while i < data.len: + let c = data[i] + outs &= c + inc i + if c == '"': # set raster attrs + break + while i < data.len and data[i] != '#': # skip aspect ratio attrs + inc i + outs &= "1;1;" & $realw & ';' & $realh + if i < data.len: + let ol = outs.len + outs.setLen(ol + data.len - i) + copyMem(addr outs[ol], unsafeAddr data[i], data.len - i) + proc outputSixelImage(term: Terminal; x, y: int; image: CanvasImage; data: openArray[char]) = let offx = image.offx @@ -809,28 +828,18 @@ proc outputSixelImage(term: Terminal; x, y: int; image: CanvasImage; let disph = image.disph let realw = dispw - offx let realh = disph - offy - if data.len < 4: # bounds check + let preludeLen = image.preludeLen + if preludeLen > data.len or data.len < 4: return - let preludeLen = int(data.getU32BE(0)) - if preludeLen > data.len: + let L = data.len - int(data.getU32BE(data.len - 4)) - 4 + if L < 0: return var outs = term.cursorGoto(x, y) - # set transparency if the image has transparent sixels; omit it - # otherwise, for then some terminals (e.g. foot) handle the image more - # efficiently - let trans = image.transparent - outs &= DCS & "0;" & $int(trans) & "q" - # set raster attributes - outs &= "\"1;1;" & $realw & ';' & $realh + outs.appendSixelAttrs(data.toOpenArray(0, preludeLen - 1), realw, realh) 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 # time. Otherwise, the image is re-coded in a cropped form. - if preludeLen >= data.len or L < 0: # bounds check - term.write(ST) - elif realh == image.height: # don't crop + if realh == image.height: # don't crop term.write(data.toOpenArray(preludeLen, L - 1)) else: let si = preludeLen + int(data.getU32BE(L + (offy div 6) * 4)) |