def draw_linear_gradient(
    surf,
    color,
    start_percentage=0.125,
    stop_percentage=1,
    max_lightness_percentage=1.0,
    min_lightness_percentage=0.2,
    direction="left_to_right",
):
    """Draw linear gradient on given surface.

    Since operations are done in-place in the given surface,
    nothing meaningful is returned.

    Parameters
    ==========
    surf (pygame.Surface instance)
        surface wherein to draw the gradient.
    color (sequence of RGB values)
        the rgb values are integers such that
        0 <= integer <= 255, representing values for
        red, green and blue channels respectively;
        a fourth integer may be present, representing
        the alpha, but it is ignored anyway; these
        values represent the base color for the gradient.
    start_percentage, stop_percentage (0.0 <= float <= 1.0)
        represent the interval of the surface's width
        in percentage wherein the color goes from
        maximum lightness to minimum lightness.
    max_lightness_percentage,
    min_lightness_percentage (0.0 <= float <= 1.0)
        represent the maximum and minimum percentage of
        the original lightness used in the gradient; that
        is, the color will go from the max lightness to
        the minimum lightness in the gradient.
    direction (string)
        indicates the direction of the gradient; must be
        one of the following: 'left_to_right',
        'right_to_left', 'top_to_bottom' or 'bottom_to_top'.
    """
    ### if the gradient is vertical (from bottom to top or
    ### vice-versa), backup the original surf and obtain
    ### a new surf rotated 90 degrees

    if direction in ("bottom_to_top", "top_to_bottom"):

        backup_surf = surf
        surf = rotate_surface(surf, 90)

    ### store needed data for future calculations

    width, height = surf.get_size()

    start = round(width * start_percentage)
    stop = round(width * stop_percentage)
    total = stop - start

    lightness_factor = 1.0 - min_lightness_percentage

    ### define the hue, lightness and saturation of the
    ### base color

    hue, lightness, saturation = rgb_to_hls(*[v / 255 for v in color[:3]])

    ### iterate over all vertical sections of the
    ### surface represented by all possible values of
    ### x within the width of the surface

    for x in range(width):

        ## if x is before or at the start, the max
        ## lightness percentage is used as the percentage
        if x <= start:
            percent = max_lightness_percentage

        ## if x is at or after the stop, the min
        ## lightness percentage is used as the percentage
        elif x >= stop:
            percent = min_lightness_percentage

        ## if it is between the start and stop, though,
        ## we use the max lightness percentage minus
        ## the progress towards the stop

        elif start < x < stop:

            progress = (x - start) / total

            percent = max_lightness_percentage - (progress * lightness_factor)

        ## we then calculate the lightness
        current_lightness = lightness * percent

        ## obtain the resulting color

        color = [
            round(value * 255)
            for value in hls_to_rgb(hue, current_lightness, saturation)
        ]

        ## and use it to draw a line on the vertical section
        draw_line(surf, color, (x, 0), (x, height), 1)

    ### direction setups

    ## if the direction is right to left, just obtain a new
    ## surface corresponding to the current one rotated
    ## 180 degrees then blit such surface over the current
    ## one (resulting in the current surface being overriden
    ## by the rotated one)

    if direction == "right_to_left":

        new_surf = rotate_surface(surf, 180)
        surf.blit(new_surf, (0, 0))

    ## if the direction is vertical, specific setups are
    ## needed

    elif direction in ("bottom_to_top", "top_to_bottom"):

        # define the amount of rotation needed according
        # to the specific vertical direction
        rotation_amount = 90 if direction == "bottom_to_top" else -90

        # rotate the current surface by negative 90 degrees
        # and blit it over the backup surf (which is a
        # reference to the original surf before being
        # rotated)

        new_surf = rotate_surface(surf, rotation_amount)
        backup_surf.blit(new_surf, (0, 0))

    ### for debugging: uncomment drawing command below to
    ### see line from where the gradient begin to shift
    ### (when the direction is 'left_to_right')
    ###
    ### draw_line(
    ###   surf, (255,)*3, (start, 0), (start, height), 1
    ### )
Draw linear gradient on given surface.

    Since operations are done in-place in the given surface,
    nothing meaningful is returned.

    Parameters
    ==========
    surf (pygame.Surface instance)
        surface wherein to draw the gradient.
    color (sequence of RGB values)
        the rgb values are integers such that
        0 <= integer <= 255, representing values for
        red, green and blue channels respectively;
        a fourth integer may be present, representing
        the alpha, but it is ignored anyway; these
        values represent the base color for the gradient.
    start_percentage, stop_percentage (0.0 <= float <= 1.0)
        represent the interval of the surface's width
        in percentage wherein the color goes from
        maximum lightness to minimum lightness.
    max_lightness_percentage,
    min_lightness_percentage (0.0 <= float <= 1.0)
        represent the maximum and minimum percentage of
        the original lightness used in the gradient; that
        is, the color will go from the max lightness to
        the minimum lightness in the gradient.
    direction (string)
        indicates the direction of the gradient; must be
        one of the following: 'left_to_right',
        'right_to_left', 'top_to_bottom' or 'bottom_to_top'.
    
nodezator/surfsman/draw.py