mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Migrate com.facebook.react.views.text.FontMetricsUtil to Kotlin (#47510)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/47510 As per title. Changelog: [Internal] Reviewed By: tdn120 Differential Revision: D65598073 fbshipit-source-id: 401750f2df9bd434a8310f107f46a686bfa6601c
This commit is contained in:
committed by
Facebook GitHub Bot
parent
e64513bf4e
commit
697a422bf5
@@ -7200,9 +7200,9 @@ public final class com/facebook/react/views/text/DefaultStyleValuesUtil {
|
||||
public static final fun getDefaultTextColorHint (Landroid/content/Context;)Landroid/content/res/ColorStateList;
|
||||
}
|
||||
|
||||
public class com/facebook/react/views/text/FontMetricsUtil {
|
||||
public fun <init> ()V
|
||||
public static fun getFontMetrics (Ljava/lang/CharSequence;Landroid/text/Layout;Landroid/text/TextPaint;Landroid/content/Context;)Lcom/facebook/react/bridge/WritableArray;
|
||||
public final class com/facebook/react/views/text/FontMetricsUtil {
|
||||
public static final field INSTANCE Lcom/facebook/react/views/text/FontMetricsUtil;
|
||||
public static final fun getFontMetrics (Ljava/lang/CharSequence;Landroid/text/Layout;Landroid/text/TextPaint;Landroid/content/Context;)Lcom/facebook/react/bridge/WritableArray;
|
||||
}
|
||||
|
||||
public abstract class com/facebook/react/views/text/ReactBaseTextShadowNode : com/facebook/react/uimanager/LayoutShadowNode {
|
||||
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.views.text;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.text.Layout;
|
||||
import android.text.TextPaint;
|
||||
import android.util.DisplayMetrics;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
|
||||
public class FontMetricsUtil {
|
||||
|
||||
private static final String CAP_HEIGHT_MEASUREMENT_TEXT = "T";
|
||||
private static final String X_HEIGHT_MEASUREMENT_TEXT = "x";
|
||||
private static final float AMPLIFICATION_FACTOR = 100;
|
||||
|
||||
public static WritableArray getFontMetrics(
|
||||
CharSequence text, Layout layout, TextPaint paint, Context context) {
|
||||
DisplayMetrics dm = context.getResources().getDisplayMetrics();
|
||||
WritableArray lines = Arguments.createArray();
|
||||
// To calculate xHeight and capHeight we have to render an "x" and "T" and manually measure
|
||||
// their height.
|
||||
// In order to get more precision than Android offers, we blow up the text size by 100 and
|
||||
// measure it.
|
||||
// Luckily, text size affects rendering linearly, so we can do this trick.
|
||||
TextPaint paintCopy = new TextPaint(paint);
|
||||
paintCopy.setTextSize(paintCopy.getTextSize() * AMPLIFICATION_FACTOR);
|
||||
Rect capHeightBounds = new Rect();
|
||||
paintCopy.getTextBounds(
|
||||
CAP_HEIGHT_MEASUREMENT_TEXT, 0, CAP_HEIGHT_MEASUREMENT_TEXT.length(), capHeightBounds);
|
||||
double capHeight = capHeightBounds.height() / AMPLIFICATION_FACTOR / dm.density;
|
||||
Rect xHeightBounds = new Rect();
|
||||
paintCopy.getTextBounds(
|
||||
X_HEIGHT_MEASUREMENT_TEXT, 0, X_HEIGHT_MEASUREMENT_TEXT.length(), xHeightBounds);
|
||||
double xHeight = xHeightBounds.height() / AMPLIFICATION_FACTOR / dm.density;
|
||||
for (int i = 0; i < layout.getLineCount(); i++) {
|
||||
boolean endsWithNewLine = text.length() > 0 && text.charAt(layout.getLineEnd(i) - 1) == '\n';
|
||||
float lineWidth = endsWithNewLine ? layout.getLineMax(i) : layout.getLineWidth(i);
|
||||
Rect bounds = new Rect();
|
||||
layout.getLineBounds(i, bounds);
|
||||
WritableMap line = Arguments.createMap();
|
||||
line.putDouble("x", layout.getLineLeft(i) / dm.density);
|
||||
line.putDouble("y", bounds.top / dm.density);
|
||||
line.putDouble("width", lineWidth / dm.density);
|
||||
line.putDouble("height", bounds.height() / dm.density);
|
||||
line.putDouble("descender", layout.getLineDescent(i) / dm.density);
|
||||
line.putDouble("ascender", -layout.getLineAscent(i) / dm.density);
|
||||
line.putDouble("baseline", layout.getLineBaseline(i) / dm.density);
|
||||
line.putDouble("capHeight", capHeight);
|
||||
line.putDouble("xHeight", xHeight);
|
||||
line.putString(
|
||||
"text", text.subSequence(layout.getLineStart(i), layout.getLineEnd(i)).toString());
|
||||
lines.pushMap(line);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.views.text
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.text.Layout
|
||||
import android.text.TextPaint
|
||||
import com.facebook.react.bridge.Arguments
|
||||
import com.facebook.react.bridge.WritableArray
|
||||
|
||||
public object FontMetricsUtil {
|
||||
|
||||
private const val CAP_HEIGHT_MEASUREMENT_TEXT = "T"
|
||||
private const val X_HEIGHT_MEASUREMENT_TEXT = "x"
|
||||
private const val AMPLIFICATION_FACTOR = 100f
|
||||
|
||||
@JvmStatic
|
||||
public fun getFontMetrics(
|
||||
text: CharSequence,
|
||||
layout: Layout,
|
||||
paint: TextPaint,
|
||||
context: Context
|
||||
): WritableArray {
|
||||
val dm = context.resources.displayMetrics
|
||||
val lines = Arguments.createArray()
|
||||
|
||||
// To calculate xHeight and capHeight we have to render an "x" and "T" and manually measure
|
||||
// their height. In order to get more precision than Android offers, we blow up the text size by
|
||||
// 100 and
|
||||
// measure it. Luckily, text size affects rendering linearly, so we can do this trick.
|
||||
val paintCopy = TextPaint(paint).apply { textSize *= AMPLIFICATION_FACTOR }
|
||||
|
||||
val capHeightBounds = Rect()
|
||||
paintCopy.getTextBounds(
|
||||
CAP_HEIGHT_MEASUREMENT_TEXT, 0, CAP_HEIGHT_MEASUREMENT_TEXT.length, capHeightBounds)
|
||||
val capHeight = capHeightBounds.height() / AMPLIFICATION_FACTOR / dm.density
|
||||
|
||||
val xHeightBounds = Rect()
|
||||
paintCopy.getTextBounds(
|
||||
X_HEIGHT_MEASUREMENT_TEXT, 0, X_HEIGHT_MEASUREMENT_TEXT.length, xHeightBounds)
|
||||
val xHeight = xHeightBounds.height() / AMPLIFICATION_FACTOR / dm.density
|
||||
|
||||
for (i in 0 until layout.lineCount) {
|
||||
val endsWithNewLine = text.isNotEmpty() && text[layout.getLineEnd(i) - 1] == '\n'
|
||||
val lineWidth = if (endsWithNewLine) layout.getLineMax(i) else layout.getLineWidth(i)
|
||||
val bounds = Rect()
|
||||
layout.getLineBounds(i, bounds)
|
||||
val line =
|
||||
Arguments.createMap().apply {
|
||||
putDouble("x", (layout.getLineLeft(i) / dm.density).toDouble())
|
||||
putDouble("y", (bounds.top / dm.density).toDouble())
|
||||
putDouble("width", (lineWidth / dm.density).toDouble())
|
||||
putDouble("height", (bounds.height() / dm.density).toDouble())
|
||||
putDouble("descender", (layout.getLineDescent(i) / dm.density).toDouble())
|
||||
putDouble("ascender", (-layout.getLineAscent(i) / dm.density).toDouble())
|
||||
putDouble("baseline", (layout.getLineBaseline(i) / dm.density).toDouble())
|
||||
putDouble("capHeight", capHeight.toDouble())
|
||||
putDouble("xHeight", xHeight.toDouble())
|
||||
putString(
|
||||
"text", text.subSequence(layout.getLineStart(i), layout.getLineEnd(i)).toString())
|
||||
}
|
||||
lines.pushMap(line)
|
||||
}
|
||||
return lines
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user