diff options
Diffstat (limited to 'src/osd/windows/window.cpp')
-rw-r--r-- | src/osd/windows/window.cpp | 79 |
1 files changed, 71 insertions, 8 deletions
diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp index 88c2e2d5ad1..173ea376d7f 100644 --- a/src/osd/windows/window.cpp +++ b/src/osd/windows/window.cpp @@ -1613,6 +1613,12 @@ void win_window_info::draw_video_contents(HDC dc, int update) } +static inline int better_mode(int width0, int height0, int width1, int height1, float desired_aspect) +{ + float aspect0 = (float)width0 / (float)height0; + float aspect1 = (float)width1 / (float)height1; + return (fabs(desired_aspect - aspect0) < fabs(desired_aspect - aspect1)) ? 0 : 1; +} //============================================================ // constrain_to_aspect_ratio @@ -1626,15 +1632,19 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad INT32 propwidth, propheight; INT32 minwidth, minheight; INT32 maxwidth, maxheight; - INT32 viswidth, visheight; INT32 adjwidth, adjheight; - float pixel_aspect; + float desired_aspect = 1.0f; + osd_dim window_dim = get_size(); + INT32 target_width = window_dim.width(); + INT32 target_height = window_dim.height(); + INT32 xscale = 1, yscale = 1; + int newwidth, newheight; osd_monitor_info *monitor = winwindow_video_window_monitor(&rect); assert(GetCurrentThreadId() == window_threadid); // get the pixel aspect ratio for the target monitor - pixel_aspect = monitor->aspect(); + float pixel_aspect = monitor->aspect(); // determine the proposed width/height propwidth = rect.width() - extrawidth; @@ -1662,6 +1672,61 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad // get the minimum width/height for the current layout m_target->compute_minimum_size(minwidth, minheight); + // compute the appropriate visible area if we're trying to keepaspect + if (video_config.keepaspect) + { + // make sure the monitor is up-to-date + m_target->compute_visible_area(target_width, target_height, m_monitor->aspect(), m_target->orientation(), target_width, target_height); + desired_aspect = (float)target_width / (float)target_height; + } + + // non-integer scaling - often gives more pleasing results in full screen + if (!video_config.fullstretch) + { + // compute maximum integral scaling to fit the window + xscale = (target_width + 2) / newwidth; + yscale = (target_height + 2) / newheight; + + // try a little harder to keep the aspect ratio if desired + if (video_config.keepaspect) + { + // if we could stretch more in the X direction, and that makes a better fit, bump the xscale + while (newwidth * (xscale + 1) <= window_dim.width() && + better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale + 1), newheight * yscale, desired_aspect)) + xscale++; + + // if we could stretch more in the Y direction, and that makes a better fit, bump the yscale + while (newheight * (yscale + 1) <= window_dim.height() && + better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale + 1), desired_aspect)) + yscale++; + + // now that we've maxed out, see if backing off the maximally stretched one makes a better fit + if (window_dim.width() - newwidth * xscale < window_dim.height() - newheight * yscale) + { + while (better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect) && (xscale >= 0)) + xscale--; + } + else + { + while (better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale - 1), desired_aspect) && (yscale >= 0)) + yscale--; + } + } + + // ensure at least a scale factor of 1 + if (xscale <= 0) xscale = 1; + if (yscale <= 0) yscale = 1; + + // apply the final scale + newwidth *= xscale; + newheight *= yscale; + } + else + { + newwidth = target_width; + newheight = target_height; + } + // clamp against the absolute minimum propwidth = MAX(propwidth, MIN_WINDOW_DIM); propheight = MAX(propheight, MIN_WINDOW_DIM); @@ -1692,12 +1757,9 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad propwidth = MIN(propwidth, maxwidth); propheight = MIN(propheight, maxheight); - // compute the visible area based on the proposed rectangle - m_target->compute_visible_area(propwidth, propheight, pixel_aspect, m_target->orientation(), viswidth, visheight); - // compute the adjustments we need to make - adjwidth = (viswidth + extrawidth) - rect.width(); - adjheight = (visheight + extraheight) - rect.height(); + adjwidth = (propwidth + extrawidth) - rect.width(); + adjheight = (propheight + extraheight) - rect.height(); // based on which corner we're adjusting, constrain in different ways osd_rect ret(rect); @@ -1724,6 +1786,7 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad ret = rect.move_by(0, -adjheight).resize(rect.width() + adjwidth, rect.height() + adjheight); break; } + return ret; } |