@ -87,6 +87,26 @@ get_preferred_display_bounds(struct size *bounds) {
return true ;
}
// Indicate if the width should be kept on computing the optimal rectangle size
// to display the content in the window.
// Return true if the width should be kept, false if the height should be kept.
static bool
should_keep_width ( struct size window_size , struct size content_size ) {
// 32 bits because we need to multiply two 16 bits values
uint32_t ww = window_size . width ;
uint32_t wh = window_size . height ;
uint32_t cw = content_size . width ;
uint32_t ch = content_size . height ;
// To avoid keeping alternatively width and height on successive resizes
// due to rounding to integer, always prefer height (arbitrarily) if in the
// error range.
// err = ceil of content aspect ratio
unsigned err = ( cw + ch - 1 ) / ch ;
return cw * wh > ch * ( ww + err ) ;
}
// return the optimal size of the window, with the following constraints:
// - it attempts to keep at least one dimension of the current_size (i.e. it
// crops the black borders)
@ -99,33 +119,33 @@ get_optimal_size(struct size current_size, struct size content_size) {
return current_size ;
}
struct size display_size ;
// 32 bits because we need to multiply two 16 bits values
uint32_t w ;
uint32_t h ;
struct size window_size ;
struct size display_size ;
if ( ! get_preferred_display_bounds ( & display_size ) ) {
// could not get display bounds, do not constraint the size
w = current_size . width ;
h = current_size . height ;
w indow_size. width = current_size . width ;
window_size. height = current_size . height ;
} else {
w = MIN ( current_size . width , display_size . width ) ;
h = MIN ( current_size . height , display_size . height ) ;
w indow_size. width = MIN ( current_size . width , display_size . width ) ;
window_size. height = MIN ( current_size . height , display_size . height ) ;
}
bool keep_width = content_size . width * h > content_size . height * w ;
bool keep_width = should_keep_width ( window_size , content_size ) ;
if ( keep_width ) {
// remove black borders on top and bottom
h = content_size . height * w / content_size . width ;
window_size . height = content_size . height * window_size . width
/ content_size . width ;
} else {
// remove black borders on left and right (or none at all if it already
// fits)
w = content_size . width * h / content_size . height ;
window_size . width = content_size . width * window_size . height
/ content_size . height ;
}
// w and h must fit into 16 bits
assert ( w < 0x10000 & & h < 0x10000 ) ;
return ( struct size) { w , h } ;
// w idth and height must fit into 16 bits
assert ( w indow_size. width < 0x10000 & & window_size. height < 0x10000 ) ;
return window_ size;
}
// same as get_optimal_size(), but read the current size from the window
@ -164,17 +184,19 @@ get_initial_optimal_size(struct size content_size, uint16_t req_width,
static void
update_content_rect ( struct screen * screen ) {
int w w ;
int w h;
SDL_GL_GetDrawableSize ( screen - > window , & w w , & w h) ;
int w ;
int h;
SDL_GL_GetDrawableSize ( screen - > window , & w , & h) ;
// 32 bits because we need to multiply two 16 bits values
uint32_t cw = screen - > content_size . width ;
uint32_t ch = screen - > content_size . height ;
struct size window_size = { w , h } ;
uint16_t ww = window_size . width ;
uint16_t wh = window_size . height ;
uint16_t cw = screen - > content_size . width ;
uint16_t ch = screen - > content_size . height ;
SDL_Rect * rect = & screen - > rect ;
bool keep_width = cw * wh > ch * ww ;
bool keep_width = should_keep_width ( window_size , screen - > content_size ) ;
if ( keep_width ) {
rect - > x = 0 ;
rect - > w = ww ;