Browse Source

fix: 使用TextPaint副本避免修改共享paint影响绘制线程

HapeLee 5 months ago
parent
commit
81fc3ea7e4

+ 17 - 21
app/src/main/java/io/legado/app/ui/book/read/page/provider/TextChapterLayout.kt

@@ -1365,7 +1365,7 @@ class TextChapterLayout(
 
     /**
      * 对有自定义字体的高亮字符重新测量宽度,确保排版和绘制使用同一套字体度量。
-     * 不使用 getTextWidthsCompat 避免对子串错误添加 letterSpacing。
+     * 使用 textPaint 副本测量,避免修改共享 paint 的 typeface 影响绘制线程。
      */
     private fun remeasureWithHighlightFonts(
         text: String,
@@ -1373,26 +1373,22 @@ class TextChapterLayout(
         textPaint: TextPaint,
         widthsArray: FloatArray
     ) {
-        val originalTypeface = textPaint.typeface
-        try {
-            var i = 0
-            while (i < text.length) {
-                val fontPath = charStyles[i]?.fontPath.orEmpty()
-                if (fontPath.isEmpty()) { i++; continue }
-                // 找连续使用同一字体的区间
-                val segStart = i
-                i++
-                while (i < text.length && charStyles[i]?.fontPath.orEmpty() == fontPath) i++
-                val segEnd = i
-                val typeface = TextColumn.getTypeface(fontPath) ?: continue
-                textPaint.typeface = typeface
-                val segLen = segEnd - segStart
-                val segWidths = FloatArray(segLen)
-                textPaint.getTextWidths(text, segStart, segEnd, segWidths)
-                segWidths.copyInto(widthsArray, segStart)
-            }
-        } finally {
-            textPaint.typeface = originalTypeface
+        val measurePaint = TextPaint(textPaint)
+        var i = 0
+        while (i < text.length) {
+            val fontPath = charStyles[i]?.fontPath.orEmpty()
+            if (fontPath.isEmpty()) { i++; continue }
+            // 找连续使用同一字体的区间
+            val segStart = i
+            i++
+            while (i < text.length && charStyles[i]?.fontPath.orEmpty() == fontPath) i++
+            val segEnd = i
+            val typeface = TextColumn.getTypeface(fontPath) ?: continue
+            measurePaint.typeface = typeface
+            val segLen = segEnd - segStart
+            val segWidths = FloatArray(segLen)
+            measurePaint.getTextWidths(text, segStart, segEnd, segWidths)
+            segWidths.copyInto(widthsArray, segStart)
         }
     }