stub maven support
[nikiroo-utils.git] / src / jexer / io / SwingScreen.java
index 3d0729e4feecd719b78431d93e1e54da46c9e30a..ee8467dd076008970784d1225609f516cbc9a469 100644 (file)
@@ -3,7 +3,7 @@
  *
  * The MIT License (MIT)
  *
- * Copyright (C) 2016 Kevin Lamonte
+ * Copyright (C) 2017 Kevin Lamonte
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -59,7 +59,7 @@ public final class SwingScreen extends Screen {
     /**
      * If true, use triple buffering thread.
      */
-    private static final boolean tripleBuffer = true;
+    private static boolean tripleBuffer = true;
 
     /**
      * Cursor style to draw.
@@ -308,8 +308,10 @@ public final class SwingScreen extends Screen {
          * Public constructor.
          *
          * @param screen the Screen that Backend talks to
+         * @param fontSize the size in points.  Good values to pick are: 16,
+         * 20, 22, and 24.
          */
-        public SwingFrame(final SwingScreen screen) {
+        public SwingFrame(final SwingScreen screen, final int fontSize) {
             this.screen = screen;
             setDOSColors();
 
@@ -325,6 +327,14 @@ public final class SwingScreen extends Screen {
                 cursorStyle = CursorStyle.BLOCK;
             }
 
+            if (System.getProperty("jexer.Swing.tripleBuffer") != null) {
+                if (System.getProperty("jexer.Swing.tripleBuffer").
+                    equals("false")) {
+
+                    SwingScreen.tripleBuffer = false;
+                }
+            }
+
             setTitle("Jexer Application");
             setBackground(Color.black);
 
@@ -334,13 +344,13 @@ public final class SwingScreen extends Screen {
                         getContextClassLoader();
                 InputStream in = loader.getResourceAsStream(FONTFILE);
                 Font terminusRoot = Font.createFont(Font.TRUETYPE_FONT, in);
-                Font terminus = terminusRoot.deriveFont(Font.PLAIN, 20);
+                Font terminus = terminusRoot.deriveFont(Font.PLAIN, fontSize);
                 setFont(terminus);
                 gotTerminus = true;
             } catch (Exception e) {
                 e.printStackTrace();
                 // setFont(new Font("Liberation Mono", Font.PLAIN, 24));
-                setFont(new Font(Font.MONOSPACED, Font.PLAIN, 24));
+                setFont(new Font(Font.MONOSPACED, Font.PLAIN, fontSize));
             }
             pack();
 
@@ -371,6 +381,87 @@ public final class SwingScreen extends Screen {
             }
         }
 
+        /**
+         * Figure out what textAdjustX and textAdjustY should be, based on
+         * the location of a vertical bar (to find textAdjustY) and a
+         * horizontal bar (to find textAdjustX).
+         *
+         * @return true if textAdjustX and textAdjustY were guessed at
+         * correctly
+         */
+        private boolean getFontAdjustments() {
+            BufferedImage image = null;
+
+            // What SHOULD happen is that the topmost/leftmost white pixel is
+            // at position (gr2x, gr2y).  But it might also be off by a pixel
+            // in either direction.
+
+            Graphics2D gr2 = null;
+            int gr2x = 3;
+            int gr2y = 3;
+            image = new BufferedImage(textWidth * 2, textHeight * 2,
+                BufferedImage.TYPE_INT_ARGB);
+
+            gr2 = image.createGraphics();
+            gr2.setFont(getFont());
+            gr2.setColor(java.awt.Color.BLACK);
+            gr2.fillRect(0, 0, textWidth * 2, textHeight * 2);
+            gr2.setColor(java.awt.Color.WHITE);
+            char [] chars = new char[1];
+            chars[0] = jexer.bits.GraphicsChars.VERTICAL_BAR;
+            gr2.drawChars(chars, 0, 1, gr2x, gr2y + textHeight - maxDescent);
+            gr2.dispose();
+
+            for (int x = 0; x < textWidth; x++) {
+                for (int y = 0; y < textHeight; y++) {
+
+                    /*
+                    System.err.println("X: " + x + " Y: " + y + " " +
+                        image.getRGB(x, y));
+                     */
+
+                    if ((image.getRGB(x, y) & 0xFFFFFF) != 0) {
+                        textAdjustY = (gr2y - y);
+
+                        // System.err.println("textAdjustY: " + textAdjustY);
+                        x = textWidth;
+                        break;
+                    }
+                }
+            }
+
+            gr2 = image.createGraphics();
+            gr2.setFont(getFont());
+            gr2.setColor(java.awt.Color.BLACK);
+            gr2.fillRect(0, 0, textWidth * 2, textHeight * 2);
+            gr2.setColor(java.awt.Color.WHITE);
+            chars[0] = jexer.bits.GraphicsChars.SINGLE_BAR;
+            gr2.drawChars(chars, 0, 1, gr2x, gr2y + textHeight - maxDescent);
+            gr2.dispose();
+
+            for (int x = 0; x < textWidth; x++) {
+                for (int y = 0; y < textHeight; y++) {
+
+                    /*
+                    System.err.println("X: " + x + " Y: " + y + " " +
+                        image.getRGB(x, y));
+                     */
+
+                    if ((image.getRGB(x, y) & 0xFFFFFF) != 0) {
+                        textAdjustX = (gr2x - x);
+
+                        // System.err.println("textAdjustX: " + textAdjustX);
+                        return true;
+                    }
+                }
+            }
+
+            // Something weird happened, don't rely on this function.
+            // System.err.println("getFontAdjustments: false");
+            return false;
+        }
+
+
         /**
          * Figure out my font dimensions.
          */
@@ -391,13 +482,14 @@ public final class SwingScreen extends Screen {
                 textHeight++;
             }
 
-            if (System.getProperty("os.name").startsWith("Windows")) {
-                textAdjustY = -1;
-                textAdjustX = 0;
-            }
-            if (System.getProperty("os.name").startsWith("Mac")) {
-                textAdjustY = -1;
-                textAdjustX = 0;
+            if (getFontAdjustments() == false) {
+                // We were unable to programmatically determine textAdjustX
+                // and textAdjustY, so try some guesses based on VM vendor.
+                String runtime = System.getProperty("java.runtime.name");
+                if ((runtime != null) && (runtime.contains("Java(TM)"))) {
+                    textAdjustY = -1;
+                    textAdjustX = 0;
+                }
             }
         }
 
@@ -452,11 +544,19 @@ public final class SwingScreen extends Screen {
             }
 
             // Generate glyph and draw it.
-
-            image = new BufferedImage(textWidth, textHeight,
-                BufferedImage.TYPE_INT_ARGB);
-            Graphics2D gr2 = image.createGraphics();
-            gr2.setFont(getFont());
+            Graphics2D gr2 = null;
+            int gr2x = xPixel;
+            int gr2y = yPixel;
+            if (tripleBuffer) {
+                image = new BufferedImage(textWidth, textHeight,
+                    BufferedImage.TYPE_INT_ARGB);
+                gr2 = image.createGraphics();
+                gr2.setFont(getFont());
+                gr2x = 0;
+                gr2y = 0;
+            } else {
+                gr2 = (Graphics2D) gr;
+            }
 
             Cell cellColor = new Cell();
             cellColor.setTo(cell);
@@ -469,7 +569,7 @@ public final class SwingScreen extends Screen {
 
             // Draw the background rectangle, then the foreground character.
             gr2.setColor(attrToBackgroundColor(cellColor));
-            gr2.fillRect(0, 0, textWidth, textHeight);
+            gr2.fillRect(gr2x, gr2y, textWidth, textHeight);
 
             // Handle blink and underline
             if (!cell.isBlink()
@@ -478,25 +578,30 @@ public final class SwingScreen extends Screen {
                 gr2.setColor(attrToForegroundColor(cellColor));
                 char [] chars = new char[1];
                 chars[0] = cell.getChar();
-                gr2.drawChars(chars, 0, 1, 0 + textAdjustX,
-                    0 + textHeight - maxDescent + textAdjustY);
+                gr2.drawChars(chars, 0, 1, gr2x + textAdjustX,
+                    gr2y + textHeight - maxDescent + textAdjustY);
 
                 if (cell.isUnderline()) {
-                    gr2.fillRect(0, 0 + textHeight - 2, textWidth, 2);
+                    gr2.fillRect(gr2x, gr2y + textHeight - 2, textWidth, 2);
                 }
             }
-            gr2.dispose();
 
-            // We need a new key that will not be mutated by invertCell().
-            Cell key = new Cell();
-            key.setTo(cell);
-            if (cell.isBlink() && !cursorBlinkVisible) {
-                glyphCacheBlink.put(key, image);
-            } else {
-                glyphCache.put(key, image);
+            if (tripleBuffer) {
+                gr2.dispose();
+
+                // We need a new key that will not be mutated by
+                // invertCell().
+                Cell key = new Cell();
+                key.setTo(cell);
+                if (cell.isBlink() && !cursorBlinkVisible) {
+                    glyphCacheBlink.put(key, image);
+                } else {
+                    glyphCache.put(key, image);
+                }
+
+                gr.drawImage(image, xPixel, yPixel, this);
             }
 
-            gr.drawImage(image, xPixel, yPixel, this);
         }
 
         /**
@@ -639,16 +744,24 @@ public final class SwingScreen extends Screen {
 
     /**
      * Public constructor.
+     *
+     * @param windowWidth the number of text columns to start with
+     * @param windowHeight the number of text rows to start with
+     * @param fontSize the size in points.  Good values to pick are: 16, 20,
+     * 22, and 24.
      */
-    public SwingScreen() {
+    public SwingScreen(final int windowWidth, final int windowHeight,
+        final int fontSize) {
+
         try {
             SwingUtilities.invokeAndWait(new Runnable() {
                 public void run() {
-                    SwingScreen.this.frame = new SwingFrame(SwingScreen.this);
+                    SwingScreen.this.frame = new SwingFrame(SwingScreen.this,
+                        fontSize);
                     SwingScreen.this.sessionInfo =
                         new SwingSessionInfo(SwingScreen.this.frame,
-                            frame.textWidth,
-                            frame.textHeight);
+                            frame.textWidth, frame.textHeight,
+                            windowWidth, windowHeight);
 
                     SwingScreen.this.setDimensions(sessionInfo.getWindowWidth(),
                         sessionInfo.getWindowHeight());