summaryrefslogtreecommitdiffstats
path: root/common/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/common.c')
-rw-r--r--common/common.c71
1 files changed, 63 insertions, 8 deletions
diff --git a/common/common.c b/common/common.c
index e8a100dcc4..6607f95c3c 100644
--- a/common/common.c
+++ b/common/common.c
@@ -96,10 +96,10 @@ char *mp_format_time(double time, bool fractions)
// Set rc to the union of rc and rc2
void mp_rect_union(struct mp_rect *rc, const struct mp_rect *rc2)
{
- rc->x0 = FFMIN(rc->x0, rc2->x0);
- rc->y0 = FFMIN(rc->y0, rc2->y0);
- rc->x1 = FFMAX(rc->x1, rc2->x1);
- rc->y1 = FFMAX(rc->y1, rc2->y1);
+ rc->x0 = MPMIN(rc->x0, rc2->x0);
+ rc->y0 = MPMIN(rc->y0, rc2->y0);
+ rc->x1 = MPMAX(rc->x1, rc2->x1);
+ rc->y1 = MPMAX(rc->y1, rc2->y1);
}
// Returns whether or not a point is contained by rc
@@ -112,10 +112,10 @@ bool mp_rect_contains(struct mp_rect *rc, int x, int y)
// Return false if the result is empty.
bool mp_rect_intersection(struct mp_rect *rc, const struct mp_rect *rc2)
{
- rc->x0 = FFMAX(rc->x0, rc2->x0);
- rc->y0 = FFMAX(rc->y0, rc2->y0);
- rc->x1 = FFMIN(rc->x1, rc2->x1);
- rc->y1 = FFMIN(rc->y1, rc2->y1);
+ rc->x0 = MPMAX(rc->x0, rc2->x0);
+ rc->y0 = MPMAX(rc->y0, rc2->y0);
+ rc->x1 = MPMIN(rc->x1, rc2->x1);
+ rc->y1 = MPMIN(rc->y1, rc2->y1);
return rc->x1 > rc->x0 && rc->y1 > rc->y0;
}
@@ -126,6 +126,28 @@ bool mp_rect_equals(struct mp_rect *rc1, struct mp_rect *rc2)
rc1->x1 == rc2->x1 && rc1->y1 == rc2->y1;
}
+// Compute rc1-rc2, put result in res_array, return number of rectangles in
+// res_array. In the worst case, there are 4 rectangles, so res_array must
+// provide that much storage space.
+int mp_rect_subtract(const struct mp_rect *rc1, const struct mp_rect *rc2,
+ struct mp_rect res[4])
+{
+ struct mp_rect rc = *rc1;
+ if (!mp_rect_intersection(&rc, rc2))
+ return 0;
+
+ int cnt = 0;
+ if (rc1->y0 < rc.y0)
+ res[cnt++] = (struct mp_rect){rc1->x0, rc1->y0, rc1->x1, rc.y0};
+ if (rc1->x0 < rc.x0)
+ res[cnt++] = (struct mp_rect){rc1->x0, rc.y0, rc.x0, rc.y1};
+ if (rc1->x1 > rc.x1)
+ res[cnt++] = (struct mp_rect){rc.x1, rc.y0, rc1->x1, rc.y1};
+ if (rc1->y1 > rc.y1)
+ res[cnt++] = (struct mp_rect){rc1->x0, rc.y1, rc1->x1, rc1->y1};
+ return cnt;
+}
+
// This works like snprintf(), except that it starts writing the first output
// character to str[strlen(str)]. This returns the number of characters the
// string would have *appended* assuming a large enough buffer, will make sure
@@ -318,3 +340,36 @@ char **mp_dup_str_array(void *tctx, char **s)
MP_TARRAY_APPEND(tctx, r, num_r, NULL);
return r;
}
+
+// Return rounded down integer log 2 of v, i.e. position of highest set bit.
+// mp_log2(0) == 0
+// mp_log2(1) == 0
+// mp_log2(31) == 4
+// mp_log2(32) == 5
+unsigned int mp_log2(uint32_t v)
+{
+#if defined(__GNUC__) && __GNUC__ >= 4
+ return v ? 31 - __builtin_clz(v) : 0;
+#else
+ for (int x = 31; x >= 0; x--) {
+ if (v & (((uint32_t)1) << x))
+ return x;
+ }
+ return 0;
+#endif
+}
+
+// If a power of 2, return it, otherwise return the next highest one, or 0.
+// mp_round_next_power_of_2(65) == 128
+// mp_round_next_power_of_2(64) == 64
+// mp_round_next_power_of_2(0) == 1
+// mp_round_next_power_of_2(UINT32_MAX) == 0
+uint32_t mp_round_next_power_of_2(uint32_t v)
+{
+ if (!v)
+ return 1;
+ if (!(v & (v - 1)))
+ return v;
+ int l = mp_log2(v) + 1;
+ return l == 32 ? 0 : (uint32_t)1 << l;
+}