diff options
author | bptato <nincsnevem662@gmail.com> | 2024-12-03 19:43:22 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-12-03 19:43:22 +0100 |
commit | 6d92a2e6679c481c8a88fc50d750e2ea8af67a23 (patch) | |
tree | e462bef801a80242cbb42608595d6377236af799 | |
parent | 05b97c934468ef23cf83f11083b1b9aef883dfb0 (diff) | |
download | chawan-6d92a2e6679c481c8a88fc50d750e2ea8af67a23.tar.gz |
pager, term: use cell offset with kitty images
Gets rid of rounding errors when positioning images. Theoretically this is possible with Sixel too, but as always, it's ten times as difficult to implement as with Kitty, so I'll leave it for later.
-rw-r--r-- | src/css/layout.nim | 2 | ||||
-rw-r--r-- | src/css/render.nim | 12 | ||||
-rw-r--r-- | src/local/pager.nim | 4 | ||||
-rw-r--r-- | src/local/term.nim | 31 |
4 files changed, 35 insertions, 14 deletions
diff --git a/src/css/layout.nim b/src/css/layout.nim index fe5afdcc..2e1fcd03 100644 --- a/src/css/layout.nim +++ b/src/css/layout.nim @@ -1599,7 +1599,7 @@ proc addInlineImage(ictx: var InlineContext; state: var InlineState; let atom = InlineAtom( t: iatImage, bmp: bmp, - size: size(w = int(bmp.width), h = int(bmp.height)) #TODO overflow + size: size(w = bmp.width, h = bmp.height) #TODO overflow ) let computed = state.fragment.computed let lctx = ictx.lctx diff --git a/src/css/render.nim b/src/css/render.nim index 8e8185dc..d7d57e35 100644 --- a/src/css/render.nim +++ b/src/css/render.nim @@ -230,6 +230,8 @@ type PosBitmap* = ref object x*: int y*: int + offx*: int + offy*: int width*: int height*: int bmp*: NetworkBitmap @@ -367,9 +369,15 @@ proc renderInlineFragment(grid: var FlexibleGrid; state: var RenderState; # "paint" background, i.e. add formatting (but don't actually color it) grid.paintBackground(state, defaultColor, x1, y1, x2, y2, fragment.node, noPaint = true) + let x = (offset.x div state.attrs.ppc).toInt + let y = (offset.y div state.attrs.ppl).toInt + let offx = (offset.x - x.toLayoutUnit * state.attrs.ppc).toInt + let offy = (offset.y - y.toLayoutUnit * state.attrs.ppl).toInt state.images.add(PosBitmap( - x: (offset.x div state.attrs.ppc).toInt, - y: (offset.y div state.attrs.ppl).toInt, + x: x, + y: y, + offx: offx, + offy: offy, width: atom.size.w.toInt, height: atom.size.h.toInt, bmp: atom.bmp diff --git a/src/local/pager.nim b/src/local/pager.nim index 6fe2ce63..61833418 100644 --- a/src/local/pager.nim +++ b/src/local/pager.nim @@ -697,8 +697,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.preludeLen, cached.transparent, - redrawNext) + pager.bufHeight, erry, offx, dispw, image.offx, image.offy, + 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 bc9919b8..3820b16d 100644 --- a/src/local/term.nim +++ b/src/local/term.nim @@ -91,6 +91,10 @@ type # offset (crop start) offx: int offy: int + # kitty only: X/Y offset *inside* cell. (TODO implement for sixel too) + # has nothing to do with offx/offy. + offx2: int + offy2: int # size cap (crop end) # Note: this 0-based, so the final display size is # (dispw - offx, disph - offy) @@ -710,12 +714,17 @@ func findImage(term: Terminal; pid, imageId: int; rx, ry, width, height, # x, y, maxw, maxh in cells # x, y can be negative, then image starts outside the screen -proc positionImage(term: Terminal; image: CanvasImage; x, y, maxw, maxh: int): - bool = +proc positionImage(term: Terminal; image: CanvasImage; + x, y, maxw, maxh, offx2, offy2: int): bool = image.x = x image.y = y - let xpx = x * term.attrs.ppc - let ypx = y * term.attrs.ppl + image.offx2 = offx2 + image.offy2 = offy2 + var xpx = x * term.attrs.ppc + var ypx = y * term.attrs.ppl + if term.imageMode == imKitty: + xpx += image.offx2 + ypx += image.offy2 # calculate offset inside image to start from image.offx = -min(xpx, 0) image.offy = -min(ypx, 0) @@ -790,8 +799,8 @@ 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, preludeLen: int; transparent: bool; - redrawNext: var bool): CanvasImage = + rx, ry, maxw, maxh, erry, offx, dispw, offx2, offy2, preludeLen: int; + transparent: bool; redrawNext: var bool): CanvasImage = if (let image = term.findImage(pid, imageId, rx, ry, width, height, erry, offx, dispw); image != nil): # reuse image on screen @@ -799,7 +808,7 @@ proc loadImage*(term: Terminal; data: Blob; pid, imageId, x, y, width, height, # only clear sixels; with kitty we just move the existing image if term.imageMode == imSixel: term.clearImage(image, maxh) - if not term.positionImage(image, x, y, maxw, maxh): + if not term.positionImage(image, x, y, maxw, maxh, offx2, offy2): # no longer on screen image.dead = true return nil @@ -814,13 +823,15 @@ proc loadImage*(term: Terminal; data: Blob; pid, imageId, x, y, width, height, data: data, rx: rx, ry: ry, + offx2: offx2, + offy2: offy2, width: width, height: height, erry: erry, transparent: transparent, preludeLen: preludeLen ) - if term.positionImage(image, x, y, maxw, maxh): + if term.positionImage(image, x, y, maxw, maxh, offx2, offy2): redrawNext = true return image # no longer on screen @@ -909,6 +920,7 @@ proc outputKittyImage(term: Terminal; x, y: int; image: CanvasImage) = var outs = term.cursorGoto(x, y) & APC & "GC=1,s=" & $image.width & ",v=" & $image.height & ",x=" & $image.offx & ",y=" & $image.offy & + ",X=" & $image.offx2 & ",Y=" & $image.offy2 & ",w=" & $(image.dispw - image.offx) & ",h=" & $(image.disph - image.offy) & # for now, we always use placement id 1 @@ -966,7 +978,8 @@ proc clearCanvas*(term: Terminal) = let maxh = term.attrs.height - 1 var newImages: seq[CanvasImage] = @[] for image in term.canvasImages: - if term.positionImage(image, image.x, image.y, maxw, maxh): + if term.positionImage(image, image.x, image.y, maxw, maxh, image.offx2, + image.offy2): image.damaged = true image.marked = true newImages.add(image) |