/* FvwmButtons v2.0.41-plural-Z-alpha, copyright 1996, Jarl Totland * This module, and the entire GoodStuff program, and the concept for * interfacing this module to the Window Manager, are all original work * by Robert Nation * * Copyright 1993, Robert Nation. No guarantees or warantees or anything * are provided or implied in any way whatsoever. Use this program at your * own risk. Permission to use this program for any purpose is given, * as long as the copyright is kept intact. */ #include "misc.h" /** *** ConstrainSize() *** Adjust a given width and height to account for the constraints imposed by *** size hints. *** The general algorithm, especially the aspect ratio stuff, is borrowed from *** uwm's CheckConsistency routine. **/ void ConstrainSize (XSizeHints *hints, int *widthp, int *heightp) { #define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) ) int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta; int baseWidth, baseHeight; int dwidth = *widthp, dheight = *heightp; if(hints->flags & PMinSize) { minWidth = hints->min_width; minHeight = hints->min_height; if(hints->flags & PBaseSize) { baseWidth = hints->base_width; baseHeight = hints->base_height; } else { baseWidth = hints->min_width; baseHeight = hints->min_height; } } else if(hints->flags & PBaseSize) { minWidth = hints->base_width; minHeight = hints->base_height; baseWidth = hints->base_width; baseHeight = hints->base_height; } else { minWidth = 1; minHeight = 1; baseWidth = 1; baseHeight = 1; } if(hints->flags & PMaxSize) { maxWidth = hints->max_width; maxHeight = hints->max_height; } else { maxWidth = 10000; maxHeight = 10000; } if(hints->flags & PResizeInc) { xinc = hints->width_inc; yinc = hints->height_inc; } else { xinc = 1; yinc = 1; } /* * First, clamp to min and max values */ if (dwidth < minWidth) dwidth = minWidth; if (dheight < minHeight) dheight = minHeight; if (dwidth > maxWidth) dwidth = maxWidth; if (dheight > maxHeight) dheight = maxHeight; /* * Second, fit to base + N * inc */ dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth; dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight; /* * Third, adjust for aspect ratio */ #define maxAspectX hints->max_aspect.x #define maxAspectY hints->max_aspect.y #define minAspectX hints->min_aspect.x #define minAspectY hints->min_aspect.y /* * The math looks like this: * * minAspectX dwidth maxAspectX * ---------- <= ------- <= ---------- * minAspectY dheight maxAspectY * * If that is multiplied out, then the width and height are * invalid in the following situations: * * minAspectX * dheight > minAspectY * dwidth * maxAspectX * dheight < maxAspectY * dwidth * */ if (hints->flags & PAspect) { if (minAspectX * dheight > minAspectY * dwidth) { delta = makemult(minAspectX * dheight / minAspectY - dwidth, xinc); if (dwidth + delta <= maxWidth) dwidth += delta; else { delta = makemult(dheight - dwidth*minAspectY/minAspectX, yinc); if (dheight - delta >= minHeight) dheight -= delta; } } if (maxAspectX * dheight < maxAspectY * dwidth) { delta = makemult(dwidth * maxAspectY / maxAspectX - dheight, yinc); if (dheight + delta <= maxHeight) dheight += delta; else { delta = makemult(dwidth - maxAspectX*dheight/maxAspectY, xinc); if (dwidth - delta >= minWidth) dwidth -= delta; } } } *widthp = dwidth; *heightp = dheight; return; #undef makemult #undef maxAspectX #undef maxAspectY #undef minAspectX #undef minAspectY }