即使同一行上有可用空间,CTFramesetterSuggestFrameSizeWithConstraints 也会换行

如何解决即使同一行上有可用空间,CTFramesetterSuggestFrameSizeWithConstraints 也会换行

我们正在尝试使用 Core Text API CTFramesetterSuggestFrameSizeWithConstraints 获取建议的帧大小。

让,E = \uFFFC ; W = \u200B ; S = \u00A0

CTFrameSetter 是使用以下属性字符串创建的:

WSESWWSESW

字符 S 和 E 被赋予 CTRunDelegates,它们具有 CTRunDelegateGetWidthCallback,分别返回 0100 .

执行以下代码时:

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);

API 返回的 pathSize 为 100,我们得到两个单独的行

然后我们使用以下代码创建 CTFrameRef:

auto rect = CGRectMake(0,200,pathSize.height);
auto path = CGPathCreateWithRect(rect,nil));
auto frame = CTFramesetterCreateFrame(framesetter_.get(),path,(CFDictionaryRef)frameOptions));

问题

  1. 为什么 CTFramesetterSuggestFrameSizeWithConstraints 返回一个宽度为 100 的 pathSize,而显然约束宽度 (200) 应该足以容纳一行中的整个文本。

  2. CoreText 如何决定在一次运行中应将属性字符串中的哪些字形/字符范围放在一起? 在上面的例子中,我们得到以下两行:

第 1 行:W S E SWW (4 CTTextRun)

第 2 行:S E SW (3 CTTextRun)

有人可以帮我回答与上述场景相关的这两个问题吗?提前致谢!

编辑 1:

为问题和我们当前的方法添加更多上下文: Image reference

“Parent”、“Child1”、“Child2”请参考上图。

“Parent”代表我们想要布局和计算尺寸的框/矩形。我们想把文本放在“父”框中。 “Child1”、“Child2”在我们的文本中由“E”字符表示。

  1. 首先,我们尝试计算“父”框的大小。
  2. 我们使用“父”框的计算大小作为
    的约束 CTFramesetterSuggestFrameSizeWithConstraints,然后使用其返回值创建CTFrame

大小计算 :“父”框的大小计算取决于多种因素 - 可能有一个指定的大小作为外部参数,或者它可能来自它的容器框,或者可能相等到足以适合其文本内容的大小(由一些最小,最大限制)。 因此,它并不总是不受约束(单行),有时甚至不依赖于文本内容

让我们看一下计算依赖于文本内容的情况:

因此我们使用以下方法计算没有任何约束的文本的宽度:

CTFramesetterSuggestFrameSizeWithConstraints(framesetter_.get(),CGSizeMake(CGFLOAT_MAX,CGFLOAT_MAX),&fitRange); 

这将返回 100 (child1) + 100 (child2) = 200 pts 的值。假设我们有足够的空间,200 pts 是“父”框的大小。

文本布局:此时,我们只有“父”框的计算大小,没有关于它是如何计算的信息。

如果现在我们使用 200 pts 的约束和 CTFramesetterSuggestFrameSizeWithConstraints,它会返回 100pts 并将文本分成两行。

这就是我们遇到的问题 - 用于创建 CTFrame 时不受约束的文本大小会导致意外的换行。

解决方法

对于您的第一个问题,正如评论中所讨论的那样,因为 CTFramesetter 具有各种可能添加填充或进行字形调整的规则。这取决于很多事情(并且不承诺随着时间的推移保持一致),因此您无法猜测。只需询问 CTFramesetter(或 CTLine)尺寸是多少,并相应地调整您的布局。或者,如果您有一个硬约束(这必须适合 100 分),然后设置它,它会换行。但是,如果您说“嗯,101 分也可以”,那么 100 分就不是限制条件。让你的约束成为实际的约束,或者让它不受约束(在这种情况下你可能想要 CTLine,而不是 CTFramesetter)。

对于第二个问题,CTRun 是一个附加了所有相同属性值的范围。 NSAttributedString 对此很聪明,即使您以重叠方式设置属性,也可以将等效的相邻区域合并在一起。然而,它并不承诺总是这样做。连续的 CTRun 对象具有相同的属性是合法的。当以复杂的方式应用属性或将属性字符串连接在一起时,就会发生这种情况。

如果您检查 NSAttributedString 的属性,您会发现第一个和第二个字符、第二个和第三个字符之间可能存在一些差异,然后字符 4-6 具有完全相同的属性。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?