当我使用canvas.drawText时为什么字距调整错误?

时间:2014-04-25 07:16:29

标签: android canvas paint drawtext kerning

当我在自定义视图中调用函数canvas.drawText()时,我得到了奇怪的结果,如下所示:

protected void onDraw(Canvas canvas) {

    super.onDraw(canvas);
    canvas.translate(50, 50);
    mPaint.setTextSize(60);

    String str = "helloworld";
    float[] wids = new float[10];
    mPaint.getTextWidths(str, wids);
    float width = 0;
    for (int j = 0; j < wids.length; j++) {
        String string = String.valueOf(str.charAt(j));
        canvas.drawText(string, width, 50, mPaint);   //draw by characters
        width = width + mPaint.measureText(string);   //the start X
    }
}

和此:

protected void onDraw(Canvas canvas) {

    super.onDraw(canvas);
    canvas.translate(50, 50);
    mPaint.setTextSize(60);
    String str = "helloworld";
    canvas.drawText(str, 0, 50, mPaint); // draw by strings
    }

为什么两种方法运行不同?我需要画角色,但它的字距是错误的! 有人可以指导我吗?

2 个答案:

答案 0 :(得分:0)

基于pskink Why the kerning is wrong when I use canvas.drawText?评论中的建议的自动字距调整解决方案 但是也支持用固定值覆盖字距调整(如在例如SVG中)

if (isKerningValueSet) {
    glyphPosition += kerningValue;
} else {
    float previousChar = paint.measureText(line, Math.max(0, index - 1), index);
    float previousAndCurrentChar = paint.measureText(line, Math.max(0, index - 1), index + 1);
    float onlyCurrentChar = paint.measureText(line, index, index + 1);
    float kernedCharWidth = previousAndCurrentChar - previousChar;
    float kerning = kernedCharWidth - onlyCurrentChar;
    glyphPosition += kerning;
}

答案 1 :(得分:-1)

我用它来进行字距调整。这是用coffeescript btw写的,虽然很容易转换它。

_fillText = Canvas.Context2d::fillText
Canvas.Context2d::fillText = (str, x, y, args...) ->

  # no kerning? default behavior
  return _fillText.apply this, arguments unless @kerning?

  # we need to remember some stuff as we loop
  offset = 0

  _.each str, (letter) =>

    _fillText.apply this, [
      letter
      x + offset + @kerning
      y
    ].concat args # in case any additional args get sent to fillText at any time

    offset += @measureText(letter).width + @kerning

然后使用它

context.kerning = 20
context.fillText(....)

这是javascript(没有args...部分,但我认为默认情况下不会向fillText发送任何其他内容)

var _fillText;

_fillText = Canvas.Context2d.prototype.fillText;

Canvas.Context2d.prototype.fillText = function(str, x, y) {
  var offset;
  // Fallback unless we need kerning
  if (this.kerning == null) {
    return _fillText.apply(this, arguments);
  }
  offset = 0;
  return _.each(str, (function(_this) {
    return function(letter) {
      _fillText.call(_this, letter, x + offset + _this.kerning, y);
      return offset += _this.measureText(letter).width + _this.kerning;
    };
  })(this));
};