changeset 119:91c341698f7e

Use FontRenderContext based on rendering hints when Graphics is not available. Obtain text rendering hints from desktop properties.
author Mikhail Kryshen <mikhail@kryshen.net>
date Tue, 03 Apr 2012 18:28:12 +0400
parents b6b83ca37318
children 87ebc46cc66d
files src/net/kryshen/indyvon/component.clj src/net/kryshen/indyvon/core.clj src/net/kryshen/indyvon/layers.clj
diffstat 3 files changed, 49 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/src/net/kryshen/indyvon/component.clj	Fri Mar 02 18:53:38 2012 +0400
+++ b/src/net/kryshen/indyvon/component.clj	Tue Apr 03 18:28:12 2012 +0400
@@ -26,9 +26,6 @@
    (java.awt.geom Rectangle2D$Double)
    (javax.swing JFrame JPanel JOptionPane)))
 
-(defn font-context [^Component component]
-  (.getFontRenderContext (.getFontMetrics component (.getFont component))))
-
 (defn- paint-component [^Component c ^Graphics g scene]
   (let [size (.getSize c)]
     (.setColor g (:back-color *theme*))
@@ -36,7 +33,7 @@
     (draw-scene! scene g (.width size) (.height size))))
 
 (defn- preferred-size [^Component c scene]
-  (let [geom (scene-geometry scene (font-context c))]
+  (let [geom (scene-geometry scene)]
     (Dimension. (width geom) (height geom))))
 
 (defn ^JPanel make-jpanel
@@ -44,7 +41,10 @@
      (make-jpanel layer (root-event-dispatcher)))
   ([layer event-dispatcher]
      (let [panel (proxy [JPanel] [])
-           scene (make-scene layer event-dispatcher panel)]
+           scene (make-scene
+                  layer event-dispatcher panel
+                  (.getDesktopProperty (java.awt.Toolkit/getDefaultToolkit)
+                                       "awt.font.desktophints"))]
        (update-proxy
         panel
         {"paintComponent" #(paint-component %1 %2 scene)
--- a/src/net/kryshen/indyvon/core.clj	Fri Mar 02 18:53:38 2012 +0400
+++ b/src/net/kryshen/indyvon/core.clj	Tue Apr 03 18:28:12 2012 +0400
@@ -34,8 +34,6 @@
 
 (def ^:dynamic ^Graphics2D *graphics*)
 
-(def ^:dynamic ^FontRenderContext *font-context*)
-
 (def ^:dynamic *width*
   "Width of the rendering area.")
 
@@ -269,6 +267,16 @@
 ;; Rendering
 ;;
 
+(defn ^FontRenderContext font-context
+  "Returns FontRenderContext for the current Layer context."
+  []
+  (if (bound? (var *graphics*))
+    (.getFontRenderContext *graphics*)
+    (let [scene *scene*]
+      (if-let [^Component c (:component scene)]
+        (.getFontRenderContext (.getFontMetrics c (.getFont c)))
+        (:font-context scene)))))
+
 (defn ^AffineTransform relative-transform
   "Returns AffineTransform: layer context -> AWT component."
   []
@@ -392,8 +400,7 @@
           old (.getRenderingHints g)]
       (try
         (.addRenderingHints g hints)
-        (binding [*font-context* (.getFontRenderContext g)]
-          (apply f args))
+        (apply f args)
         (finally
          (.setRenderingHints g old))))
     (apply f args)))
@@ -412,8 +419,7 @@
          old-t# (.getTransform g#)]
      (try
        (.transform g# ~transform)
-       (binding [*font-context* (.getFontRenderContext g#)]
-         ~@body)
+       ~@body
        (finally
         (.setTransform g# old-t#)))))
 
@@ -664,15 +670,39 @@
 ;; Scene
 ;;
 
-(defrecord Scene [layer event-dispatcher component next-state])
+(defrecord Scene [layer
+                  event-dispatcher
+                  component
+                  rendering-hints
+                  font-context
+                  next-state])
+
+;; Define rendering hints that affect font metrics to make sure that
+;; Graphics and Scene FontRenderContexts are consistent.
+(def ^:private default-rendering-hints
+  {RenderingHints/KEY_TEXT_ANTIALIASING
+   RenderingHints/VALUE_TEXT_ANTIALIAS_DEFAULT,
+   RenderingHints/KEY_FRACTIONALMETRICS
+   RenderingHints/VALUE_FRACTIONALMETRICS_DEFAULT})
 
 (defn make-scene
   ([layer]
      (make-scene layer dummy-event-dispatcher nil))
   ([layer event-dispatcher]
      (make-scene layer event-dispatcher nil))
-  ([layer event-dispatcher component]
-     (->Scene layer event-dispatcher component (atom nil))))
+  ([layer event-dispatcher ^Component component]
+     (make-scene layer event-dispatcher component nil))
+  ([layer event-dispatcher ^Component component hints]
+     (let [hints (merge default-rendering-hints hints)]
+       (->Scene layer
+                event-dispatcher
+                component
+                hints
+                (FontRenderContext.
+                 nil
+                 (get hints RenderingHints/KEY_TEXT_ANTIALIASING)
+                 (get hints RenderingHints/KEY_FRACTIONALMETRICS))
+                (atom nil)))))
 
 (defn- get-and-set!
   "Atomically sets the value of atom to newval and returns the old
@@ -685,22 +715,10 @@
 
 (defn draw-scene!
   [scene ^Graphics2D graphics width height]
-  ;; (.setRenderingHint graphics
-  ;;                    RenderingHints/KEY_INTERPOLATION
-  ;;                    RenderingHints/VALUE_INTERPOLATION_BILINEAR)
-  ;; (.setRenderingHint graphics
-  ;;                    RenderingHints/KEY_ALPHA_INTERPOLATION
-  ;;                    RenderingHints/VALUE_ALPHA_INTERPOLATION_QUALITY)
-  ;; (.setRenderingHint graphics
-  ;;                    RenderingHints/KEY_ANTIALIASING
-  ;;                    RenderingHints/VALUE_ANTIALIAS_ON)
-  ;; (.setRenderingHint graphics
-  ;;                    RenderingHints/KEY_TEXT_ANTIALIASING
-  ;;                    RenderingHints/VALUE_TEXT_ANTIALIAS_ON)
+  (.addRenderingHints graphics (:rendering-hints scene))
   (binding [*states* (get-and-set! (:next-state scene) nil)
             *scene* scene
             *graphics* graphics
-            *font-context* (.getFontRenderContext graphics)
             *initial-transform* (.getTransform graphics)
             *inverse-initial-transform* (-> graphics
                                             .getTransform
@@ -722,9 +740,8 @@
          (remove-observers tmp-watcher)
          (commit (:event-dispatcher scene)))))))
   
-(defn scene-geometry [scene font-context]
-  (binding [*scene* scene
-            *font-context* font-context]
+(defn scene-geometry [scene]
+  (binding [*scene* scene]
     (geometry (:layer scene))))
 
 (defn set-cursor! [^Cursor cursor]
--- a/src/net/kryshen/indyvon/layers.clj	Fri Mar 02 18:53:38 2012 +0400
+++ b/src/net/kryshen/indyvon/layers.clj	Tue Apr 03 18:28:12 2012 +0400
@@ -213,7 +213,7 @@
           (let [w *width*
                 h *height*
                 font (.getFont *graphics*)
-                layouts (layout-text lines font *font-context*)
+                layouts (layout-text lines font (font-context))
                 y (align-y (text-height layouts) h v-align)]
             (loop [layouts layouts, y y]
               (when-first [^TextLayout layout layouts]
@@ -223,7 +223,7 @@
                   (.draw layout *graphics* x (+ y ascent))
                   (recur (next layouts) (+ y lh)))))))
         (geometry [layer]
-          (let [layouts (layout-text lines (:font *theme*) *font-context*)
+          (let [layouts (layout-text lines (:font *theme*) (font-context))
                 w (text-width layouts)
                 h (text-height layouts)]
             (->Size w h)))))))