size = {200, 50};
style = {FontColor -> Black, FontSize -> Automatic,
TextAlignment -> Left, LineIndentMaxFraction -> 0};
img = ConstantImage[LightYellow, size];
text = ResourceFunction["RandomText"][#] & /@ {1, 3, 5, 10};
First[If[
Rasterize[
p =
Pane[Style[#, FontSize -> #2, Sequence @@ style], size/2,
ImageSize -> {size[[1]]/2, Automatic}],
"RasterSize"][[2]] <= ImageDimensions[img][[2]], {#2,
Overlay[{ImageResize[img, size/2], p}]}, Nothing] & @@@
Thread[{#, Table[i, {i, 20, 4, -0.5}]}]] & /@ text

Response from OP:
So this is a great start but a few things before I accept:
- Not always is the maximal value being computed (see below). There should be no margin space between the glyph and rectangle edge.
- Handle any font family and font styling.
- Should work for any length text, even single characters, so the search should start from a much high number (I put 70 below) and so it needs to be much faster.
Improved test example generator:
size = {300, 120};
style = {FontColor -> Black, FontWeight -> RandomChoice[{Bold,Plain}], FontSlant -> RandomChoice[{Plain,Italic}] , FontSize -> Automatic, FontFamily->RandomChoice[$FontFamilies],
TextAlignment -> Center};
text = ResourceFunction["RandomText"][#] & /@ {1, 3, 5, 10};
{Slider2D[Dynamic@size,{{100,50},{500,200},{10,10}},ImageSize->{100,50}],Dynamic[size]}
img = ConstantImage[Green, size];
AbsoluteTiming@First[If[
Rasterize[
p =
Pane[Style[#, FontSize -> #2, Sequence @@ style], size/2,
ImageSize -> {size[[1]]/2, Automatic}(FrameMargins->{0,0})],
"RasterSize"][[2]] <= ImageDimensions[img][[2]], {#2,
Overlay[{ImageResize[img, size/2], p}]}, Nothing] & @@@
Thread[{#, Table[i, {i, 70, 4, -.5}]}]] & /@ text
Running this gives many examples, the first one I tried didn't choose a maximal size to fill the rect exactly: see the word "pottage" below, the loop gave 42, but 44 works too as you can see.

==========================================
Thank you for your comments. Here is a much faster version using a precision of 0.25 points. Italics are a pain sometimes. I also played with the alignment of the overlay itself. This version picks one random text (between 1 and 10 words) every time.
fitText[] :=
Module[{fontSizes, size, style, text, lowVal, hiVal, lastTrials,
escape, possibilities, trialIndex, trialFont, result, img},
fontSizes = Table[i, {i, 4, 70, .25}];
size = {300, 120};
img = ConstantImage[Green, size];
style = {FontColor -> Black,
FontWeight -> RandomChoice[{Bold, Plain}],
FontSlant -> RandomChoice[{Plain, Italic}], FontSize -> Automatic,
FontFamily -> RandomChoice[$FontFamilies],
TextAlignment -> Center};
text = ResourceFunction["RandomText"][RandomChoice[Range[1, 10]]];
lowVal = 1;
hiVal = Length[fontSizes];
lastTrials = {};
escape = False;
Do[
possibilities = hiVal + lowVal - 1;
trialIndex = Ceiling[possibilities/2.];
trialFont = fontSizes[[trialIndex]];
If[MemberQ[lastTrials, trialFont], escape = True];
AppendTo[lastTrials, trialFont];
result =
If[Rasterize[
p =
Pane[Style[text, FontSize -> trialFont, Sequence @@ style],
size/2, ImageSize -> {size[[1]]/2, Automatic}],
"RasterSize"][[2]] <= ImageDimensions[img][[2]], True,
False];
If[result, lowVal = trialIndex + 1, hiVal = trialIndex - 1];
If[escape, Break[]];
, 100];
{trialFont,
Overlay[{ImageResize[img, size/2], p},
Alignment -> {Center, Center}]}
]
Here is the result of calling Table[fitText[], 30]

Final Response from OP:
That is an improvement! I'm still seeing many cases like this where the font could easily be bigger:

The results should all be "tighter fits" and have less marginal space (e.g. look like the pink boxes I drew).
DiscretizeGraphics[Text[...]]in thetext3Ddiscussion give you some ideas? Here: https://mathematica.stackexchange.com/questions/131798/placing-text-in-3d-not-facing-viewer – Nicholas G Apr 26 '22 at 23:55Overlay[{img, Pane[Style[#, FontColor -> Black, TextAlignment -> Left, LineIndentMaxFraction -> 0], size/2, ImageSizeAction -> "ResizeToFit"]}] & /@ text? – kglr Apr 27 '22 at 05:21