From 99c7b02994ccf0e42a1846ed6fcc0d4f4f594fc7 Mon Sep 17 00:00:00 2001 From: Emanuel Krollmann Date: Thu, 5 Sep 2024 14:19:56 +0200 Subject: [PATCH] Added(terminal): Add true italic font support --- .../TermuxTerminalSessionActivityClient.java | 4 +- .../com/termux/view/TerminalRenderer.java | 55 ++++++++++++++++--- .../java/com/termux/view/TerminalView.java | 6 +- .../termux/shared/termux/TermuxConstants.java | 4 ++ 4 files changed, 56 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionActivityClient.java b/app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionActivityClient.java index cd38163116..8eed808224 100644 --- a/app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionActivityClient.java +++ b/app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionActivityClient.java @@ -495,6 +495,7 @@ public void checkForFontAndColors() { try { File colorsFile = TermuxConstants.TERMUX_COLOR_PROPERTIES_FILE; File fontFile = TermuxConstants.TERMUX_FONT_FILE; + File italicFontFile = TermuxConstants.TERMUX_ITALIC_FONT_FILE; final Properties props = new Properties(); if (colorsFile.isFile()) { @@ -511,7 +512,8 @@ public void checkForFontAndColors() { updateBackgroundColor(); final Typeface newTypeface = (fontFile.exists() && fontFile.length() > 0) ? Typeface.createFromFile(fontFile) : Typeface.MONOSPACE; - mActivity.getTerminalView().setTypeface(newTypeface); + final Typeface newItalicTypeface = (italicFontFile.exists() && italicFontFile.length() > 0) ? Typeface.createFromFile(italicFontFile) : newTypeface; + mActivity.getTerminalView().setTypefaces(newTypeface, newItalicTypeface); } catch (Exception e) { Logger.logStackTraceWithMessage(LOG_TAG, "Error in checkForFontAndColors()", e); } diff --git a/terminal-view/src/main/java/com/termux/view/TerminalRenderer.java b/terminal-view/src/main/java/com/termux/view/TerminalRenderer.java index a4bef7d37c..b56fd7d344 100644 --- a/terminal-view/src/main/java/com/termux/view/TerminalRenderer.java +++ b/terminal-view/src/main/java/com/termux/view/TerminalRenderer.java @@ -20,6 +20,7 @@ public final class TerminalRenderer { final int mTextSize; final Typeface mTypeface; + final Typeface mItalicTypeface; private final Paint mTextPaint = new Paint(); /** The width of a single mono spaced character obtained by {@link Paint#measureText(String)} on a single 'X'. */ @@ -31,15 +32,33 @@ public final class TerminalRenderer { /** The {@link #mFontLineSpacing} + {@link #mFontAscent}. */ final int mFontLineSpacingAndAscent; + + /** The width of a single mono spaced italic character obtained by {@link Paint#measureText(String)} on a single 'X'. */ + final float mItalicFontWidth; + /** The {@link Paint#getFontSpacing()}. See http://www.fampennings.nl/maarten/android/08numgrid/font.png */ + final int mItalicFontLineSpacing; + /** The {@link Paint#ascent()}. See http://www.fampennings.nl/maarten/android/08numgrid/font.png */ + private final int mItalicFontAscent; + /** The {@link #mFontLineSpacing} + {@link #mFontAscent}. */ + final int mItalicFontLineSpacingAndAscent; + private final float[] asciiMeasures = new float[127]; - public TerminalRenderer(int textSize, Typeface typeface) { + public TerminalRenderer(int textSize, Typeface typeface, Typeface italicTypeface) { mTextSize = textSize; mTypeface = typeface; + mItalicTypeface = italicTypeface; - mTextPaint.setTypeface(typeface); + mTextPaint.setTypeface(italicTypeface); mTextPaint.setAntiAlias(true); mTextPaint.setTextSize(textSize); + mItalicFontLineSpacing = (int) Math.ceil(mTextPaint.getFontSpacing()); + mItalicFontAscent = (int) Math.ceil(mTextPaint.ascent()); + mItalicFontLineSpacingAndAscent = mItalicFontLineSpacing + mItalicFontAscent; + mItalicFontWidth = mTextPaint.measureText("X"); + + mTextPaint.setTypeface(typeface); + typeface.getStyle(); mFontLineSpacing = (int) Math.ceil(mTextPaint.getFontSpacing()); mFontAscent = (int) Math.ceil(mTextPaint.ascent()); @@ -168,6 +187,24 @@ private void drawTextRun(Canvas canvas, char[] text, int[] palette, float y, int final boolean strikeThrough = (effect & TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH) != 0; final boolean dim = (effect & TextStyle.CHARACTER_ATTRIBUTE_DIM) != 0; + final float fontWidth; + final int fontAscent; + final int fontLineSpacingAndAscent; + + if (italic) { + fontWidth = mItalicFontWidth; + fontAscent = mItalicFontAscent; + fontLineSpacingAndAscent = mItalicFontLineSpacingAndAscent; + + mTextPaint.setTypeface(mItalicTypeface); + } else { + fontWidth = mFontWidth; + fontAscent = mFontAscent; + fontLineSpacingAndAscent = mFontLineSpacingAndAscent; + + mTextPaint.setTypeface(mTypeface); + } + if ((foreColor & 0xff000000) != 0xff000000) { // Let bold have bright colors if applicable (one of the first 8): if (bold && foreColor >= 0 && foreColor < 8) foreColor += 8; @@ -186,10 +223,10 @@ private void drawTextRun(Canvas canvas, char[] text, int[] palette, float y, int backColor = tmp; } - float left = startColumn * mFontWidth; - float right = left + runWidthColumns * mFontWidth; + float left = startColumn * fontWidth; + float right = left + runWidthColumns * fontWidth; - mes = mes / mFontWidth; + mes = mes / fontWidth; boolean savedMatrix = false; if (Math.abs(mes - runWidthColumns) > 0.01) { canvas.save(); @@ -202,12 +239,12 @@ private void drawTextRun(Canvas canvas, char[] text, int[] palette, float y, int if (backColor != palette[TextStyle.COLOR_INDEX_BACKGROUND]) { // Only draw non-default background. mTextPaint.setColor(backColor); - canvas.drawRect(left, y - mFontLineSpacingAndAscent + mFontAscent, right, y, mTextPaint); + canvas.drawRect(left, y - fontLineSpacingAndAscent + fontAscent, right, y, mTextPaint); } if (cursor != 0) { mTextPaint.setColor(cursor); - float cursorHeight = mFontLineSpacingAndAscent - mFontAscent; + float cursorHeight = fontLineSpacingAndAscent - fontAscent; if (cursorStyle == TerminalEmulator.TERMINAL_CURSOR_STYLE_UNDERLINE) cursorHeight /= 4.; else if (cursorStyle == TerminalEmulator.TERMINAL_CURSOR_STYLE_BAR) right -= ((right - left) * 3) / 4.; canvas.drawRect(left, y - cursorHeight, right, y, mTextPaint); @@ -228,12 +265,12 @@ private void drawTextRun(Canvas canvas, char[] text, int[] palette, float y, int mTextPaint.setFakeBoldText(bold); mTextPaint.setUnderlineText(underline); - mTextPaint.setTextSkewX(italic ? -0.35f : 0.f); + mTextPaint.setTextSkewX(italic && mItalicTypeface == mTypeface ? -0.35f : 0.f); mTextPaint.setStrikeThruText(strikeThrough); mTextPaint.setColor(foreColor); // The text alignment is the default Paint.Align.LEFT. - canvas.drawTextRun(text, startCharIndex, runWidthChars, startCharIndex, runWidthChars, left, y - mFontLineSpacingAndAscent, false, mTextPaint); + canvas.drawTextRun(text, startCharIndex, runWidthChars, startCharIndex, runWidthChars, left, y - fontLineSpacingAndAscent, false, mTextPaint); } if (savedMatrix) canvas.restore(); diff --git a/terminal-view/src/main/java/com/termux/view/TerminalView.java b/terminal-view/src/main/java/com/termux/view/TerminalView.java index 435c102515..63a9d636e7 100644 --- a/terminal-view/src/main/java/com/termux/view/TerminalView.java +++ b/terminal-view/src/main/java/com/termux/view/TerminalView.java @@ -512,12 +512,12 @@ public void onContextMenuClosed(Menu menu) { * @param textSize the new font size, in density-independent pixels. */ public void setTextSize(int textSize) { - mRenderer = new TerminalRenderer(textSize, mRenderer == null ? Typeface.MONOSPACE : mRenderer.mTypeface); + mRenderer = new TerminalRenderer(textSize, mRenderer == null ? Typeface.MONOSPACE : mRenderer.mTypeface, mRenderer == null ? Typeface.MONOSPACE : mRenderer.mItalicTypeface); updateSize(); } - public void setTypeface(Typeface newTypeface) { - mRenderer = new TerminalRenderer(mRenderer.mTextSize, newTypeface); + public void setTypefaces(Typeface newTypeface, Typeface newItalicTypeFace) { + mRenderer = new TerminalRenderer(mRenderer.mTextSize, newTypeface, newItalicTypeFace); updateSize(); invalidate(); } diff --git a/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java b/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java index 534936ffca..c9076c1bf4 100644 --- a/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java +++ b/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java @@ -772,6 +772,10 @@ public final class TermuxConstants { /** Termux app and Termux:Styling font.ttf file */ public static final File TERMUX_FONT_FILE = new File(TERMUX_FONT_FILE_PATH); + /** Termux app and Termux:Styling font-italic.ttf file path */ + public static final String TERMUX_ITALIC_FONT_FILE_PATH = TERMUX_DATA_HOME_DIR_PATH + "/font-italic.ttf"; + /** Termux app and Termux:Styling font-italic.ttf file */ + public static final File TERMUX_ITALIC_FONT_FILE = new File(TERMUX_ITALIC_FONT_FILE_PATH); /** Termux app and plugins crash log file path */ public static final String TERMUX_CRASH_LOG_FILE_PATH = TERMUX_HOME_DIR_PATH + "/crash_log.md"; // Default: "/data/data/com.termux/files/home/crash_log.md"