trunk/src/osd/windows/window.cpp
| r253695 | r253696 | |
| 1613 | 1613 | } |
| 1614 | 1614 | |
| 1615 | 1615 | |
| 1616 | static inline int better_mode(int width0, int height0, int width1, int height1, float desired_aspect) |
| 1617 | { |
| 1618 | float aspect0 = (float)width0 / (float)height0; |
| 1619 | float aspect1 = (float)width1 / (float)height1; |
| 1620 | return (fabs(desired_aspect - aspect0) < fabs(desired_aspect - aspect1)) ? 0 : 1; |
| 1621 | } |
| 1616 | 1622 | |
| 1617 | 1623 | //============================================================ |
| 1618 | 1624 | // constrain_to_aspect_ratio |
| r253695 | r253696 | |
| 1626 | 1632 | INT32 propwidth, propheight; |
| 1627 | 1633 | INT32 minwidth, minheight; |
| 1628 | 1634 | INT32 maxwidth, maxheight; |
| 1629 | | INT32 viswidth, visheight; |
| 1630 | 1635 | INT32 adjwidth, adjheight; |
| 1631 | | float pixel_aspect; |
| 1636 | float desired_aspect = 1.0f; |
| 1637 | osd_dim window_dim = get_size(); |
| 1638 | INT32 target_width = window_dim.width(); |
| 1639 | INT32 target_height = window_dim.height(); |
| 1640 | INT32 xscale = 1, yscale = 1; |
| 1641 | int newwidth, newheight; |
| 1632 | 1642 | osd_monitor_info *monitor = winwindow_video_window_monitor(&rect); |
| 1633 | 1643 | |
| 1634 | 1644 | assert(GetCurrentThreadId() == window_threadid); |
| 1635 | 1645 | |
| 1636 | 1646 | // get the pixel aspect ratio for the target monitor |
| 1637 | | pixel_aspect = monitor->aspect(); |
| 1647 | float pixel_aspect = monitor->aspect(); |
| 1638 | 1648 | |
| 1639 | 1649 | // determine the proposed width/height |
| 1640 | 1650 | propwidth = rect.width() - extrawidth; |
| r253695 | r253696 | |
| 1662 | 1672 | // get the minimum width/height for the current layout |
| 1663 | 1673 | m_target->compute_minimum_size(minwidth, minheight); |
| 1664 | 1674 | |
| 1675 | // compute the appropriate visible area if we're trying to keepaspect |
| 1676 | if (video_config.keepaspect) |
| 1677 | { |
| 1678 | // make sure the monitor is up-to-date |
| 1679 | m_target->compute_visible_area(target_width, target_height, m_monitor->aspect(), m_target->orientation(), target_width, target_height); |
| 1680 | desired_aspect = (float)target_width / (float)target_height; |
| 1681 | } |
| 1682 | |
| 1683 | // non-integer scaling - often gives more pleasing results in full screen |
| 1684 | if (!video_config.fullstretch) |
| 1685 | { |
| 1686 | // compute maximum integral scaling to fit the window |
| 1687 | xscale = (target_width + 2) / newwidth; |
| 1688 | yscale = (target_height + 2) / newheight; |
| 1689 | |
| 1690 | // try a little harder to keep the aspect ratio if desired |
| 1691 | if (video_config.keepaspect) |
| 1692 | { |
| 1693 | // if we could stretch more in the X direction, and that makes a better fit, bump the xscale |
| 1694 | while (newwidth * (xscale + 1) <= window_dim.width() && |
| 1695 | better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale + 1), newheight * yscale, desired_aspect)) |
| 1696 | xscale++; |
| 1697 | |
| 1698 | // if we could stretch more in the Y direction, and that makes a better fit, bump the yscale |
| 1699 | while (newheight * (yscale + 1) <= window_dim.height() && |
| 1700 | better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale + 1), desired_aspect)) |
| 1701 | yscale++; |
| 1702 | |
| 1703 | // now that we've maxed out, see if backing off the maximally stretched one makes a better fit |
| 1704 | if (window_dim.width() - newwidth * xscale < window_dim.height() - newheight * yscale) |
| 1705 | { |
| 1706 | while (better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect) && (xscale >= 0)) |
| 1707 | xscale--; |
| 1708 | } |
| 1709 | else |
| 1710 | { |
| 1711 | while (better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale - 1), desired_aspect) && (yscale >= 0)) |
| 1712 | yscale--; |
| 1713 | } |
| 1714 | } |
| 1715 | |
| 1716 | // ensure at least a scale factor of 1 |
| 1717 | if (xscale <= 0) xscale = 1; |
| 1718 | if (yscale <= 0) yscale = 1; |
| 1719 | |
| 1720 | // apply the final scale |
| 1721 | newwidth *= xscale; |
| 1722 | newheight *= yscale; |
| 1723 | } |
| 1724 | else |
| 1725 | { |
| 1726 | newwidth = target_width; |
| 1727 | newheight = target_height; |
| 1728 | } |
| 1729 | |
| 1665 | 1730 | // clamp against the absolute minimum |
| 1666 | 1731 | propwidth = MAX(propwidth, MIN_WINDOW_DIM); |
| 1667 | 1732 | propheight = MAX(propheight, MIN_WINDOW_DIM); |
| r253695 | r253696 | |
| 1692 | 1757 | propwidth = MIN(propwidth, maxwidth); |
| 1693 | 1758 | propheight = MIN(propheight, maxheight); |
| 1694 | 1759 | |
| 1695 | | // compute the visible area based on the proposed rectangle |
| 1696 | | m_target->compute_visible_area(propwidth, propheight, pixel_aspect, m_target->orientation(), viswidth, visheight); |
| 1697 | | |
| 1698 | 1760 | // compute the adjustments we need to make |
| 1699 | | adjwidth = (viswidth + extrawidth) - rect.width(); |
| 1700 | | adjheight = (visheight + extraheight) - rect.height(); |
| 1761 | adjwidth = (propwidth + extrawidth) - rect.width(); |
| 1762 | adjheight = (propheight + extraheight) - rect.height(); |
| 1701 | 1763 | |
| 1702 | 1764 | // based on which corner we're adjusting, constrain in different ways |
| 1703 | 1765 | osd_rect ret(rect); |
| r253695 | r253696 | |
| 1724 | 1786 | ret = rect.move_by(0, -adjheight).resize(rect.width() + adjwidth, rect.height() + adjheight); |
| 1725 | 1787 | break; |
| 1726 | 1788 | } |
| 1789 | |
| 1727 | 1790 | return ret; |
| 1728 | 1791 | } |
| 1729 | 1792 | |