enable antialiasing
[fanfix.git] / src / jexer / backend / ECMA48Terminal.java
index 5b5db6bbf4160930795de814cf82b6a56e1066f6..ad643f4407acab61a1bfc135869550bc5bc5b28a 100644 (file)
@@ -28,6 +28,9 @@
  */
 package jexer.backend;
 
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
 import java.awt.image.BufferedImage;
 import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
@@ -1643,7 +1646,10 @@ public class ECMA48Terminal extends LogicalScreen
      * @return the width in pixels of a character cell
      */
     public int getTextWidth() {
-        return (widthPixels / sessionInfo.getWindowWidth());
+        if (sessionInfo.getWindowWidth() > 0) {
+            return (widthPixels / sessionInfo.getWindowWidth());
+        }
+        return 16;
     }
 
     /**
@@ -1652,7 +1658,10 @@ public class ECMA48Terminal extends LogicalScreen
      * @return the height in pixels of a character cell
      */
     public int getTextHeight() {
-        return (heightPixels / sessionInfo.getWindowHeight());
+        if (sessionInfo.getWindowHeight() > 0) {
+            return (heightPixels / sessionInfo.getWindowHeight());
+        }
+        return 20;
     }
 
     /**
@@ -2899,6 +2908,7 @@ public class ECMA48Terminal extends LogicalScreen
                         // them.
                         jexerImageOption = JexerImageOption.DISABLED;
                     }
+                    resetParser();
                     return;
                 case 't':
                     // windowOps
@@ -3191,12 +3201,10 @@ public class ECMA48Terminal extends LogicalScreen
         int imageWidth = cells.get(0).getImage().getWidth();
         int imageHeight = cells.get(0).getImage().getHeight();
 
-        // cells.get(x).getImage() has a dithered bitmap containing indexes
-        // into the color palette.  Piece these together into one larger
-        // image for final rendering.
+        // Piece these together into one larger image for final rendering.
         int totalWidth = 0;
-        int fullWidth = cells.size() * getTextWidth();
-        int fullHeight = getTextHeight();
+        int fullWidth = cells.size() * imageWidth;
+        int fullHeight = imageHeight;
         for (int i = 0; i < cells.size(); i++) {
             totalWidth += cells.get(i).getImage().getWidth();
         }
@@ -3206,10 +3214,8 @@ public class ECMA48Terminal extends LogicalScreen
 
         int [] rgbArray;
         for (int i = 0; i < cells.size() - 1; i++) {
-            int tileWidth = Math.min(cells.get(i).getImage().getWidth(),
-                imageWidth);
-            int tileHeight = Math.min(cells.get(i).getImage().getHeight(),
-                imageHeight);
+            int tileWidth = imageWidth;
+            int tileHeight = imageHeight;
 
             if (false && cells.get(i).isInvertedImage()) {
                 // I used to put an all-white cell over the cursor, don't do
@@ -3277,7 +3283,7 @@ public class ECMA48Terminal extends LogicalScreen
         image.setRGB((cells.size() - 1) * imageWidth, 0, totalWidth,
             imageHeight, rgbArray, 0, totalWidth);
 
-        if (totalWidth < getTextWidth()) {
+        if (totalWidth < imageWidth) {
             int backgroundColor = cells.get(cells.size() - 1).getBackground().getRGB();
 
             for (int imageX = image.getWidth() - totalWidth;
@@ -3289,6 +3295,28 @@ public class ECMA48Terminal extends LogicalScreen
             }
         }
 
+        if ((image.getWidth() != cells.size() * getTextWidth())
+            || (image.getHeight() != getTextHeight())
+        ) {
+            // Rescale the image to fit the text cells it is going into.
+            BufferedImage newImage;
+            newImage = new BufferedImage(cells.size() * getTextWidth(),
+                getTextHeight(), BufferedImage.TYPE_INT_ARGB);
+
+            Graphics gr = newImage.getGraphics();
+            if (gr instanceof Graphics2D) {
+                ((Graphics2D) gr).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                    RenderingHints.VALUE_ANTIALIAS_ON);
+                ((Graphics2D) gr).setRenderingHint(RenderingHints.KEY_RENDERING,
+                    RenderingHints.VALUE_RENDER_QUALITY);
+            }
+            gr.drawImage(image, 0, 0, newImage.getWidth(),
+                newImage.getHeight(), null, null);
+            gr.dispose();
+            image = newImage;
+            fullHeight = image.getHeight();
+        }
+
         // Dither the image.  It is ok to lose the original here.
         if (palette == null) {
             palette = new SixelPalette();
@@ -3506,8 +3534,8 @@ public class ECMA48Terminal extends LogicalScreen
         // Piece cells.get(x).getImage() pieces together into one larger
         // image for final rendering.
         int totalWidth = 0;
-        int fullWidth = cells.size() * getTextWidth();
-        int fullHeight = getTextHeight();
+        int fullWidth = cells.size() * imageWidth;
+        int fullHeight = imageHeight;
         for (int i = 0; i < cells.size(); i++) {
             totalWidth += cells.get(i).getImage().getWidth();
         }
@@ -3517,10 +3545,8 @@ public class ECMA48Terminal extends LogicalScreen
 
         int [] rgbArray;
         for (int i = 0; i < cells.size() - 1; i++) {
-            int tileWidth = Math.min(cells.get(i).getImage().getWidth(),
-                imageWidth);
-            int tileHeight = Math.min(cells.get(i).getImage().getHeight(),
-                imageHeight);
+            int tileWidth = imageWidth;
+            int tileHeight = imageHeight;
             if (false && cells.get(i).isInvertedImage()) {
                 // I used to put an all-white cell over the cursor, don't do
                 // that anymore.
@@ -3587,7 +3613,7 @@ public class ECMA48Terminal extends LogicalScreen
         image.setRGB((cells.size() - 1) * imageWidth, 0, totalWidth,
             imageHeight, rgbArray, 0, totalWidth);
 
-        if (totalWidth < getTextWidth()) {
+        if (totalWidth < imageWidth) {
             int backgroundColor = cells.get(cells.size() - 1).getBackground().getRGB();
 
             for (int imageX = image.getWidth() - totalWidth;
@@ -3599,6 +3625,28 @@ public class ECMA48Terminal extends LogicalScreen
             }
         }
 
+        if ((image.getWidth() != cells.size() * getTextWidth())
+            || (image.getHeight() != getTextHeight())
+        ) {
+            // Rescale the image to fit the text cells it is going into.
+            BufferedImage newImage;
+            newImage = new BufferedImage(cells.size() * getTextWidth(),
+                getTextHeight(), BufferedImage.TYPE_INT_ARGB);
+
+            Graphics gr = newImage.getGraphics();
+            if (gr instanceof Graphics2D) {
+                ((Graphics2D) gr).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                    RenderingHints.VALUE_ANTIALIAS_ON);
+                ((Graphics2D) gr).setRenderingHint(RenderingHints.KEY_RENDERING,
+                    RenderingHints.VALUE_RENDER_QUALITY);
+            }
+            gr.drawImage(image, 0, 0, newImage.getWidth(),
+                newImage.getHeight(), null, null);
+            gr.dispose();
+            image = newImage;
+            fullHeight = image.getHeight();
+        }
+
         /*
          * From https://iterm2.com/documentation-images.html:
          *
@@ -3755,8 +3803,8 @@ public class ECMA48Terminal extends LogicalScreen
         // Piece cells.get(x).getImage() pieces together into one larger
         // image for final rendering.
         int totalWidth = 0;
-        int fullWidth = cells.size() * getTextWidth();
-        int fullHeight = getTextHeight();
+        int fullWidth = cells.size() * imageWidth;
+        int fullHeight = imageHeight;
         for (int i = 0; i < cells.size(); i++) {
             totalWidth += cells.get(i).getImage().getWidth();
         }
@@ -3766,10 +3814,8 @@ public class ECMA48Terminal extends LogicalScreen
 
         int [] rgbArray;
         for (int i = 0; i < cells.size() - 1; i++) {
-            int tileWidth = Math.min(cells.get(i).getImage().getWidth(),
-                imageWidth);
-            int tileHeight = Math.min(cells.get(i).getImage().getHeight(),
-                imageHeight);
+            int tileWidth = imageWidth;
+            int tileHeight = imageHeight;
             if (false && cells.get(i).isInvertedImage()) {
                 // I used to put an all-white cell over the cursor, don't do
                 // that anymore.
@@ -3836,7 +3882,7 @@ public class ECMA48Terminal extends LogicalScreen
         image.setRGB((cells.size() - 1) * imageWidth, 0, totalWidth,
             imageHeight, rgbArray, 0, totalWidth);
 
-        if (totalWidth < getTextWidth()) {
+        if (totalWidth < imageWidth) {
             int backgroundColor = cells.get(cells.size() - 1).getBackground().getRGB();
 
             for (int imageX = image.getWidth() - totalWidth;
@@ -3848,6 +3894,28 @@ public class ECMA48Terminal extends LogicalScreen
             }
         }
 
+        if ((image.getWidth() != cells.size() * getTextWidth())
+            || (image.getHeight() != getTextHeight())
+        ) {
+            // Rescale the image to fit the text cells it is going into.
+            BufferedImage newImage;
+            newImage = new BufferedImage(cells.size() * getTextWidth(),
+                getTextHeight(), BufferedImage.TYPE_INT_ARGB);
+
+            Graphics gr = newImage.getGraphics();
+            if (gr instanceof Graphics2D) {
+                ((Graphics2D) gr).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                    RenderingHints.VALUE_ANTIALIAS_ON);
+                ((Graphics2D) gr).setRenderingHint(RenderingHints.KEY_RENDERING,
+                    RenderingHints.VALUE_RENDER_QUALITY);
+            }
+            gr.drawImage(image, 0, 0, newImage.getWidth(),
+                newImage.getHeight(), null, null);
+            gr.dispose();
+            image = newImage;
+            fullHeight = image.getHeight();
+        }
+
         if (jexerImageOption == JexerImageOption.PNG) {
             // Encode as PNG
             ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream(1024);