We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 3597

Summary: Inconsistent implementation of logical versus physical window dimensions / coordinates
Product: SDL Reporter: MichaelIbison <ngc5548>
Component: renderAssignee: Sam Lantinga <slouken>
Status: ASSIGNED --- QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2 CC: ngc5548
Version: 2.0.5   
Hardware: x86_64   
OS: Windows 10   
Attachments: jpg of pentagram drawn using SDL_RenderDrawLine superimposed on noise

Description MichaelIbison 2017-03-01 22:07:28 UTC
Created attachment 2700 [details]
jpg of pentagram drawn using SDL_RenderDrawLine superimposed on noise

When physical & logical dimensions differ SDL_RenderDrawLine() behaves strangely. 

Generally, but not always

SDL_RenderDrawLine(r,x1,y1,x2,y2) 

draws a line from logical coordinate (x1,y1) to logical coordinate (x2,y2) but at the *physical* resolution, not the logical resolution. Though the start and end points are correctly interpreted, the line is comprised of (filled-in / written-to) pixels at the physical, rather than logical resolution.

An exception is if x1==x2 or y1==y2, i.e. if the line is vertical or horizontal. In *that* case the line is drawn at the logical resolution.

To illustrate, when the physical dimensions of the display are exactly 40 times the logical dimensions, the routine PLT_DrawWheel() (below) called as 

PLT_DrawWheel(r, 0, 255, 255, 5, 0.9, 0.0, 0.0);

gives a pentagram which in the attached image is superimposed on gray-level noise rendered at the logical resolution. Notice how the lines that are not vertical or horizontal terminate at the 'corners' of the logical resolution pixels. 

Ideally, one would want to be able to choose between these two types of behavior. In any case, having them applied inconsistently is a bug.


---------------------------------------------------------------------

#include <math.h>
#include <SDL.h>

#define PI 3.14159265359
#define CVT_TO_INT(x) ((int)round(x))

void PLT_DrawWheel(SDL_Renderer* r, Uint8 red, Uint8 green, Uint8 blue, int numSpokes,  double rimSize, double hubSize /* in [0,1] - relative to window */, double angularOffset /* in [0,1] */)
{
int w,h,i;
SDL_RenderGetLogicalSize(r,&w,&h);
SDL_SetRenderDrawColor(r,red,green,blue,ALPHA_MASK);

double originX=(((double)w)/2.0);
double originY=(((double)h)/2.0);
double hubRadius=hubSize * ((double)h)/2.0;
double rimRadius=rimSize * ((double)h)/2.0;


for(i=0;i<numSpokes;i++)
	{
	double angle1 = 2.0*PI*(angularOffset + ((double)i)/((double)numSpokes));
	double angle2 = 2.0*PI*(angularOffset + ((double)(i+1))/((double)numSpokes));

	int p1=CVT_TO_INT(originX+hubRadius*cos(angle1));
	int q1=CVT_TO_INT(originY+hubRadius*sin(angle1));
        int p2=CVT_TO_INT(originX+hubRadius*cos(angle2));
	int q2=CVT_TO_INT(originY+hubRadius*sin(angle2));

        int x1=CVT_TO_INT(originX+rimRadius*cos(angle1));
	int y1=CVT_TO_INT(originY+rimRadius*sin(angle1));
        int x2=CVT_TO_INT(originX+rimRadius*cos(angle2));
	int y2=CVT_TO_INT(originY+rimRadius*sin(angle2));

/* The statements commented out below trap and adjust the horizontal and vertical cases as a work-around to the rendering inconsistency. */

   // (p1==x1) x1++;
   // if (q1==y1) y1++;
        SDL_RenderDrawLine(r,p1,q1,x1,y1);
   //if (x1==x2) x2++;
   //if (y1==y2) y2++;
        SDL_RenderDrawLine(r,x1,y1,x2,y2);
	//if (p1==p2) p2++;
   //if (q1==q2) q2++; 
        SDL_RenderDrawLine(r,p1,q1,p2,q2);
	}
SDL_RenderPresent(r);
}
Comment 1 Sam Lantinga 2017-08-11 19:12:15 UTC
Yes, this is because texture and fill can be changed to sub-pixel precision, but we don't currently have sub-pixel line widths in the rendering drivers.