UIFont的“point size”究竟是什么?

50

我很难理解UIFont中的点大小代表什么,它不是像素,并且似乎也不符合标准定义的点大小(即与1/72英寸有关)。

我使用-[NSString sizeWithFont:]测量了各种字号的字体的像素大小,得到了以下结果:

| Point Size | Pixel Size |
| ---------- | ---------- |
| 10.0       | 13.0       |
| 20.0       | 24.0       |
| 30.0       | 36.0       |
| 40.0       | 47.0       |
| 50.0       | 59.0       |
| 72.0       | 84.0       |
| 99.0       | 115.0      |
| 100.0      | 116.0      |

(我使用 [@"A" sizeWithFont:[UIFont systemFontOfSize:theSize]] 方法)

从72.0点大小来看,由于这是在一个DPI为163的设备上,因此1英寸不是72.0像素,而应该是163.0像素,对吗?

有人可以解释一下UIFont术语中的“点”是什么吗?也就是说,我的上述方法是错误的,如果我使用其他东西,我会看到字体在72点时是163像素吗?还是说点只是从其他地方定义的?


你已经检查过这个了吗:https://dev59.com/0nNA5IYBdhLWcg3wL6sc? - tiguero
如果你读了那个链接,就会明白为什么我期望上面表格中的72应该对应163像素。但实际不是这样的,相差太远了。 - mattjgalloway
我不理解你的论点;仅仅因为你使用72点字体测量字母“A”的大小(以像素为单位),只是表明它将占用大约半英寸的空间。你似乎假设字母“A”应该占据屏幕上的一英寸空间。 - trojanfoe
1
sizeWithFont: 中的像素高度包括上升和下降,因此它是整个行高的像素高度。另外,我的问题仍然存在 - 点大小与任何现实世界的关系是什么。再次注意,点大小和像素大小似乎没有任何明显的关系。 - mattjgalloway
1
重要提示... https://dev59.com/hFoT5IYBdhLWcg3wvRpk#38315462 - Fattie
5个回答

13

字体有一个内部坐标系,可以将其视为一个单位正方形,字形的向量坐标在其中指定,适合所有字体的任意大小+字体设计师选择的任意边距。

在72.0点处,字体的单位正方形为一英寸。 字体y的字形x与这个英寸正方形相对应的大小是任意的。因此,字体设计师可以使字体相对于其他字体看起来大或小。 这是字体的“特色”之一。

因此,以72点绘制“A”告诉您它的高度将是相同字体中以36点绘制“A”的两倍-除此之外没有关于实际位图大小的任何信息。

即,对于给定的字体,确定点大小和像素之间的关系的唯一方法是测量它。


3
所有的解释都很好,但并不是我所看到的。我注意到,字体大小翻倍并不会使像素大小翻倍,这与你所说的相反。此外,从我所看到的来看,测量的尺寸是整个行高,我假设这就是72点每1英寸中的1英寸指的是什么?在iPhone上,我所测量的是72点字体约为0.5英寸。 - mattjgalloway
1
我仍然不太明白你的意思。你说每英寸72点与行高无关,但是每英寸72点与什么有关呢?此外,请注意99.0的值 - 根据你的解释,你会期望它接近于10点乘以10的值,但实际上相差甚远。 - mattjgalloway
实际上,我添加了一个100.0点的大小,这也远远超出了10点乘以10的大小。 - mattjgalloway
正如我所说,72点/英寸与字体内部坐标系的转换有关。在72点时,1个字体单位(字体坐标系没有名称)等于72点。重要的是,无法从这些信息(我知道一个字体单位将是72点)中得知字形的像素大小 - 这完全取决于字体。你试过不同的字体吗?试试Geneva和Courier。 - hooleyhoop
啊,好的,现在更有意义了,谢谢。所以当渲染时,实际高度与物理高度没有关系,基本上点是另一种度量单位,它们与像素大小成比例(大约是抗锯齿),但比例只是系统相关的,并没有定义吗? - mattjgalloway
显示剩余8条评论

6

我不确定 -[NSString sizeWithFont:] 如何测量高度。它使用行高还是贝塞尔曲线峰值之间的差异?你使用了什么文本?

我认为 -[UIFont lineHeight] 更适合测量高度。

编辑: 此外,请注意,没有任何测量方法返回像素大小。它返回以 points 为单位的尺寸。您必须将结果乘以 [UIScreen mainScreen].scale

请注意,在构建字体时使用的 typographic points 和来自 iOS default logical coordinate spacepoints 之间的区别。不幸的是,文档中没有很清楚地解释这种差异。


lineHeight 也是以点为单位的,所以不幸的是与问题无关。我使用了文本 @"A"。但请记住,这也与问题无关。 - mattjgalloway
@mattjgalloway编辑了答案。有两个不同的单位,都被称为“点”。 - Sulthan
但这也不对,对吧?我知道屏幕比例中的点和像素之间的区别,但这与此有很大不同。请注意我的结果表 - 就我所看到的结果而言,比率趋向于1.16。这似乎是一个奇怪的比率。 - mattjgalloway
1
奇怪的是,我的结果的点数似乎大约为 pixels = ROUND((1 + points) * (115 / 99)) - mattjgalloway

4

我同意这很令人困惑。我试图在这里给你一些基本的解释,以使事情更清晰。

首先,DPI(每英寸点数)来自于打印在物理纸张上的技术。字体也是如此。点单位被发明出来来描述文本的物理打印大小,因为英寸对于通常的文本大小来说太大了。然后人们发明了点,即1/72英寸的长度(实际上在历史上演变而来),以便轻松地描述文本大小。所以,如果您正在使用Word或其他文字处理软件编写用于打印的文档,则使用72pt字体将获得绝对的一英寸高度文本。

其次,理论文本高度通常与您的眼睛实际可以看到的渲染笔画不同。原始的文本高度概念来自于用于打印的实际字形。所有字母都刻在字形块上,它们共享相同的高度 - 与字体点高度相匹配。但是,根据不同的字母和不同的字体设计,文本的实际可见部分可能比理论高度短一点。Helvetica Neue实际上非常标准。如果您测量字母“k”的顶部到字母“p”的底部,它将与字体高度相匹配。

第三,计算机显示器同时混淆了DPI和点的定义。计算机显示器的分辨率由其原生像素描述,例如1024 x 768或1920 x 1080。软件实际上不关心您的显示器的物理大小,因为如果它们像在纸张上打印一样缩放屏幕内容,所有内容都会非常模糊 - 物理分辨率不足以使一切平滑合法。软件使用一种非常简单和死板的方式:对于您使用的任何显示器,固定DPI。对于Windows,它是96DPI;对于Mac,它是72DPI。也就是说,无论您的显示器上有多少像素构成一英寸,软件都会忽略它。当操作系统在72pt中呈现文本时,在Windows上它始终为96px高,在Mac上为72px高。(这就是为什么Microsoft Word文档在Mac上看起来总是更小,通常需要将缩放比例设置为125%的原因。)

最后,在iOS上,情况非常类似,无论是iPhone、iPod touch、iPad还是Apple Watch,iOS都使用非Retina屏幕的固定72DPI,@2x Retina显示屏的144DPI,以及用于iPhone 6 Plus的@3x Retina显示屏的216DPI。

忘记真实的英寸。它只存在于实际打印中,而不是在显示中。对于在屏幕上显示文本的软件,它只是物理像素的人工比例。


3

我一开始想知道这是否与 [CSS像素被定义为每“英寸”96个][1],而UI布局点被定义为每“英寸”72个有关。 (当然,“英寸”与物理英寸无关。)为什么网络标准会影响UIKit业务呢?嗯,您可能会注意到,在调试器或崩溃报告中检查堆栈跟踪时,即使您没有使用 UIWebView,也有一些WebKit代码作为许多UIKit的基础。实际上,事情比那更简单。

首先,字体大小是从普通拉丁文文本的最低下行符到最高上行符进行测量的 - 例如从“j”的底部到“k”的顶部,或者为了方便在一个字符中进行测量,“ƒ”的高度。(这是U + 0192“带钩子的小写字母f”,可以在美国Mac键盘上使用选项F轻松输入。人们在很久以前用它来缩写“文件夹”。)您会注意到,使用该方案进行测量时,在像素高度(在1x显示器上)与指定的字体大小相匹配 - 例如,使用[UIFont systemFontOfSize:14],"ƒ"的高度将为14个像素。(测量大写字母“A”仅占字体大小中的任意一部分空间。在较小的字体大小下,这部分可能会发生变化;当将字体矢量呈现为像素时,“提示”会修改结果以产生更可读的屏幕文本。)

但是,字体包含各种不适合该指标定义的空间的字形。有带有东欧语言中上行符上方的变音符号的字母,还有各种标点符号和特殊字符,它们都适合于“布局框”,其尺寸要大得多。 (在Mac OS X的特殊字符窗口中查看数学符号部分,可以找到很多例子。)

-[NSString sizeWithFont:] 返回的CGSize中,宽度考虑了字符串中的具体字符,但高度仅反映了行数。行高是由字体指定的度量,与囊括字体最大字符的“布局框”相关。


好的,解释得非常好。但是我仍然不太理解 UIFont 中的“点”是什么。当屏幕上显示时,哪个字体大小的哪一部分将衡量特定的大小?不过,我喜欢 ƒ 的想法。我会试着用一下! - mattjgalloway
我在72.0点尝试了一个ƒ,但它的高度不是72.0像素。这只是一个在14处起作用然后发散的魔数吗?问题仍然存在 - “什么是点”。 - mattjgalloway
UIFont 中,点与 UIKit 几何中的其他点相同。它如何对应于呈现的文本是可变的。字体的“点大小”设置了一个边界高度,通常与字形的上升和下降高度相关联(以及总行高的子范围,其中一些可能被其他字形使用)。然而,字体设计师可以在该几何结构内做任何他们想做的事情,因此字形大小可能不匹配点大小,并且行高始终会比点大小略高(并且应该在给定字体内保持一致)。 - rickster
感谢您的这篇文章;您可能会对这个问题感兴趣.. https://dev59.com/hFoT5IYBdhLWcg3wvRpk @rickster - Fattie

0
据我所知,事实是UIFont在撒谎。所有的UIKit都对字体进行了修改。如果你想要真相,你需要使用CoreText,但在很多情况下它会更慢!(所以在像素高度表的情况下,我认为它添加了一些+bx因子,其中x是点大小。)
那么为什么会这样呢?速度!UIKit四舍五入并调整间距,以便可以缓存位图。或者至少这是我的理解!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接