19

I do some tests on drawing text on path. I made a background picture by setting bitmap to the canvas. Then, I draw text on a path to canvas, rotated by matrix. I have to shorten the code, I will only post the important part because it is too long. This images shown below are cropped with gimp, so don´t be irritated by the different sizes. My Rect, Path and Matrix objects:

    RectF drawTextOval;
    Path drawTextPath;
    Matrix mDrawnMatrix;

Now, this is what I am doin to draw text on circle path:

    drawTextOval.set(drawTextPosX - drawTextArc, drawTextPosY
                    - drawTextArc, drawTextPosX + drawTextArc, drawTextPosY
                    + drawTextArc);
            drawTextPath.addArc(drawTextOval, 0, 360);

            drawTextPath.computeBounds(drawTextOval, true);
            mDrawnMatrix.postRotate(drawTextArcStart,
                    (drawTextOval.right + drawTextOval.left) / 2,
                    (drawTextOval.bottom + drawTextOval.top) / 2);
            drawTextPath.transform(mDrawnMatrix);

            patternCanvas.drawTextOnPath(drawText, drawTextPath, 0, 0,
                    mFixedTextPaint); 

Until this point, everything looks fine:

enter image description here

But after saving the whole screen, the rotated text looks warped at the saved .png image. All the other components looking good. I made some other drawings with text, linear or angular, all this works. Even some .png bitmaps drawing to canvas and the background image...all are looking normally. But the on circle path drawn text looks like this:

enter image description here

I don´t do any scaling on the bitmap, just saving the canvas image with:

    FileOutputStream fos = new FileOutputStream(saveFile);
        this.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
        Bitmap bitmap = this.getDrawingCache();


        bitmap.compress(CompressFormat.PNG, 100, fos);
        fos.flush();
        fos.close();

Why does the text look warped? Does anyone see my mistake? Thanks in advance...

EDIT

I tried some stuff and find out that setting any density to false or disable hardware acceleration in Manifest will show the effect at runtime before saving. That suggests to me, that when saving bitmap with getDrawingCache(), the scaling is disabled at this time. But why?

The last thing I found out, that the lower the curvature the lower is the text scaling. If the text is just a little bit curved, it seems good.

enter image description here

Prince Dholakiya
  • 3,255
  • 27
  • 43
Opiatefuchs
  • 9,800
  • 2
  • 36
  • 49
  • Without looking at the code I notice that the saved image seems square while the source image is not square. Is that the case? – Simon May 20 '13 at 19:09
  • thanks for your reply. I just cropped this pics with Gimp, this is not the reason. I made a lot of tests with other bitmaps drawn on the same canvas and straight or angular drawn text, all looks ok. Only this drawn text is warped. – Opiatefuchs May 20 '13 at 19:23
  • Did you try `getDrawingCache(true)` not? – ozbek May 23 '13 at 08:30
  • yes, tried, but does not work. It looks like saving bitmaps will cause some extra scaling on text element which are drawn on path. – Opiatefuchs May 23 '13 at 10:43
  • I tried to create a new Bitmap, create a Canvas on it, and call onDraw with the new canvas (instead of using getDrawingCache(). The effect still remains. I tried to disable hardware acceleration, and then the warp effect is visible also on screen. This suggests that there is a different drawing path to the actual screen with opengl, and a different path to draw into a memory bitmap. The memory path is broken. Couldn't find a way around it though. – yoah May 28 '13 at 16:34
  • thanks for your help. Finally, this could be a bug in android. But I can´t believe that there is no way to fix it... – Opiatefuchs May 28 '13 at 16:43
  • If there is no simpler way, you could do it the hard way: break the text to letters, advance on the path by the letter width, find the position and rotation, and draw each letter rotated in place. If your path is a circle it's not too bad. – yoah May 28 '13 at 16:59
  • it would be worth a try. But I will give one more week to this open bounty before testing it. If your suggestion will be my last try and it works, I will give You a vote if You set this as an answer. But wait one more week before doin this. – Opiatefuchs May 28 '13 at 18:13
  • It seems that there are two ways of rendering text along a path. Method 1 is like letters hanging on a washing line: their shape isn't affected by the path the washing line takes; the other method is to imagine the letters on a piece of thin rubber which it then stretched along the path with the ends kept perpedicular to the path. However, I cannot find a way of controlling which method is used. On my HTC, your example code produces the "warped" version on the screen, for example. – Neil Townsend May 31 '13 at 16:32
  • nice and metaphorically description.. :). For the moment, I disabled this feature from the project and will finish the remaining. But after that, I will try all here discussed solutions. – Opiatefuchs May 31 '13 at 19:07
  • If this is still open @Opiatefuchs and you're willing to provide me with the whole class that draws, I could try to find a solution for you – Juan Cortés Jun 10 '13 at 15:47
  • @Juan-for now, I just disable this feature in my app, I want to enable it again. I will contact You if I am ready, could need a little time.... – Opiatefuchs Jun 13 '13 at 07:27
  • Have you tried scaling the matrix and canvas ? I Tested your code and added matrix/canvas scaling - mDrawnMatrix.setScale(1 / getDensity(), 1 / getDensity()); + canvas.scale(getDensity(),getDensity()); And any artifacts i had before using the scaling were gone. – Sagi Antebi Jun 13 '13 at 16:59

1 Answers1

1

I would try setting the

this.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);

before drawing to screen, since lower quality might imply a simpler transformation of the text. This is just guessing of course. Currently your only setting the high quality before writing to disk. Or simply remove it from the write to disk method to check if it affect the way the text is drawn.

Carl-Emil Kjellstrand
  • 1,233
  • 1
  • 10
  • 17