react-native-advanced-text 0.2.4 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -25,7 +25,6 @@ import com.facebook.react.uimanager.events.RCTEventEmitter
25
25
  import android.text.Selection
26
26
  import android.graphics.Typeface
27
27
  import androidx.core.text.getSpans
28
- import com.facebook.react.common.assets.ReactFontManager
29
28
 
30
29
  class AdvancedTextView : TextView {
31
30
 
@@ -164,25 +163,9 @@ class AdvancedTextView : TextView {
164
163
  fun setAdvancedFontFamily(family: String) {
165
164
  if (fontFamily == family) return
166
165
  fontFamily = family
167
- typeface = resolveTypeface(family, Typeface.NORMAL)
166
+ typeface = Typeface.create(family, Typeface.NORMAL)
168
167
  }
169
168
 
170
- /**
171
- * `Typeface.create(family, style)` only resolves OS-registered families; it
172
- * silently substitutes a system font for anything bundled under
173
- * `assets/fonts/` (the RN/Expo custom-font pipeline) instead of failing.
174
- * The Fabric ShadowNode measures this component's text via
175
- * `TextLayoutManager`, which resolves fonts through `ReactFontManager` -
176
- * so a custom font here rendered with the substituted typeface has
177
- * different glyph widths than what was measured, wrapping onto a
178
- * different number of lines and producing extra height for some strings
179
- * but not others. Going through `ReactFontManager` keeps the rendered
180
- * typeface identical to the measured one (and is a no-op for system font
181
- * names, which it falls back to `Typeface.create` for anyway).
182
- */
183
- private fun resolveTypeface(family: String, style: Int): Typeface =
184
- ReactFontManager.getInstance().getTypeface(family, style, context.assets)
185
-
186
169
  fun setMenuOptions(menuOptions: List<String>) {
187
170
  if (this.menuOptions == menuOptions) return
188
171
  this.menuOptions = menuOptions
@@ -288,9 +271,9 @@ class AdvancedTextView : TextView {
288
271
  setTextSize(fontSize)
289
272
 
290
273
  typeface = when (fontWeight) {
291
- "bold" -> resolveTypeface(fontFamily, Typeface.BOLD)
292
- "italic" -> resolveTypeface(fontFamily, Typeface.ITALIC)
293
- else -> resolveTypeface(fontFamily, Typeface.NORMAL)
274
+ "bold" -> Typeface.create(fontFamily, Typeface.BOLD)
275
+ "italic" -> Typeface.create(fontFamily, Typeface.ITALIC)
276
+ else -> Typeface.create(fontFamily, Typeface.NORMAL)
294
277
  }
295
278
 
296
279
 
@@ -11,7 +11,6 @@
11
11
 
12
12
  #include <algorithm>
13
13
  #include <cctype>
14
- #include <limits>
15
14
  #include <string>
16
15
 
17
16
  #include <react/renderer/attributedstring/AttributedStringBox.h>
@@ -33,10 +32,6 @@ std::string toLowerAscii(std::string value) {
33
32
  return value;
34
33
  }
35
34
 
36
- // Fallback only: an approximate ratio of a single line's natural height to
37
- // its font size, used if a real measurement (Android) isn't available/valid.
38
- constexpr Float kLineHeightFudgeFactor = 1.2;
39
-
40
35
  } // namespace
41
36
 
42
37
  AdvancedTextViewShadowNode::AdvancedTextViewShadowNode(
@@ -47,47 +42,7 @@ AdvancedTextViewShadowNode::AdvancedTextViewShadowNode(
47
42
  static_cast<const AdvancedTextViewShadowNode&>(sourceShadowNode)
48
43
  .textLayoutManager_) {}
49
44
 
50
- #if defined(ANDROID)
51
- Float AdvancedTextViewShadowNode::measureNaturalSingleLineHeight(
52
- const LayoutContext& layoutContext,
53
- const TextAttributes& baseTextAttributes) const {
54
- // Same font/size/weight/style as the real fragment, but with `lineHeight`
55
- // cleared so this reports the font's own, unscaled single-line height --
56
- // exactly what Android's `setLineSpacing(0, multiplier)` multiplies.
57
- auto probeAttributes = baseTextAttributes;
58
- probeAttributes.lineHeight = std::numeric_limits<Float>::quiet_NaN();
59
-
60
- auto probe = AttributedString{};
61
- probe.appendFragment(AttributedString::Fragment{
62
- .string = "M",
63
- .textAttributes = probeAttributes,
64
- .parentShadowView = ShadowView(*this),
65
- });
66
-
67
- auto paragraphAttributes = ParagraphAttributes{};
68
-
69
- auto textLayoutContext = TextLayoutContext{};
70
- textLayoutContext.pointScaleFactor = layoutContext.pointScaleFactor;
71
- textLayoutContext.surfaceId = getSurfaceId();
72
-
73
- // Unconstrained so a single glyph can never be forced to wrap.
74
- auto unconstrainedLayoutConstraints = LayoutConstraints{
75
- {0, 0},
76
- {std::numeric_limits<Float>::infinity(),
77
- std::numeric_limits<Float>::infinity()}};
78
-
79
- auto measurement = textLayoutManager_->measure(
80
- AttributedStringBox{probe},
81
- paragraphAttributes,
82
- textLayoutContext,
83
- unconstrainedLayoutConstraints);
84
-
85
- return measurement.size.height;
86
- }
87
- #endif
88
-
89
- AttributedString AdvancedTextViewShadowNode::getAttributedString(
90
- const LayoutContext& layoutContext) const {
45
+ AttributedString AdvancedTextViewShadowNode::getAttributedString() const {
91
46
  const auto& props = getConcreteProps();
92
47
 
93
48
  auto textAttributes = TextAttributes::defaultTextAttributes();
@@ -113,32 +68,13 @@ AttributedString AdvancedTextViewShadowNode::getAttributedString(
113
68
  textAttributes.letterSpacing = props.letterSpacing;
114
69
  }
115
70
 
116
- // The component treats `lineHeight` as a multiple of the font's own
117
- // natural line height (see setLineSpacing(0, multiplier) in
118
- // AdvancedTextView.kt / the NSParagraphStyle-based spacing in
119
- // AdvancedTextView.mm) -- NOT the absolute per-line value
120
- // `TextAttributes.lineHeight` expects. A multiplier of 1 *is* the natural
121
- // line height, so there is nothing to override in that case (and
122
- // overriding it with an approximation, as this used to do unconditionally,
123
- // made even the "no lineHeight override" case measure taller or shorter
124
- // than the real render).
125
- if (props.lineHeight > 0 && props.lineHeight != 1.0) {
126
- #if defined(ANDROID)
127
- // Android's natural single-line height depends on the resolved
128
- // font/size/weight and isn't a fixed ratio of fontSize, so a constant
129
- // approximation drifts from AdvancedTextView.kt's real
130
- // setLineSpacing()-based layout by an amount that compounds with every
131
- // wrapped line -- which is why the error scaled with paragraph length.
132
- // Measure the real natural height for these exact attributes instead.
133
- auto naturalLineHeight =
134
- measureNaturalSingleLineHeight(layoutContext, textAttributes);
135
- textAttributes.lineHeight = naturalLineHeight > 0
136
- ? props.lineHeight * naturalLineHeight
137
- : props.lineHeight * textAttributes.fontSize * kLineHeightFudgeFactor;
138
- #else
71
+ if (props.lineHeight > 0) {
72
+ // The component treats `lineHeight` as a multiple of the font size
73
+ // (see AdvancedTextView.mm / AdvancedTextView.kt). `TextAttributes`
74
+ // expects an absolute value; approximate the platform default single
75
+ // line height as 1.2 * fontSize.
139
76
  textAttributes.lineHeight =
140
- props.lineHeight * textAttributes.fontSize * kLineHeightFudgeFactor;
141
- #endif
77
+ props.lineHeight * textAttributes.fontSize * 1.2;
142
78
  }
143
79
 
144
80
  auto attributedString = AttributedString{};
@@ -173,7 +109,7 @@ Size AdvancedTextViewShadowNode::measureContent(
173
109
  textLayoutContext.surfaceId = getSurfaceId();
174
110
 
175
111
  auto measurement = textLayoutManager_->measure(
176
- AttributedStringBox{getAttributedString(layoutContext)},
112
+ AttributedStringBox{getAttributedString()},
177
113
  paragraphAttributes,
178
114
  textLayoutContext,
179
115
  layoutConstraints);
@@ -86,20 +86,7 @@ class AdvancedTextViewShadowNode final : public ConcreteViewShadowNode<
86
86
  * Builds a single-fragment `AttributedString` from the component props
87
87
  * (text + font attributes), mirroring how the native views render it.
88
88
  */
89
- AttributedString getAttributedString(const LayoutContext& layoutContext) const;
90
-
91
- #if defined(ANDROID)
92
- /*
93
- * Measures the natural (multiplier == 1) height of a single line set in
94
- * `baseTextAttributes`, by measuring a single glyph with `lineHeight`
95
- * cleared. Used to turn the component's `lineHeight` multiplier prop into
96
- * the absolute value `TextAttributes.lineHeight` expects, using this
97
- * font's *real* metrics instead of an approximation.
98
- */
99
- Float measureNaturalSingleLineHeight(
100
- const LayoutContext& layoutContext,
101
- const TextAttributes& baseTextAttributes) const;
102
- #endif
89
+ AttributedString getAttributedString() const;
103
90
 
104
91
  // Lazily created on first measure, then reused / copied across clones.
105
92
  mutable std::shared_ptr<const TextLayoutManager> textLayoutManager_;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-advanced-text",
3
- "version": "0.2.4",
3
+ "version": "0.2.7",
4
4
  "description": " Advanced text component for React Native with custom select options.",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",