about summary refs log tree commit diff stats
path: root/src/local
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-06-27 21:50:31 +0200
committerbptato <nincsnevem662@gmail.com>2024-06-28 21:26:33 +0200
commit8268ba2cf049be1865875e3e01305a500fa533e2 (patch)
tree7ce60624f9212e65dad0c1a2d168eb6ab7c03ec9 /src/local
parentf9734e2b3900781901bb5f268137bd9adbfc33ef (diff)
downloadchawan-8268ba2cf049be1865875e3e01305a500fa533e2.tar.gz
img, loader: add image resizing, misc fixes
* resize images with stb_image_resize
* use tee for output handle redirection (redirectToFile blocks)
* cache original image files
* accept lseek in sandbox
* misc stbi fixes

For now, I just pulled in stb_image_resize v1. v2 is an extra 150K in
size, not sure if it's worth the cost. (Either way, we can always switch
later if needed, since the API is almost the same.)

Next step: move sixel/kitty encoders to CGI, and cache their output in
memory instead of the intermediate RGBA representation.
Diffstat (limited to 'src/local')
-rw-r--r--src/local/pager.nim45
1 files changed, 33 insertions, 12 deletions
diff --git a/src/local/pager.nim b/src/local/pager.nim
index 643e7689..cd0df216 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -21,6 +21,7 @@ import io/socketstream
 import io/stdio
 import io/tempfile
 import io/urlfilter
+import layout/renderdocument
 import loader/connecterror
 import loader/headers
 import loader/loader
@@ -472,7 +473,7 @@ proc redraw(pager: Pager) {.jsfunc.} =
     if pager.container.select != nil:
       pager.container.select.redraw = true
 
-proc loadCachedImage(pager: Pager; container: Container; bmp: NetworkBitmap) =
+proc loadCachedImage(pager: Pager; container: Container; image: PosBitmap) =
   #TODO this is kinda dumb, because we cannot unload cached images.
   # ideally the filesystem cache should serve as the only cache, but right
   # now it's just sort of a temporary place before the image is dumped to
@@ -481,22 +482,42 @@ proc loadCachedImage(pager: Pager; container: Container; bmp: NetworkBitmap) =
   # load start" event in container, and then add one in the pager?
   # the first option seems better; it's simpler, and buffers can add arbitrary
   # cache files if they just tell the pager it's an image anyway.
-  let cacheId = pager.loader.addCacheFile(bmp.outputId,
-    pager.loader.clientPid, container.process)
-  let request = newRequest(newURL("cache:" & $cacheId).get)
+  let bmp = NetworkBitmap(image.bmp)
+  let request = newRequest(newURL("cache:" & $bmp.cacheId).get)
   let cachedImage = CachedImage(bmp: bmp)
-  pager.loader.fetch(request).then(proc(res: JSResult[Response]): EmptyPromise =
+  pager.loader.shareCachedItem(bmp.cacheId, pager.loader.clientPid,
+    container.process)
+  pager.loader.fetch(request).then(proc(res: JSResult[Response]):
+      Promise[JSResult[Response]] =
     if res.isNone:
-      let i = container.cachedImages.find(cachedImage)
-      container.cachedImages.del(i)
-      return nil
-    return res.get.saveToBitmap(bmp)
+      return
+    let response = res.get
+    let headers = newHeaders()
+    if uint64(image.width) != bmp.width or uint64(image.height) != bmp.height:
+      headers.add("Cha-Image-Target-Dimensions", $image.width & 'x' &
+        $image.height)
+    let request = newRequest(
+      newURL("img-codec+" & bmp.contentType.after('/') & ":decode").get,
+      httpMethod = hmPost,
+      headers = headers,
+      body = RequestBody(t: rbtOutput, outputId: response.outputId),
+    )
+    let r = pager.loader.fetch(request)
+    response.resume()
+    response.unregisterFun()
+    response.body.sclose()
+    return r
+  ).then(proc(res: JSResult[Response]): EmptyPromise =
+    let response = res.get
+    # take target sizes
+    bmp.width = uint64(image.width)
+    bmp.height = uint64(image.height)
+    return response.saveToBitmap(bmp)
   ).then(proc() =
     container.redraw = true
     cachedImage.loaded = true
-    pager.loader.removeCachedItem(cacheId)
+    pager.loader.removeCachedItem(bmp.cacheId)
   )
-  pager.loader.resume(bmp.outputId) # get rid of dangling output
   container.cachedImages.add(cachedImage)
 
 proc initImages(pager: Pager; container: Container) =
@@ -509,7 +530,7 @@ proc initImages(pager: Pager; container: Container) =
       let cached = container.findCachedImage(bmp.imageId)
       imageId = bmp.imageId
       if cached == nil:
-        pager.loadCachedImage(container, bmp)
+        pager.loadCachedImage(container, image)
         continue
       image.bmp = cached.bmp
       if not cached.loaded: