X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fjexer%2FTTerminalWindow.java;h=c7456358df7193db8d8be27481ecac6133e863a5;hb=0d86ab8480cabbe32fc87588304ddc795a4df14f;hp=b36e86b62dfca47b0d6f95864f19c3b6b1d1cf15;hpb=b3d79e993958180c33d1a54bcfcde9745152c279;p=fanfix.git diff --git a/src/jexer/TTerminalWindow.java b/src/jexer/TTerminalWindow.java index b36e86b..c745635 100644 --- a/src/jexer/TTerminalWindow.java +++ b/src/jexer/TTerminalWindow.java @@ -28,10 +28,10 @@ */ package jexer; -import java.awt.image.BufferedImage; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; +import java.awt.image.BufferedImage; import java.io.InputStream; import java.io.IOException; @@ -44,6 +44,7 @@ import java.util.Map; import java.util.ResourceBundle; import jexer.backend.ECMA48Terminal; +import jexer.backend.GlyphMaker; import jexer.backend.MultiScreen; import jexer.backend.SwingTerminal; import jexer.bits.Cell; @@ -96,26 +97,9 @@ public class TTerminalWindow extends TScrollableWindow private boolean closeOnExit = false; /** - * System-dependent Y adjustment for text in the character cell - * (double-height). - */ - private int doubleTextAdjustY = 0; - - /** - * System-dependent X adjustment for text in the character cell - * (double-height). - */ - private int doubleTextAdjustX = 0; - - /** - * Descent of a character cell in pixels (double-height). - */ - private int doubleMaxDescent = 0; - - /** - * Double-width font. + * Double-height font. */ - private Font doubleFont = null; + private GlyphMaker doubleFont; /** * Last text width value. @@ -127,23 +111,18 @@ public class TTerminalWindow extends TScrollableWindow */ private int lastTextHeight = -1; - /** - * A cache of previously-rendered double-width glyphs. - */ - private Map glyphCache; - - /** - * A cache of previously-rendered double-width glyphs for blinking text, - * when it is not visible. - */ - private Map glyphCacheBlink; - /** * The blink state, used only by ECMA48 backend and when double-width * chars must be drawn. */ private boolean blinkState = true; + /** + * Timer flag, used only by ECMA48 backend and when double-width chars + * must be drawn. + */ + private boolean haveTimer = false; + // ------------------------------------------------------------------------ // Constructors ----------------------------------------------------------- // ------------------------------------------------------------------------ @@ -550,13 +529,17 @@ public class TTerminalWindow extends TScrollableWindow return; } - if (mouse.isMouseWheelUp()) { - verticalDecrement(); - return; - } - if (mouse.isMouseWheelDown()) { - verticalIncrement(); - return; + // If the emulator is tracking mouse buttons, it needs to see wheel + // events. + if (emulator.getMouseProtocol() == ECMA48.MouseProtocol.OFF) { + if (mouse.isMouseWheelUp()) { + verticalDecrement(); + return; + } + if (mouse.isMouseWheelDown()) { + verticalIncrement(); + return; + } } if (mouseOnEmulator(mouse)) { synchronized (emulator) { @@ -761,6 +744,10 @@ public class TTerminalWindow extends TScrollableWindow // Add shortcut text newStatusBar(i18n.getString("statusBarRunning")); + + // Pass the correct text cell width/height to the emulator + emulator.setTextWidth(getScreen().getTextWidth()); + emulator.setTextHeight(getScreen().getTextHeight()); } /** @@ -941,21 +928,23 @@ public class TTerminalWindow extends TScrollableWindow private void putDoubleWidthCharXY(final DisplayLine line, final int x, final int y, final Cell cell) { - int textWidth = 16; - int textHeight = 20; + int textWidth = getScreen().getTextWidth(); + int textHeight = getScreen().getTextHeight(); boolean cursorBlinkVisible = true; if (getScreen() instanceof SwingTerminal) { SwingTerminal terminal = (SwingTerminal) getScreen(); - - textWidth = terminal.getTextWidth(); - textHeight = terminal.getTextHeight(); cursorBlinkVisible = terminal.getCursorBlinkVisible(); } else if (getScreen() instanceof ECMA48Terminal) { ECMA48Terminal terminal = (ECMA48Terminal) getScreen(); - textWidth = terminal.getTextWidth(); - textHeight = terminal.getTextHeight(); + if (!terminal.hasSixel()) { + // The backend does not have sixel support, draw this as text + // and bail out. + putCharXY(x, y, cell); + putCharXY(x + 1, y, ' ', cell); + return; + } cursorBlinkVisible = blinkState; } else { // We don't know how to dray glyphs to this screen, draw them as @@ -966,58 +955,24 @@ public class TTerminalWindow extends TScrollableWindow } if ((textWidth != lastTextWidth) || (textHeight != lastTextHeight)) { - // Screen size has changed, reset all fonts. - setupFonts(textHeight); + // Screen size has changed, reset the font. + setupFont(textHeight); lastTextWidth = textWidth; lastTextHeight = textHeight; } assert (doubleFont != null); - BufferedImage image = null; - if (cell.isBlink() && !cursorBlinkVisible) { - image = glyphCacheBlink.get(cell); + BufferedImage image; + if (line.getDoubleHeight() == 1) { + // Double-height top half: don't draw the underline. + Cell newCell = new Cell(); + newCell.setTo(cell); + newCell.setUnderline(false); + image = doubleFont.getImage(newCell, textWidth * 2, textHeight * 2, + cursorBlinkVisible); } else { - image = glyphCache.get(cell); - } - if (image == null) { - // Generate glyph and draw it to an image. - image = new BufferedImage(textWidth * 2, textHeight * 2, - BufferedImage.TYPE_INT_ARGB); - Graphics2D gr2 = image.createGraphics(); - gr2.setFont(doubleFont); - - // Draw the background rectangle, then the foreground character. - if (getScreen() instanceof ECMA48Terminal) { - // BUG: the background color is coming in the same as the - // foreground color. For now, don't draw it. - } else { - gr2.setColor(SwingTerminal.attrToBackgroundColor(cell)); - gr2.fillRect(0, 0, image.getWidth(), image.getHeight()); - } - if (!cell.isBlink() - || (cell.isBlink() && cursorBlinkVisible) - ) { - gr2.setColor(SwingTerminal.attrToForegroundColor(cell)); - char [] chars = new char[1]; - chars[0] = cell.getChar(); - gr2.drawChars(chars, 0, 1, doubleTextAdjustX, - (textHeight * 2) - doubleMaxDescent + doubleTextAdjustY); - - if (cell.isUnderline() && (line.getDoubleHeight() != 1)) { - gr2.fillRect(0, textHeight - 2, textWidth, 2); - } - } - gr2.dispose(); - - // Now save this generated image, using 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); - } + image = doubleFont.getImage(cell, textWidth * 2, textHeight * 2, + cursorBlinkVisible); } // Now that we have the double-wide glyph drawn, copy the right @@ -1029,6 +984,11 @@ public class TTerminalWindow extends TScrollableWindow right.setChar(' '); BufferedImage leftImage = null; BufferedImage rightImage = null; + /* + System.err.println("image " + image + " textWidth " + textWidth + + " textHeight " + textHeight); + */ + switch (line.getDoubleHeight()) { case 1: // Top half double height @@ -1056,61 +1016,41 @@ public class TTerminalWindow extends TScrollableWindow } left.setImage(leftImage); right.setImage(rightImage); + // Since we have image data, ditch the character here. Otherwise, a + // drawBoxShadow() over the terminal window will show the characters + // which looks wrong. + left.setChar(' '); + right.setChar(' '); putCharXY(x, y, left); putCharXY(x + 1, y, right); } /** - * Set up the single and double-width fonts. + * Set up the double-width font. * * @param fontSize the size of font to request for the single-width font. * The double-width font will be 2x this value. */ - private void setupFonts(final int fontSize) { - try { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - InputStream in = loader.getResourceAsStream(SwingTerminal.FONTFILE); - Font terminusRoot = Font.createFont(Font.TRUETYPE_FONT, in); - Font terminusDouble = terminusRoot.deriveFont(Font.PLAIN, - fontSize * 2); - doubleFont = terminusDouble; - } catch (java.awt.FontFormatException e) { - new TExceptionDialog(getApplication(), e); - doubleFont = new Font(Font.MONOSPACED, Font.PLAIN, fontSize * 2); - } catch (java.io.IOException e) { - new TExceptionDialog(getApplication(), e); - doubleFont = new Font(Font.MONOSPACED, Font.PLAIN, fontSize * 2); - } - - // Get font descent. - BufferedImage image = new BufferedImage(fontSize * 10, fontSize * 10, - BufferedImage.TYPE_INT_ARGB); - Graphics2D gr = image.createGraphics(); - gr.setFont(doubleFont); - FontMetrics fm = gr.getFontMetrics(); - doubleMaxDescent = fm.getMaxDescent(); - - gr.dispose(); - - // (Re)create the glyph caches. - glyphCache = new HashMap(); - glyphCacheBlink = new HashMap(); + private void setupFont(final int fontSize) { + doubleFont = GlyphMaker.getDefault().size(fontSize * 2); // Special case: the ECMA48 backend needs to have a timer to drive // its blink state. if (getScreen() instanceof jexer.backend.ECMA48Terminal) { - // Blink every 500 millis. - long millis = 500; - getApplication().addTimer(millis, true, - new TAction() { - public void DO() { - blinkState = !blinkState; - getApplication().doRepaint(); + if (!haveTimer) { + // Blink every 500 millis. + long millis = 500; + getApplication().addTimer(millis, true, + new TAction() { + public void DO() { + blinkState = !blinkState; + getApplication().doRepaint(); + } } - } - ); + ); + haveTimer = true; + } } - } }