@@ -231,8 +231,14 @@ void TextLayoutManager::GetTextLayout(
231
231
232
232
TextMeasurement::Attachments attachments;
233
233
if (paragraphAttributes.adjustsFontSizeToFit ) {
234
+ auto minimumFontScale = 0 .01f ;
235
+ // Uncomment below part when minimumFontScale is available in ParagraphAttributes
236
+ // if (paragraphAttributes.minimumFontScale && paragraphAttributes.minimumFontScale >= 0.01f &&
237
+ // paragraphAttributes.minimumFontScale <= 1.0f) {
238
+ // minimumFontScale = paragraphAttributes.minimumFontScale;
239
+ // }
234
240
GetTextLayoutByAdjustingFontSizeToFit (
235
- attributedStringBox, paragraphAttributes, layoutConstraints, spTextLayout, attachments);
241
+ attributedStringBox, paragraphAttributes, layoutConstraints, spTextLayout, attachments, minimumFontScale );
236
242
} else {
237
243
GetTextLayout (attributedStringBox, paragraphAttributes, layoutConstraints.maximumSize , spTextLayout, attachments);
238
244
}
@@ -243,52 +249,63 @@ void TextLayoutManager::GetTextLayoutByAdjustingFontSizeToFit(
243
249
const ParagraphAttributes ¶graphAttributes,
244
250
LayoutConstraints layoutConstraints,
245
251
winrt::com_ptr<IDWriteTextLayout> &spTextLayout,
246
- TextMeasurement::Attachments &attachments) noexcept {
252
+ TextMeasurement::Attachments &attachments,
253
+ float minimumFontScale) noexcept {
247
254
/* This function constructs a text layout from the given parameters.
248
255
If the generated text layout doesn't fit within the given layout constraints,
249
256
it will reduce the font size and construct a new text layout. This process will
250
257
be repeated until the text layout meets the constraints.*/
251
258
252
259
DWRITE_TEXT_METRICS metrics;
253
260
254
- // Better Approach should be implemented , this uses O(n)
255
- do {
256
- if (spTextLayout) // Font Size reduction
257
- {
258
- constexpr auto fontReduceFactor = 1 . 0f ;
259
-
260
- auto attributedStringToResize = attributedStringBox. getValue ();
261
+ // Better Approach should be implemented, this uses O(n)
262
+ constexpr auto fontReduceFactor = 1 . 0f ;
263
+ auto attributedStringToResize = attributedStringBox. getValue ();
264
+ auto fragmentsCopyToResize = attributedStringToResize. getFragments ();
265
+ if (fragmentsCopyToResize. empty ()) {
266
+ return ; // No fragments to process
267
+ }
261
268
262
- auto fragmentsCopyToResize = attributedStringToResize.getFragments ();
269
+ float initialFontSize = fragmentsCopyToResize[0 ].textAttributes .fontSize ;
270
+ float currentFontSize = initialFontSize;
263
271
264
- attributedStringToResize.getFragments ().clear ();
272
+ // Calculate the minimum font size as per Android/IOS
273
+ float minimumFontSize = std::max (minimumFontScale * initialFontSize, 4 .0f );
265
274
266
- for (auto fragment : fragmentsCopyToResize) {
267
- fragment.textAttributes .fontSize -= fontReduceFactor;
275
+ // Initial measurement
276
+ GetTextLayout (attributedStringBox, paragraphAttributes, layoutConstraints.maximumSize , spTextLayout, attachments);
277
+ if (spTextLayout) {
278
+ winrt::check_hresult (spTextLayout->GetMetrics (&metrics));
279
+ } else {
280
+ return ;
281
+ }
268
282
269
- attributedStringToResize.appendFragment (std::move (fragment));
270
- }
271
- attributedStringBox = facebook::react::AttributedStringBox (attributedStringToResize);
283
+ // Loop until the font size is reduced to the minimum or the layout fits
284
+ while ((currentFontSize > minimumFontSize) &&
285
+ ((paragraphAttributes.maximumNumberOfLines != 0 &&
286
+ paragraphAttributes.maximumNumberOfLines < static_cast <int >(metrics.lineCount )) ||
287
+ metrics.height > metrics.layoutHeight || metrics.width > metrics.layoutWidth )) {
288
+ // Reduce the font size by 1 point (or a configurable factor)
289
+ currentFontSize = std::max (currentFontSize - fontReduceFactor, minimumFontSize);
290
+
291
+ // Adjust font size for all fragments proportionally
292
+ attributedStringToResize.getFragments ().clear ();
293
+ for (auto fragment : fragmentsCopyToResize) {
294
+ fragment.textAttributes .fontSize =
295
+ std::max (fragment.textAttributes .fontSize * (currentFontSize / initialFontSize), minimumFontSize);
296
+ attributedStringToResize.appendFragment (std::move (fragment));
272
297
}
273
298
274
- GetTextLayout ( attributedStringBox, paragraphAttributes, layoutConstraints. maximumSize , spTextLayout, attachments );
299
+ attributedStringBox = facebook::react::AttributedStringBox (attributedStringToResize );
275
300
301
+ // Re-measure the text layout
302
+ GetTextLayout (attributedStringBox, paragraphAttributes, layoutConstraints.maximumSize , spTextLayout, attachments);
276
303
if (spTextLayout) {
277
- const auto defaultMinFontSize = 2 .0f ;
278
-
279
- // TODO : changes for minimumFontScale prop can be added.
280
-
281
- if (spTextLayout->GetFontSize () <= defaultMinFontSize) {
282
- break ; // reached minimum font size , so no more size reducing
283
- }
284
304
winrt::check_hresult (spTextLayout->GetMetrics (&metrics));
285
305
} else {
286
306
return ;
287
307
}
288
-
289
- } while ((paragraphAttributes.maximumNumberOfLines != 0 &&
290
- paragraphAttributes.maximumNumberOfLines < static_cast <int >(metrics.lineCount )) ||
291
- metrics.height > metrics.layoutHeight || metrics.width > metrics.layoutWidth );
308
+ }
292
309
}
293
310
294
311
// measure entire text (inluding attachments)
0 commit comments