热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

macOSRetina显示屏上OpenJDK11Swing等宽字体渲染问题的解决方案

本文探讨了在macOSRetina显示屏上使用OpenJDK11开发代码编辑器时遇到的等宽字体渲染问题,并提供了详细的分析和可能的解决方案。

在开发一个代码编辑器时,我遇到了一个仅在 macOS Retina 显示屏上使用 OpenJDK 11 时出现的等宽字体渲染问题。以下是两个屏幕截图的对比,顶部是使用 OpenJDK 11(版本 11.0.5 HotSpot),底部是使用 JDK 8(可能是 Apple / Oracle JDK 8):

macOS Retina 显示屏上 OpenJDK 11 Swing 等宽字体渲染问题

从图中可以看出,OpenJDK 11 渲染的字体比 JDK 8 更宽。这是一个严重的问题,因为我在计算等宽列的宽度时使用了 FontRenderContext#getStringBounds 方法。使用默认的等宽字体(看起来像是 Menlo)和字体大小 14,每个字符的宽度应该是 8 像素,这在 JDK 8 上是正确的,但在 OpenJDK 11 上却变成了 8.5 像素。例如,第一行非注释行包含 38 个字符,在 JDK 8 上需要 38 * 8 * 2 = 608 像素,但在 OpenJDK 11 上则需要约 646 像素。

更奇怪的是,这个问题似乎是由使用 AttributedText 渲染 Graphics2D#drawString 实例引起的。如果我改为使用纯文本并调用 g.setFont,OpenJDK 11 的渲染结果与 JDK 8 完全一致。因此,问题可能出在渲染 AttributedCharacterIterator 的特定实现上。

为了找到解决方案,我进行了进一步的调试。我发现差异出现在 ExtendedTextSourceLabel#createGV 和更深层次的 SunLayoutEngine#layout 调用中,最终调用了本机代码。虽然字体描述符相同,但在 JDK 8 中,字形数据中的 _positions 被设置为整数值,而在 OpenJDK 11 中,它们被设置为小数值(且不一定是 0.5 的倍数),这表明问题可能与 macOS 本机字体支持有关。

此外,我还发现这个问题取决于字体大小,而不仅仅是字体是否“本机”或捆绑在一起。例如,使用类路径上的 Inconsolata.ttf 字体,当字体大小为 32 时:

enter image description here

此时,根据 FontRenderContext#getStringBounds 计算的字体进度为 17.0(通过灰色矩形可视化),但实际渲染略窄。当字体大小为 33 时:

enter image description here

这进一步证实了问题的复杂性。目前,我正在寻找一种不改变整个实现的解决方案,比如通过设置某些系统属性来解决问题。如果您有任何建议或遇到类似问题,请分享您的经验。


推荐阅读
author-avatar
晓志1998_809
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有