getTextBounds中bounds的坐标原点

在使用getTextBouds的时候,demo绘制了一个大写的字母A,log打印了一下

Rect bounds = new Rect();
........
paint.getTextBounds(text,0,text.length(),bounds);

bounds.top = -318;
bounds.bottom = 0;
遂认为原点是文字TextBounds的左下角。
但事实却打脸了,犯了盲人摸象的错误,以偏概全。
Api中是这样说明的:

Return in bounds (allocated by the caller) the smallest rectangle that
encloses all of the characters, with an implied origin at (0,0).

然而并没有明确 implied origin 到底是哪个点。上面我认为原点是bounds的左下角,然而并不是,所以baseline的起点应该是唯一合理的原点了,下面来验证。

OK,我们再来看一下drawText方法

/**
 * Draw the text, with origin at (x,y), using the specified paint. The
 * origin is interpreted based on the Align setting in the paint.
 *
 * @param text  The text to be drawn
 * @param x     The x-coordinate of the origin of the text being drawn
 * @param y     The y-coordinate of the baseline of the text being drawn
 * @param paint The paint used for the text (e.g. color, size, style)
 */
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
    native_drawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
            paint.getNativeInstance(), paint.mNativeTypeface);
}

这里的y,是baseline对应的y轴坐标值。
所以,事实上,我们要计算出y轴的坐标值和外框Rect中点middle的y坐标之间的差值。
然后middle+差值,就是baseline应该的坐标。

minus = (bounds.top + bounds.bottom)/2;
注意,top在baseline上方,所以是负值,bottom在baseline下方(也有可能和baseline重合),所以是零或者正值。
minus计算出来是个负值,所以middle = middle - minus;
这样处理了一下,文字果然居中了。
so,上面的猜测是正确的,原点就是baseline的左边起点,问题搞定了。

核心细节有两个:

  1. drawText绘制文字时,y是baseline的y
  2. bounds的implied origin at (0,0).这个点是baseline的左边起点

来个图方便理解

getTextBounds中bounds的坐标原点_第1张图片
drawText.png

你可能感兴趣的:(getTextBounds中bounds的坐标原点)