To my surprise I\'ve just discovered that drawLine and drawRect don\'t include the ending position, i.e.:
canvas.drawLine(100, 100, 100, 100, paint);
Your question reveals an inconsistency in the drawing API of Android. You say
So, if I want to draw a vertical line that goes exactly from beginY to endY (inclusive), I have to do the following:
canvas.drawLine(constX, beginY, constX, endY + 1)
Notice that I didn't add 1 to the ending X position, only to ending Y (xstays the same as I want a vertical line).
The sentence in brackets is in my opinion the key to understand the nature of the inconsistency:
You also could add 1 to the ending X position (or even to the beginning X position!), and you would get exactly the pixel-wise identical line. Why is that? Because the underlying algorithm to transform from Android's "left pixel in/right pixel out"-concept to the "start and end pixel in"-concept is as follows (shown only for x, for y it's the same):
int left, top, right, bottom; // left/top pixel inclusive, right/bottom pixel exclusive
int x1, y1, x2, y2; // x1/y1 and x2/y2 pixels inclusive
if ( left == right ) {
x1 = x2 = left;
} else if ( left < right ) {
x1 = left;
x2 = right - 1;
} else {
x1 = right;
x2 = left - 1;
}
The result of this (in my opinion sub-optimal) conversion is that the line
canvas.drawLine(150, 150, 149, 160, paint);
is exactly parallel to
canvas.drawLine(150, 150, 151, 160, paint);
I think everybody would expect kind of inverse V, since the end points are separated by at least 1 pixel (their distance being two pixels) and the starting points are identical.
But tested on various devices and Android versions, the 1st perfectly vertical line is in pixel column 149 and the 2nd in column 150.
BTW: The correct transformation to use the "start and end pixel in"-concept is:
int x1, y1, x2, y2; // x1/y1 and x2/y2 pixels inclusive
if ( x1 <= x2 )
++x2;
else
++x1;
if ( y1 <= y2 )
++y2;
else
++y1;
canvas.drawLine(x1, y1, x2, y2, paint);