Skip to content

Core

momapy.rendering.core

Bases classes and functions for rendering maps or layout elements

Classes:

Name Description
Renderer

Base class for renderers

StatefulRenderer

Base class for stateful renderers

Functions:

Name Description
register_renderer

Register a renderer class

render_layout_element

Render a layout element to a file in the given format with the given registered renderer

render_layout_elements

Render a collection of layout elements to a file in the given format with the given registered renderer

render_map

Render a map to a file in the given format with the given registered renderer

render_maps

Render a collection of maps to a file in the given format with the given registered renderer

Renderer dataclass

Renderer()

Bases: ABC

Base class for renderers

Methods:

Name Description
begin_session

Begin a session

end_session

End a session

get_bolder_font_weight

Return the lightest font weight bolder than the given font weight

get_lighter_font_weight

Return the boldest font weight lighter than the given font weight

new_page

Make a new page

render_drawing_element

Render a drawing element

render_layout_element

Render a layout element

render_map

Render a map

begin_session abstractmethod

begin_session()

Begin a session

Source code in src/momapy/rendering/core.py
@abc.abstractmethod
def begin_session(self):
    """Begin a session"""
    pass

end_session abstractmethod

end_session()

End a session

Source code in src/momapy/rendering/core.py
@abc.abstractmethod
def end_session(self):
    """End a session"""
    pass

get_bolder_font_weight classmethod

get_bolder_font_weight(font_weight: FontWeight | float) -> float

Return the lightest font weight bolder than the given font weight

Source code in src/momapy/rendering/core.py
@classmethod
def get_bolder_font_weight(
    cls, font_weight: momapy.drawing.FontWeight | float
) -> float:
    """Return the lightest font weight bolder than the given font weight"""
    if isinstance(font_weight, momapy.drawing.FontWeight):
        font_weight = cls.font_weight_value_mapping.get(font_weight)
        if font_weight is None:
            raise ValueError(
                f"font weight must be a float, {momapy.drawing.FontWeight.NORMAL}, or {momapy.drawing.FontWeight.BOLD}"
            )
    if font_weight < 400:
        new_font_weight = 400
    elif font_weight < 600:
        new_font_weight = 700
    else:
        new_font_weight = 900
    return new_font_weight

get_lighter_font_weight classmethod

get_lighter_font_weight(font_weight: FontWeight | float) -> float

Return the boldest font weight lighter than the given font weight

Source code in src/momapy/rendering/core.py
@classmethod
def get_lighter_font_weight(
    cls, font_weight: momapy.drawing.FontWeight | float
) -> float:
    """Return the boldest font weight lighter than the given font weight"""
    if isinstance(font_weight, momapy.drawing.FontWeight):
        font_weight = cls.font_weight_value_mapping.get(font_weight)
        if font_weight is None:
            raise ValueError(
                f"font weight must be a float, {momapy.drawing.FontWeight.NORMAL}, or {momapy.drawing.FontWeight.BOLD}"
            )
    if font_weight > 700:
        new_font_weight = 700
    elif font_weight > 500:
        new_font_weight = 400
    else:
        new_font_weight = 100
    return new_font_weight

new_page abstractmethod

new_page(width, height)

Make a new page

Source code in src/momapy/rendering/core.py
@abc.abstractmethod
def new_page(self, width, height):
    """Make a new page"""
    pass

render_drawing_element abstractmethod

render_drawing_element(drawing_element: DrawingElement)

Render a drawing element

Source code in src/momapy/rendering/core.py
@abc.abstractmethod
def render_drawing_element(self, drawing_element: momapy.drawing.DrawingElement):
    """Render a drawing element"""
    pass

render_layout_element abstractmethod

render_layout_element(layout_element: LayoutElement)

Render a layout element

Source code in src/momapy/rendering/core.py
@abc.abstractmethod
def render_layout_element(self, layout_element: momapy.core.LayoutElement):
    """Render a layout element"""
    pass

render_map abstractmethod

render_map(map_: Map)

Render a map

Source code in src/momapy/rendering/core.py
@abc.abstractmethod
def render_map(self, map_: momapy.core.Map):
    """Render a map"""
    pass

StatefulRenderer dataclass

StatefulRenderer(_current_state: dict = dict(), _states: list[dict] = list())

Bases: Renderer

Base class for stateful renderers

Methods:

Name Description
begin_session

Begin a session

end_session

End a session

get_bolder_font_weight

Return the lightest font weight bolder than the given font weight

get_current_state

Return the current state

get_current_value

Return the current value for an attribute

get_initial_value

Return the initial value for an attribute

get_lighter_font_weight

Return the boldest font weight lighter than the given font weight

new_page

Make a new page

render_drawing_element

Render a drawing element

render_layout_element

Render a layout element

render_map

Render a map

restore

Set the current state to the last saved state

save

Save the current state

set_current_state

Set the current state to the given state

set_current_state_from_drawing_element

Set the current state to a state given by a drawing element

set_current_value

Set the current value for an attribute

begin_session abstractmethod

begin_session()

Begin a session

Source code in src/momapy/rendering/core.py
@abc.abstractmethod
def begin_session(self):
    """Begin a session"""
    pass

end_session abstractmethod

end_session()

End a session

Source code in src/momapy/rendering/core.py
@abc.abstractmethod
def end_session(self):
    """End a session"""
    pass

get_bolder_font_weight classmethod

get_bolder_font_weight(font_weight: FontWeight | float) -> float

Return the lightest font weight bolder than the given font weight

Source code in src/momapy/rendering/core.py
@classmethod
def get_bolder_font_weight(
    cls, font_weight: momapy.drawing.FontWeight | float
) -> float:
    """Return the lightest font weight bolder than the given font weight"""
    if isinstance(font_weight, momapy.drawing.FontWeight):
        font_weight = cls.font_weight_value_mapping.get(font_weight)
        if font_weight is None:
            raise ValueError(
                f"font weight must be a float, {momapy.drawing.FontWeight.NORMAL}, or {momapy.drawing.FontWeight.BOLD}"
            )
    if font_weight < 400:
        new_font_weight = 400
    elif font_weight < 600:
        new_font_weight = 700
    else:
        new_font_weight = 900
    return new_font_weight

get_current_state

get_current_state() -> dict[str, Any]

Return the current state

Source code in src/momapy/rendering/core.py
def get_current_state(self) -> dict[str, typing.Any]:
    """Return the current state"""
    return self._current_state

get_current_value

get_current_value(attr_name: str) -> Any

Return the current value for an attribute

Source code in src/momapy/rendering/core.py
def get_current_value(self, attr_name: str) -> typing.Any:
    """Return the current value for an attribute"""
    return self.get_current_state()[attr_name]

get_initial_value

get_initial_value(attr_name: str) -> Any

Return the initial value for an attribute

Source code in src/momapy/rendering/core.py
def get_initial_value(self, attr_name: str) -> typing.Any:
    """Return the initial value for an attribute"""
    attr_value = self.initial_values.get(attr_name)
    if attr_value is None:
        attr_d = momapy.drawing.PRESENTATION_ATTRIBUTES[attr_name]
        attr_value = attr_d["initial"]
        if attr_value is None:
            attr_value = momapy.drawing.INITIAL_VALUES[attr_name]
    return attr_value

get_lighter_font_weight classmethod

get_lighter_font_weight(font_weight: FontWeight | float) -> float

Return the boldest font weight lighter than the given font weight

Source code in src/momapy/rendering/core.py
@classmethod
def get_lighter_font_weight(
    cls, font_weight: momapy.drawing.FontWeight | float
) -> float:
    """Return the boldest font weight lighter than the given font weight"""
    if isinstance(font_weight, momapy.drawing.FontWeight):
        font_weight = cls.font_weight_value_mapping.get(font_weight)
        if font_weight is None:
            raise ValueError(
                f"font weight must be a float, {momapy.drawing.FontWeight.NORMAL}, or {momapy.drawing.FontWeight.BOLD}"
            )
    if font_weight > 700:
        new_font_weight = 700
    elif font_weight > 500:
        new_font_weight = 400
    else:
        new_font_weight = 100
    return new_font_weight

new_page abstractmethod

new_page(width, height)

Make a new page

Source code in src/momapy/rendering/core.py
@abc.abstractmethod
def new_page(self, width, height):
    """Make a new page"""
    pass

render_drawing_element abstractmethod

render_drawing_element(drawing_element: DrawingElement)

Render a drawing element

Source code in src/momapy/rendering/core.py
@abc.abstractmethod
def render_drawing_element(self, drawing_element: momapy.drawing.DrawingElement):
    """Render a drawing element"""
    pass

render_layout_element abstractmethod

render_layout_element(layout_element: LayoutElement)

Render a layout element

Source code in src/momapy/rendering/core.py
@abc.abstractmethod
def render_layout_element(self, layout_element: momapy.core.LayoutElement):
    """Render a layout element"""
    pass

render_map abstractmethod

render_map(map_: Map)

Render a map

Source code in src/momapy/rendering/core.py
@abc.abstractmethod
def render_map(self, map_: momapy.core.Map):
    """Render a map"""
    pass

restore

restore()

Set the current state to the last saved state

Source code in src/momapy/rendering/core.py
def restore(self):
    """Set the current state to the last saved state"""
    if len(self._states) > 0:
        state = self._states.pop()
        self.set_current_state(state)
        self.self_restore()
    else:
        raise Exception("no state to be restored")

save

save()

Save the current state

Source code in src/momapy/rendering/core.py
def save(self):
    """Save the current state"""
    self._states.append(copy.deepcopy(self.get_current_state()))
    self.self_save()

set_current_state

set_current_state(state: dict)

Set the current state to the given state

Source code in src/momapy/rendering/core.py
def set_current_state(self, state: dict):
    """Set the current state to the given state"""
    for attr_name, attr_value in state.items():
        self.set_current_value(attr_name, attr_value)

set_current_state_from_drawing_element

set_current_state_from_drawing_element(drawing_element: DrawingElement)

Set the current state to a state given by a drawing element

Source code in src/momapy/rendering/core.py
def set_current_state_from_drawing_element(
    self, drawing_element: momapy.drawing.DrawingElement
):
    """Set the current state to a state given by a drawing element"""
    state = self._get_state_from_drawing_element(drawing_element)
    self.set_current_state(state)

set_current_value

set_current_value(attr_name: str, attr_value: Any)

Set the current value for an attribute

Source code in src/momapy/rendering/core.py
def set_current_value(self, attr_name: str, attr_value: typing.Any):
    """Set the current value for an attribute"""
    if attr_value is None:
        attr_d = momapy.drawing.PRESENTATION_ATTRIBUTES[attr_name]
        if not attr_d["inherited"]:
            attr_value = self.initial_values.get(attr_name)
            if attr_value is None:
                attr_value = attr_d["initial"]
            if attr_value is None:
                attr_value = momapy.drawing.INITIAL_VALUES[attr_name]
    if attr_name == "font_weight":
        if isinstance(attr_value, momapy.drawing.FontWeight):
            if (
                attr_value == momapy.drawing.FontWeight.NORMAL
                or attr_value == momapy.drawing.FontWeight.BOLD
            ):
                attr_value = self.font_weight_value_mapping[attr_value]
            elif attr_value == momapy.drawing.FontWeight.BOLDER:
                attr_value = self.get_bolder_font_weight(
                    self.get_current_value("font_weight")
                )
            elif attr_value == momapy.drawing.FontWeight.LIGHTER:
                attr_value = self.get_lighter_font_weight(
                    self.get_current_value("font_weight")
                )
    if attr_value is not None:
        self._current_state[attr_name] = attr_value

register_renderer

register_renderer(name, renderer_cls)

Register a renderer class

Source code in src/momapy/rendering/core.py
def register_renderer(name, renderer_cls):
    """Register a renderer class"""
    renderers[name] = renderer_cls

render_layout_element

render_layout_element(layout_element: LayoutElement, file_path: str | PathLike, format_: str = 'pdf', renderer: str = 'skia', style_sheet: StyleSheet | None = None, to_top_left: bool = False)

Render a layout element to a file in the given format with the given registered renderer

Parameters:

Name Type Description Default
layout_element LayoutElement

The layout element to render

required
file_path str | PathLike

The output file path

required
format_ str

The output format

'pdf'
renderer str

The registered renderer to use. See register_renderer to register renderers

'skia'
style_sheet StyleSheet | None

An optional style sheet to apply before rendering

None
to_top_left bool

Whether to move the layout element to the top left or not before rendering

False
Source code in src/momapy/rendering/core.py
def render_layout_element(
    layout_element: momapy.core.LayoutElement,
    file_path: str | os.PathLike,
    format_: str = "pdf",
    renderer: str = "skia",
    style_sheet: momapy.styling.StyleSheet | None = None,
    to_top_left: bool = False,
):
    """Render a layout element to a file in the given format with the given registered renderer

    Args:
        layout_element: The layout element to render
        file_path: The output file path
        format_: The output format
        renderer: The registered renderer to use. See [register_renderer][momapy.rendering.core.register_renderer] to register renderers
        style_sheet: An optional style sheet to apply before rendering
        to_top_left: Whether to move the layout element to the top left or not before rendering
    """
    render_layout_elements(
        layout_elements=[layout_element],
        file_path=file_path,
        format_=format_,
        renderer=renderer,
        style_sheet=style_sheet,
        to_top_left=to_top_left,
    )

render_layout_elements

render_layout_elements(layout_elements: Collection[LayoutElement], file_path: str | PathLike, format_: str = 'pdf', renderer: str = 'skia', style_sheet: StyleSheet | None = None, to_top_left: bool = False, multi_pages: bool = True)

Render a collection of layout elements to a file in the given format with the given registered renderer

Source code in src/momapy/rendering/core.py
def render_layout_elements(
    layout_elements: collections.abc.Collection[momapy.core.LayoutElement],
    file_path: str | os.PathLike,
    format_: str = "pdf",
    renderer: str = "skia",
    style_sheet: momapy.styling.StyleSheet | None = None,
    to_top_left: bool = False,
    multi_pages: bool = True,
):
    """Render a collection of layout elements to a file in the given format with the given registered renderer"""

    def _prepare_layout_elements(layout_elements, style_sheet=None, to_top_left=False):
        bboxes = [layout_element.bbox() for layout_element in layout_elements]
        bbox = momapy.positioning.fit(bboxes)
        max_x = bbox.x + bbox.width / 2
        max_y = bbox.y + bbox.height / 2
        if style_sheet is not None or to_top_left:
            new_layout_elements = []
            for layout_element in layout_elements:
                if isinstance(layout_element, momapy.core.LayoutElement):
                    new_layout_elements.append(
                        momapy.builder.builder_from_object(layout_element)
                    )
                elif isinstance(layout_element, momapy.core.LayoutElementBuilder):
                    new_layout_elements.append(copy.deepcopy(layout_element))
            layout_elements = new_layout_elements
        if style_sheet is not None:
            if (
                not isinstance(style_sheet, collections.abc.Collection)
                or isinstance(style_sheet, str)
                or isinstance(style_sheet, momapy.styling.StyleSheet)
            ):
                style_sheets = [style_sheet]
            else:
                style_sheets = style_sheet
            style_sheets = [
                (
                    momapy.styling.StyleSheet.from_file(style_sheet)
                    if not isinstance(style_sheet, momapy.styling.StyleSheet)
                    else style_sheet
                )
                for style_sheet in style_sheets
            ]
            style_sheet = momapy.styling.combine_style_sheets(style_sheets)
            for layout_element in layout_elements:
                momapy.styling.apply_style_sheet(layout_element, style_sheet)
        if to_top_left:
            min_x = bbox.x - bbox.width / 2
            min_y = bbox.y - bbox.height / 2
            max_x -= min_x
            max_y -= min_y
            translation = momapy.geometry.Translation(-min_x, -min_y)
            for layout_element in layout_elements:
                if layout_element.group_transform is None:
                    layout_element.group_transform = momapy.core.TupleBuilder()
                layout_element.group_transform.append(translation)
        return layout_elements, max_x, max_y

    if not multi_pages:
        prepared_layout_elements, max_x, max_y = _prepare_layout_elements(
            layout_elements, style_sheet, to_top_left
        )
        renderer = renderers[renderer].from_file(file_path, max_x, max_y, format_)
        renderer.begin_session()
        for prepared_layout_element in prepared_layout_elements:
            renderer.render_layout_element(prepared_layout_element)
        renderer.end_session()
    else:
        if layout_elements:
            layout_element = layout_elements[0]
            prepared_layout_elements, max_x, max_y = _prepare_layout_elements(
                [layout_element], style_sheet, to_top_left
            )
            renderer = renderers[renderer].from_file(file_path, max_x, max_y, format_)
            renderer.begin_session()
            renderer.render_layout_element(prepared_layout_elements[0])
            for layout_element in layout_elements[1:]:
                prepared_layout_elements, max_x, max_y = _prepare_layout_elements(
                    [layout_element], style_sheet, to_top_left
                )
                renderer.new_page(max_x, max_y)
                renderer.render_layout_element(prepared_layout_elements[0])
        else:
            renderer = renderers[renderer].from_file(file_path, 0, 0, format_)
        renderer.end_session()

render_map

render_map(map_: Map, file_path: str | PathLike, format_: str = 'pdf', renderer: str = 'skia', style_sheet: StyleSheet | None = None, to_top_left: bool = False)

Render a map to a file in the given format with the given registered renderer

Source code in src/momapy/rendering/core.py
def render_map(
    map_: momapy.core.Map,
    file_path: str | os.PathLike,
    format_: str = "pdf",
    renderer: str = "skia",
    style_sheet: momapy.styling.StyleSheet | None = None,
    to_top_left: bool = False,
):
    """Render a map to a file in the given format with the given registered renderer"""
    render_maps([map_], file_path, format_, renderer, style_sheet, to_top_left)

render_maps

render_maps(maps: Collection[Map], file_path: str | PathLike, format_: str = 'pdf', renderer: str = 'skia', style_sheet: StyleSheet | None = None, to_top_left: bool = False, multi_pages: bool = True)

Render a collection of maps to a file in the given format with the given registered renderer

Source code in src/momapy/rendering/core.py
def render_maps(
    maps: collections.abc.Collection[momapy.core.Map],
    file_path: str | os.PathLike,
    format_: str = "pdf",
    renderer: str = "skia",
    style_sheet: momapy.styling.StyleSheet | None = None,
    to_top_left: bool = False,
    multi_pages: bool = True,
):
    """Render a collection of maps to a file in the given format with the given registered renderer"""
    layout_elements = [map_.layout for map_ in maps]
    render_layout_elements(
        layout_elements=layout_elements,
        file_path=file_path,
        format_=format_,
        renderer=renderer,
        style_sheet=style_sheet,
        to_top_left=to_top_left,
        multi_pages=multi_pages,
    )