def preserve_ratio(svg, node, font_size, width, height, viewbox=None):
    """Compute scale and translation needed to preserve ratio."""
    viewbox = viewbox or node.get_viewbox()
    if viewbox:
        viewbox_width, viewbox_height = viewbox[2:]
    elif svg.tree == node:
        viewbox_width, viewbox_height = svg.get_intrinsic_size(font_size)
        if None in (viewbox_width, viewbox_height):
            return 1, 1, 0, 0
    else:
        return 1, 1, 0, 0

    scale_x = width / viewbox_width if viewbox_width else 1
    scale_y = height / viewbox_height if viewbox_height else 1

    aspect_ratio = node.get('preserveAspectRatio', 'xMidYMid').split()
    align = aspect_ratio[0]
    if align == 'none':
        x_position = 'min'
        y_position = 'min'
    else:
        meet_or_slice = aspect_ratio[1] if len(aspect_ratio) > 1 else None
        if meet_or_slice == 'slice':
            scale_value = max(scale_x, scale_y)
        else:
            scale_value = min(scale_x, scale_y)
        scale_x = scale_y = scale_value
        x_position = align[1:4].lower()
        y_position = align[5:].lower()

    if node.tag == 'marker':
        translate_x, translate_y = svg.point(
            node.get('refX'), node.get('refY', '0'), font_size)
    else:
        translate_x = 0
        if x_position == 'mid':
            translate_x = (width - viewbox_width * scale_x) / 2
        elif x_position == 'max':
            translate_x = width - viewbox_width * scale_x

        translate_y = 0
        if y_position == 'mid':
            translate_y += (height - viewbox_height * scale_y) / 2
        elif y_position == 'max':
            translate_y += height - viewbox_height * scale_y

    if viewbox:
        translate_x -= viewbox[0] * scale_x
        translate_y -= viewbox[1] * scale_y

    return scale_x, scale_y, translate_x, translate_y
Compute scale and translation needed to preserve ratio.
weasyprint/svg/utils.py