我想出了一种测试(经验估计)最大字体大小的方法,以便继续渲染表情符号。
这个函数的工作方式是创建一个1x1的位图,并尝试在其中心绘制地球球体表情符号()。然后它检查单个像素,无论它是透明还是彩色。
我选择地球球体表情符号,因为我认为我们可以相当确信,任何艺术家都不会在地球中间钻一个洞。(否则我们就大麻烦了。)
测试采用二进制搜索方式进行,因此运行时间应该是对数级别的。
(有趣的事实:我的两部测试手机上的最大字体大小都是256
。)
public static float getMaxEmojiFontSize() {
return getMaxEmojiFontSize(new Paint(), 8, 999999, 1);
}
public static float getMaxEmojiFontSize(Paint p, float minTestSize, float maxTestSize, float maxError) {
Bitmap b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
float sizeLowerLimit = minTestSize;
float sizeUpperLimit = maxTestSize;
Canvas c = new Canvas(b);
float size;
for (size = sizeLowerLimit; size < maxTestSize; size *= 2) {
if (!canRenderEmoji(b, c, p, size)) {
sizeUpperLimit = size;
break;
}
sizeLowerLimit = size;
}
while (sizeUpperLimit - sizeLowerLimit > maxError) {
float middleSize = (sizeUpperLimit + sizeLowerLimit) / 2f;
if (!canRenderEmoji(b, c, p, middleSize)) {
sizeUpperLimit = middleSize;
} else {
sizeLowerLimit = middleSize;
}
}
return sizeLowerLimit;
}
private static boolean canRenderEmoji(Bitmap b, Canvas can, Paint p, float size) {
final String EMOJI = "\uD83C\uDF0D";
can.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
p.setTextSize(size);
{
float ascent = Math.abs(p.ascent());
float descent = Math.abs(p.descent());
float halfHeight = (ascent + descent) / 2.0f;
p.setTextAlign(Paint.Align.CENTER);
can.drawText(EMOJI, 0.5f, 0.5f + halfHeight - descent, p);
}
return b.getPixel(0, 0) != 0;
}
Canvas.drawText()
,TextView
也不能绘制大型表情符号。我自己也做了测试,发现最大尺寸为256,但不知道 Skia 中的错误。现在有了解释,感谢! - Jenix