changeset 59:b68de6a43f29

Asynchronous drawing (incomplete).
author Mikhail Kryshen <mikhail@kryshen.net>
date Mon, 23 Aug 2010 14:06:13 +0400
parents 64b67aa224f4
children 7e456697924d
files src/net/kryshen/indyvon/demo.clj src/net/kryshen/indyvon/layers.clj
diffstat 2 files changed, 60 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/net/kryshen/indyvon/demo.clj	Fri Aug 20 21:44:03 2010 +0400
+++ b/src/net/kryshen/indyvon/demo.clj	Mon Aug 23 14:06:13 2010 +0400
@@ -38,7 +38,7 @@
            (.setColor Color/YELLOW)
            (.fillRect 0 0 *width* *height*))
          (with-rotate 0.5 0 0
-           (draw! layer1b 10 5))
+           (draw! layer1b 30 25))
          (draw! layer1 55 5))
       (layer-size [layer] (Size. 70 65))))
 
@@ -71,7 +71,7 @@
      (reify
       Layer
       (render! [layer]
-         ;;(*update*)
+         (*update*)
          (doto *graphics*
            (.setColor (rand-nth [Color/BLACK Color/BLUE Color/RED]))
            (.drawLine 0 0 *width* *height*))
--- a/src/net/kryshen/indyvon/layers.clj	Fri Aug 20 21:44:03 2010 +0400
+++ b/src/net/kryshen/indyvon/layers.clj	Mon Aug 23 14:06:13 2010 +0400
@@ -12,8 +12,11 @@
    (net.kryshen.indyvon.core Size Location)
    (java.lang.ref SoftReference)
    (java.awt Font Cursor Image Toolkit)
-   (java.awt.image ImageObserver)
-   (java.awt.font FontRenderContext TextLayout)))
+   (java.awt.image ImageObserver BufferedImage)
+   (java.awt.font FontRenderContext TextLayout)
+   (java.util.concurrent ThreadPoolExecutor
+                         ThreadPoolExecutor$DiscardOldestPolicy
+                         ArrayBlockingQueue TimeUnit)))
 
 ;; Define as macro to avoid unnecessary calculation of inner and outer
 ;; sizes in the first case.
@@ -170,6 +173,59 @@
               height (if (pos? height) height 1)]
           (Size. width height))))))
 
+;; (defn- validate-buffer [^Image image restore-fn]
+;;   (if (and image
+;;            (>= (.getWidth image nil) *width*)
+;;            (>= (.getHeight image nil) *height*))
+;;     image
+;;     ;;(let [image (BufferedImage. *width* *height* BufferedImage/TYPE_INT_ARGB)]
+;;     (let [image (.createImage *target* *width* *height*)]
+;;       (restore-fn image)
+;;       image)))
+
+(defn async-layer
+  "Creates layer that draws the content asynchroniously in an
+   offscreen buffer."
+  [content width height]
+  ;; TODO: dynamic size.
+  (let [executor (ThreadPoolExecutor. 1 1 0 TimeUnit/SECONDS
+                   (ArrayBlockingQueue. 1)
+                   (ThreadPoolExecutor$DiscardOldestPolicy.))
+        buffers (ref
+                 [(BufferedImage. width height BufferedImage/TYPE_INT_ARGB)
+                  (BufferedImage. width height BufferedImage/TYPE_INT_ARGB)])
+        updated (ref false)
+        draw-offscreen
+         (fn []
+           (let [b (dosync (let [b (peek @buffers)]
+                             (alter buffers pop)
+                             b))]
+             ;; TODO: set complete layer context.
+             (binding [*graphics* (.getGraphics b)
+                       *width* width
+                       *height* height
+                       ;; !!!
+                       *update* #(.execute executor draw-offscreen)]
+               (render! content))
+             (dosync
+              (alter buffers conj b)
+              (ref-set updated true))))]
+    (reify
+     Layer
+     (render! [layer]
+        (let [b (dosync
+                 (if @updated
+                   (do (peek @buffers)
+                       (alter buffers pop)
+                       (ref-set updated false))
+                   (do (first @buffers)
+                       (alter buffers next))))]
+          (.drawImage *graphics* b)
+          (dosync
+           (alter buffers #(cons b %)))))
+     (layer-size [layer]
+        (Size. width height)))))
+
 (defn viewport
   "Creates scrollable viewport layer."
   ([content] (viewport content :left :top))