+//! Helper routine for gfx_line().
+static int gfx_findRegion(int x, int y, Rect *cr)
+{
+ int code = 0;
+
+ if (y >= cr->ymax)
+ code |= 1; /* below */
+ else if (y < cr->ymin)
+ code |= 2; /* above */
+
+ if (x >= cr->xmax)
+ code |= 4; /* right */
+ else if (x < cr->xmin)
+ code |= 8; /* left */
+
+ return code;
+}
+
+/**
+ * Draw a sloped line segment.
+ *
+ * Draw a sloped line segment identified by the provided
+ * start and end coordinates on the bitmap \a bm.
+ *
+ * The line endpoints are clipped inside the current bitmap
+ * clipping rectangle using the Cohen-Sutherland algorithm,
+ * which is very fast.
+ *
+ * \note The point at coordinates \a x2 \a y2 is not drawn.
+ *
+ * \note This function does \b not update the current pen position.
+ *
+ * \todo Compute updated Bresenham error term.
+ */
+void gfx_line(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2)
+{
+#if CONFIG_GFX_CLIPPING
+ int clip1 = gfx_findRegion(x1, y1, &bm->cr);
+ int clip2 = gfx_findRegion(x2, y2, &bm->cr);
+
+ /* Loop while there is at least one point outside */
+ while (clip1 | clip2)
+ {
+ /* Check for line totally outside */
+ if (clip1 & clip2)
+ return;
+
+ int c = clip1 ? clip1 : clip2;
+ int x, y;
+
+ if (c & 1) /* Below */
+ {
+ x = x1 + (x2 - x1) * (bm->cr.ymax - y1) / (y2 - y1);
+ y = bm->cr.ymax - 1;
+ }
+ else if (c & 2) /* Above */
+ {
+ x = x1 + (x2 - x1) * (bm->cr.ymin - y1) / (y2 - y1);
+ y = bm->cr.ymin;
+ }
+ else if (c & 4) /* Right */
+ {
+ y = y1 + (y2 - y1) * (bm->cr.xmax - x1) / (x2 - x1);
+ x = bm->cr.xmax - 1;
+ }
+ else /* Left */
+ {
+ y = y1 + (y2 - y1) * (bm->cr.xmin - x1) / (x2 - x1);
+ x = bm->cr.xmin;
+ }
+
+ if (c == clip1) /* First endpoint was clipped */
+ {
+ // TODO: adjust Bresenham error term
+ //coord_t clipdx = ABS(x - x1);
+ //coord_t clipdy = ABS(y - y1);
+ //e += (clipdy * e2) + ((clipdx - clipdy) * e1);
+
+ x1 = x;
+ y1 = y;
+ clip1 = gfx_findRegion(x1, y1, &bm->cr);
+ }
+ else /* Second endpoint was clipped */
+ {
+ x2 = x;
+ y2 = y;
+ clip2 = gfx_findRegion(x2, y2, &bm->cr);
+ }
+ }
+#endif /* CONFIG_GFX_CLIPPING */
+
+ gfx_lineUnclipped(bm, x1, y1, x2, y2);
+}