diff --git a/.vscode/launch.json b/.vscode/launch.json
index fe27067..277d84d 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,7 +10,7 @@
"request": "launch",
"module": "emblematic",
"justMyCode": true,
- "args": ["--output-file=output.svg", "--background-file=/store/Documents/Workspaces/RYGhub/logos/current/bg.svg", "--foreground-file=/home/steffo/Pictures/Font Awesome/svgs/solid/apple-whole.svg"]
+ "args": ["basic", "--background=/store/Documents/Workspaces/RYGhub/logos/current/watermark.svg", "--icon=/home/steffo/Pictures/Font Awesome/svgs", "--fill=#feedb4", "--output-dir=/home/steffo/Workspaces/Steffo99/emblematic-1/output"]
}
]
}
diff --git a/Dockerfile b/Dockerfile
index 9fa3d3b..e1dcff3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,12 +1,8 @@
-# TODO: If you're building a library, remove this file!
-
FROM python:3-alpine AS system
-# TODO: Add whatever dependency your image may require
RUN apk add --update build-base python3-dev py-pip musl-dev
RUN pip install "poetry"
FROM system AS workdir
-# TODO: Use the name of your project
WORKDIR /usr/src/emblematic
FROM workdir AS dependencies
@@ -20,9 +16,8 @@ RUN poetry install
FROM package AS entrypoint
ENV PYTHONUNBUFFERED=1
-ENTRYPOINT ["poetry", "run", "python", "-m"]
-# TODO: Set the name of your Python module
-CMD ["emblematic"]
+ENTRYPOINT ["poetry", "run", "python", "-m", "emblematic"]
+CMD []
FROM entrypoint AS labels
# TODO: Set a Docker image title
diff --git a/README.md b/README.md
index 7aa6d32..7e57598 100644
--- a/README.md
+++ b/README.md
@@ -2,11 +2,11 @@
Simple icon generator
-\[ **[Documentation]** | **[Available on PyPI]** | [Repository] \]
+\[ **[Documentation]** | **[PyPI]** | [Repository] \]
[Documentation]: https://emblematic.readthedocs.io/latest/
-[Available on PyPI]: https://pypi.org/project/emblematic
+[PyPI]: https://pypi.org/project/emblematic
[Repository]: https://github.com/Steffo99/emblematic/
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100644
index 991d280..0000000
--- a/docker-compose.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-version: "3.9"
-
-services:
- emblematic:
- image: "ghcr.io/Steffo99/emblematic:latest"
- restart: unless-stopped
- env_file:
- - "stack.env"
diff --git a/docs/source/api.rst b/docs/source/api.rst
new file mode 100644
index 0000000..a9a5104
--- /dev/null
+++ b/docs/source/api.rst
@@ -0,0 +1,17 @@
+*******************************************************************************
+API reference
+*******************************************************************************
+
+
+============
+``.compose``
+============
+
+.. automodule:: emblematic.compose
+
+
+==========
+``.files``
+==========
+
+.. automodule:: emblematic.files
diff --git a/docs/source/conf.py b/docs/source/conf.py
index d23d71f..3289a86 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -96,7 +96,6 @@ nitpicky = False
# Intersphinx URLs
intersphinx_mapping = {
"python": ("https://docs.python.org/3.10", None),
- "poetry":
}
# Manpages URL
manpages_url = "https://man.archlinux.org/"
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 18cf377..3bc8457 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -15,7 +15,8 @@ Table of contents
.. toctree::
installation
-
+ usage
+ api
============
diff --git a/docs/source/installation.rst b/docs/source/installation.rst
index 55e4000..79c42a3 100644
--- a/docs/source/installation.rst
+++ b/docs/source/installation.rst
@@ -40,7 +40,7 @@ Using pip
$ # On Fish
$ source .venv/bin/activate.fish
- .. code-block:: wincon
+ .. code-block:: doscon
> ; On Windows
> .venv/Scripts/activate.ps1
@@ -50,7 +50,7 @@ Using pip
To install |this| using :mod:`pip`:
-#. Add |this| to your `requirements.txt` file:
+#. Add |this| to your ``requirements.txt`` file:
.. code-block:: text
@@ -75,6 +75,7 @@ To install |this| using :mod:`pipx`:
$ pipx install emblematic
+
===========
From source
===========
@@ -133,7 +134,7 @@ To contribute to |this|, you need to setup the project's environment using :mod:
.. hint::
- Setting ``virtualenvs.in-project`` to :data:`True` is recommended!
+ It is recommended to set ``virtualenvs.in-project`` to :data:`True`!
.. code-block:: console
diff --git a/docs/source/ryg6-ice-cream.png b/docs/source/ryg6-ice-cream.png
new file mode 100644
index 0000000..355adbc
Binary files /dev/null and b/docs/source/ryg6-ice-cream.png differ
diff --git a/docs/source/usage.rst b/docs/source/usage.rst
new file mode 100644
index 0000000..41d9baa
--- /dev/null
+++ b/docs/source/usage.rst
@@ -0,0 +1,55 @@
+*******************************************************************************
+Usage
+*******************************************************************************
+
+:mod:`emblematic` currently supports only a single mode of operation.
+
+
+=======================
+Generate a basic emblem
+=======================
+
+A *basic emblem* can be generated by running:
+
+.. code-block:: console
+
+ $ emblematic basic --background="./bg.svg" --icon="./icon.svg" --fill="#feedb4" --output-dir="./output/"
+
+It is composed by:
+
+1. taking the SVG background image contained in the file given as the ``--background`` option, such as the following:
+
+ .. figure:: ryg6-bg.svg
+ :width: 150
+ :height: 150
+
+2. overlaying a rescaled version of the SVG foreground icon contained in the file given as the ``--icon`` option, filled with the color given in the ``--fill`` option, such as the following:
+
+ .. figure:: fontawesome-ice-cream.svg
+ :width: 150
+ :height: 150
+
+3. converting the resulting document to a 2000x2000 PNG file for better compatibility with applications (very few support correctly the ``preserveAspectRatio`` property):
+
+ .. figure:: ryg6-ice-cream.png
+ :width: 150
+ :height: 150
+
+
+---------------------------------
+Multiple emblems with one command
+---------------------------------
+
+Multiple emblem files can be generated at once.
+
+* Pass the ``--icon`` parameter multiple times to generate emblems with the same settings but different icons:
+
+ .. code-block:: console
+
+ $ emblematic basic --background="./bg.svg" --icon="./icon1.svg" --icon="./icon2.svg" --icon="./icon3.svg" --fill="#feedb4" --output-dir="./output/"
+
+* Pass a directory as the ``--icon`` parameter to render all contained files matched by the ``**/*.svg`` glob:
+
+ .. code-block:: console
+
+ $ emblematic basic --background="./bg.svg" --icon="./fontawesome/" --fill="#feedb4" --output-dir="./output/"
diff --git a/emblematic/__init__.py b/emblematic/__init__.py
index 8c571c4..7785212 100644
--- a/emblematic/__init__.py
+++ b/emblematic/__init__.py
@@ -1,5 +1,8 @@
-# If you are building a **library**, use this file to export objects!
+from . import compose
+from . import files
+
__all__ = (
- # "",
+ "compose",
+ "files",
)
diff --git a/emblematic/__main__.py b/emblematic/__main__.py
index f0f149f..5a78c5c 100644
--- a/emblematic/__main__.py
+++ b/emblematic/__main__.py
@@ -1,37 +1,84 @@
+"""
+Command-line interface for :mod:`emblematic`.
+
+Implemented with :mod:`click`.
+"""
+
import click
import bs4
+import pathlib
+import cairosvg
+
+from .files import get_svgs
+from .compose import compose_basic
-@click.command()
+@click.group()
+def main():
+ pass
+
+
+@main.command("basic")
@click.option(
- "-o", "--output-file", "output_file",
- help="File to output the icon to.",
- required=True,
- type=click.File(mode="w"),
-)
-@click.option(
- "-b", "--background-file", "background_file",
- help="File to use as the background of the icon.",
- required=True,
+ "-b", "--background", "bg_file",
type=click.File(mode="r"),
+ required=True,
+ help="SVG file to be used as background.",
)
@click.option(
- "-f", "--foreground-file", "foreground_file",
- help="File to use as the foreground of the icon.",
+ "-i", "--icon", "icon_paths",
+ type=click.Path(exists=True),
required=True,
- type=click.File(mode="r"),
+ multiple=True,
+ help="SVG files or directories of files to be used as foreground.",
)
-def main(output_file, background_file, foreground_file):
- background_soup = bs4.BeautifulSoup(background_file, "lxml-xml")
- foreground_soup = bs4.BeautifulSoup(foreground_file, "lxml-xml")
+@click.option(
+ "-f", "--fill", "icon_fill",
+ type=str,
+ required=True,
+ help="The color to fill icons with."
+)
+@click.option(
+ "-o", "--output-dir", "output_dir",
+ type=click.Path(exists=True, file_okay=False, dir_okay=True),
+ required=True,
+ help="The directory where output files should be placed in."
+)
+def basic(bg_file, icon_paths, icon_fill, output_dir):
+ icon_paths = map(pathlib.Path, icon_paths)
+ icon_paths = map(get_svgs, icon_paths)
+ icon_paths = sum(icon_paths, start=[])
- foreground_tag = foreground_soup.path
- foreground_scaled_tag = bs4.BeautifulSoup("""""", "lxml-xml")
- foreground_scaled_tag.g.append(foreground_tag)
+ output_dir = pathlib.Path(output_dir)
- background_soup.svg.append(foreground_scaled_tag)
+ bg_doc = bs4.BeautifulSoup(bg_file, features="lxml-xml")
+ bg = bg_doc.svg
+
+ for icon_path in icon_paths:
+ icon_path: pathlib.Path
+ output_path = output_dir.joinpath(f"{icon_path.stem}.png")
+
+ with open(icon_path) as icon_file:
+ click.echo(icon_path, nl=False)
+ icon_doc = bs4.BeautifulSoup(icon_file, features="lxml-xml")
+ icon = icon_doc.svg
+ icon.path.attrs["fill"] = icon_fill
+
+ click.echo(" → ", nl=False)
+ svg_doc = compose_basic(background=bg, icon=icon)
+
+ click.echo(" → ", nl=False)
+ svg_bytes = bytes(svg_doc.prettify(), encoding="utf8")
+
+ click.echo(" → ", nl=False)
+ png_bytes = cairosvg.svg2png(bytestring=svg_bytes)
+
+ with open(output_path, mode="wb") as output_file:
+ click.echo(output_path, nl=False)
+ output_file.write(png_bytes)
+
+ click.echo()
- output_file.write(background_soup.prettify())
if __name__ == "__main__":
diff --git a/emblematic/compose.py b/emblematic/compose.py
index 5b9615d..5a35062 100644
--- a/emblematic/compose.py
+++ b/emblematic/compose.py
@@ -1,36 +1,43 @@
+"""
+Module containing the functions used to generate ``