From eb826131340426237bea4193e77521d73e9b1064 Mon Sep 17 00:00:00 2001 From: takahirom Date: Sat, 15 Feb 2025 21:05:21 +0900 Subject: [PATCH 1/4] Fix issue where Roborazzi crash when the font is not available --- .../takahirom/roborazzi/AwtRoboCanvas.kt | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt b/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt index 7d4b846f..1a4fb213 100644 --- a/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt +++ b/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt @@ -11,6 +11,7 @@ import java.awt.BasicStroke import java.awt.Color import java.awt.Font import java.awt.Graphics2D +import java.awt.GraphicsEnvironment import java.awt.Rectangle import java.awt.RenderingHints import java.awt.font.FontRenderContext @@ -237,9 +238,9 @@ class AwtRoboCanvas(width: Int, height: Int, filled: Boolean, bufferedImageType: } override fun differ( - other: RoboCanvas, - resizeScale: Double, - imageComparator: ImageComparator + other: RoboCanvas, + resizeScale: Double, + imageComparator: ImageComparator ): ImageComparator.ComparisonResult { other as AwtRoboCanvas val otherImage = other.bufferedImage @@ -443,7 +444,7 @@ class AwtRoboCanvas(width: Int, height: Int, filled: Boolean, bufferedImageType: // fill with 4dp margin val textMargin = (4 * oneDpPx).toInt() // Set size to 12dp - val font = Font("Courier New", Font.BOLD, fontSize) + val font = getFont(Font.BOLD, fontSize) val textLayout = TextLayout(text, font, comparisonImageGraphics.fontRenderContext) val bounds = textLayout.bounds val rect = Rectangle( @@ -519,7 +520,8 @@ class AwtRoboCanvas(width: Int, height: Int, filled: Boolean, bufferedImageType: for (x in 0 until width) { for (y in 0 until height) { if (x >= originalImage.width || y >= originalImage.height - || x >= comparedImage.width || y >= comparedImage.height) { + || x >= comparedImage.width || y >= comparedImage.height + ) { diffImage.setRGB(x, y, -0x10000) continue } @@ -553,9 +555,21 @@ private fun BufferedImage.scale(scale: Double): BufferedImage { return after } +internal fun getFont(style: Int, size: Int): Font { + return if (hasCourierNewFont) { + Font("Courier New", style, size) + } else { + Font(null, style, size) + } +} + +internal val hasCourierNewFont: Boolean by lazy { + GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames.contains("Courier New") +} + private fun BufferedImage.graphics(block: (Graphics2D) -> T): T { val graphics = createGraphics() - graphics.font = Font("Courier New", Font.BOLD, 12) + graphics.font = getFont(Font.BOLD, 12) val result = block(graphics) graphics.dispose() return result From 1eaca4e2a0195e5219f8b1547bc9095cb14dcfbc Mon Sep 17 00:00:00 2001 From: takahirom Date: Sat, 15 Feb 2025 21:46:41 +0900 Subject: [PATCH 2/4] Use Font.MONOSPACED and ignore case --- .../kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt | 5 +++-- sample-generate-preview-tests/build.gradle.kts | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt b/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt index 1a4fb213..7c241de8 100644 --- a/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt +++ b/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt @@ -559,12 +559,13 @@ internal fun getFont(style: Int, size: Int): Font { return if (hasCourierNewFont) { Font("Courier New", style, size) } else { - Font(null, style, size) + Font(Font.MONOSPACED, style, size) } } internal val hasCourierNewFont: Boolean by lazy { - GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames.contains("Courier New") + GraphicsEnvironment.getLocalGraphicsEnvironment() + .availableFontFamilyNames.any { it.equals("Courier New", ignoreCase = true) } } private fun BufferedImage.graphics(block: (Graphics2D) -> T): T { diff --git a/sample-generate-preview-tests/build.gradle.kts b/sample-generate-preview-tests/build.gradle.kts index debd0293..7a8a9d7f 100644 --- a/sample-generate-preview-tests/build.gradle.kts +++ b/sample-generate-preview-tests/build.gradle.kts @@ -49,6 +49,7 @@ android { it.systemProperties["robolectric.pixelCopyRenderMode"] = "hardware" // For large preview it.maxHeapSize = "4096m" + it.jvmArgs("-noverify") } } } From 05823b7de55fa0cd86d63e354da0656eabd32689 Mon Sep 17 00:00:00 2001 From: takahirom Date: Sun, 16 Feb 2025 12:58:27 +0900 Subject: [PATCH 3/4] Use getSystemProperty to make font customizable --- .../com/github/takahirom/roborazzi/AwtRoboCanvas.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt b/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt index 7c241de8..daa5aa3f 100644 --- a/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt +++ b/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt @@ -555,9 +555,13 @@ private fun BufferedImage.scale(scale: Double): BufferedImage { return after } +internal val fontName by lazy { + getSystemProperty("roborazzi.theme.typography.font.name", "Courier New") +} + internal fun getFont(style: Int, size: Int): Font { return if (hasCourierNewFont) { - Font("Courier New", style, size) + Font(fontName, style, size) } else { Font(Font.MONOSPACED, style, size) } @@ -565,7 +569,7 @@ internal fun getFont(style: Int, size: Int): Font { internal val hasCourierNewFont: Boolean by lazy { GraphicsEnvironment.getLocalGraphicsEnvironment() - .availableFontFamilyNames.any { it.equals("Courier New", ignoreCase = true) } + .availableFontFamilyNames.any { it.equals(fontName, ignoreCase = true) } } private fun BufferedImage.graphics(block: (Graphics2D) -> T): T { From d86d26cc77d2029762d6dd033db20b8aed4dbe3b Mon Sep 17 00:00:00 2001 From: takahirom Date: Sun, 16 Feb 2025 13:22:04 +0900 Subject: [PATCH 4/4] Rename --- .../com/github/takahirom/roborazzi/AwtRoboCanvas.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt b/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt index daa5aa3f..fc73f484 100644 --- a/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt +++ b/roborazzi-painter/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/AwtRoboCanvas.kt @@ -555,21 +555,21 @@ private fun BufferedImage.scale(scale: Double): BufferedImage { return after } -internal val fontName by lazy { +internal val preferredFontName: String by lazy { getSystemProperty("roborazzi.theme.typography.font.name", "Courier New") } internal fun getFont(style: Int, size: Int): Font { - return if (hasCourierNewFont) { - Font(fontName, style, size) + return if (hasPreferredFont) { + Font(preferredFontName, style, size) } else { Font(Font.MONOSPACED, style, size) } } -internal val hasCourierNewFont: Boolean by lazy { +internal val hasPreferredFont: Boolean by lazy { GraphicsEnvironment.getLocalGraphicsEnvironment() - .availableFontFamilyNames.any { it.equals(fontName, ignoreCase = true) } + .availableFontFamilyNames.any { it.equals(preferredFontName, ignoreCase = true) } } private fun BufferedImage.graphics(block: (Graphics2D) -> T): T {