changeset 168:5b80af180da0

Function to apply AffineTransform to a View.
author Mikhail Kryshen <mikhail@kryshen.net>
date Sun, 30 Nov 2014 18:45:12 +0300
parents a51fcaf00264
children 8471a45645ad
files src/indyvon/core.clj src/indyvon/views.clj
diffstat 2 files changed, 40 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/indyvon/core.clj	Sat Nov 29 19:44:53 2014 +0300
+++ b/src/indyvon/core.clj	Sun Nov 30 18:45:12 2014 +0300
@@ -550,10 +550,11 @@
   (with-hints hints
     (apply f args)))
 
-;; TODO: constructor for AffineTransform.
-;; (transform :scale 0.3 0.5
-;;            :translate 5 10
-;;            :rotate (/ Math/PI 2))
+;; TODO: Composable transformations:
+;; (with-transform (-> (scale 0.3 0.5)
+;;                     (rotate-deg 30)
+;;                     (translate 5 10))
+;;   ...)
 
 (defmacro with-transform [transform & body]
   `(let [g# *graphics*
@@ -564,6 +565,10 @@
        (finally
         (.setTransform g# old-t#)))))
 
+(defn with-transform* [transform f & args]
+  (with-transform transform
+    (apply f args)))
+
 (defmacro with-rotate [theta ax ay & body]
   `(let [transform# (AffineTransform/getRotateInstance ~theta ~ax ~ay)]
      (with-transform transform# ~@body)))
--- a/src/indyvon/views.clj	Sat Nov 29 19:44:53 2014 +0300
+++ b/src/indyvon/views.clj	Sun Nov 30 18:45:12 2014 +0300
@@ -24,8 +24,8 @@
   (:import
    (java.awt Font Image Toolkit)
    java.awt.image.ImageObserver
-   (java.awt.geom Area AffineTransform Rectangle2D$Double Point2D
-                  Point2D$Double)
+   (java.awt.geom Area AffineTransform Rectangle2D Rectangle2D$Double
+                  Point2D Point2D$Double)
    (java.awt.font FontRenderContext TextLayout)
    java.util.concurrent.TimeUnit
    (com.google.common.cache Cache CacheBuilder CacheLoader)))
@@ -344,6 +344,35 @@
         (with-hints* hints geometry view)
         (geometry view)))))
 
+(defn- transform-bounds
+  ^Rectangle2D [^AffineTransform tr ^double w ^double h]
+  (.getBounds2D
+   (.createTransformedShape tr (Rectangle2D$Double. 0 0 w h))))
+
+(defn transform [tr view]
+  (reify View
+    (render! [v]
+      (let [g (geometry view)
+            w (double (width g))
+            h (double (height g))
+            ^Rectangle2D bounds (transform-bounds tr w h)
+            g *graphics*]
+        (.translate g (- (.getX bounds)) (- (.getY bounds)))
+        (.transform g tr)
+        ;; TODO: scale w and h to fit *width* and *height*.
+        (draw! view 0 0 w h)))
+    (geometry [_]
+      (let [g (geometry view)
+            w (double (width g))
+            h (double (height g))
+            ^Rectangle2D bounds (transform-bounds tr w h)]
+        (->Size (.getWidth bounds) (.getHeight bounds))))))
+
+(defn rotate [^double degrees view]
+  (transform
+   (AffineTransform/getRotateInstance (Math/toRadians degrees))
+   view))
+
 ;;
 ;; Measuring time
 ;;