Unverified Commit e8b3b444 authored by Nikolay Igotti's avatar Nikolay Igotti Committed by GitHub

Add API to access fonts from resources. (#509)

* Add API to access fonts from resources.

* More font locations
parent 108f7eb3
......@@ -4,7 +4,6 @@ import org.gradle.api.tasks.testing.AbstractTestTask
import org.jetbrains.compose.internal.publishing.MavenCentralProperties
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
plugins {
......
......@@ -5,6 +5,7 @@ import java.awt.Font
import java.awt.FontFormatException
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.util.concurrent.ConcurrentHashMap
......@@ -42,6 +43,8 @@ class AwtFontManager(fontPaths: Array<String> = emptyArray()) {
OS.Linux -> {
val pathsToCheck = arrayOf(
System.getProperty("user.home") + File.separator + ".fonts",
"/usr/share/fonts",
"/usr/local/share/fonts",
"/usr/share/fonts/truetype",
"/usr/share/fonts/TTF"
)
......@@ -61,12 +64,18 @@ class AwtFontManager(fontPaths: Array<String> = emptyArray()) {
}
}
private fun isFont(extension: String): Boolean {
return extension == "ttf" ||
extension == "ttc" ||
extension == "otf"
}
private fun findFontFiles(paths: List<String>): List<File> {
val files = mutableListOf<File>()
paths.forEach { path ->
val fontDirectory = File(path)
if (fontDirectory.exists()) {
fontDirectory.walk().filter { it.isFile && it.extension.lowercase() == "ttf" }.forEach {
fontDirectory.walk().filter { it.isFile && isFont(it.extension.lowercase()) }.forEach {
files.add(it)
}
}
......@@ -74,20 +83,31 @@ class AwtFontManager(fontPaths: Array<String> = emptyArray()) {
return files
}
private suspend fun cacheAllFonts() {
fontsMap.clear()
val fontFiles = findFontFiles(customFontPaths) + findFontFiles(systemFontsPaths())
for (file in fontFiles) {
try {
val f = FileInputStream(file.absolutePath).use {
private fun addFontFromFile(file: File): Boolean {
val f = try {
FileInputStream(file.absolutePath).use {
Font.createFont(Font.TRUETYPE_FONT, it)
}
} catch (e: FontFormatException){
return false
} catch (e: IOException) {
return false
}
val name = f.family
val list = fontsMap.computeIfAbsent(name) { mutableListOf() }
synchronized(list) {
list.add(FontDescriptor(file.absoluteFile, f.style))
}
return true
}
private suspend fun cacheAllFonts() {
fontsMap.clear()
val fontFiles = findFontFiles(customFontPaths) + findFontFiles(systemFontsPaths())
for (file in fontFiles) {
try {
addFontFromFile(file)
yield()
} catch (e: FontFormatException) {
} catch (e: IOException) {
......@@ -186,6 +206,26 @@ class AwtFontManager(fontPaths: Array<String> = emptyArray()) {
customFontPaths += path
}
/**
* Add custom resource entry as a font known to this resource manager.
*
* @return true, if font was found and identified, and false otherwise
*/
fun addResourceFont(resource: String, loader: ClassLoader = Thread.currentThread().contextClassLoader): Boolean {
val res = loader.getResourceAsStream(resource) ?: ClassLoader.getSystemResourceAsStream(resource) ?: return false
val file = File.createTempFile("tmp", ".ttf")
file.deleteOnExit()
FileOutputStream(file).use { out ->
out.write(res.readAllBytes())
}
return addFontFromFile(file).also {
if (it)
customFontPaths += file.absolutePath
else
file.delete()
}
}
/**
* If all AWT fonts were cached. Check this property before using non-suspend version
* of font conversion APIs.
......
......@@ -93,4 +93,19 @@ class AwtFontInterop {
assertTrue("Font must be file", path.exists() && path.isFile)
}
}
// This test is disabled due to convoluted setup of tests.
// @Test
fun addCustomResource() {
runTest {
assumeOk()
val fontManager = AwtFontManager()
assertTrue("Custom resource must be found",
fontManager.addResourceFont("/fonts/JetBrainsMono-Bold.ttf", Library.javaClass.classLoader))
val path = fontManager.findFontFamilyFile("JetBrains Mono")
assertTrue("Custom font must be found", path != null)
path!!
assertTrue("Font must be file", path.exists() && path.isFile)
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment