mirror of
https://gitlab.com/AutumnMeowMeow/jexer
synced 2024-09-19 11:50:19 -06:00
Use more consistent fonts for braille and legacy computing symbols
This commit is contained in:
parent
d4ed006243
commit
eda549b9cc
4 changed files with 132 additions and 8 deletions
|
@ -1616,16 +1616,33 @@ public class ECMA48Terminal extends LogicalScreen
|
|||
* draw everything else afterwards. This works OK, but performance
|
||||
* is still a drag on larger pictures.
|
||||
*/
|
||||
GlyphMaker glyphMaker = GlyphMaker.getInstance(getTextHeight());
|
||||
for (int y = 0; y < height; y++) {
|
||||
boolean unsetRow = false;
|
||||
for (int x = 0; x < width; x++) {
|
||||
// If physical had non-image data that is now image data, the
|
||||
// entire row must be redrawn.
|
||||
Cell lCell = logical[x][y];
|
||||
Cell pCell = physical[x][y];
|
||||
if (lCell.isImage() && !pCell.isImage()) {
|
||||
unsetImageRow(y);
|
||||
break;
|
||||
unsetRow = true;
|
||||
}
|
||||
int ch = lCell.getChar();
|
||||
if (!lCell.isImage()
|
||||
&& (StringUtils.isLegacyComputingSymbol(ch)
|
||||
|| StringUtils.isBraille(ch))
|
||||
&& glyphMaker.canDisplay(ch)
|
||||
) {
|
||||
// If a fallback font is available that can support
|
||||
// Symbols for Legacy Computing, always use it.
|
||||
BufferedImage newImage = glyphMaker.getImage(lCell,
|
||||
getTextWidth(), getTextHeight(), getBackend());
|
||||
lCell.setImage(newImage);
|
||||
unsetRow = true;
|
||||
}
|
||||
}
|
||||
if (unsetRow) {
|
||||
unsetImageRow(y);
|
||||
}
|
||||
}
|
||||
for (int y = 0; y < height; y++) {
|
||||
|
|
|
@ -126,6 +126,11 @@ class GlyphMakerFont {
|
|||
*/
|
||||
private HashMap<Cell, BufferedImage> glyphCache;
|
||||
|
||||
/**
|
||||
* If true, this font loaded OK.
|
||||
*/
|
||||
private boolean loaded = false;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Constructors -----------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -140,7 +145,7 @@ class GlyphMakerFont {
|
|||
|
||||
if (filename.length() == 0) {
|
||||
// Fallback font
|
||||
font = new Font(Font.MONOSPACED, Font.PLAIN, fontSize - 2);
|
||||
font = new Font(Font.MONOSPACED, Font.PLAIN, fontSize);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -149,16 +154,17 @@ class GlyphMakerFont {
|
|||
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
InputStream in = loader.getResourceAsStream(filename);
|
||||
fontRoot = Font.createFont(Font.TRUETYPE_FONT, in);
|
||||
font = fontRoot.deriveFont(Font.PLAIN, fontSize - 2);
|
||||
font = fontRoot.deriveFont(Font.PLAIN, fontSize);
|
||||
loaded = true;
|
||||
} catch (FontFormatException e) {
|
||||
// Ideally we would report an error here, either via System.err
|
||||
// or TExceptionDialog. However, I do not want GlyphMaker to
|
||||
// know about available backends, so we quietly fallback to
|
||||
// whatever is available as MONO.
|
||||
font = new Font(Font.MONOSPACED, Font.PLAIN, fontSize - 2);
|
||||
font = new Font(Font.MONOSPACED, Font.PLAIN, fontSize);
|
||||
} catch (IOException e) {
|
||||
// See comment above.
|
||||
font = new Font(Font.MONOSPACED, Font.PLAIN, fontSize - 2);
|
||||
font = new Font(Font.MONOSPACED, Font.PLAIN, fontSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,6 +321,16 @@ class GlyphMakerFont {
|
|||
public boolean canDisplay(final int codePoint) {
|
||||
return font.canDisplay(codePoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* See if this font loaded OK.
|
||||
*
|
||||
* @return true if this font loaded OK, otherwise it is rendering using
|
||||
* MONO
|
||||
*/
|
||||
public boolean isLoaded() {
|
||||
return loaded;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -381,6 +397,11 @@ public class GlyphMaker {
|
|||
*/
|
||||
private GlyphMakerFont makerFallback;
|
||||
|
||||
/**
|
||||
* The system mono font.
|
||||
*/
|
||||
private GlyphMakerFont makerSystemMono;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Constructors -----------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -392,6 +413,7 @@ public class GlyphMaker {
|
|||
*/
|
||||
private GlyphMaker(final int fontSize) {
|
||||
makerMono = new GlyphMakerFont(MONO, fontSize);
|
||||
makerSystemMono = new GlyphMakerFont("", fontSize);
|
||||
|
||||
String fontFilename = null;
|
||||
fontFilename = System.getProperty("jexer.cjkFont.filename",
|
||||
|
@ -479,10 +501,65 @@ public class GlyphMaker {
|
|||
blinkVisible);
|
||||
}
|
||||
|
||||
if (makerSystemMono.canDisplay(ch)) {
|
||||
// System.err.println("system mono: " + String.format("0x%x", ch));
|
||||
return makerSystemMono.getImage(cell, cellWidth, cellHeight,
|
||||
backend, blinkVisible);
|
||||
}
|
||||
|
||||
// When all else fails, use the default.
|
||||
// System.err.println("mono: " + String.format("0x%x", ch));
|
||||
return makerMono.getImage(cell, cellWidth, cellHeight, backend,
|
||||
blinkVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a CJK font is available.
|
||||
*
|
||||
* @return true if a CJK font is available
|
||||
*/
|
||||
public boolean isCjk() {
|
||||
return makerCjk.isLoaded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an emoji font is available.
|
||||
*
|
||||
* @return true if an emoji font is available
|
||||
*/
|
||||
public boolean isEmoji() {
|
||||
return makerEmoji.isLoaded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a fallback font is available.
|
||||
*
|
||||
* @return true if a fallback font is available
|
||||
*/
|
||||
public boolean isFallback() {
|
||||
return makerFallback.isLoaded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a fallback font has a glyph for the specified character.
|
||||
*
|
||||
* @param codePoint the character (Unicode code point) for which a glyph
|
||||
* is needed.
|
||||
* @return true if this Font has a glyph for the character; false
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean canDisplay(final int codePoint) {
|
||||
if ((makerFallback.isLoaded() && makerFallback.canDisplay(codePoint))
|
||||
|| (makerEmoji.isLoaded() && makerEmoji.canDisplay(codePoint))
|
||||
|| (makerCjk.isLoaded() && makerCjk.canDisplay(codePoint))
|
||||
|
||||
// Put the system mono font ahead of terminus.
|
||||
|| makerSystemMono.canDisplay(codePoint)
|
||||
|| (makerMono.isLoaded() && makerMono.canDisplay(codePoint))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ import javax.swing.SwingUtilities;
|
|||
import jexer.TKeypress;
|
||||
import jexer.bits.Cell;
|
||||
import jexer.bits.CellAttributes;
|
||||
import jexer.bits.StringUtils;
|
||||
import jexer.event.TCommandEvent;
|
||||
import jexer.event.TInputEvent;
|
||||
import jexer.event.TKeypressEvent;
|
||||
|
@ -1477,9 +1478,17 @@ public class SwingTerminal extends LogicalScreen
|
|||
return;
|
||||
}
|
||||
|
||||
if (!swing.getFont().canDisplay(cell.getChar())) {
|
||||
GlyphMaker glyphMaker = GlyphMaker.getInstance(textHeight);
|
||||
int ch = cell.getChar();
|
||||
// If a fallback font is available that can support Symbols for
|
||||
// Legacy Computing, always use it. This is for consistency --
|
||||
// we assume the fallback font has better coverage than Terminus.
|
||||
if (((StringUtils.isLegacyComputingSymbol(ch)
|
||||
|| StringUtils.isBraille(ch))
|
||||
&& glyphMaker.canDisplay(ch))
|
||||
|| !swing.getFont().canDisplay(ch)
|
||||
) {
|
||||
// The main font cannot display this glyph. Try a fallback font.
|
||||
GlyphMaker glyphMaker = GlyphMaker.getInstance(textHeight);
|
||||
BufferedImage newImage = glyphMaker.getImage(cell, textWidth,
|
||||
textHeight, getBackend(), cursorBlinkVisible);
|
||||
|
||||
|
|
|
@ -512,6 +512,27 @@ public class StringUtils {
|
|||
return ((ch >= 0x1f004) && (ch <= 0x1fffd));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if character is in the Symbols for Legacy Computing range.
|
||||
*
|
||||
* @param ch character to check
|
||||
* @return true if this character is in the Symbols for Legacy Computing
|
||||
* range
|
||||
*/
|
||||
public static boolean isLegacyComputingSymbol(final int ch) {
|
||||
return ((ch >= 0x1fb00) && (ch <= 0x1fbff));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if character is in the braille range.
|
||||
*
|
||||
* @param ch character to check
|
||||
* @return true if this character is in the braille range
|
||||
*/
|
||||
public static boolean isBraille(final int ch) {
|
||||
return ((ch >= 0x2800) && (ch <= 0x28ff));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Base64 -----------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue