Canvas' drawLine and drawRect not including end position?

后端 未结 4 1066
无人共我
无人共我 2021-02-13 03:20

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);
4条回答
  •  感情败类
    2021-02-13 03:37

    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);
    

提交回复
热议问题