def cohensutherland(left, top, right, bottom, x1, y1, x2, y2):
    """Clips a line to a rectangular area.

    This implements the Cohen-Sutherland line clipping algorithm. ``left``,
    ``top``, ``right`` and ``bottom`` define the bounds of the clipping area,
    by which the line from ``(x1, y1)`` to ``(x2, y2)`` will be clipped.

    Args:
        left (int): The left boundary of the clipping area.
        top (int): The top boundary of the clipping area.
        right (int): The right boundary of the clipping area.
        bottom (int): The bottom boundary of the clipping area.
        x1 (int): The x-coordinate of the starting point of the line.
        y1 (int): The y-coordinate of the starting point of the line.
        x2 (int): The x-coordinate of the end point of the line.
        y2 (int): The y-coordinate of the end point of the line.

    Returns:
        tuple: The start and end coordinates of the clipped line in the form
        ``(cx1, cy1, cx2, cy2)``. If the line does not intersect with the
        rectangular clipping area, all 4 values will be ``None``.

    """
    LEFT, RIGHT, LOWER, UPPER = 1, 2, 4, 8

    if bottom > top:
        bottom, top = (top, bottom)

    def _getclip(xa, ya):
        p = 0
        if xa < left:
            p = LEFT
        elif xa > right:
            p = RIGHT
        if ya < bottom:
            p |= LOWER
        elif ya > top:
            p |= UPPER
        return p

    k1 = _getclip(x1, y1)
    k2 = _getclip(x2, y2)
    while (k1 | k2) != 0:
        if (k1 & k2) != 0:
            return None, None, None, None
        opt = k2 if k2 > k1 else k1
        if opt & UPPER:
            x = x1 + (x2 - x1) * (1.0 * (top - y1)) / (y2 - y1)
            y = top
        elif opt & LOWER:
            x = x1 + (x2 - x1) * (1.0 * (bottom - y1)) / (y2 - y1)
            y = bottom
        elif opt & RIGHT:
            y = y1 + (y2 - y1) * (1.0 * (right - x1)) / (x2 - x1)
            x = right
        elif opt & LEFT:
            y = y1 + (y2 - y1) * (1.0 * (left - x1)) / (x2 - x1)
            x = left
        else:
            # this should not happen
            raise RuntimeError("invalid clipping state")

        if opt == k1:
            x1, y1 = x, y
            k1 = _getclip(x1, y1)
        else:
            x2, y2 = x, y
            k2 = _getclip(x2, y2)

    return x1, y1, x2, y2