From 9a2009d1829189a54f4c98461c2f8355a0d84b9b Mon Sep 17 00:00:00 2001 From: Helium314 Date: Fri, 17 Jan 2025 21:47:13 +0100 Subject: [PATCH] allow using user-provided font fixes #494 --- .../keyboard/keyboard/KeyboardView.java | 4 +- .../keyboard/keyboard/MainKeyboardView.java | 2 +- .../clipboard/ClipboardHistoryView.kt | 1 + .../keyboard/internal/KeyPreviewView.java | 7 ++- .../settings/AppearanceSettingsFragment.kt | 48 +++++++++++++++++++ .../keyboard/latin/settings/Settings.java | 23 +++++++++ .../suggestions/SuggestionStripView.java | 4 ++ app/src/main/res/values/strings.xml | 2 + .../main/res/xml/prefs_screen_appearance.xml | 6 +++ 9 files changed, 94 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/keyboard/KeyboardView.java b/app/src/main/java/helium314/keyboard/keyboard/KeyboardView.java index 35f8e6670..b1fc5aba8 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/KeyboardView.java +++ b/app/src/main/java/helium314/keyboard/keyboard/KeyboardView.java @@ -95,6 +95,7 @@ public class KeyboardView extends View { @NonNull private final Paint mPaint = new Paint(); private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics(); + protected final Typeface mTypeface; public KeyboardView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.keyboardViewStyle); @@ -144,6 +145,7 @@ public class KeyboardView extends View { keyAttr.recycle(); mPaint.setAntiAlias(true); + mTypeface = Settings.getInstance().readCustomTypeface(); } @Nullable @@ -381,7 +383,7 @@ public class KeyboardView extends View { float labelBaseline = centerY; final String label = key.getLabel(); if (label != null) { - paint.setTypeface(key.selectTypeface(params)); + paint.setTypeface(mTypeface == null ? key.selectTypeface(params) : mTypeface); paint.setTextSize(key.selectTextSize(params)); final float labelCharHeight = TypefaceUtils.getReferenceCharHeight(paint); final float labelCharWidth = TypefaceUtils.getReferenceCharWidth(paint); diff --git a/app/src/main/java/helium314/keyboard/keyboard/MainKeyboardView.java b/app/src/main/java/helium314/keyboard/keyboard/MainKeyboardView.java index 4fa989e81..c004822b3 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/MainKeyboardView.java +++ b/app/src/main/java/helium314/keyboard/keyboard/MainKeyboardView.java @@ -798,7 +798,7 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy final int width = key.getWidth(); final int height = key.getHeight(); paint.setTextAlign(Align.CENTER); - paint.setTypeface(Typeface.DEFAULT); + paint.setTypeface(mTypeface == null ? Typeface.DEFAULT : mTypeface); paint.setTextSize(mLanguageOnSpacebarTextSize); final String customText = Settings.getInstance().getCurrent().mSpaceBarText; final String spaceText; diff --git a/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt b/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt index 1ead80770..1f55d191f 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt @@ -156,6 +156,7 @@ class ClipboardHistoryView @JvmOverloads constructor( val params = KeyDrawParams() params.updateParams(clipboardLayoutParams.bottomRowKeyboardHeight, keyVisualAttr) + Settings.getInstance().readCustomTypeface()?.let { params.mTypeface = it } setupClipKey(params) setupBottomRowKeyboard(editorInfo, keyboardActionListener) diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyPreviewView.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyPreviewView.java index e24a240e4..56a1d53d9 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyPreviewView.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyPreviewView.java @@ -8,6 +8,7 @@ package helium314.keyboard.keyboard.internal; import android.content.Context; import android.graphics.Rect; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.text.TextPaint; import android.text.TextUtils; @@ -20,6 +21,7 @@ import androidx.appcompat.widget.AppCompatTextView; import helium314.keyboard.keyboard.Key; import helium314.keyboard.latin.R; import helium314.keyboard.latin.common.StringUtilsKt; +import helium314.keyboard.latin.settings.Settings; import java.util.HashSet; @@ -33,6 +35,7 @@ public class KeyPreviewView extends AppCompatTextView { private final Rect mBackgroundPadding = new Rect(); private static final HashSet sNoScaleXTextSet = new HashSet<>(); + private final Typeface mTypeface; public KeyPreviewView(final Context context, final AttributeSet attrs) { this(context, attrs, 0); @@ -41,6 +44,7 @@ public class KeyPreviewView extends AppCompatTextView { public KeyPreviewView(final Context context, final AttributeSet attrs, final int defStyleAttr) { super(context, attrs, defStyleAttr); setGravity(Gravity.CENTER); + mTypeface = Settings.getInstance().readCustomTypeface(); } public void setPreviewVisual(final Key key, final KeyboardIconsSet iconsSet, final KeyDrawParams drawParams) { @@ -54,7 +58,8 @@ public class KeyPreviewView extends AppCompatTextView { setCompoundDrawables(null, null, null, null); setTextColor(drawParams.mPreviewTextColor); setTextSize(TypedValue.COMPLEX_UNIT_PX, key.selectPreviewTextSize(drawParams)); - setTypeface(key.selectPreviewTypeface(drawParams)); + // wie hier machen? + setTypeface(mTypeface == null ? key.selectPreviewTypeface(drawParams) : mTypeface); // TODO Should take care of temporaryShiftLabel here. setTextAndScaleX(key.getPreviewLabel()); } diff --git a/app/src/main/java/helium314/keyboard/latin/settings/AppearanceSettingsFragment.kt b/app/src/main/java/helium314/keyboard/latin/settings/AppearanceSettingsFragment.kt index 6ed61bab4..93d3b0f51 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/AppearanceSettingsFragment.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/AppearanceSettingsFragment.kt @@ -7,6 +7,7 @@ import android.content.Intent import android.content.SharedPreferences import android.content.res.Configuration import android.graphics.BitmapFactory +import android.graphics.Typeface import android.net.Uri import android.os.Build import android.os.Bundle @@ -36,12 +37,14 @@ import helium314.keyboard.latin.R import helium314.keyboard.latin.common.FileUtils import helium314.keyboard.latin.customIconNames import helium314.keyboard.latin.databinding.ReorderDialogItemBinding +import helium314.keyboard.latin.utils.DeviceProtectedUtils import helium314.keyboard.latin.utils.ResourceUtils import helium314.keyboard.latin.utils.confirmDialog import helium314.keyboard.latin.utils.getStringResourceOrName import helium314.keyboard.latin.utils.infoDialog import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import java.io.File import java.lang.Float.max import java.lang.Float.min import java.util.* @@ -86,6 +89,12 @@ class AppearanceSettingsFragment : SubScreenFragment() { loadImage(uri, true, true) } + private val fontFilePicker = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + if (it.resultCode != Activity.RESULT_OK) return@registerForActivityResult + val uri = it.data?.data ?: return@registerForActivityResult + saveCustomTypeface(uri) + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) addPreferencesFromResource(R.xml.prefs_screen_appearance) @@ -106,6 +115,7 @@ class AppearanceSettingsFragment : SubScreenFragment() { } findPreference("custom_background_image")?.setOnPreferenceClickListener { onClickLoadImage(false) } findPreference("custom_background_image_landscape")?.setOnPreferenceClickListener { onClickLoadImage(true) } + findPreference("custom_font")?.setOnPreferenceClickListener { onClickCustomFont() } findPreference(Settings.PREF_CUSTOM_ICON_NAMES)?.setOnPreferenceClickListener { if (needsReload) KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext()) @@ -389,6 +399,44 @@ class AppearanceSettingsFragment : SubScreenFragment() { KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext()) } + private fun onClickCustomFont(): Boolean { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT) + .addCategory(Intent.CATEGORY_OPENABLE) + .setType("*/*") + val fontFile = Settings.getCustomFontFile(requireContext()) + if (fontFile.exists()) { + AlertDialog.Builder(requireContext()) + .setTitle(R.string.custom_font) + .setPositiveButton(R.string.load) { _, _ -> fontFilePicker.launch(intent) } + .setNegativeButton(android.R.string.cancel, null) + .setNeutralButton(R.string.delete) { _, _ -> + fontFile.delete() + Settings.clearCachedTypeface() + KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext()) + } + .show() + } else { + fontFilePicker.launch(intent) + } + return true + } + + private fun saveCustomTypeface(uri: Uri) { + val fontFile = Settings.getCustomFontFile(requireContext()) + val tempFile = File(DeviceProtectedUtils.getFilesDir(context), "temp_file") + FileUtils.copyContentUriToNewFile(uri, requireContext(), tempFile) + try { + val typeface = Typeface.createFromFile(tempFile) + fontFile.delete() + tempFile.renameTo(fontFile) + Settings.clearCachedTypeface() + KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext()) + } catch (_: Exception) { + infoDialog(requireContext(), R.string.file_read_error) + tempFile.delete() + } + } + private fun setupScalePrefs(prefKey: String, defaultValue: Float) { val prefs = sharedPreferences val pref = findPreference(prefKey) as? SeekBarDialogPreference diff --git a/app/src/main/java/helium314/keyboard/latin/settings/Settings.java b/app/src/main/java/helium314/keyboard/latin/settings/Settings.java index 3cdf55482..da3efd11d 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/Settings.java +++ b/app/src/main/java/helium314/keyboard/latin/settings/Settings.java @@ -14,6 +14,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.BitmapFactory; import android.graphics.Color; +import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; @@ -196,6 +197,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang // static cache for background images to avoid potentially slow reload on every settings reload private final static Drawable[] sCachedBackgroundImages = new Drawable[4]; + private static Typeface sCachedTypeface; private Map mCustomToolbarKeyCodes = null; private Map mCustomToolbarLongpressCodes = null; @@ -729,4 +731,25 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang mCustomToolbarLongpressCodes = ToolbarUtilsKt.readCustomLongpressCodes(mPrefs); return mCustomToolbarLongpressCodes.get(key.name()); } + + public static File getCustomFontFile(final Context context) { + return new File(DeviceProtectedUtils.getFilesDir(context), "custom_font"); + } + + @Nullable + public Typeface readCustomTypeface() { + // dammit, dann würde wenns keins gibt bei jedem zugriff gesucht -> 2 variablen nehmen? custom und hasCustom? + // ein clear brauchen wir sowieso on theme changed (und auch triggern wenn man ne font setzt/löscht) + // try/catch! + if (sCachedTypeface == null) { + try { + sCachedTypeface = Typeface.createFromFile(getCustomFontFile(mContext)); + } catch (Exception e) { } + } + return sCachedTypeface; + } + + public static void clearCachedTypeface() { + sCachedTypeface = null; + } } diff --git a/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripView.java b/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripView.java index 679865578..3503cfbf0 100644 --- a/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripView.java +++ b/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripView.java @@ -15,6 +15,7 @@ import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.Color; import android.graphics.PorterDuff; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.ShapeDrawable; @@ -155,11 +156,14 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mToolbar = findViewById(R.id.toolbar); mToolbarContainer = findViewById(R.id.toolbar_container); + final Typeface customTypeface = Settings.getInstance().readCustomTypeface(); for (int pos = 0; pos < SuggestedWords.MAX_SUGGESTIONS; pos++) { final TextView word = new TextView(context, null, R.attr.suggestionWordStyle); word.setContentDescription(getResources().getString(R.string.spoken_empty_suggestion)); word.setOnClickListener(this); word.setOnLongClickListener(this); + if (customTypeface != null) + word.setTypeface(customTypeface); colors.setBackground(word, ColorType.STRIP_BACKGROUND); mWordViews.add(word); final View divider = inflater.inflate(R.layout.suggestion_divider, null); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7bc3cc2fc..b4dc0c057 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -313,6 +313,8 @@ Bottom padding scale Custom text on space bar + + Set custom font from file English (UK) diff --git a/app/src/main/res/xml/prefs_screen_appearance.xml b/app/src/main/res/xml/prefs_screen_appearance.xml index 45df45d8f..e02f3702f 100644 --- a/app/src/main/res/xml/prefs_screen_appearance.xml +++ b/app/src/main/res/xml/prefs_screen_appearance.xml @@ -117,6 +117,12 @@ android:defaultValue="" android:persistent="true" /> + +