Category Archives: Linux
上下跳动的文字
我觉得我自从手搓几个low-level的文本绘制之后这个问题其实已经变成专家了。问题本身其实还是很有趣的,这里特别总结一下。 不少人可能都注意到了 Linux 下面有时候会有一种奇怪的现象,就是你输入文字的时候,一旦输入了汉字,汉字可能会把整行文字的位置降低。删除掉汉字的时候,则又会恢复到原本。这是为什么呢? 其实道理是很简单的,就是你这一行文字混合了两种不同的字体。为什么明明没有单独配置但是却使用了不同的字体?因为系统默认使用的英文字体本身,可能并不包含汉字。因此当需要显示汉字(或者其他任何不存在于这个字体的字符)时,就只能回落(fallback)到另外的字体上。你也许注意到了,即使两种字体配置为同一个大小(point),但是实际显示在屏幕上的大小可能是不同的。当两个字体同时在一行文本中使用的时候,为了将他们对齐,则需要使用一个标准将两个字体的文本对齐。这个标准就是基线(baseline)。 这里还有两个重要的线 ascent 和 descent。ascent 就是从 baseline 到字体的最高点,descent 就是 baseline 到字体的最低点。可以假想一下,当另一个字体混入的时候,如果它的 ascent 高于原本字体的 ascent,自然就需要将文本整体“下推”。 通过辅助线,我们可以明显观察到 DejaVu 和中文字体组合之后可以出现明显的下沉现象。 对于编辑器来说,只有两种方式,一种允许每行的高度不同,从而适配文字本身的大小, 另一种则是每行高度相同,但带来的副作用可能是会对 fallback 到的较高的字体砍头去尾。 这里有一个展示了 katepart 曾经长时间存在的文字渲染问题,当字体可能下推文本过多时,超过了原本的行高,则不得不砍掉了一些。右侧是经过我修复之后的 katepart。 这里所谓的修复是什么呢?其实非常的简单,就是把“下推”的文字拉回原本只有单个字体的基线位置。简单的来说,就是进行这样的运算:在 y 轴上偏移一个这样的数值:(渲染文本的整体 ascent – 字体本身的 ascent)。 这样运算之后,那些并非 fallback 的字符将不会被「下推」,而保持在原始的位置。fallback 到其他字体的字符则会对应的上拉一些位置。你可能会问了,这样似乎并没有解决字体被砍头的问题啊?确实,但字体设计的时候,一般会在顶部留有余地不会紧密排列,经过这样调整之后,反而会让大部分即使是 … Continue reading
Linux 的 HiDPI 配置问题
其实这个问题对我来说从来也不是个问题,因为我已经基本深入理解了这个问题的本质……然而似乎有不少人对于怎么配置,为什么这么配置,为什么又出了问题一知半解,因为最近在 Twitter 上回复一些比较复杂的内容,特此整理记录一下。 在过去,电脑的屏幕一般都是 96 DPI,DPI 的含义是每英寸点数(像素点),具体计算的方法也非常简单,用像素的个数除以屏幕的长宽即可。随着技术发展(显示器和处理器),电脑逐渐可以支持更高的 DPI 用于显示。抛开具体发展不提,但是这里引入了一个问题,你程序并不支持在这样的屏幕上正常显示。通常来说的问题就是界面特别小。 为什么? 因为程序过去从来也不需要考虑这个问题,都是按照像素来进行的设计,例如显示一个 100 x 100 的窗口,在 96 DPI 上大小正常,但是 DPI 翻倍的话,就只有原来的 1/4 大。人的眼睛在乎的是它现实中有多大(像素 / DPI = 长度),而不是有多少像素点。为了让程序能够正常显示,同时又不需要修改太多代码,大家也是努力想了很多办法。 1、设置字体大小。 界面框架大小不提,字看不清那是最难受的,因此只调整字体大小这样的设置,成为了大部分人解决问题的第一步。但是,在 X 上,这个设置是全局的,因此也就不能针对不同的屏幕,来设置一个统一的 DPI。一个屏幕大一个屏幕小也可以说是常态了,不少人就选择设置一个居中的值来自己适应。毕竟人是活的,程序是死的,改变不了世界那就只好自己适应世界。 2、程序来支持内部缩放。 这里,当然也就是 Qt / Gtk 这样的大框架才有精力和能力去支持这种功能。这个功能在程序不需要进行额外修改,或者只进行少量修改的前提下,直接在内部添加坐标的转换功能,乘以一个倍数,变相将程序放大。这样,在高分辨率的前提下,就可以用正常的大小显示界面。 3、设置分辨率来进行缩放 也许有人说,显示器不都可以配置分辨率么?你3200×1800的屏幕,我强行设置 1600×900 … Continue reading
仿原神 UI 的 KDE 系统配色
原神痴竟是我自己 下载地址:https://uploads.csslayer.info/uploads/Genshin.colors
QML 的 Repeater 和 Loader 组合使用问题
Repeater,在对于需要生成多个 Item,但又不适合 ListView 的情况是很适用的。对于 Repeater 需要嵌套不同种类的 Delegate 的情况,有一些不同的解决方案。 例如,你针对不同的数据需要生成不同的 Item A 或者 Item B,那么一种选择就是把他们都作为子 Item 放到 Delegate 里面,然后选择性的进行 visible 的设置,来达到只现实一个的目的。这样带来的缺点也是显而易见的: 需要真的实际创建多个并不使用的 Item 对不同的 Item 设置值的时候,可能并不一定会有适合当前不显示的这个 Item 的值。例如,某项属性并不见于 Type B中,在实现的时候却不得不放进一个 dummy value 来避免程序错误。 而另一种选择就是,会选择 Repeater 嵌套一个 Loader ,用 loader 来动态的选择加载某个源文件,或者 Component,通过使用 … Continue reading
Job DSL vs Pipeline in Jenkins
我自己的 CI 长久以来都是手动配置 Free-Style Project,有很多重复的部分很不方便统一修改。所以就打算搞得比较自动化一点方便批量修改任务,一开始是想用什么 Template 之类,但是后来就发现了 Job DSL 和 Pipeline。 姑且来说,这两个解决的问题有重合的部分,但是也有不一样的地方。Pipeline 基本就是用一个 Groovy 的子集(还是相似的东西?),来描述一个 Job,支持的功能比较多。而 Job DSL 是用 Groovy 的一个脚本来生成 Job。实践当中你可以两个都用。 Pipeline 最基本的用法就是在代码库里面放一个 Jenkinsfile,里面描述 pipeline。当然这么做是有缺点的,因为你还是没有自动化多个不同的项目的任务生成。总之是一个类似把 Jenkins 当作 travis 的用法。 我踩的第一个坑就是没有意识到这两个东西虽然都是 Groovy,但是使用的是两套 API。需要分别查看各自的文档。我犯的一个错误就是把 Pipeline 里面的用法放到 Job DSL 里面用……结果当然是没法通过了,而且我还一直没有意识到这个问题折腾了好久。 总之,最后总算是搞清了这个问题,然后我发现我一开始写的 Job … Continue reading