“This is the 15th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

The last pixel

Recently, there was something wrong with the function of text editing. After editing, there was always some deviation between the original image view and the image view saved in canvas. The deviation was only a few pixels, but AFTER finding it, I felt really uncomfortable, so I started to try…

demand

I have a piece of TEXT JSON data, this PIECE of JSON data should be consistent with Canvas drawing or TextView display.

{
"x":0,
"y":0,
"size":1000,
"text":"M"
}
Copy the code

It’s a simple piece of JSON, turn it into an object, and then type a comment.

Size – The size of the text, in pixels text – the content of the text

My implementation method

Draw the view

Directly use View setX, setY method to control the display of View, because View setX, setY is also the coordinates of the upper left corner, so directly set in. The complete code looks like this. (I’ve set the text size to 1000 to make it more noticeable.)

TextView textView = new TextView(this); textView.setX(mTextBean.getX()); textView.setY(mTextBean.getY()); textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextBean.getSize()); textView.setText(mTextBean.getText()); textView.setBackgroundColor(Color.parseColor("#03DAC5")); Textview.getpaint ().setAntiAlias(false); container.addView(textView);Copy the code

Here, the size is set to specify the pixel unit, and the anti-aliasing is set, because if anti-aliasing is set, there will be gradient color, which will affect our conclusion.

Painted Canvas

Canvas is also very common to draw a text, the problem is in the drawText method, I thought it is the bottom left corner to draw, so I use 0 + mTextBean.getSize() as the Y coordinate, this is not reliable! The project was tight, there was no time to care about it, and it was shelved.

TextPaint textPaint = new TextPaint(); Textpaint.setflags (paint.anti_alias_flag); textPaint.setTextSize(mTextBean.getSize()); Paint.FontMetrics fontMetrics = textPaint.getFontMetrics(); Bitmap baseBitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(baseBitmap); canvas.drawText(mTextBean.getText(), 0, 0 + mTextBean.getSize(), textPaint); image.setImageBitmap(baseBitmap);Copy the code

The analysis process

TextView setX, setY represents the coordinates of the top left corner. But the drawText() on Canvas is more than just the lower left corner.

  • The coordinates of drawText() are related to the alignment of textPaint

There are three ways of alignment, corresponding to the picture respectively

Image from image link

Paint.Align.LEFT (default)

Paint.Align.CENTER

Paint.Align.RIGHT

  • DrawText () where y is baseLine

BaseLine is a bit more complicated, but the picture is easier to understand.

The y of the argument in drawText() corresponds to the BaseLine, so how do I move the upper-left coordinate to the BaseLine?

Let’s look at another graph, which represents the properties of FontMetrics.

So we’ll just put y + math.abs (Top) in JSON.

The modified code looks like this.

canvas.drawText(mTextBean.getText(), 0, 0 + Math.abs(fontMetrics.top), textPaint);
Copy the code

rendering

legacy

The default Text is 20px from the left to the top and 19px from the right to the top.

The guess may be the reason for including the baseLine line. I have to manually +1.