def compute_variable_dimension(context, side_boxes, vertical, available_size):
    """Compute and set a margin box fixed dimension on ``box``

    Described in: https://drafts.csswg.org/css-page-3/#margin-dimension

    :param side_boxes:
        Three boxes on a same side (as opposed to a corner).
        A list of:
        - A @*-left or @*-top margin box
        - A @*-center or @*-middle margin box
        - A @*-right or @*-bottom margin box
    :param vertical:
        ``True`` to set height, margin-top and margin-bottom;
        ``False`` for width, margin-left and margin-right.
    :param available_size:
        The distance between the page box’s left right border edges

    """
    box_class = VerticalBox if vertical else HorizontalBox
    side_boxes = [box_class(context, box) for box in side_boxes]
    box_a, box_b, box_c = side_boxes

    for box in side_boxes:
        if box.margin_a == 'auto':
            box.margin_a = 0
        if box.margin_b == 'auto':
            box.margin_b = 0

    if not box_b.box.is_generated:
        # Non-generated boxes get zero for every box-model property
        assert box_b.inner == 0
        if box_a.inner == box_c.inner == 'auto':
            # A and C both have 'width: auto'
            if available_size > (
                    box_a.outer_max_content_size +
                    box_c.outer_max_content_size):
                # sum of the outer max-content widths
                # is less than the available width
                flex_space = (
                    available_size -
                    box_a.outer_max_content_size -
                    box_c.outer_max_content_size)
                flex_factor_a = box_a.outer_max_content_size
                flex_factor_c = box_c.outer_max_content_size
                flex_factor_sum = flex_factor_a + flex_factor_c
                if flex_factor_sum == 0:
                    flex_factor_sum = 1
                box_a.outer = box_a.max_content_size + (
                    flex_space * flex_factor_a / flex_factor_sum)
                box_c.outer = box_c.max_content_size + (
                    flex_space * flex_factor_c / flex_factor_sum)
            elif available_size > (
                    box_a.outer_min_content_size +
                    box_c.outer_min_content_size):
                # sum of the outer min-content widths
                # is less than the available width
                flex_space = (
                    available_size -
                    box_a.outer_min_content_size -
                    box_c.outer_min_content_size)
                flex_factor_a = (
                    box_a.max_content_size - box_a.min_content_size)
                flex_factor_c = (
                    box_c.max_content_size - box_c.min_content_size)
                flex_factor_sum = flex_factor_a + flex_factor_c
                if flex_factor_sum == 0:
                    flex_factor_sum = 1
                box_a.outer = box_a.min_content_size + (
                    flex_space * flex_factor_a / flex_factor_sum)
                box_c.outer = box_c.min_content_size + (
                    flex_space * flex_factor_c / flex_factor_sum)
            else:
                # otherwise
                flex_space = (
                    available_size -
                    box_a.outer_min_content_size -
                    box_c.outer_min_content_size)
                flex_factor_a = box_a.min_content_size
                flex_factor_c = box_c.min_content_size
                flex_factor_sum = flex_factor_a + flex_factor_c
                if flex_factor_sum == 0:
                    flex_factor_sum = 1
                box_a.outer = box_a.min_content_size + (
                    flex_space * flex_factor_a / flex_factor_sum)
                box_c.outer = box_c.min_content_size + (
                    flex_space * flex_factor_c / flex_factor_sum)
        else:
            # only one box has 'width: auto'
            if box_a.inner == 'auto':
                box_a.outer = available_size - box_c.outer
            elif box_c.inner == 'auto':
                box_c.outer = available_size - box_a.outer
    else:
        if box_b.inner == 'auto':
            # resolve any auto width of the middle box (B)
            ac_max_content_size = 2 * max(
                box_a.outer_max_content_size, box_c.outer_max_content_size)
            if available_size > (
                    box_b.outer_max_content_size + ac_max_content_size):
                flex_space = (
                    available_size -
                    box_b.outer_max_content_size -
                    ac_max_content_size)
                flex_factor_b = box_b.outer_max_content_size
                flex_factor_ac = ac_max_content_size
                flex_factor_sum = flex_factor_b + flex_factor_ac
                if flex_factor_sum == 0:
                    flex_factor_sum = 1
                box_b.outer = box_b.max_content_size + (
                    flex_space * flex_factor_b / flex_factor_sum)
            else:
                ac_min_content_size = 2 * max(
                    box_a.outer_min_content_size, box_c.outer_min_content_size)
                if available_size > (
                        box_b.outer_min_content_size + ac_min_content_size):
                    flex_space = (
                        available_size -
                        box_b.outer_min_content_size -
                        ac_min_content_size)
                    flex_factor_b = (
                        box_b.max_content_size - box_b.min_content_size)
                    flex_factor_ac = ac_max_content_size - ac_min_content_size
                    flex_factor_sum = flex_factor_b + flex_factor_ac
                    if flex_factor_sum == 0:
                        flex_factor_sum = 1
                    box_b.outer = box_b.min_content_size + (
                        flex_space * flex_factor_b / flex_factor_sum)
                else:
                    flex_space = (
                        available_size -
                        box_b.outer_min_content_size -
                        ac_min_content_size)
                    flex_factor_b = box_b.min_content_size
                    flex_factor_ac = ac_min_content_size
                    flex_factor_sum = flex_factor_b + flex_factor_ac
                    if flex_factor_sum == 0:
                        flex_factor_sum = 1
                    box_b.outer = box_b.min_content_size + (
                        flex_space * flex_factor_b / flex_factor_sum)
        if box_a.inner == 'auto':
            box_a.outer = (available_size - box_b.outer) / 2
        if box_c.inner == 'auto':
            box_c.outer = (available_size - box_b.outer) / 2

    # And, we’re done!
    assert 'auto' not in [box.inner for box in side_boxes]
    # Set the actual attributes back.
    for box in side_boxes:
        box.restore_box_attributes()
Compute and set a margin box fixed dimension on ``box``

Described in: https://drafts.csswg.org/css-page-3/#margin-dimension

:param side_boxes:
Three boxes on a same side (as opposed to a corner).
A list of:
- A @*-left or @*-top margin box
- A @*-center or @*-middle margin box
- A @*-right or @*-bottom margin box
:param vertical:
``True`` to set height, margin-top and margin-bottom;
``False`` for width, margin-left and margin-right.
:param available_size:
The distance between the page box’s left right border edges
weasyprint/layout/page.py