解决imagettftext()因为–enable-gd-jis-conv导致乱码的另一种方法

虽然 imagettftext() 文档标明只接受UTF-8编码,但如果PHP编译时启用–enable-gd-jis-conv选项的话,那么非ASCII字符(例如汉字、拼音、希腊文和箭头) 会被当成EUC-JP编码 (phpinfo中美其名曰“支持JIS编码的字体”), 从而导致乱码(由于西文字体没有假名或汉字,一般表现为全部是方框)。

Although imagettftext() documentation indicates it only accepts UTF-8 encoding, but if –enable-gd-jis-conv is specified when compiling PHP, then non-ASCII characters (like Chinese, accented characters, Greek and arrows) will be (mis-)treated as EUC-JP encoding (referred to as “JIS-mapped Japanese Font Support” in phpinfo) leading to mojibake (this usually shows up as hollow rectangles, as most fonts for western text lacks glyphs for kanji or kana).

网上大部分对此的解决方法是重新编译PHP,但是这只有自己架设服务器的时候才有用。对于付费空间 (特别是每个月不到1美元的付费空间) 就没辙了。不过imagettftext()也接受另外一种字符表示方法,类似HTML的字符参考。说“类似”是因为GD只接受数字参考,所以内部函数 (如 mb_convert_encoding) 转出来的没用。 以下的函数可以将UTF-8转换成字符参考:

A popular response online is to recompile PHP, but that only works if you’re running your own server. For paid hosting (especially paid hosting that costs less than a dollar a month) this method is kinda stumped. But imagettftext() also accepts another way for representing characters, similar to HTML’s character references. “Similar” because it only accepts numeric references, so named references converted by internal functions (like mb_convert_encoding) is of no use. The function below converts UTF-8 into character references:

//created by Kakurady
//no rights reserved
//no warranties explicit or implicit either
function to_entities($string){
    $len = strlen($string);
    $buf = "";
    for($i = 0; $i < $len; $i++){
        if (ord($string[$i]) <= 127){
            $buf .= $string[$i];
        } else if (ord ($string[$i]) <192){
            //unexpected 2nd, 3rd or 4th byte
            $buf .= "&#xfffd";
        } else if (ord ($string[$i]) <224){
            //first byte of 2-byte seq
            $buf .= sprintf("&#%d;",
                ((ord($string[$i + 0]) & 31) << 6) +
                (ord($string[$i + 1]) & 63)
            );
            $i += 1;
        } else if (ord ($string[$i]) <240){
            //first byte of 3-byte seq
            $buf .= sprintf("&#%d;",
                ((ord($string[$i + 0]) & 15) << 12) +
                ((ord($string[$i + 1]) & 63) << 6) +
                (ord($string[$i + 2]) & 63)
            );
            $i += 2;
        } else {
            //first byte of 4-byte seq
            $buf .= sprintf("&#%d;",
                ((ord($string[$i + 0]) & 7) << 18) +
                ((ord($string[$i + 1]) & 63) << 12) +
                ((ord($string[$i + 2]) & 63) << 6) +
                (ord($string[$i + 3]) & 63)
            );
            $i += 3;
        }
    }
    return $buf;
}

imagettftext($im, 11, 0, 5, 11, $black, $font,  to_entities($text));

应该复习,却鼓捣这东西……

777: 7 courses, 7 days, 7 assignments.

好吧7门作业对于中国大学生来说根本算不了什么-w-
The title is not a reference to 999: Nine Hours, Nine Persons, Nine Doors. No, it’s not! Uh-uh! Nope!


So for some slackitude reasons, I had 6 assignments piled up, all due on the week of Feburary 1st or the Monday immediately after. (Actually 7, as I forgot to ask for one professor’s web site.) Since there is an anime con in the weekend, my plan was to complete everything during the weekdays, for there won’t be any time to do them during the weekend, and undone homework would be a really bad thing to have at a con.

During the week, I handed in a web client and suh-vuh, a demo of a ball bouncing in a dish, a token ring simulator (kinda) and an artificial stupidity. 2 Java classes, one C++ project, one C file, and the odd one Python spaghetti (glad that semicolon does nothing in Python), one missed class (just… one… more… compile…), and everything’s finally done… on Saturday lunchtime. The panels I wanted to go are all finished. Oh well, better slow than missed bugs, I suppose.

大概是因为懒惰的关系吧,从二月一日到二月八日的一个星期多一天,竟然堆了7门作业要交 (虽然有一门我不知道)。打算周末去动漫展,所以决定在周末前把作业全部做完——没做完的作业可不是一件适合带到动漫展的东西。

一周中交上了网络客户端和糊误器各一件,在盘子里弹跳的球一个,令牌网模拟器一块,还有人工无能一只。2个Java类、一个C++工程、一个C文件、还有明显不同的Python乌东面一份 (还好多写一个分号也没问题),终于在……周六中午完成了。想去的动漫展讲座,全部讲完了。哎,总比漏了程序错误强吧。


今年是第二次参加GAnime,大概是因为懒惰的关系吧,没有提前注册,而是在现场缴的入场费。因为没有像去年一样和兽友在一起,并且照相机也不见了,所以感觉比较没劲。

展览会场作过了装修,今年感觉十分的现代 (后现代? 后后现代?),但是不知道为什么,面向中庭的窗全被用儿童画盖上了。实话说,不和谐。当然,从窗看下去,展会的忙碌和外面的购物中心的空荡,确实差别很大。不过我还是觉得,能够看到参展者吃饭 (特别是动漫展的时候,coser 在吃饭) 会觉得这地方很亲近。

游戏室周日很早就撤了,《王国之心II》存档记录时间:6 小时。也许不应该呆在游戏室,而是去听听讲座什么的。去年的动漫藏书室,今年是放映室,唯一的一个英语放映室。

结论:不管是动漫展还是兽展,一个人去就没有意思。

This is the second time attending GAnime, so for some slackitude reasons, I didn’t register beforehand, and paid admission on the spot instead. Because didn’t had furries together like last time, and my camera also disappeared, it was relatively less interesting.

The location has been renovated, it feels very modern this year (post-modern? post-post-modern?); but for some reason the windows to the atrium have been covered with drawings by children. Frankly, not harmonious. Of course, between the busy conference center up here and the empty shopping center down there, it is a big contrast. But I still feel it makes the place friendlier if you can see other attendees (especially in the case of anime con, cosplayers) eating.

The games room were cleaned out very early on Sunday, save record for Kingdom Hearts II indicates playtime of 6 hours. Maybe I should have gone to panels instead. Where was manga library last year, was a screening room this year, the only English one.

Conclusion: No matter if it’s an anime con or a furry con, going alone is not very interesting.

Perfect Day

Recently I’m having a bit of… issues with my browsing habits. In one week, I had two day-long sessions of endless gaming and random web browsing, while assignments (and garbage) pile up. And I had hardly a day that I slept well.

So when I came out from the first period, still sleepy, I thought to myself, even if I can’t do my best all the time, I’ll at least do it for today. Even if I think I can’t, it helps to try, right? Just a little experiment. And I had a busy morning, took a nap, wrote some mail, etc.

While I was preparing to leave, I thought since the next class is of a course I’m retaking, and I don’t need to listen, why not take the laptop there?

Well, turns out if I have a computer, in addition to showing the course notes, I can also keep myself distracted with lots of new happenings and tangentially related definitions to the lecture. Lack of power outlet doesn’t hinder me at all. I can’t even write this blog post with the urge to check something else.

In the end, my perfect day experiment was not a success.
Continue reading Perfect Day

欲速则不达。

今天早晨起来发现还有10分钟就要上课,于是匆匆忙忙地去拿衣服…咔啦一声,磁带机掉在地上,四分五裂。

还好,磁带机和掉出来的小弹簧很容易装回去,也没有任何问题……但是装完已经过了半小时,再去教室,助教已经几乎把题目讲完了。

磁带机干什么用?万年不听的Berlitz法语课程。

Woke up to find it 10 minutes to class, so hastily tried to grab clothes… with a “crack”, the cassette player fell to the ground, separated into pieces.

Thankfully the cassette player and the tiny spring that fell out were very easy to put back by hand, but when I finished, already 30 minutes has passed, and the TA had almost finished explaining the assignment.

What is the cassette player for? Berlitz French self-teaching course, which has never been listened to in a thousand years.


另外:

  • Transformice 着迷中~
  • Windows Live Spaces将关闭,全部用户将移动到Wordpress.com. 从五年前的第一篇网络日志到去年底的最后一篇更新,一共178篇,怎么办呢?还有人在那里读我的日志吗?会有人在新的网站上读我的日志吗?两个中间要不要关一个呢?

Also:

  • Finally managed to connect to Transformice and got addicted immediately~
  • Windows Live Spaces is being shut down with all users migrating to WordPress.com. Starting from my first blog entry in my life five years ago, to the last one at the end of last year, I have written 178 entries on it. Is anyone still following that blog? Will anyone follow me there? Should I close one down? What should I do?