We are trying to get the suggested frame size using the Core Text API CTFramesetterSuggestFrameSizeWithConstraints.
Let, E = uFFFC ; W = u200B ; S = u00A0
The CTFrameSetter is created with the following attributed string:
WSESWWSESW
The character S and E are given CTRunDelegates which have the CTRunDelegateGetWidthCallback that return 0 and say 100 respectively.
When the following code is executed :
auto frameOptions = @{ (id)kCTFrameProgressionAttributeName: @(kCTFrameProgressionTopToBottom)) };
auto constraintSize = CGSizeMake(200, CGFLOAT_MAX);
CFRange fitRange = CFRangeMake(0, 0);
auto pathSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter_.get(), CFRangeMake(0, 0),(CFDictionaryRef)frameOptions, constraintSize, &fitRange);
The pathSize returned by the API comes out to 100 and we get two separate lines
We then create the CTFrameRef using the following piece of code:
auto rect = CGRectMake(0, 0, 200, pathSize.height);
auto path = CGPathCreateWithRect(rect, nil));
auto frame = CTFramesetterCreateFrame(framesetter_.get(),
CFRangeMake(0, 0), path, (CFDictionaryRef)frameOptions));
Question:
Why does the CTFramesetterSuggestFrameSizeWithConstraints return a pathSize which has a width of 100 when clearly the constraint width (200) should be sufficient to accommodate the entire text in a single line.
How does CoreText decide which glyps/character range from attributed string should be put together in a single run?
In the above example we get the following two lines :
Line 1: W S E SWW (4 CTTextRun)
Line 2: S E SW (3 CTTextRun)
Can somebody please help me with answers to these two questions related to the abovementioned scenario. Thanks in advance!
Edit 1:
Adding some more context to the problem and our current approach:
Image reference
Please refer to the image above for reference to "Parent", "Child1", "Child2".
"Parent" represents the box/rect that we want to layout and compute sizes for. We want to put the text in the "Parent" box. "Child1", "Child2" are represented by 'E' characters in our text.
- First, we try to compute the size for the "Parent" box.
- We use the computed size of the "Parent" box as constraints for the
CTFramesetterSuggestFrameSizeWithConstraints and then use its return value to create CTFrame
Size Computation : The size computation of "Parent" box depends of multiple factors - there could be a specified size as a external parameter, or it could come from its container box, or could be equal to the size (clamped by some min, max) enough to fit its text content.
So, it is not always unconstrained (single line) or, sometimes even not dependent on the text content.
Let's look at the case when the computation is dependent on the text content:
So we calculate the width of the text without any constraints using:
CTFramesetterSuggestFrameSizeWithConstraints(framesetter_.get(), CFRangeMake(0, 0),
(CFDictionaryRef)frameOptions, CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX), &fitRange);
This returns the value of 100 (child1) + 100 (child2) = 200 pts exactly. Let say we have enough space and 200 pts is what is set as the size of the "Parent" box.
Text Layout : At this point, we only have the computed size of the "Parent" Box and no information on how it was calculated.
If now we now use the constraints of 200 pts with CTFramesetterSuggestFrameSizeWithConstraints, it returns 100pts and breaks the text in two lines.
This is where we have a problem - the unconstrained text size when used to create CTFrame gives an unexpected line break.
question from:
https://stackoverflow.com/questions/65945071/ctframesettersuggestframesizewithconstraints-line-breaks-even-when-there-is-spac