# Python interface

`emblematic` has a Python interface that can be called from other Python scripts to programmatically generate emblems.

## Installation

`emblematic` is distributed both via PyPI and Steffo’s Forge.

Use your favorite package manager to install it in your project.

For example, with Poetry via PyPI:

    $ poetry add emblematic

Or, with pip via Steffo’s Forge:

> $ pip install –index-url ‘https://forge.steffo.eu/api/packages/steffo/pypi/simple/’ emblematic

## Usage

### Composition

This package should usually be imported as `emblematic.composition`:

    from emblematic.composition import compose_basic, compose_solid, compose_shadow, compose_duotone

Each of the `compose_*` functions correspond to a mode of the Command-line interface, except that they take as input instances of `bs4.BeautifulSoup` to operate on.

A very basic usage example is:

    from bs4 import BeautifulSoup
    from emblematic.composition import compose_basic

    with open("background.svg", encoding="utf-8") as bg_file:
        with open("foreground.svg", encoding="utf-8") as fg_file:
            bg_soup = BeautifulSoup(bg_file, features="lxml-xml")
            fg_soup = BeautifulSoup(fg_file, features="lxml-xml")

    final_soup = compose_basic(
        background=bg_soup,
        foreground=fg_soup,
        final_width_px=512.0,
        final_height_px=512.0,
    )

    final_pretty = final_soup.prettify()

    with open("final.svg", encoding="utf-8") as final_file:
        final_file.write(final_pretty)

### Converting to PNG

If you want to additionally convert to PNG with Inkscape, like the Command-line interface does, and assuming you have properly installed the Prerequisites, you can use `subprocess` similarly to this:

    import subprocess

    ...

    destination = "final.png"
    width_px = int(512.0)
    height_px = int(512.0)

    result = subprocess.run(
        args=[
            "inkscape",
            "--pipe",
            "--export-type=png",
            f"--export-filename={destination}",
            f"--export-width={width_px}",
            f"--export-height={height_px}"
        ],
        input=svg_data.encode("utf-8"),
    )
    if result.returncode != 0:
        raise ChildProcessError("Conversion to PNG with Inkscape returned non-zero exit code: ", result.returncode)

## API reference

### Emblem composition

Composition of emblems from multiple documents, making use of various `operations`.

emblematic.composition.compose_basic(background: BeautifulSoup, foreground: BeautifulSoup, *, final_width_px: float, final_height_px: float) → BeautifulSoup

  Create an emblem by overlaying the given foreground document on the given background document, rescaling both to the given dimensions.

  Warning

  This function will alter the two given documents, make sure to copy them with `__copy__` if this is undesirable.

  Warning

  This function will not check that the inputs are valid, make sure that the given documents contain a svg tag each.

  Parameters:

    - background – The background document.

    - foreground – The foreground document, most likely an icon.

    - final_width_px – The desired width of the final document.

    - final_height_px – The desired height of the final document.

  Returns:

    The document containing the created emblem.

emblematic.composition.compose_solid(background: BeautifulSoup, foreground: BeautifulSoup, *, foreground_fill: str, final_width_px: float, final_height_px: float) → BeautifulSoup

  Like `compose_basic()`, but fills all paths in the foreground document with the given color.

  Use-case is FontAwesome Solid icons, but should work with most others as well.

  Parameters:

    - background – The background document.

    - foreground – The foreground document, most likely an icon.

    - foreground_fill – The color to fill the foreground with.

    - final_width_px – The desired width of the final document.

    - final_height_px – The desired height of the final document.

  Returns:

    The document containing the created emblem.

emblematic.composition.compose_shadow(background: BeautifulSoup, foreground: BeautifulSoup, *, foreground_fill: str, shadow_x_px: float, shadow_y_px: float, shadow_stddev: float, shadow_color: str, final_width_px: float, final_height_px: float) → BeautifulSoup

  Like `compose_solid()`, but adds a shadow to the icon.

  Warning

  This function will replace any defs tag the foreground document may contain with its own.

  Parameters:

    - background – The background document.

    - foreground – The foreground document, most likely an icon.

    - foreground_fill – The color to fill the foreground with.

    - shadow_x_px – The horizontal pixel offset of the shadow.

    - shadow_y_px – The vertical pixel offset of the shadow.

    - shadow_stddev – The standard deviation of the blur.

    - shadow_color – The color to fill the shadow with.

    - final_width_px – The desired width of the final document.

    - final_height_px – The desired height of the final document.

  Returns:

    The document containing the created emblem.

emblematic.composition.compose_duotone(background: BeautifulSoup, foreground: BeautifulSoup, *, primary_fill: str, secondary_fill: str, final_width_px: float, final_height_px: float) → BeautifulSoup

  Like `compose_basic()`, but fills the path with the `fa-primary` id with the first color given, and the path with the `fa-secondary` id with the second color given.

  This function will remove any defs tag the foreground document may contain.

  Use-case is FontAwesome Duotone icons.

  Parameters:

    - background – The background document.

    - foreground – The foreground document, most likely an icon.

    - primary_fill – The color to fill the primary part of the icon with.

    - secondary_fill – The color to fill the secondary part of the icon with.

    - final_width_px – The desired width of the final document.

    - final_height_px – The desired height of the final document.

  Returns:

    The document containing the created emblem.

### SVG modification

Basic operations that can be performed on `<svg>` tags, like stretching and centering.

Except for `combine()`, all these methods operate in-place.

emblematic.svg.stretch_center(tag: Tag, width_pct: float = 100.0, height_pct: float = 100.0) → None

  Make a SVG tag fill a portion of its parent, ignoring its original aspect ratio.

  Parameters:

    - tag – The tag to edit.

    - width_pct – The width percentage to fill.

    - height_pct – The height percentage to fill.

emblematic.svg.contain_center(tag: Tag, width_pct: float = 100.0, height_pct: float = 100.0) → None

  Make a SVG tag fill a portion of its parent, respecting its original aspect ratio by making it smaller than the area if necessary, then centering.

  Parameters:

    - tag – The tag to edit.

    - width_pct – The width percentage to fill.

    - height_pct – The height percentage to fill.

emblematic.svg.combine(*tags: Tag, width_px: float, height_px: float) → BeautifulSoup

  Create a new SVG document of the given absolute size containing all the given tags.

  Parameters:

    - tags – The tags to combine.

    - width_px – The absolute width in pixels of the new document.

    - height_px – The absolute height in pixels of the new document.

  Returns:

    The created SVG document.

emblematic.svg.remove_defs(tag: Tag) → None

  Remove all defs tags from the given SVG tag.

  Parameters:

    tag – The tag to edit.

emblematic.svg.create_defs(doc: BeautifulSoup, tag: Tag) → Tag

  Create a defs tag in the given SVG tag.

  Parameters:

    - doc – The document the tag is contained in.

    - tag – The svg tag to create defs in.

  Returns:

    The created defs tag.

emblematic.svg.create_dropshadow(doc: BeautifulSoup, tag: Tag, id_: str, shadow_x_px: float, shadow_y_px: float, shadow_stddev: float, shadow_color: str) → Tag

  Create a filter tag describing a shadow with gaussian blur in the given defs tag.

  Parameters:

    - doc – The document the tag is contained in.

    - tag – The defs tag to create filter in.

    - id – The id to give to the filter.

    - shadow_x_px – The horizontal pixel offset of the shadow.

    - shadow_y_px – The vertical pixel offset of the shadow.

    - shadow_stddev – The standard deviation of the blur.

    - shadow_color – The color of the shadow.

  Returns:

    The created filter tag.

emblematic.svg.fill_all(tag: Tag, color: str) → None

  Fill, with the given color, all paths in the given SVG tag.

  Parameters:

    - tag – The tag to edit.

    - color – The color to fill paths with.

emblematic.svg.fill_specific(tag: Tag, class_: str, color: str) → None

  Fill, with the given color, the paths with the given `class` in the given SVG tag.

  Parameters:

    - tag – The tag to edit.

    - class – The class name to find.

    - color – The color to fill paths with.

### Command-line interface definition

#### Arguments and options

emblematic.cli.argopts.option_background_file(f: FC) → FC

emblematic.cli.argopts.arguments_foreground_filename(f: FC) → FC

emblematic.cli.argopts.option_output_dir(f: FC) → FC

emblematic.cli.argopts.option_save_svg(f: FC) → FC

emblematic.cli.argopts.option_save_png(f: FC) → FC

emblematic.cli.argopts.option_width_px(f: FC) → FC

emblematic.cli.argopts.option_height_px(f: FC) → FC

emblematic.cli.argopts.option_foreground_color(f: FC) → FC

emblematic.cli.argopts.option_primary_color(f: FC) → FC

emblematic.cli.argopts.option_secondary_color(f: FC) → FC

emblematic.cli.argopts.option_shadow_offset_x_px(f: FC) → FC

emblematic.cli.argopts.option_shadow_offset_y_px(f: FC) → FC

emblematic.cli.argopts.option_shadow_stddev(f: FC) → FC

emblematic.cli.argopts.option_shadow_color(f: FC) → FC

#### Commands

#### File detection

Module containing functions to operate on files or directories.

class emblematic.cli.files.WorkUnit(source: Path, destination_stem: Path)
  classmethod find(sources: Iterable[Path], destination: Path, dir_glob: str = '**/*.svg') → set[WorkUnit]

    Create a `set` of `WorkUnit` from a list of sources and a destination directory.

    If a source is a directory, this function selects all files inside matching `dir_glob`, producing destination paths preserving the original source directory structure.

    Warning

    This method assumes the sources exist. Check before calling it!

    Warning

    This method assumes the destination exists and is a directory already. Check before calling it!

    Parameters:

      - sources – An iterable of the paths to the sources to use. Sources can be both files or directories.

      - destination – Path to the destination directory.

      - dir_glob – Glob to use to find files inside directory sources.

    Returns:

      The resulting `set` of `WorkUnit`.

  create_destination_parents()

    Create the parent directories of `destination_stem`, if they do not already exist.

  destination_svg() → Path
    Returns:

      `destination_stem`, but with the `.svg` file extension.

  write_svg(svg_data: str) → Path

    Write the given SVG document to `destination_svg()`.

    Warning

    This method assumes the parent directories exist. Create them with `create_destination_parents()` before running it!

    Parameters:

      svg_data – The SVG document, in string form.

  destination_png() → Path
    Returns:

      `destination_stem`, but with the `.png` file extension.

  write_png(svg_data: str, *, width_px: int, height_px: int) → Path

    Write the given SVG document as PNG to `destination_png()`, calling Inkscape in a `subprocess` to perform the conversion.

    Warning

    This method assumes the parent directories exist. Create them with `create_destination_parents()` before running it!

    Parameters:

      - svg_data – The SVG document, in string form.

      - width_px – The width in pixels of the resulting image.

      - height_px – The height in pixels of the resulting image.