Index: uspace/lib/gfx/include/gfx/coord.h
===================================================================
--- uspace/lib/gfx/include/gfx/coord.h	(revision 4d9c8071cfd4fd433a31ad7f0edce89077cb3892)
+++ uspace/lib/gfx/include/gfx/coord.h	(revision fdc8e4053a18f2b30fdf821c1f0a755b6e34908e)
@@ -45,5 +45,7 @@
     gfx_coord_t *);
 extern void gfx_rect_translate(gfx_coord2_t *, gfx_rect_t *, gfx_rect_t *);
+extern void gfx_rect_rtranslate(gfx_coord2_t *, gfx_rect_t *, gfx_rect_t *);
 extern void gfx_rect_envelope(gfx_rect_t *, gfx_rect_t *, gfx_rect_t *);
+extern void gfx_rect_clip(gfx_rect_t *, gfx_rect_t *, gfx_rect_t *);
 extern void gfx_rect_points_sort(gfx_rect_t *, gfx_rect_t *);
 extern bool gfx_rect_is_empty(gfx_rect_t *);
Index: uspace/lib/gfx/src/coord.c
===================================================================
--- uspace/lib/gfx/src/coord.c	(revision 4d9c8071cfd4fd433a31ad7f0edce89077cb3892)
+++ uspace/lib/gfx/src/coord.c	(revision fdc8e4053a18f2b30fdf821c1f0a755b6e34908e)
@@ -87,5 +87,5 @@
 /** Move (translate) rectangle.
  *
- * @param trans Translation
+ * @param trans Translation offset
  * @param src Source rectangle
  * @param dest Destination rectangle
@@ -93,6 +93,18 @@
 void gfx_rect_translate(gfx_coord2_t *trans, gfx_rect_t *src, gfx_rect_t *dest)
 {
-	gfx_coord2_add(trans, &src->p0, &dest->p0);
-	gfx_coord2_add(trans, &src->p1, &dest->p1);
+	gfx_coord2_add(&src->p0, trans, &dest->p0);
+	gfx_coord2_add(&src->p1, trans, &dest->p1);
+}
+
+/** Reverse move (translate) rectangle.
+ *
+ * @param trans Translation offset
+ * @param src Source rectangle
+ * @param dest Destination rectangle
+ */
+void gfx_rect_rtranslate(gfx_coord2_t *trans, gfx_rect_t *src, gfx_rect_t *dest)
+{
+	gfx_coord2_subtract(&src->p0, trans, &dest->p0);
+	gfx_coord2_subtract(&src->p1, trans, &dest->p1);
 }
 
@@ -100,4 +112,8 @@
  *
  * Envelope is the minimal rectangle covering all pixels of both rectangles.
+ *
+ * @param a First rectangle
+ * @param b Second rectangle
+ * @param dest Place to store enveloping rectangle
  */
 void gfx_rect_envelope(gfx_rect_t *a, gfx_rect_t *b, gfx_rect_t *dest)
@@ -124,4 +140,26 @@
 	dest->p1.x = max(sa.p1.x, sb.p1.x);
 	dest->p1.y = max(sa.p1.y, sb.p1.y);
+}
+
+/** Compute intersection of two rectangles.
+ *
+ * If the two rectangles do not intersect, the result will be an empty
+ * rectangle (check with gfx_rect_is_empty()).
+ *
+ * @param rect Source rectangle
+ * @param clip Clipping rectangle
+ * @param dest Place to store clipped rectangle
+ */
+void gfx_rect_clip(gfx_rect_t *rect, gfx_rect_t *clip, gfx_rect_t *dest)
+{
+	gfx_rect_t srect, sclip;
+
+	gfx_rect_points_sort(rect, &srect);
+	gfx_rect_points_sort(clip, &sclip);
+
+	dest->p0.x = min(max(srect.p0.x, sclip.p0.x), sclip.p1.x);
+	dest->p0.y = min(max(srect.p0.y, sclip.p0.y), sclip.p1.y);
+	dest->p1.x = max(sclip.p0.x, min(srect.p1.x, sclip.p1.x));
+	dest->p1.y = max(sclip.p0.y, min(srect.p1.y, sclip.p1.y));
 }
 
Index: uspace/lib/gfx/test/coord.c
===================================================================
--- uspace/lib/gfx/test/coord.c	(revision 4d9c8071cfd4fd433a31ad7f0edce89077cb3892)
+++ uspace/lib/gfx/test/coord.c	(revision fdc8e4053a18f2b30fdf821c1f0a755b6e34908e)
@@ -34,8 +34,4 @@
 PCUT_TEST_SUITE(coord);
 
-extern void gfx_coord2_add(gfx_coord2_t *, gfx_coord2_t *, gfx_coord2_t *);
-extern void gfx_coord2_subtract(gfx_coord2_t *, gfx_coord2_t *, gfx_coord2_t *);
-extern void gfx_rect_translate(gfx_coord2_t *, gfx_rect_t *, gfx_rect_t *);
-
 /** gfx_coord2_add should add two coordinate vectors */
 PCUT_TEST(coord2_add)
@@ -51,6 +47,6 @@
 	gfx_coord2_add(&a, &b, &d);
 
-	PCUT_ASSERT_EQUALS(a.x + b.x, d.x);
-	PCUT_ASSERT_EQUALS(a.y + b.y, d.y);
+	PCUT_ASSERT_INT_EQUALS(a.x + b.x, d.x);
+	PCUT_ASSERT_INT_EQUALS(a.y + b.y, d.y);
 }
 
@@ -68,6 +64,6 @@
 	gfx_coord2_subtract(&a, &b, &d);
 
-	PCUT_ASSERT_EQUALS(a.x - b.x, d.x);
-	PCUT_ASSERT_EQUALS(a.y - b.y, d.y);
+	PCUT_ASSERT_INT_EQUALS(a.x - b.x, d.x);
+	PCUT_ASSERT_INT_EQUALS(a.y - b.y, d.y);
 }
 
@@ -89,8 +85,31 @@
 	gfx_rect_translate(&offs, &srect, &drect);
 
-	PCUT_ASSERT_EQUALS(offs.x + srect.p0.x, drect.p0.x);
-	PCUT_ASSERT_EQUALS(offs.y + srect.p0.y, drect.p0.y);
-	PCUT_ASSERT_EQUALS(offs.x + srect.p1.x, drect.p1.x);
-	PCUT_ASSERT_EQUALS(offs.y + srect.p1.y, drect.p1.y);
+	PCUT_ASSERT_INT_EQUALS(offs.x + srect.p0.x, drect.p0.x);
+	PCUT_ASSERT_INT_EQUALS(offs.y + srect.p0.y, drect.p0.y);
+	PCUT_ASSERT_INT_EQUALS(offs.x + srect.p1.x, drect.p1.x);
+	PCUT_ASSERT_INT_EQUALS(offs.y + srect.p1.y, drect.p1.y);
+}
+
+/** gfx_rect_rtranslate should reverse-translate rectangle */
+PCUT_TEST(rect_rtranslate)
+{
+	gfx_coord2_t offs;
+	gfx_rect_t srect;
+	gfx_rect_t drect;
+
+	offs.x = 5;
+	offs.y = 6;
+
+	srect.p0.x = 10;
+	srect.p0.y = 11;
+	srect.p1.x = 20;
+	srect.p1.y = 22;
+
+	gfx_rect_rtranslate(&offs, &srect, &drect);
+
+	PCUT_ASSERT_INT_EQUALS(srect.p0.x - offs.x, drect.p0.x);
+	PCUT_ASSERT_INT_EQUALS(srect.p0.y - offs.y, drect.p0.y);
+	PCUT_ASSERT_INT_EQUALS(srect.p1.x - offs.x, drect.p1.x);
+	PCUT_ASSERT_INT_EQUALS(srect.p1.y - offs.y, drect.p1.y);
 }
 
@@ -101,6 +120,6 @@
 
 	gfx_span_points_sort(1, 2, &a, &b);
-	PCUT_ASSERT_EQUALS(1, a);
-	PCUT_ASSERT_EQUALS(2, b);
+	PCUT_ASSERT_INT_EQUALS(1, a);
+	PCUT_ASSERT_INT_EQUALS(2, b);
 }
 
@@ -111,6 +130,6 @@
 
 	gfx_span_points_sort(1, 1, &a, &b);
-	PCUT_ASSERT_EQUALS(1, a);
-	PCUT_ASSERT_EQUALS(1, b);
+	PCUT_ASSERT_INT_EQUALS(1, a);
+	PCUT_ASSERT_INT_EQUALS(1, b);
 }
 
@@ -121,6 +140,6 @@
 
 	gfx_span_points_sort(1, 0, &a, &b);
-	PCUT_ASSERT_EQUALS(1, a);
-	PCUT_ASSERT_EQUALS(2, b);
+	PCUT_ASSERT_INT_EQUALS(1, a);
+	PCUT_ASSERT_INT_EQUALS(2, b);
 }
 
@@ -143,8 +162,8 @@
 
 	gfx_rect_envelope(&a, &b, &e);
-	PCUT_ASSERT_EQUALS(1, e.p0.x);
-	PCUT_ASSERT_EQUALS(2, e.p0.y);
-	PCUT_ASSERT_EQUALS(3, e.p1.x);
-	PCUT_ASSERT_EQUALS(4, e.p1.y);
+	PCUT_ASSERT_INT_EQUALS(1, e.p0.x);
+	PCUT_ASSERT_INT_EQUALS(2, e.p0.y);
+	PCUT_ASSERT_INT_EQUALS(3, e.p1.x);
+	PCUT_ASSERT_INT_EQUALS(4, e.p1.y);
 }
 
@@ -167,8 +186,8 @@
 
 	gfx_rect_envelope(&a, &b, &e);
-	PCUT_ASSERT_EQUALS(1, e.p0.x);
-	PCUT_ASSERT_EQUALS(2, e.p0.y);
-	PCUT_ASSERT_EQUALS(3, e.p1.x);
-	PCUT_ASSERT_EQUALS(4, e.p1.y);
+	PCUT_ASSERT_INT_EQUALS(1, e.p0.x);
+	PCUT_ASSERT_INT_EQUALS(2, e.p0.y);
+	PCUT_ASSERT_INT_EQUALS(3, e.p1.x);
+	PCUT_ASSERT_INT_EQUALS(4, e.p1.y);
 }
 
@@ -191,8 +210,8 @@
 
 	gfx_rect_envelope(&a, &b, &e);
-	PCUT_ASSERT_EQUALS(1, e.p0.x);
-	PCUT_ASSERT_EQUALS(2, e.p0.y);
-	PCUT_ASSERT_EQUALS(7, e.p1.x);
-	PCUT_ASSERT_EQUALS(8, e.p1.y);
+	PCUT_ASSERT_INT_EQUALS(1, e.p0.x);
+	PCUT_ASSERT_INT_EQUALS(2, e.p0.y);
+	PCUT_ASSERT_INT_EQUALS(7, e.p1.x);
+	PCUT_ASSERT_INT_EQUALS(8, e.p1.y);
 }
 
@@ -215,8 +234,8 @@
 
 	gfx_rect_envelope(&a, &b, &e);
-	PCUT_ASSERT_EQUALS(1, e.p0.x);
-	PCUT_ASSERT_EQUALS(2, e.p0.y);
-	PCUT_ASSERT_EQUALS(7, e.p1.x);
-	PCUT_ASSERT_EQUALS(8, e.p1.y);
+	PCUT_ASSERT_INT_EQUALS(1, e.p0.x);
+	PCUT_ASSERT_INT_EQUALS(2, e.p0.y);
+	PCUT_ASSERT_INT_EQUALS(7, e.p1.x);
+	PCUT_ASSERT_INT_EQUALS(8, e.p1.y);
 }
 
@@ -239,8 +258,8 @@
 
 	gfx_rect_envelope(&a, &b, &e);
-	PCUT_ASSERT_EQUALS(1, e.p0.x);
-	PCUT_ASSERT_EQUALS(2, e.p0.y);
-	PCUT_ASSERT_EQUALS(7, e.p1.x);
-	PCUT_ASSERT_EQUALS(8, e.p1.y);
+	PCUT_ASSERT_INT_EQUALS(1, e.p0.x);
+	PCUT_ASSERT_INT_EQUALS(2, e.p0.y);
+	PCUT_ASSERT_INT_EQUALS(7, e.p1.x);
+	PCUT_ASSERT_INT_EQUALS(8, e.p1.y);
 }
 
@@ -263,8 +282,8 @@
 
 	gfx_rect_envelope(&a, &b, &e);
-	PCUT_ASSERT_EQUALS(1, e.p0.x);
-	PCUT_ASSERT_EQUALS(2, e.p0.y);
-	PCUT_ASSERT_EQUALS(7, e.p1.x);
-	PCUT_ASSERT_EQUALS(8, e.p1.y);
+	PCUT_ASSERT_INT_EQUALS(1, e.p0.x);
+	PCUT_ASSERT_INT_EQUALS(2, e.p0.y);
+	PCUT_ASSERT_INT_EQUALS(7, e.p1.x);
+	PCUT_ASSERT_INT_EQUALS(8, e.p1.y);
 }
 
@@ -287,8 +306,152 @@
 
 	gfx_rect_envelope(&a, &b, &e);
-	PCUT_ASSERT_EQUALS(1, e.p0.x);
-	PCUT_ASSERT_EQUALS(1, e.p0.y);
-	PCUT_ASSERT_EQUALS(4, e.p1.x);
-	PCUT_ASSERT_EQUALS(4, e.p1.y);
+	PCUT_ASSERT_INT_EQUALS(1, e.p0.x);
+	PCUT_ASSERT_INT_EQUALS(1, e.p0.y);
+	PCUT_ASSERT_INT_EQUALS(4, e.p1.x);
+	PCUT_ASSERT_INT_EQUALS(4, e.p1.y);
+}
+
+/** Clip rectangle with rect completely inside the clipping rectangle */
+PCUT_TEST(rect_clip_rect_inside)
+{
+	gfx_rect_t rect;
+	gfx_rect_t clip;
+	gfx_rect_t dest;
+
+	rect.p0.x = 3;
+	rect.p0.y = 4;
+	rect.p1.x = 5;
+	rect.p1.y = 6;
+
+	clip.p0.x = 1;
+	clip.p0.y = 2;
+	clip.p1.x = 7;
+	clip.p1.y = 8;
+
+	gfx_rect_clip(&rect, &clip, &dest);
+	PCUT_ASSERT_INT_EQUALS(3, dest.p0.x);
+	PCUT_ASSERT_INT_EQUALS(4, dest.p0.y);
+	PCUT_ASSERT_INT_EQUALS(5, dest.p1.x);
+	PCUT_ASSERT_INT_EQUALS(6, dest.p1.y);
+}
+
+/** Clip rectangle with rect covering the clipping rectangle */
+PCUT_TEST(rect_clip_rect_covering)
+{
+	gfx_rect_t rect;
+	gfx_rect_t clip;
+	gfx_rect_t dest;
+
+	rect.p0.x = 1;
+	rect.p0.y = 2;
+	rect.p1.x = 7;
+	rect.p1.y = 8;
+
+	clip.p0.x = 3;
+	clip.p0.y = 4;
+	clip.p1.x = 5;
+	clip.p1.y = 6;
+
+	gfx_rect_clip(&rect, &clip, &dest);
+	PCUT_ASSERT_INT_EQUALS(3, dest.p0.x);
+	PCUT_ASSERT_INT_EQUALS(4, dest.p0.y);
+	PCUT_ASSERT_INT_EQUALS(5, dest.p1.x);
+	PCUT_ASSERT_INT_EQUALS(6, dest.p1.y);
+}
+
+/** Clip rectangle with rect outside, having lower coordinates */
+PCUT_TEST(rect_clip_rect_out_ll)
+{
+	gfx_rect_t rect;
+	gfx_rect_t clip;
+	gfx_rect_t dest;
+
+	rect.p0.x = 1;
+	rect.p0.y = 2;
+	rect.p1.x = 3;
+	rect.p1.y = 4;
+
+	clip.p0.x = 5;
+	clip.p0.y = 6;
+	clip.p1.x = 7;
+	clip.p1.y = 8;
+
+	gfx_rect_clip(&rect, &clip, &dest);
+	PCUT_ASSERT_INT_EQUALS(5, dest.p0.x);
+	PCUT_ASSERT_INT_EQUALS(6, dest.p0.y);
+	PCUT_ASSERT_INT_EQUALS(5, dest.p1.x);
+	PCUT_ASSERT_INT_EQUALS(6, dest.p1.y);
+}
+
+/** Clip rectangle with rect outside, having higher coordinates */
+PCUT_TEST(rect_clip_rect_out_hh)
+{
+	gfx_rect_t rect;
+	gfx_rect_t clip;
+	gfx_rect_t dest;
+
+	rect.p0.x = 5;
+	rect.p0.y = 6;
+	rect.p1.x = 7;
+	rect.p1.y = 8;
+
+	clip.p0.x = 1;
+	clip.p0.y = 2;
+	clip.p1.x = 3;
+	clip.p1.y = 4;
+
+	gfx_rect_clip(&rect, &clip, &dest);
+	PCUT_ASSERT_INT_EQUALS(3, dest.p0.x);
+	PCUT_ASSERT_INT_EQUALS(4, dest.p0.y);
+	PCUT_ASSERT_INT_EQUALS(3, dest.p1.x);
+	PCUT_ASSERT_INT_EQUALS(4, dest.p1.y);
+}
+
+/** Clip rectangle with rect partially outside, having lower coordinates */
+PCUT_TEST(rect_clip_rect_ll)
+{
+	gfx_rect_t rect;
+	gfx_rect_t clip;
+	gfx_rect_t dest;
+
+	rect.p0.x = 1;
+	rect.p0.y = 2;
+	rect.p1.x = 5;
+	rect.p1.y = 6;
+
+	clip.p0.x = 3;
+	clip.p0.y = 4;
+	clip.p1.x = 7;
+	clip.p1.y = 8;
+
+	gfx_rect_clip(&rect, &clip, &dest);
+	PCUT_ASSERT_INT_EQUALS(3, dest.p0.x);
+	PCUT_ASSERT_INT_EQUALS(4, dest.p0.y);
+	PCUT_ASSERT_INT_EQUALS(5, dest.p1.x);
+	PCUT_ASSERT_INT_EQUALS(6, dest.p1.y);
+}
+
+/** Clip rectangle with rect partially outside, having higher coordinates */
+PCUT_TEST(rect_clip_rect_hh)
+{
+	gfx_rect_t rect;
+	gfx_rect_t clip;
+	gfx_rect_t dest;
+
+	rect.p0.x = 3;
+	rect.p0.y = 4;
+	rect.p1.x = 7;
+	rect.p1.y = 8;
+
+	clip.p0.x = 1;
+	clip.p0.y = 2;
+	clip.p1.x = 5;
+	clip.p1.y = 6;
+
+	gfx_rect_clip(&rect, &clip, &dest);
+	PCUT_ASSERT_INT_EQUALS(3, dest.p0.x);
+	PCUT_ASSERT_INT_EQUALS(4, dest.p0.y);
+	PCUT_ASSERT_INT_EQUALS(5, dest.p1.x);
+	PCUT_ASSERT_INT_EQUALS(6, dest.p1.y);
 }
 
@@ -299,6 +462,6 @@
 
 	gfx_span_points_sort(1, 2, &s0, &s1);
-	PCUT_ASSERT_EQUALS(1, s0);
-	PCUT_ASSERT_EQUALS(2, s1);
+	PCUT_ASSERT_INT_EQUALS(1, s0);
+	PCUT_ASSERT_INT_EQUALS(2, s1);
 }
 
@@ -309,6 +472,6 @@
 
 	gfx_span_points_sort(2, 1, &s0, &s1);
-	PCUT_ASSERT_EQUALS(2, s0);
-	PCUT_ASSERT_EQUALS(3, s1);
+	PCUT_ASSERT_INT_EQUALS(2, s0);
+	PCUT_ASSERT_INT_EQUALS(3, s1);
 }
 
