#35 CJK WIP
authorKevin Lamonte <kevin.lamonte@gmail.com>
Tue, 6 Aug 2019 12:00:45 +0000 (07:00 -0500)
committerKevin Lamonte <kevin.lamonte@gmail.com>
Tue, 6 Aug 2019 12:00:45 +0000 (07:00 -0500)
src/jexer/TApplication.java
src/jexer/TButton.java
src/jexer/backend/ECMA48Terminal.java
src/jexer/backend/LogicalScreen.java
src/jexer/tterminal/ECMA48.java

index b44664ee7d5926fd00dca5240115a9dcafb61738..4428d29f79d64bb5183926330f3c115fb2b924da 100644 (file)
@@ -1534,6 +1534,19 @@ public class TApplication implements Runnable {
      * @param y row position
      */
     private void invertCell(final int x, final int y) {
+        invertCell(x, y, false);
+    }
+
+    /**
+     * Invert the cell color at a position.  This is used to track the mouse.
+     *
+     * @param x column position
+     * @param y row position
+     * @param onlyThisCell if true, only invert this cell
+     */
+    private void invertCell(final int x, final int y,
+        final boolean onlyThisCell) {
+
         if (debugThreads) {
             System.err.printf("%d %s invertCell() %d %d\n",
                 System.currentTimeMillis(), Thread.currentThread(), x, y);
@@ -1573,6 +1586,29 @@ public class TApplication implements Runnable {
             }
         }
         getScreen().putCharXY(x, y, cell);
+        if ((onlyThisCell == true) || (cell.getWidth() == Cell.Width.SINGLE)) {
+            return;
+        }
+
+        // This cell is one half of a fullwidth glyph.  Invert the other
+        // half.
+        if (cell.getWidth() == Cell.Width.LEFT) {
+            if (x < getScreen().getWidth() - 1) {
+                Cell rightHalf = getScreen().getCharXY(x + 1, y);
+                if (rightHalf.getWidth() == Cell.Width.RIGHT) {
+                    invertCell(x + 1, y, true);
+                    return;
+                }
+            }
+        }
+        assert (cell.getWidth() == Cell.Width.RIGHT);
+
+        if (x > 0) {
+            Cell leftHalf = getScreen().getCharXY(x - 1, y);
+            if (leftHalf.getWidth() == Cell.Width.LEFT) {
+                invertCell(x - 1, y, true);
+            }
+        }
     }
 
     /**
index 33fe73328b1773f9b42225537a70771fc8c8b6d6..534c12a441b9db40ce07f760e947b7c5e6cf796c 100644 (file)
@@ -32,6 +32,7 @@ import jexer.bits.CellAttributes;
 import jexer.bits.Color;
 import jexer.bits.GraphicsChars;
 import jexer.bits.MnemonicString;
+import jexer.bits.StringUtils;
 import jexer.event.TKeypressEvent;
 import jexer.event.TMouseEvent;
 import static jexer.TKeypress.kbEnter;
@@ -98,7 +99,7 @@ public class TButton extends TWidget {
         setX(x);
         setY(y);
         setHeight(2);
-        setWidth(mnemonic.getRawLabel().length() + 3);
+        setWidth(StringUtils.width(mnemonic.getRawLabel()) + 3);
 
         shadowColor = new CellAttributes();
         shadowColor.setTo(getWindow().getBackground());
index 39ca236552d37302786fa1be4747d50b425aa7ec..e22e4fe91e277e1afd5abbeb0d6e83b917d4743f 100644 (file)
@@ -2851,7 +2851,9 @@ public class ECMA48Terminal extends LogicalScreen
 
         int [] rgbArray;
         for (int i = 0; i < cells.size() - 1; i++) {
-            if (cells.get(i).isInvertedImage()) {
+            if (false && cells.get(i).isInvertedImage()) {
+                // I used to put an all-white cell over the cursor, don't do
+                // that anymore.
                 rgbArray = new int[imageWidth * imageHeight];
                 for (int j = 0; j < rgbArray.length; j++) {
                     rgbArray[j] = 0xFFFFFF;
@@ -2883,7 +2885,9 @@ public class ECMA48Terminal extends LogicalScreen
             }
         }
         totalWidth -= ((cells.size() - 1) * imageWidth);
-        if (cells.get(cells.size() - 1).isInvertedImage()) {
+        if (false && cells.get(cells.size() - 1).isInvertedImage()) {
+            // I used to put an all-white cell over the cursor, don't do that
+            // anymore.
             rgbArray = new int[totalWidth * imageHeight];
             for (int j = 0; j < rgbArray.length; j++) {
                 rgbArray[j] = 0xFFFFFF;
index 513c599145440e8a9682ef5c764b8e5d650e9c29..3149e68c282b3168bf5ed6cb78e29762bd06ee6e 100644 (file)
  */
 package jexer.backend;
 
+import java.awt.image.BufferedImage;
+
+import jexer.backend.GlyphMaker;
 import jexer.bits.Cell;
 import jexer.bits.CellAttributes;
 import jexer.bits.GraphicsChars;
+import jexer.bits.StringUtils;
 
 /**
  * A logical screen composed of a 2D array of Cells.
@@ -113,6 +117,17 @@ public class LogicalScreen implements Screen {
      */
     protected int cursorY;
 
+    /**
+     * The last used height of a character cell in pixels, only used for
+     * full-width chars.
+     */
+    private int lastTextHeight = -1;
+
+    /**
+     * The glyph drawer for full-width chars.
+     */
+    private GlyphMaker glyphMaker = null;
+
     // ------------------------------------------------------------------------
     // Constructors -----------------------------------------------------------
     // ------------------------------------------------------------------------
@@ -379,6 +394,11 @@ public class LogicalScreen implements Screen {
             return;
         }
 
+        if ((StringUtils.width(ch.getChar()) == 2) && (!ch.isImage())) {
+            putFullwidthCharXY(x, y, ch);
+            return;
+        }
+
         int X = x + offsetX;
         int Y = y + offsetY;
 
@@ -421,6 +441,11 @@ public class LogicalScreen implements Screen {
             return;
         }
 
+        if (StringUtils.width(ch) == 2) {
+            putFullwidthCharXY(x, y, ch, attr);
+            return;
+        }
+
         int X = x + offsetX;
         int Y = y + offsetY;
 
@@ -461,6 +486,11 @@ public class LogicalScreen implements Screen {
             return;
         }
 
+        if (StringUtils.width(ch) == 2) {
+            putFullwidthCharXY(x, y, ch);
+            return;
+        }
+
         int X = x + offsetX;
         int Y = y + offsetY;
 
@@ -927,4 +957,73 @@ public class LogicalScreen implements Screen {
         }
     }
 
+    /**
+     * Render one fullwidth cell.
+     *
+     * @param x column coordinate.  0 is the left-most column.
+     * @param y row coordinate.  0 is the top-most row.
+     * @param cell the cell to draw
+     */
+    public final void putFullwidthCharXY(final int x, final int y,
+        final Cell cell) {
+
+        if (lastTextHeight != getTextHeight()) {
+            glyphMaker = GlyphMaker.getInstance(getTextHeight());
+            lastTextHeight = getTextHeight();
+        }
+        BufferedImage image = glyphMaker.getImage(cell, getTextWidth() * 2,
+            getTextHeight());
+        BufferedImage leftImage = image.getSubimage(0, 0, getTextWidth(),
+            getTextHeight());
+        BufferedImage rightImage = image.getSubimage(getTextWidth(), 0,
+            getTextWidth(), getTextHeight());
+
+        Cell left = new Cell();
+        left.setTo(cell);
+        left.setImage(leftImage);
+        left.setWidth(Cell.Width.LEFT);
+        // Blank out the char itself, so that shadows do not leave artifacts.
+        left.setChar(' ');
+        putCharXY(x, y, left);
+
+        Cell right = new Cell();
+        right.setTo(cell);
+        right.setImage(rightImage);
+        right.setWidth(Cell.Width.RIGHT);
+        // Blank out the char itself, so that shadows do not leave artifacts.
+        right.setChar(' ');
+        putCharXY(x + 1, y, right);
+    }
+
+    /**
+     * Render one fullwidth character with attributes.
+     *
+     * @param x column coordinate.  0 is the left-most column.
+     * @param y row coordinate.  0 is the top-most row.
+     * @param ch character to draw
+     * @param attr attributes to use (bold, foreColor, backColor)
+     */
+    public final void putFullwidthCharXY(final int x, final int y,
+        final char ch, final CellAttributes attr) {
+
+        Cell cell = new Cell(ch);
+        cell.setAttr(attr);
+        putFullwidthCharXY(x, y, cell);
+    }
+
+    /**
+     * Render one fullwidth character with attributes.
+     *
+     * @param x column coordinate.  0 is the left-most column.
+     * @param y row coordinate.  0 is the top-most row.
+     * @param ch character to draw
+     */
+    public final void putFullwidthCharXY(final int x, final int y,
+        final char ch) {
+
+        Cell cell = new Cell(ch);
+        cell.setAttr(getAttrXY(x, y));
+        putFullwidthCharXY(x, y, cell);
+    }
+
 }
index f00164ba869b5f32d1a282889693828428c15464..f9c98661b83c65a9329582ea12092cae2ea5db2f 100644 (file)
@@ -488,7 +488,7 @@ public class ECMA48 implements Runnable {
     /**
      * The glyph drawer for full-width chars.
      */
-    GlyphMaker glyphMaker = null;
+    private GlyphMaker glyphMaker = null;
 
     /**
      * DECSC/DECRC save/restore a subset of the total state.  This class