Skip to main content

No project description provided

Project description

Invariant GFX

A deterministic, functional graphics pipeline built on Invariant. Invariant GFX allows developers to build complex visual assets (icons, badges, dynamic UI components, Stream Deck buttons, data visualizations) by plugging together reusable "pipeline parts" in a DAG-based system.

Note: This project builds on Invariant, a deterministic execution engine for DAGs. For information about Invariant's core concepts (DAG execution, caching, execution model, parameter markers, etc.), see the upstream README and Invariant documentation.

Features

  • Smart Layout: Ops can inspect upstream artifact dimensions to calculate positions dynamically
  • Anchor-Based Composition: Position layers relative to previously-placed named layers using absolute() and relative() builder functions
  • Content-Sized Layout: Flow-based arrangement (row/column) with automatic sizing

Relationship to Invariant

Invariant GFX is a child project of Invariant:

  • Invariant (Parent): Provides the DAG execution engine, caching infrastructure, and core protocols. Invariant has NO image awareness—it is domain-agnostic.
  • Invariant GFX (Child): Provides graphics-specific Ops (gfx:render_text, gfx:composite, gfx:render_svg, etc.) and Artifacts (ImageArtifact, BlobArtifact). All image/Pillow concerns live here.

Invariant GFX uses Invariant's Executor and store infrastructure directly—no wrapper class is needed.

Op Standard Library

Invariant GFX provides a standard library of graphics operations, registered under the gfx: namespace:

Group A: Sources (Data Ingestion)

  • gfx:resolve_resource: Resolves bundled resources (icons, images) via JustMyResource (e.g., "lucide:thermometer")
  • gfx:create_solid: Generates solid color canvases (RGBA)

Group B: Transformers (Rendering)

  • gfx:render_svg: Converts SVG blobs into raster artifacts using cairosvg
  • gfx:render_text: Creates tight-fitting "Text Pill" artifacts (supports string font names via JustMyType and direct BlobArtifact font injection)
  • gfx:resize: Scales an ImageArtifact to target dimensions (LANCZOS resampling)

Group C: Composition (Combiners)

  • gfx:composite: Fixed-size composition engine with anchor-based positioning (absolute(), relative())
  • gfx:layout: Content-sized arrangement engine (row/column flow)

Group D: Type Conversion (Casting)

  • gfx:blob_to_image: Parses raw binary data (PNG, JPEG, WEBP) into ImageArtifact

For detailed Op specifications, see docs/architecture.md.

Installation

# Clone the repository
git clone <repository-url>
cd invariant-gfx

# Install dependencies
uv sync

Note: This project depends on a local development version of Invariant. The dependency is configured in pyproject.toml as a file path reference.

Quick Start

This example demonstrates graphics-specific operations. For details on Invariant's execution model, parameter markers (ref(), cel(), ${...}), and context injection, see the upstream README.

from invariant import Executor, Node, ref
from invariant.registry import OpRegistry
from invariant.store.memory import MemoryStore

from invariant_gfx import register_core_ops
from invariant_gfx.anchors import absolute, relative

# Register graphics ops
registry = OpRegistry()
register_core_ops(registry)  # Registers gfx:* ops

# Define the graph template (designed at 72px reference size)
graph = {
    # Render text with proportional sizing
    "text": Node(
        op_name="gfx:render_text",
        params={
            "text": "Hello",
            "font": "Geneva",
            "size": "${decimal(root.width) * decimal('14') / decimal('72')}",  # 14pt at 72px, scales proportionally
            "color": (255, 255, 255, 255),  # White RGBA
        },
        deps=["root"],
    ),
    # Create background (size from context)
    "background": Node(
        op_name="gfx:create_solid",
        params={
            "size": ("${root.width}", "${root.height}"),
            "color": (40, 40, 40, 255),  # Dark gray RGBA
        },
        deps=["root"],
    ),
    # Composite: center text on background
    "final": Node(
        op_name="gfx:composite",
        params={
            "layers": [
                {
                    "image": ref("background"),
                    "id": "background",
                },
                {
                    "image": ref("text"),
                    "anchor": relative("background", "c@c"),
                    "id": "text",
                },
            ],
        },
        deps=["background", "text"],
    ),
}

# Execute the graph
store = MemoryStore()
executor = Executor(registry=registry, store=store)

# Render at 72x72 (text at 14pt)
results = executor.execute(graph, context={"root": {"width": 72, "height": 72}})
results["final"].image.save("output_72.png", format="PNG")

# Render at 144x144 (text scales to 28pt automatically)
results = executor.execute(graph, context={"root": {"width": 144, "height": 144}})
results["final"].image.save("output_144.png", format="PNG")

For more complete examples, see:

  • examples/thermometer_button.py — Icon + text + layout + composite pipeline
  • examples/text_badge.py — Dynamic SVG resizing driven by text dimensions
  • examples/color_dashboard.py — Multi-cell dashboard with nested layouts

For the full Thermometer pipeline and template + context pattern, see docs/architecture.md.

Status

Architecture: Complete and documented

Implementation: V1 op library complete

  • Artifact types (ImageArtifact, BlobArtifact): ✅ Implemented
  • Anchor functions (absolute(), relative()): ✅ Implemented
  • Op standard library (8 ops): ✅ Implemented
  • register_core_ops() registration: ✅ Implemented
  • Integration with JustMyType/JustMyResource: ✅ Implemented
  • Unit tests (94 tests): ✅ All passing
  • E2E tests (Use Cases 1 & 2): ✅ Passing
  • E2E context injection (Use Case 3): ⏳ Placeholder

See docs/status.md for detailed implementation status.

Architecture

Invariant GFX uses Invariant's execution model. For details on the two-phase execution model (Context Resolution and Action Execution), see the upstream documentation.

For Invariant GFX-specific architecture documentation, see docs/architecture.md.

For AI agents working with this codebase, see AGENTS.md.

Development

# Run tests
uv run pytest

# Run linting
uv run ruff check src/ tests/

# Format code
uv run ruff format src/ tests/

License

MIT License - see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

invariant_gfx-0.1.0.tar.gz (106.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

invariant_gfx-0.1.0-py3-none-any.whl (18.1 kB view details)

Uploaded Python 3

File details

Details for the file invariant_gfx-0.1.0.tar.gz.

File metadata

  • Download URL: invariant_gfx-0.1.0.tar.gz
  • Upload date:
  • Size: 106.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for invariant_gfx-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6ba6d92c1394931ea95947d491ae5c8cfeca6c8547538cfb4de5375658481bae
MD5 717f624544e8fe301fce07961766ad53
BLAKE2b-256 0ae0f102350eb2b013b47849296a317811987ec43c8062ab756ff52b5c0269e8

See more details on using hashes here.

File details

Details for the file invariant_gfx-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: invariant_gfx-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 18.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for invariant_gfx-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c16e4b782fdf59685c2168ecf6b6cb6549564caf5a98dafa69521adfd4f8e072
MD5 7766011a835324caf526a3b29984a070
BLAKE2b-256 9db581f94faa338bb0cb925ffcce7c8bc5575792ec998a1249e01aa7f441cfae

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page