Color Emoji in openSUSE

上一篇文章里我们讲了 fontconfig 常见的几个坑,今天我们来继续讲一讲 openSUSE 的 Colored Emoji 支持。也就是如何配置 Noto Color Emoji 这个字体用于网页显示(用于终端显示是另一回事,涉及到比如 vte 的 teminal 之类的,有几个相关的 bug 涉及到比如宽度之类的;GTK/Qt 显示又是另一回事,涉及到 cairo)。 为什么是这个字体呢?我也很无奈啊…Noto 系列是 openSUSE 的默认字体,可以说除了英文 locale 别的都是 Noto 来显示的,Noto Color Emoji 跟其它 Noto 字体的 metrics 兼容。这一点就秒杀了其它 Emoji 字体。再者 Emoji 字体本身就不多,目前为止也就 45-generic.conf 里列出的那么不到十个,EmojiOne Color 因为版权问题不再开发了,真正 Linux 上能用的 Colored Emoji 也就剩下一个 Twitter Color Emoji 了。剩下的要么专有的要么没有颜色。 我们先来回忆一下之前的说法: 除了比如 Unicode Full Emoji List 这种专门用于测试 emoji 显示的 URL,大部分我们常见的网页在 css 里是不写 emoji 字体的。 据我摸索的经验,字体的匹配分为三种场景 第一种是直接去匹配这个字体,fc-match “Noto Color Emoji” 这样,也就是 css 的 font-family 里直接写了这个字体。 ...

<span title='2020-11-04 00:00:00 +0800 CST'>November 4, 2020</span>

fontconfig 几个常见的坑

最近 Microsoft 加入 OIN,贡献了它的 60000+ 项专利,这使得 openSUSE 的 freetype2 终于能够开启 ClearType 引擎了。之前 infinality 项目贡献了三大块,我们引入了两大块,但是其中第一大块的 ClearType 引擎没有默认开启,第三大块的非专利色彩滤镜也一直没有。现在专利的问题没有了,freetype2 终于更新到完全体了,它现在有两个引擎,第一个引擎是 Adobe 的 CFF 引擎,主要用于 Noto Sans CJK,第二个引擎就是 infinality 贡献的 ClearType 引擎了。总之都是好东西。 后端更新了,我也需要更新 fonts-config 来默认设置 rgba 和 hintstyle。openSUSE 的 fonts-config 是一系列跟 fontconfig 一样的字体配置文件,已经很老了,于是我需要 modernize 它一下。在这个过程中我几乎看了网上能够找到的全部 fontconfig 相关文章。里面大坑套小坑,有必要专门写文来澄清一下: 第一个坑:从 monospace 中清除 sans-serif 比如 Hack 字体的官方配置,还有最著名的 eev’s rant about fontconfig,都推荐了这么一种做法: <match> <test name=“family” compare=“eq”> <string>sans-serif</string> </test> <test name=“family” compare=“eq”> <string>monospace</string> </test> <edit name=“family” mode=“delete”/> </match> 意思是如果 pattern 有 sans-serif,还有 monospace,就把 sans-serif 删除。目的是让字体只有一个 generic name。起因在于 /usr/share/fontconfig/conf.avail/49-sansserif.conf(针对所有没有 sans-serif、serif 和 monospace 的 pattern 加上 sans-serif) ...

<span title='2020-11-04 00:00:00 +0800 CST'>November 4, 2020</span>

30 秒钟在 Github Pages 上搭建一个 openSUSE 风格的部落格

之前的 Ghost 管理密码丢了 :-( 昨晚花了一个晚上的时间把之前丢失的部落格文章通过 web.archives.org 找回到了 2011 年。09~10 年的部落格文章等想怀旧的时候再继续找。下一步应该研究的是怎么恢复和整合评论。 不过这个坑就不一定哪天来填啦。 考虑到我博客更新的速度和访问量,我觉得还是不要把它放在论坛服务器上了。毕竟 Ghost 是用 nodejs 的,一直跑着太占资源;搬服务器就要迁移,我这种懒人,迁完论坛就不管的, 博客要么丢文章要么丢评论。还是用 github 来做博客好了。 Github Pages 是由 Jekyll 驱动的静态博客,使用 Markdown 来写文章,用 git 管理,这几个对我来说都不是很难,毕竟我是一个 Ruby 程序猿。Github 自己的文档基本无用,因为文档跟用户之间少了点东西。 它只告诉了我 Github Page 其实就是一个静态网页生成器加 HTTP 服务器,你喂 Markdown 格式的文章给它,它在 yourname.github.io 上显示出来。这用来建立一个单页面是足够的。 但是它并没有说你想做一个博客应该怎么办。因为其实那是 Jekyll 这个静态网页生成器的事情。你需要给它写模板。 所以我参考了 Smashing Magazine 上面的 Build A Blog With Jekyll And Github Pages,找了一个现成的 Jekyll Now 模板。自己简单改了下。风格参考了 Grover Chou 的部落格。我觉得他那个 openSUSE Leap 风格的主题很好看,于是就抄过来了。配色和样式是抄的我们 openSUSE 中文论坛。点我预览。 要是有想要用我这套主题建博客的,建立过程很简单: 去 github 上面 fork 我的 marguerite.github.io,然后点 Settings,把仓库名改成 yourname.github.io。 git clone 你的 fork 到本地,编辑一下 _config.yml,把我的信息都改成你的。 把 _posts 下面我的文章删掉,用 Markdown 写你自己的,格式是 YYYY-MM-DD-TITLE.md。支持中文标题。 完成这三步,只需 30 秒,你就有了一个 openSUSE 中文论坛风格的个人博客啦。 ...

<span title='2016-12-31 00:00:00 +0800 CST'>December 31, 2016</span>

Introducing the brand new nodejs packaging

There has been no activities for nodejs in openSUSE for a while. (Since 13.2) But it doesn’t mean it’s dead. It’s actually evolving. Today the brand-new nodejs-packaging answers all the questions. For a long time and traditionally we openSUSE prefer to keep consistence with Fedora in RPM packaging (Although small differences still present). So did nodejs packaging. We used the nodejs-packaging tool from Fedora to package for openSUSE before. But it introduced lots of troubles: ...

<span title='2016-01-23 00:00:00 +0800 CST'>January 23, 2016</span>

本周开发札记

盘点一下本周自己在 openSUSE 上面做的工作: 解决了 wine 的 desktop file 长期以来位于未知类别的 bug openSUSE 的 wine 从 Ubuntu 抄来了一些 desktop files。而这些文件的 Categories 都是错的(Categories=Wine;Emulator;Documentation;)。根据 freedesktop 的 desktop entry specification 规定,Emulator; 只能跟在 Games; 或者 System; 后面使用,所以是错的,而 Wine; 本身不是一个合法的 Desktop Category; Documentation; 又不符合。统一调整到了 System;Emulator; 类别,而一些可以独立使用的比如 notepad 则视同原生 App 调整到了对应的比如 Utility;Texteditor; 类别。 对 devel:languages:nodejs 源进行了 big cleanup 主要是为了我马上要开发的 nodejs-packaging 做准备。npm 由独立打包回归到了与 nodejs 一同打包,而我开发的 nodejs-packaging 又准备使用 bundled packaging 的模式,那么独立打包 npm 时的一些依赖包就不再需要了。这些依赖很早就被我用自动化脚本(简单的 shell script 和 ruby)从 openSUSE:Factory 批量删除了,现在 d:l:nodejs 源里还有一些 broken 状态的尸体。用自动化脚本批量 revoke 了一些 factory-auto-submit 导致的被 rejected 的 SR,然后跑脚本 wipebinaries 从服务器删除 RPM,从服务器 remote delete 掉。 ...

<span title='2016-01-23 00:00:00 +0800 CST'>January 23, 2016</span>

脑洞大开的周末

这个周末其实只打算维护下我的 upstream-notifier 的😂。好吧原来我只是想更新几个软件包,结果觉得既然都去更新包了,不如把给 upnoti 用的 json 也写了。 写的过程中要测试,发现 github 上面的有些项目的 release page 底下没有内容,于是又改 upnoti 的 github mod 支持这种情况。然后又觉得 upnoti 太慢,加了 multithread 支持,然后又开始优化性能,代码风格之类的。 好不容易搞定了,这时 home:opensuse_zh 已经更新完几个包了,没法生产环境测试了,又去 d:l:go 里把 docker 的几个依赖抓回来,发现 golang-packaging 在 sles11 上面 test 宏出错,又给自己加了一项工作任务。 然后在 features.opensuse.org 上看到有个人要 tox 整合进 openSUSE,想起来我还维护着 cutegram 和 qtox,于是去更新 cutegram。 结果觉得我的用 _service 抓 git 的软件包这么多,每次更新基本都是无脑的,干嘛不做个自动化工具呢?于是 obs-scm-autoupdater 就这么诞生了😈 写完 osa 的基本功能,又开始怀疑人生了。rpm 打包这么难,新手不爱学啊!就连我自己也经常是本来要简简单单安装个软件,比如 vokoscreen,录个视频给 konsole 的人看 bug,结果看到 vokoscreen 版本太低去更新,就把报 bug 这事岔开了。生产力就是这么低的!打包不应该那么耗时间,应该简单得像本机编译一样,甚至比那个还简单,新手才喜欢。 关于这个问题有三个办法: 第零个是不学打包直接本地编译。我烦死本地编译了,之前本地编译安装了个 basket,后来时间长了把源代码删了,没法 make uninstall,有洁癖的我就又编译了一遍就是为了卸载掉。哦对了 basket 有 kde5port 了!我当年想学 c++ 其实就是为了维护这个项目,虽然我各种待办事宜软件搞了不少,其实有 todo 的时候多半还是用脑子记,因为要么那时手头没工具要么人太烂,就好比我是学金融的却没老老实实用 skrooge 这样的手帐软件记满哪怕一个月,嘿嘿 ...

<span title='2016-01-18 00:00:00 +0800 CST'>January 18, 2016</span>

高手创造工具

今天整理出来了自己这些年碰过的软件包,不算 M17N 之类拥有 repo maintainer 角色的源里的软件包,就有 178 个。加上那些总量要过 300 了。 金融领域,一个基金经理维护 20 只左右股票组成的资产池就需要一个庞大的团队。300+ 的软件包几乎可以说是早到了 upper limit 了。至于技术,基本上再提高就不会是在打包这里了,而是去真正的学习各种编程语言来解决编译错误了,这其实做的已经是 upstream developer 的事情了。我的 github profile 这些年累积下来很好看,它说我的主力编程语言有 4 种(笑~),还被 Google HR 发过邮件(笑~)。 我维护着很多的中文社区相关的包。偶尔有一种莫名其妙的责任感:有用户在 forum.suse.org.cn 说哪个软件 openSUSE 没有,就想赶紧包出来,潇洒一 post。或者谁说 openSUSE 出了什么 bug,感觉就跟自己系统不能用了一样。几乎每天在 build.opensuse.org 和论坛上面站台,打包点东西,帮 factory 修修 bug。 这一年我掉到了 nodejs 和 go 这两个我到现在依然不会写的语言的大坑里去了。npm 有 200+ 个依赖,导致我其它包的维护几乎就是停滞了。 现在来看还是要上帝的归上帝,凯撒的归凯撒。论坛我不去,他们几个管的也挺好的,phoenixlzx 也没伸手要钱; 有些软件包不是我打的,比如 bcloud,大家也用上了;Leap 发布我没组织,用户一样也不少。有些空白总是能够填补的。openSUSE 是一个社区,能成长起来一批有自治意识、能够且有能力自主奉献的人就是对开源的贡献了。 而我自己的打包工作,我学了一些 ruby。元旦把之前实验性的 github.com/marguerite/golang-packaging 形成生产力了。这个项目简单说就是用 ruby 实现了一些 rpm macros。可以让你不需要真正懂 golang 的编译环境是怎么构建的、环境变量是怎么设置的,甚至连最后的 rpm 文件列表(%file)都不用你来写。你都不需要知道 openSUSE 的 golang 软件包安装到什么路径就能做出包,大大降低了打包需要了解的背景知识(当然这些知识还是记录在了 wiki 上面),只需要根据错误提示写固定格式的编译依赖(运行依赖 Requires 和 Provides 是自动处理的。甚至 Requires 都只是为了以后 golang 支持 shared linking 做的准备)。 ...

<span title='2016-01-12 00:00:00 +0800 CST'>January 12, 2016</span>

RPM specfile 中 值的研究

研究这个问题是因为论坛上的一个讨论:zypper reinstall package 略过楼主的实现是否正确不谈(因为他不给我看 specfile 估计是公司的软件),简单来说可以分成几个子问题: 第一个是 RPM specfile 的 %postun 部分的 $1 变量到底是什么: if [ $1 == 0 ] ; then $1 的值当然是有意义的,它代表安装在你系统上的同名软件包的版本数。比如你升级软件包,那默认是 1,但在某个状态是 2,因为这时新包装上旧包还没卸载,0 就代表这个包在你系统上已经不存在了。 http://stackoverflow.com/questions/7398834/rpm-upgrade-uninstalls-the-rpm 第二个是 RPM reinstall 的作业流程是怎样的,是遵循升级的流程也就是: 软件包升级的过程是先安装新包后卸载旧包,只有来自旧包的差异文件会被删除。也就是 pre -> install -> post; preun -> uninstall -> postun 还是另有一个流程。$1 值的变化可以推测出这个问题的答案。 第三个是使用 zypper 和 rpm 分别进行重装,$1 值的变动是不是一致的。 这个问题我们需要做一个实证,代码在这里: https://build.opensuse.org/package/show/home:MargueriteSu/rpm-reinstall-demo 相应的测试用 RPM 也可以在那边取得。下面直接上结果: sudo zypper --no-refresh install --force rpm-reinstall-demo-0.0.0-5.1.x86_64.rpm drwxr-xr-x 1 root root 0 8 月 2 22:25 demo 通过 /var/tmp/demo 的时间戳记可以发现安装前后 demo 没有被删除重建。 ...

<span title='2015-08-02 00:00:00 +0800 CST'>August 2, 2015</span>

关于 Deepin 用户开发者大会的浅见

这篇文章是唱反调的,可能会不舒服的可以离席了。 最早长微博写了一半(好吧我弄了一个真·@openSUSE娘),觉得一个喧嚣的场合不太合适搞技术的(好吧我又给自己脸上贴金了)坐下来互相交流(喷),于是就发在这里,也特意选择 DAU 大会这个话题冷下来的时候说,避免给他们造成负面的影响。深度团队要觉得我是个倒灶的就无视掉好了。 先说两点: (1) 某些 Deepin 的粉丝可能会觉得我吃不到葡萄说葡萄酸。 第一,我没有直观感受过 Deepin 作为一个发行版有多少用户(不是 Deepin Music 这些应用软件),这不像 Ubuntu 那么明显,所以从用户基数的角度来看,我没有概念,也就没有说酸的基础。 第二,我这里说的是他们的战略大方向,他们拥抱了哪些技术,营销的定位,这些东西,而不是去像黑 Ubuntu 那样,“哈 U 的用户用 U 都是为了让别人知道它在用 Linux 而不是为了解决自己的需求”。 深度团队是 Linux 中文圈里比较靠谱的团队。另一个比较靠谱的我认为是安同。而优麒麟处在第二梯队,遗产流的那种。后面如果还记得优麒麟的话,可能会拉它出来做反例。唉,我也勉强算 Linux 中文圈的大前辈了,这种褒贬倾向真不该轻易流露,会给别人造成负担的。 首先深度团队的人比较 nice。我记得有一个陈祥帮吧,曾经在 openSUSE 中文论坛给我发私信说两个社区合作的事情,当时正好生活上有一些变动,后来就不了了之了(欢迎重启)。但总体印象较好。现在的“国产操作系统”的人有一点不好,为了吸引用户而越来越没下限了,有些时候觉得跟百度 Linux 吧的人差不多。深度算是有一些水准的,相对于同样没有经历过大发行版社区培养的人来说。 其次深度的人相对比较能够出活儿。他们有 30 多个人,武汉有深之度公司,连中文圈比较稀缺的画师娘都招了,像「深谈」这样的应用程序还是很惊艳的。当然激情上面应该比安同(骚年强则中国强)要差一些,毕竟是领钱干活的个人有个回报率和职业发展的考量,但比起优麒麟眉毛胡子一把抓,开发者不少,成果稀少(估计是瞄准高端定制市场和政府采购去了),还是要好一些。 第三他们有想法,并且一定程度上比较能够遵守规则,虽然对上游的贡献不是很多,但是对自己的成果的态度还是很开放的。 所以真心希望他们能够出彩。 铺垫完了,下面开黑: Deepin 2014 发布和主要的三个演讲(Gitcafe,Crossover,Seafile)没什么好黑的。甚至还有点小艳羡,比如那一大堆赞助伙伴和合作媒体,有公司实体,我们这些爱好者群体和国外机构在华分支在本地化上确实比不了。 主要黑两点: 默认搭载 Crossover,哈,这不是我黑的,Qian Hong 还有点面子的嘛,再说你在中国做发行版都不搭载商业/免费软件,未免逼格太高。 我要黑的是,似乎 Deepin 要入 Mono 这个坑?(微博上是这么感觉的) 首先说明,我个人对于任何铺平 Windows 到 Linux 之路的举动都是支持的,但我更认为这种事情应该由「使用者教育」比如建设 Wiki 和社区来实现,而不是由技术手段去抹平差异来实现,因为之所以有差异就证明抹不平。这不是「我饿了,于是吃饭」的逻辑,而是「我饿了,吃了米饭,又去吃馒头」,不可能有米饭味儿的馒头,那是饭团。 先介绍下什么是 Mono,它是在 Linux 上搞 .NET 开发的一个东西,是 SUSE 创建的,后来觉得这个脑洞太大,把整个 mono 团队都开革了。 ...

<span title='2014-07-11 00:00:00 +0800 CST'>July 11, 2014</span>

openSUSE 下配合 Nginx 搭建 qwebirc 网页 IRC

做这个的初衷很简单:IRC 对小白太远了。 它不像论坛,打开网页就能刷; 不像 QQ/Gtalk,软件是人都能找到,装上就能上。它需要专用客户端(比如 konversation),而且装完你还不能上,还有一堆命令等着你,何况还有 20 年早期互联网流传下来的各种名词、礼仪。总之它是一整个与世隔绝的黑客生态圈。 但是吧,不学还不行,你看哪个开发者不会使用 IRC 的?于是我想先降低一下它对小白们的陌生感,做一个给蠢人用的玩意。(成功把自己从其它蠢人中分离开以示区别哦耶!) 于是最蠢的来了:qwebirc,是一个自由开源的网页 IRC 客户端,最早是给 QuakeNet 游戏网开发的。这是目前我能找到的唯一一个开源的。 看了下,发现它居然不支持多语言!好吧,硬 hack 出了一个繁体中文版(别问为什么不用简体,因为硬 hack 就是只能使用一种语言,没有动态切换,那简体用户繁体一样能看懂,自豪吧?)。 安装依赖(openSUSE 下) sudo zypper in nginx python-Twisted python-simplejson java-1_7_0-openjdk 下载 然后随便找个文件夹,因为 qwebirc 和 HTTP 服务器的关系不是常规那样的,常规是在 /srv/www/htdocs(又叫 webroot)下面放一些 html/php 文件,然后 HTTP 服务器让那个文件夹下面的东西能被访问,但是 qwebirc 其实是自己跑起来了一个专用的 http 服务器,为什么呢?据说是通用 HTTP 服务器设计不是用来服务大量的、长期活动的连接的,它们可以处理的是大量的但是都是一次性的连接,这种基于线程或者多进程的服务器(Apache 被点名了)没办法处理太多的这种连接,到时候会把你的网站一起拽下线呦! 但 qwebirc 的专用服务器是开在 9090 端口的,你不想访问 yourircserver.com:9090 这种丑丑的链接吧?所以你需要一个反向代理,还不能用被怒黑的 Apache。。。也就 nginx 了吧?好在我们别的服务器也是用的 nginx,因为 openSUSE 社区穷 VPS 内存小。。。 言归正传。找到文件夹了吧?然后在命令行下载最新的稳定版 qwebirc: wget http://qwebirc.org/download-stable-zip 它没后缀但它是个 zip,解压: ...

<span title='2013-10-12 00:00:00 +0800 CST'>October 12, 2013</span>