diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index f8f68a42ea0fc5..1e249296dadeda 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -371,7 +371,29 @@ protected void onDraw(Canvas canvas) { CharSequence text = getText(); StrokeStyleSpan strokeSpan = text instanceof Spanned ? StrokeStyleSpan.getStrokeSpan((Spanned) text) : null; - if (strokeSpan == null || !strokeSpan.draw(getPaint(), () -> super.onDraw(canvas))) { + + // Debug logging + Layout layout = getLayout(); + if (strokeSpan != null && layout != null) { + android.util.Log.d("ReactTextView", "===== ReactTextView.onDraw ====="); + android.util.Log.d("ReactTextView", "Layout lineCount: " + layout.getLineCount()); + android.util.Log.d("ReactTextView", "View size: " + getWidth() + "x" + getHeight()); + android.util.Log.d("ReactTextView", "Canvas clip bounds: " + canvas.getClipBounds()); + android.util.Log.d("ReactTextView", "Overflow mode: " + mOverflow); + for (int i = 0; i < layout.getLineCount(); i++) { + android.util.Log.d("ReactTextView", "Line " + i + " - top: " + layout.getLineTop(i) + + ", bottom: " + layout.getLineBottom(i) + + ", baseline: " + layout.getLineBaseline(i)); + } + android.util.Log.d("ReactTextView", "Text: " + text); + android.util.Log.d("ReactTextView", "About to call strokeSpan.draw()"); + } + + if (strokeSpan == null || !strokeSpan.draw(getPaint(), () -> { + android.util.Log.d("ReactTextView", ">>> Calling super.onDraw() - canvas clip: " + canvas.getClipBounds()); + super.onDraw(canvas); + android.util.Log.d("ReactTextView", "<<< super.onDraw() complete"); + })) { super.onDraw(canvas); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/StrokeStyleSpan.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/StrokeStyleSpan.kt index ac07de3b2c4da7..9609b1a8912f04 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/StrokeStyleSpan.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/StrokeStyleSpan.kt @@ -13,6 +13,7 @@ import android.graphics.PorterDuffColorFilter import android.text.Spanned import android.text.TextPaint import android.text.style.CharacterStyle +import android.util.Log public class StrokeStyleSpan( public val width: Float, @@ -32,35 +33,44 @@ public class StrokeStyleSpan( return false } + Log.d("StrokeStyleSpan", "===== STROKE DRAW START =====") + Log.d("StrokeStyleSpan", "Stroke width: $width, color: ${Integer.toHexString(color)}") + val originalStyle = paint.style val originalStrokeWidth = paint.strokeWidth val originalStrokeJoin = paint.strokeJoin val originalStrokeCap = paint.strokeCap val originalColor = paint.color - val originalColorFilter = paint.colorFilter - // Stroke pass + Log.d("StrokeStyleSpan", "Original paint - style: $originalStyle, strokeWidth: $originalStrokeWidth, color: ${Integer.toHexString(originalColor)}") + + // FILL PASS FIRST - explicitly set FILL style + paint.style = Paint.Style.FILL + paint.strokeWidth = 0f + // Keep original color so text color spans work + Log.d("StrokeStyleSpan", ">>> FILL PASS (FIRST) - style: ${paint.style}, strokeWidth: ${paint.strokeWidth}, color: ${Integer.toHexString(paint.color)}") + drawCallback.run() + Log.d("StrokeStyleSpan", "<<< FILL PASS COMPLETE") + + // STROKE PASS SECOND - draw stroke on top of fill paint.style = Paint.Style.STROKE paint.strokeWidth = width paint.strokeJoin = Paint.Join.ROUND paint.strokeCap = Paint.Cap.ROUND - paint.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN) + paint.color = color + Log.d("StrokeStyleSpan", ">>> STROKE PASS (SECOND) - style: ${paint.style}, strokeWidth: ${paint.strokeWidth}, color: ${Integer.toHexString(paint.color)}") drawCallback.run() + Log.d("StrokeStyleSpan", "<<< STROKE PASS COMPLETE") - // Fill pass - paint.style = Paint.Style.FILL - paint.strokeWidth = 0f - paint.color = originalColor - paint.colorFilter = originalColorFilter - drawCallback.run() - - // Restore + // Restore paint paint.style = originalStyle paint.strokeWidth = originalStrokeWidth paint.strokeJoin = originalStrokeJoin paint.strokeCap = originalStrokeCap paint.color = originalColor - paint.colorFilter = originalColorFilter + + Log.d("StrokeStyleSpan", "Paint restored to original state") + Log.d("StrokeStyleSpan", "===== STROKE DRAW END =====") return true }