3

I have created an applications that allows users to paint with text, including emojis. The user can rotate and resize the text to their liking. The problem occurs when the user rotates text that includes emojis. enter image description here

As you can see, there is unwanted overlap. I have deduced that this is because i draw the text twice to achieve a border affect. Whats interesting, is that the problem solves itself if the text size exceeds a certain amount. this can be seen in the bottom most test.

Here is the code that drew the above image:

    public void draw(Canvas c, int x, int y) {

    Rect re = new Rect();
    Paint p = new Paint();
    p.setColor(this.color);
    p.setTextSize(this.GetSize());
    p.getTextBounds(text, 0, text.length(), re);
    p.setAntiAlias(true);

    c.save();
    c.rotate(rotation_deg, x, y);

    c.drawText(text, x - re.width() / 2, y + ((re.height() - re.bottom) - re.height() / 2), p);

    p.setStyle(Paint.Style.STROKE);
    p.setColor(color2);
    c.drawText(text, x - re.width() / 2, y + ((re.height() - re.bottom) - re.height() / 2), p);

    c.restore();
}

removing the first draw command fixes the emoji problem, but then i just get the text stroke.

How can i rotate text that includes emojis?

One possible solution is to draw to a bitmap first, and then rotate the bitmap, but this process would waste both ram and time.

Fence_rider
  • 163
  • 1
  • 14

2 Answers2

0

Since you know how to solve the problem I would investigate using Paint.setShadowLayer(float radius, float dx, float dy, int shadowColor) and not drawing the text twice.

public void setShadowLayer (float radius, float dx, float dy, int shadowColor)

This draws a shadow layer below the main layer, with the specified offset and color, and blur radius. If radius is 0, then the shadow layer is removed.

Can be used to create a blurred shadow underneath text. Support for use with other drawing operations is constrained to the software rendering pipeline.

The alpha of the shadow will be the paint's alpha if the shadow color is opaque, or the alpha from the shadow color if not.

public void draw(Canvas c, int x, int y) {

    Rect re = new Rect();
    Paint p = new Paint();
    p.setColor(this.color);
    p.setTextSize(this.GetSize());
    p.getTextBounds(text, 0, text.length(), re);
    p.setAntiAlias(true);
    p. setShadowLayer (2.0f, 2.0f, -2.0f, this.color);

    c.save();
    c.rotate(rotation_deg, x, y);

    p.setStyle(Paint.Style.FILL_AND_STROKE);
    //p.setStyle(Paint.Style.FILL);

    p.setColor(color2);
    c.drawText(text, x - re.width() / 2, y + ((re.height() - re.bottom) - re.height() / 2), p);

    c.restore();
}
Cory Charlton
  • 8,868
  • 4
  • 48
  • 68
  • I don't know how to solve the problem without wasting ram. i am trying to draw text with a border at an angle on a canvas like this http://stackoverflow.com/questions/9132781/paint-bordered-text-in-a-canvas-android . The problem is, that when i rotate the text, the emojis do not rotate. I tried implementing the shadow layer you suggested and it also did not work... The emojis still do not rotate with the text. The shadow effect is cool though! :) – Fence_rider Apr 01 '16 at 23:38
  • @Fence_rider Weird. In your original question you mentioned that if you removed the first draw command the problem was solved. So you're saying that you did that and added the setShadowLayer call and the problem came back? – Cory Charlton Apr 02 '16 at 01:57
  • not exactly... when i remove the first draw command the emoji aligns with the text but the text has no fill, just a border. So i tried setting the shadow and removing the first draw command which resulted in the the emoji being aligned, but there was still no fill. Maybe i am setting the shadow wrong it just resulted in a black cloud surrounding the text – Fence_rider Apr 02 '16 at 02:57
  • Yeah the `p.setStyle(Paint.Style.STROKE)` is what's giving you only the border. Try setting the shadow and commenting out both the first draw command and the `p.setStyle(Paint.Style.STROKE)` line. – Cory Charlton Apr 02 '16 at 03:01
  • @Fence_rider or rather than commenting it out try changing it to `Paint.Style.FILL_AND_STROKE` or `Paint.Style.FILL` – Cory Charlton Apr 02 '16 at 03:03
  • changing p.setStyle(Paint.Style.STROKE) to p.setStyle(Paint.Style.FILL_AND_STROKE) did succeed in adding the fill back, but the emoji is still not aligned. It draws the emoji as if the canvas had not been rotated. – Fence_rider Apr 02 '16 at 03:12
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/108010/discussion-between-cory-charlton-and-fence-rider). – Cory Charlton Apr 02 '16 at 03:13
  • I am having the same problem. Did you find a solution to it? – fhsilva Apr 14 '16 at 00:41
  • @fhsilva no, i have not found a solution yet. – Fence_rider Apr 17 '16 at 01:43
0

Set the layer type to software. The problem will be fixed

 textView.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
REMIL K R
  • 21
  • 3