• Post Reply Bookmark Topic Watch Topic
  • New Topic

Trying to draw 270 degree anticlockwise rotated text on an image, but having an issue.  RSS feed

 
Hari Th
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I want to rotate text 270 degree in anticlockwise direction and then draw it on an image. Please find my sample code below. It works if I set the the size of the font <= 100.0, but when I set the size greater than 100, it doesn't draw the text at the desired place. Can someone help me on this?

 
Jesper de Jong
Java Cowboy
Sheriff
Posts: 16060
88
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch.

What is "the desired place"? If we don't know exactly what you expect the output to be, then it's hard to tell you why it isn't doing what you expect.
 
Hari Th
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Jesper for taking a look at my question.

I should have said "at the given coordinate" instead of "the desired place". If you run the above code and take a look at the saved PNG file, you will see two "A"s printed on that image. Both of them are printed at (800, 370) coordinate. My issue is related to the rotated string "A".

Let me walk through some lines of the code above and explain you the issue.

The following two lines create a font with font size 100.0 and bold style.



Here I am creating an affinetransform object with the rotation angle and then applying it to a new font.



And then with the following two lines, I am drawing the text "A" at the coordinate (800,370). The text "A" is rotated A on the image.



Issue:
The rotated text "A" is not getting printed at (800,370) coordinate when I set the font size value greater than 100.0 at the line "font = font.deriveFont(1,(float) 101.0)" above. Please note that if the font size value is less than or equal to 100.0, then the text "A" is getting printed at the (800,370) coordinate.

Now what I want to understand here is why the rotated "A" doesn't get printed at the coordinate (800,370) when the value of the font size is greater than 100.0?
 
Piet Souris
Master Rancher
Posts: 2044
75
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi Hari,

I just tried your program and indeed, the rotated "A" disappears out of sight.
I don't know why that happens, unfortunately.

However, is there any particular reason why you do

?

It takes quite some time on my laptop.
I tried the following code:

It runs faster and gives the desired outcome.

Greetz,
Piet
 
Gary W. Lucas
Ranch Hand
Posts: 67
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would have thought that by applying a transformation to the font in the derive method, you would get a rotated font. But looking at your code and playing with this, I think that the way the Java API works is a bit more complicated. I think that when you derive a font with an affine transform, it doesn't alter the font, but rather concatenates a transform into the rendering operations. This is effectively the same thing as if you were using the non-rotated font, called g2d.transform(...), and then rendered. What happens, is the whole coordinate system is rotated by 270 degrees. So when you try to draw a font at coordinates (800,370), those coordinates themselves are translated to (-370, 800). Thus your text is drawn at a position off the display.

I got the correct results by adding a translate to the transform and trying to draw the string at coordinates (0,0).




The problem with deriving a font using the code fragment above is that you have to derive a new font at each location where you wish to draw something. So Piet Souris' solution is probably better. He leaves the source font alone, but applies different transforms to the Graphics2D object. The g2d.rotate(-(Math.PI / 180 * 270), 800, 370) is convenient for this purpose because it takes care of the details of concatenating a combination of translations and a rotation to the graph. Just remember that if you want to do anything with your Graphics2D after you rotate it, you have to restore it to its original state first.

This is probably a better approach by remember to do the following:

 
Piet Souris
Master Rancher
Posts: 2044
75
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi Gary,

a fine analysis, thanks for that.

However, it leaves unanswered OP's problem: why does his/her method
work when the fond size is <= 100, but fails when it gets above 100?

Have you any idea?

Greetz,
Piet
 
Gary W. Lucas
Ranch Hand
Posts: 67
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Piet,

You ask a good question. I regret that I don't have a good answer. It is clear that, at the arbitrary font size of 100 points, the Java font rendering logic switches strategies. My guess is that it transitions from some kind of specialized (perhaps high performance) rendering to some kind of more general rendering. It looks like the handling of the AffineTransform is inconsistent between two strategies. The value 100 is clearly something that a human chose rather than being driven by digital or algorithmic considerations.

Unfortunately, I haven't been able to find any discussion of this. I've been through the Java API source code, Google, and the bugs.java.com database. A lot of the font rendering is conducted in compiled graphics code which isn't available (at least not without a lot more digging than I am ready to do).

The approach taken in the Java code from the original post is somewhat unusual. So it appears that not enough people have seen this problem that it has become well known. I've got to credit Hari Th with his persistence in finding the 100 point cutoff. My only suggestion to him would be to stick to the approach you recommended, since it avoids the issue.

Gary
 
Hari Th
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Gary for doing research on this and sharing your analysis.

I was also unable to find any documentation or any discussion about this issue. The coordinate system of the graphics2D ojbect gets changed when transformation is applied to the font and the font size is set to a value that is greater than 100.0. I struggled to understand the observed link/relationship between font transformation, font size, and the coordination system of the graphics2D.

Piet's approach also gives the desired outcome, but based on my personal experience this approach is slower than the other approach (applying transformation to the font first and then drawing it on an image). I didn't want to confuse people or divert the original topic to something else so I thought not to mix multiple issues and ask about performance related questions here.

Piet, Thanks for showing an alternative approach. You mentioned a word "faster" in your comment. Why do you think your approah is faster than the other?

I know the above question related to performance will divert the topic, which i didn't want to do. I was just trying to clarify why I didn't choose Pier's approach for my application. I am fine, if we don't want to discuss about the performance here.

 
Piet Souris
Master Rancher
Posts: 2044
75
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hari Th wrote:Thanks Gary for doing research on this and sharing your analysis.

I second that.


(...)
Piet, Thanks for showing an alternative approach. You mentioned a word "faster" in your comment. Why do you think your approah is faster than the other?

You're welcome.

Well, I did not do any time measuring, but I noticed that NetBeans took quite some time finishing
your code, while it finished my code a lot quicker. At least, that was my impression. Of course,
that may have been coincedental, so do not take my remark as being the truth and nothing but the truth!

Greetz,
Piet
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!