@@ -585,15 +585,30 @@ private static DocumentTextStyle resolveAutoSizeTextStyle(ParagraphNode node,
585585 double minSize = autoSize .minSize ();
586586 double step = Math .max (0.1 , autoSize .step ());
587587
588- // Single-line text: shrink the font size until the longest logical line
589- // measures inside the available inner width, otherwise fall back to the
590- // smallest configured size.
591- for (double size = maxSize ; size >= minSize - 1e-6 ; size -= step ) {
592- DocumentTextStyle candidate = baseStyle .withSize (size );
588+ // Single-line text: pick the largest grid size (maxSize, maxSize-step, …,
589+ // down to >= minSize) whose longest logical line measures inside the
590+ // available inner width, otherwise fall back to the smallest configured
591+ // size. The fit predicate is monotonic in size (line width is linear in
592+ // size), so binary-search the grid for the boundary instead of measuring
593+ // at every step — the same size the linear scan returned, in ~log2(n)
594+ // measurements rather than n.
595+ int maxStepCount = (int ) Math .floor ((maxSize - minSize + 1e-6 ) / step );
596+ int lo = 0 ;
597+ int hi = maxStepCount ;
598+ int fitStep = -1 ;
599+ while (lo <= hi ) {
600+ int mid = (lo + hi ) >>> 1 ;
601+ DocumentTextStyle candidate = baseStyle .withSize (maxSize - mid * step );
593602 if (paragraphFitsSingleLine (node , candidate , innerWidth , measurement )) {
594- return candidate ;
603+ fitStep = mid ; // fits — try a larger size (fewer steps down)
604+ hi = mid - 1 ;
605+ } else {
606+ lo = mid + 1 ; // too wide — need a smaller size (more steps)
595607 }
596608 }
609+ if (fitStep >= 0 ) {
610+ return baseStyle .withSize (maxSize - fitStep * step );
611+ }
597612 return baseStyle .withSize (minSize );
598613 }
599614
0 commit comments