mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
[ui] Add a specialized function for subrect allocation
While VRect_Difference worked for subrect allocation, it wasn't ideal as it tended to produce a lot of long, narrow strips that were difficult to reuse and thus wasted a lot of the super-rectangle's area. This is because it always does horizontal splits first. However, rewriting VRect_Difference didn't seem to be the best option. VRect_SubRect (the new function) takes only width and height, and splits the given rectangle such that if there are two off-cuts, they will be both the minimum and maximum possible area. This does seem to make for much better utilization of the available area. It's also faster as it does only the two splits, rather than four.
This commit is contained in:
parent
cd66dbfc97
commit
28e9a0a9ba
2 changed files with 64 additions and 0 deletions
|
@ -165,4 +165,27 @@ vrect_t *VRect_Union (const vrect_t *r1, const vrect_t *r2);
|
||||||
*/
|
*/
|
||||||
vrect_t *VRect_Merge (const vrect_t *r1, const vrect_t *r2);
|
vrect_t *VRect_Merge (const vrect_t *r1, const vrect_t *r2);
|
||||||
|
|
||||||
|
/** Return up to three rectangles resulting from carving out the upper-left
|
||||||
|
rectangle of the specified width and height.
|
||||||
|
|
||||||
|
The first rectangle in the list will be the part of the supplied rectangle
|
||||||
|
that is covered by \a width and \a height (if either parameter is larger
|
||||||
|
than the supplied rectangle, then the returned rectangle will have the same
|
||||||
|
size as the supplied rectangle in that dimension). The other rectangles,
|
||||||
|
if there are any, will be the remainder of the supplied rectangle such that
|
||||||
|
the areas are min-max (to avoid creating long narrow rectangles).
|
||||||
|
|
||||||
|
\param rect The rectangle to carve.
|
||||||
|
\param width Width of the sub-rectangle carved from \a rect.
|
||||||
|
\param height Height of the sub-rectangle carved from \a rect.
|
||||||
|
\return The carved-out sub-rectangle, plus up to two rectangles
|
||||||
|
representing the remainder of \a rect, with splits such
|
||||||
|
that the two rectangles are both minimum and maximum area.
|
||||||
|
The larger of the two remainder rectangles will allways be
|
||||||
|
last.
|
||||||
|
\note It is the caller's responsibility to delete the returned
|
||||||
|
rectangles.
|
||||||
|
*/
|
||||||
|
vrect_t *VRect_SubRect (const vrect_t *rect, int width, int height);
|
||||||
|
|
||||||
#endif//__QF_ui_vrect_h
|
#endif//__QF_ui_vrect_h
|
||||||
|
|
|
@ -258,3 +258,44 @@ cleanup:
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VISIBLE vrect_t *
|
||||||
|
VRect_SubRect (const vrect_t *rect, int width, int height)
|
||||||
|
{
|
||||||
|
if (width > rect->width) {
|
||||||
|
width = rect->width;
|
||||||
|
}
|
||||||
|
if (height > rect->height) {
|
||||||
|
height = rect->height;
|
||||||
|
}
|
||||||
|
int a = rect->height - height;
|
||||||
|
int b = rect->width - width;
|
||||||
|
vrect_t *r, *s;
|
||||||
|
if (b * height > a * width) {
|
||||||
|
// a horizontal cut produces a larger off-cut rectangle than a vertical
|
||||||
|
// cut, so do a vertical cut first so the off-cut is as small as
|
||||||
|
// possible
|
||||||
|
r = VRect_VSplit (rect, rect->x + width);
|
||||||
|
if (VRect_IsEmpty (r->next)) {
|
||||||
|
VRect_Delete (r->next);
|
||||||
|
r->next = 0;
|
||||||
|
}
|
||||||
|
s = VRect_HSplit (r, r->y + height);
|
||||||
|
} else {
|
||||||
|
r = VRect_HSplit (rect, rect->y + height);
|
||||||
|
if (VRect_IsEmpty (r->next)) {
|
||||||
|
VRect_Delete (r->next);
|
||||||
|
r->next = 0;
|
||||||
|
}
|
||||||
|
s = VRect_VSplit (r, r->x + width);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VRect_IsEmpty (s->next)) {
|
||||||
|
VRect_Delete (s->next);
|
||||||
|
s->next = r->next;
|
||||||
|
} else {
|
||||||
|
s->next->next = r->next;
|
||||||
|
}
|
||||||
|
VRect_Delete (r);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue