In fact, Gilbert's suggestion painted the string centered around the rotation point, so the rotated string has extra space (r.height - textWidth) / 2. If I subtract this value from x-position, it starts working perfectly. So, the simplified correct version should be:
g2d.drawString(text, x0 - r.height / 2, y0 + fontMetrics.getDescent());