Sno Station
Sno Station is your agents' workstation: open-source software that turns the AI agents you already run into one squad on your own machine. Two heads are better than one, and they get better with every
Professional-grade steel shape generators and CAD importers for detailers.
PluginsPython · RubyGitHub @BlueCollar-SystemsOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
PDF Vector Importer for FreeCAD — geometry, text, and image import with arc reconstruction and OCG layer support. Powered by PyMuPDF.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
BUILT. NOT BOUGHT.
Import vector geometry, text, and images from PDF files into FreeCAD as editable Part objects.
Arc reconstruction, dash mapping, color grouping, OCG layer support, and reference-based scaling -- all powered by pure-Python PDF parsing via PyMuPDF.
BlueCollar-Systems -- BUILT. NOT BOUGHT.Read the full README ↗BUILT. NOT BOUGHT.
Import vector geometry, text, and images from PDF files into FreeCAD as editable Part objects.
Arc reconstruction, dash mapping, color grouping, OCG layer support, and reference-based scaling -- all powered by pure-Python PDF parsing via PyMuPDF.
BlueCollar-Systems -- BUILT. NOT BOUGHT.
FreeCAD-PDF-Importer-Setup_vX.Y.Z.exe from the Releases page.Needs FreeCAD 1.0 or newer (a FreeCAD with Python 3.10 or newer). Tested by hand on FreeCAD 1.1.4. Not listed in FreeCAD's Addon Manager yet. Other ways to install (ZIP, manual copy, developer link) are under Installation and in INSTALL.md.
Change notes for each version are in docs/CHANGELOG.md.
The v4.0.119 test candidate attaches the Windows image rendering guard before FreeCAD restores native image visibility or display mode. The v4.0.118 desktop test displayed and saved the drawing, but its fresh reopen still reported the graphics error before the deferred image attachment. The earlier attachment targets that timing gap while preserving source pixels, native geometry, visibility and user styles. Paper attachment and earlier restoration fixes are retained. Exact v4.0.119 desktop save and fresh reopen checks remain pending before release.
The pending sentence above records the v4.0.119 candidate's pre-test state. The later local r14 operator guide records October 15 checks in FreeCAD 1.1.4 on Windows: retained foundation-document Open, normal Save As, fresh process reopen, animated Fit All, public-API image refresh and normal close. It records that the previous access violation/cyclic-scene error did not recur, two 347,008-node scenes had zero cycles, and all 4,683 shapes passed the unchanged geometry checks. Original image bytes and decoded samples were retained.
That guide also preserves the strict raw-value comparison failure: 3,831 color components reflect native 8-bit saved channels, and two temporary image paths differ. Its separate geometry/saved-byte review does not turn strict raw equality into a pass or establish whole-page rendered pixel equality.
This dated update reconciles existing operator records; no new native test was run on October 18 for this note. The candidate guide and current package index are available, but the later raw native receipts were not located in the targeted durable package/validation inventory. Locate and bind them, or repeat the bounded exact-package checks, before claiming independently reverified native acceptance. The retained October 12 scale-tool receipt concerns older source and synthetic App/Part controls, not the 4.0.119 restoration session.
New PDF imports, additional text modes, full visual comparison and other hosts remain separate checks. Local r14 is 4.0.119; GitHub Latest remains 4.0.115. Old candidates, build-time pending records and original failures remain.
The former standalone Structural-Steel-DXF-DWG-Shapes repository has been
consolidated here under steel_shapes/ so the FreeCAD
importer repo is the source home for the DXF/DWG steel shape packs. The
versioned release ZIP from that old repo is intentionally not stored here;
GitHub Releases remain the download layer, while this repo keeps the source
assets, generation scripts, checksums, license, and notes.
| Category | Capability |
|---|---|
| PDF Parsing | PyMuPDF-powered vector extraction with full path, text, and image support |
| Import Modes | Auto (default), Vector, Raster, Hybrid — every mode targets maximum fidelity (BCS-ARCH-001) |
| Text Rendering | Text, Labels, 3D Text (default), Glyphs, Geometry, Raster — orthogonal to mode |
| Arc Reconstruction | Kasa algebraic circle fit converts polyline segments back to true arcs |
| Layer Support | OCG layers (PDF Optional Content Groups) map to FreeCAD groups |
| Color Grouping | Geometry automatically organized by stroke/fill color |
| Dash Patterns | PDF dash arrays mapped to FreeCAD line styles |
| Text Import | PDF text extracted with font size, position, and rotation |
| Image Import | Embedded raster images extracted and placed at correct coordinates |
| Scale Detection | Reference-based scaling from known dimensions on the drawing |
| Steel Detection | Recognizes common structural steel shape profiles |
3D Text (the default) gives the closest look to the PDF: solid letter shapes made from the PDF's own font. They cannot be re-typed. Use Text or Labels when you need to edit or search the words, and Glyphs/Geometry when you want exact outline geometry instead.
See INSTALL.md for Windows FreeCAD 1.1 paths, dev junction install, and troubleshooting.
FreeCAD 1.1 Mod path: %APPDATA%\FreeCAD\v1-1\Mod\PDFVectorImporter (not legacy FreeCAD\Mod\).
Dev one-liner (junction to repo):
.\installer\install-dev.ps1
Searching FreeCAD's Addon Manager will not find this importer yet (it is not listed there). Use Setup.exe on Windows, or the manual install below.
FreeCAD-PDF-Importer-Setup_vX.Y.Z.exe from Releases.git clone https://github.com/BlueCollar-Systems/PDF-Importer-FreeCAD.git
PDFVectorImporter folder into your FreeCAD Mod directory:
%APPDATA%\FreeCAD\v1-1\Mod\%APPDATA%\FreeCAD\Mod\~/Library/Application Support/FreeCAD/Mod/~/.local/share/FreeCAD/Mod/PDFVectorImporter/src/lib: shared PyMuPDF in common/ and ABI-specific fontTools in cp310/ and cp311/. A source checkout without that runtime: switch to the PDF Vector Importer workbench and it offers to install PyMuPDF and fontTools for the current FreeCAD user. (You can also run it any time from PDF Vector Importer > Tools > Install / Update PDF Dependencies.)python build_release.py --python310 C:\path\to\python310.exe --python311 C:\path\to\python311.exe
Release builds are fail-closed and must run from a Git checkout. Every
shippable addon source file must be tracked and byte-identical to HEAD;
private PDF/CAD/model inputs, generated import reports, corpus folders, and
nested archives abort the build. Set the masked
BCS_PRIVATE_RELEASE_DENYLIST_B64 environment value to the project-owned
base64 JSON denylist before a local build; automation reads it from the
FREECAD_PRIVATE_RELEASE_DENYLIST_B64 repository secret and fails closed when
it is absent or malformed. The ignored PDFVectorImporter/src/lib
tree is deleted and rebuilt on every release build from the exact wheel hashes
in requirements-release-common.lock and the cp310/cp311 locks, so an
importable but stale local runtime cannot enter the ZIP. Supply exact Windows
CPython 3.10 and 3.11 interpreters; the builder validates each before installing
its ABI-specific wheel. --no-vendor-deps intentionally
refuses release creation because ignored runtime bytes are not commit-bound.
The secret decodes to this schema; use only synthetic values in documentation:
{"schema":"bcs.private-release-denylist/1.0","terms":["SYNTHETIC-PRIVATE-DRAWING-ID"]}
python build_windows_installer.py
dist/:
FreeCAD-PDF-Importer_vX.Y.Z.zipFreeCAD-PDF-Importer-Setup_vX.Y.Z.exemain PushesThe auto-release workflow mints a vX.Y.Z release automatically when a
push to main carries a version bump. The auto-release workflow builds and publishes both artifacts
atomically before the release becomes immutable. Two deliberate guards apply:
**/*.md, docs/**,
and archive paths (board Q-08-a / ANS-09-1).[skip release] (docs/test/CI-only by convention) skip
the release job entirely.Escape hatch (canonical): if a release commit's only diff is markdown —
for example a README badge correction that must still ship as a release —
the push cannot trigger auto-release. Mint it manually instead:
gh workflow run auto-release.yml
The dispatched run re-reads the committed version, runs the full release gates, and mints the tag exactly as a push-triggered run would (this is how v4.0.67's badge correction shipped).
This repository also hosts the public-domain AISC v16.0 DXF/DWG shape packs
previously distributed from Structural-Steel-DXF-DWG-Shapes.
| Location | Contents |
|---|---|
steel_shapes/dxf/ | 14 family DXF packs |
steel_shapes/dwg/ | 14 family DWG packs |
steel_shapes/source/ | AISC CSV + generation scripts |
steel_shapes/README.md | Usage, license, checksum notes |
steel_shapes/ATTRIBUTION.md | Merge provenance from the former standalone repo |
Releases: tag steel-v1.0.0 (etc.) to publish
Structural-Steel-DXF-DWG-Shapes-*.zip via the steel-shapes-release workflow.
PDF Importer addon releases continue to use v4.x.x tags.
To import several PDFs, select them all in File → Import; each one opens its own options dialog.
Batch Import provides progress and a Cancel button during object creation. An unreadable PDF is reported and the batch continues with the next input; cancelled batches count only pages confirmed complete by the import session. Selected pages share one import per PDF, including font caches and page layout. Recursive batches skip generated import-evidence folders. Page ranges are validated against each PDF before work begins, and duplicate page selections import once.
Every mode targets indistinguishable-from-source fidelity within FreeCAD's capabilities. Modes differ only in extraction strategy for different input types, not in quality tier.
| Mode | When to Use |
|---|---|
| Auto (default) | Let the importer analyze the PDF and pick the right strategy per page. Reports what it chose. |
| Vector | Clean vector PDFs (CAD exports, shop drawings, engineering drawings). |
| Raster | Scanned or image-only PDFs. Places the page as a high-DPI image. |
| Hybrid | Mixed content: vectors where clean, raster where vector extraction would be lossy. |
| Option | Result |
|---|---|
| Text | FreeCAD Draft text objects; the words stay editable |
| Labels | FreeCAD Draft label objects; the words stay editable |
| 3D Text (default) | Solid letter shapes from the PDF font (closest look; not re-typeable) |
| Glyphs | Exact letter outlines from the PDF font, one compound per source text item (not editable as words) |
| Geometry | Raw text-outline edges grouped per source text item (not editable as words) |
| Raster | One picture patch per source text item that looks exactly like the PDF (not editable) |
Plus a separate Import text toggle to skip text entirely. Glyphs and Geometry prefer Poppler/pdftocairo SVG output when available, then fall back to bundled PyMuPDF SVG paths.
The requested text mode is the delivered text mode. Alignment, rotation,
or scaling defects are fixed inside the requested mode — never by
substituting a different mode. Substitution is permitted only when the
requested mode is genuinely impossible for the exact source item. A generic
exception, a missing helper, an empty result, or a visual defect is not proof
of impossibility. An item whose requested representation failed without such
proof is still drawn at the next rung the ladder reaches, so that one item does
not cost the sheet, but that delivery is reported as degraded and is never
certified (owner directive 2026-09-19). Any authorized substitution must walk the closest remaining
representation first and is recorded per source item in import_report.json
with the attempted types, exact created/removed host IDs, cleanup result, and
the evidence that proved the requested type impossible. It is never silent.
(Owner directive 2026-07-13.)
Authorized order after item-specific proof (left rung first):
| Requested | Ladder |
|---|---|
| 3D Text | Glyphs → Geometry → Labels → Raster |
| Glyphs | Geometry → 3D Text → Labels → Raster |
| Geometry | Glyphs → 3D Text → Labels → Raster |
| Labels | 3D Text → Glyphs → Geometry → Raster |
| Raster | terminal — always achievable |
Notes:
tests/test_textmode1_invariant_fc.py,
tests/test_freecad_representation_contract.py and
tests/test_text_item_degrade_fc.py.extra.text_items_degraded
with every rung's own reason code, it adds one to result.warnings, it is
kept out of extra.host_font_map / extra.host_font_substitutions, and it
makes extra.text_representation_delivery.verified false so
import_contract_ready.ready is false for that sheet. An item that was
drawn at a lower rung is still counted in result.text_entities and in
extra.actual_text_entity_types as what was actually drawn; an item that
was dropped contributes nothing.extra.representation_contract_scope.uncertified_degraded_pages, keeps
import_contract_ready.ready false, and keeps the QA harness on DEGRADED
with a non-zero exit code.See COMPATIBILITY.md for the full matrix. Summary:
| FreeCAD Version | Python | PyMuPDF | Status |
|---|---|---|---|
| 1.1.x | 3.11 | 1.28.2 bundled offline | ✅ tested by hand on 1.1.4 (no automated FreeCAD test yet) |
| 1.0.x | 3.11 | 1.28.2 bundled offline | ⚠️ Expected (not tested) |
| 0.21.x | 3.10+ builds only | 1.28.2 bundled offline on 3.10 | ⚠️ Only builds that bundle Python 3.10+; the official 0.21 Windows installer (Python 3.8) is not supported yet |
| 26.x (new calendar version numbers) | not checked | ⚠️ not yet tested | |
| Any host using 3.12+ | 3.12+ | System/user install only | ⚠️ No bundled offline runtime |
| 0.20 and earlier | 3.8–3.9 | ❌ Not supported (needs Python 3.10+) |
Evidence levels:
✅ tested by hand: a person imported real drawings on that version; no automated FreeCAD test runs yet.⚠️ Expected: same Python and runtime as a tested version, but never run on it.❌ Not supported: known not to work.1.28.2 in the release runtime’s shared src/lib/common tree. When Poppler/pdftocairo is absent, it also backs Glyphs/Geometry text rendering.4.63.0 in the exact src/lib/cp310 or src/lib/cp311 tree selected from FreeCAD’s embedded Python ABI. The incompatible sibling tree is never added to sys.path.| Limitation | Details |
|---|---|
| Encrypted PDFs | Password-protected PDFs must be unlocked before import |
| Compression filters | Decoding is delegated to PyMuPDF. Malformed or non-standard compressed object streams may fail to parse |
| Raster-only scans | Pure raster PDFs produce no vector geometry |
| Clipped/XObject-heavy PDFs | Complex clip stacks and deeply nested form XObjects can produce partial geometry |
| Very large PDFs | Documents with >10,000 primitives may slow the import process |
| Embedded subset fonts | Valid embedded subsets are staged for native 3D Text; malformed font programs or missing/invalid character maps can still require an item-specific fallback or truthful failure |
| Older FreeCAD | Builds with Python older than 3.10 (0.20 and earlier, and the official 0.21 Windows installer) are not supported |
Large interactive imports show drawing-operation, text-character, and image-instance
counts before host-object creation. Cancellation keeps only certified pages. Resume
is persisted in the .FCStd document, so saving after cancellation allows a later
session to continue; unsaved process crashes are not claimed as recoverable.
Every import writes <pdf name>_import_report.json and keeps a copy you can find
again in the FreeCAD user data folder, under PDF Import Reports
(<pdf name>_<date-time>_import_report.json; the newest 50 are kept). The Report
view prints Import report: <path> after every import.
When an import fails, one Import Failed box gives the reason, the page and the report path, with an Open report folder button; nothing is added to your drawing. When an import finishes but some items were drawn another way or left out (text items, a drawing item drawn as plain lines, or a picture left out), one warning box says how many and where; a clean import shows no box. File > Open followed by Cancel leaves no empty document behind. Headless and batch runs never show a box; they print the same sentences.
The report carries extra.resolved_scale when a scale is detected.
factor for scaling only when confidence >= 0.70 and fallback_reason is not no_scale_detected.FreeCAD refuses bad PDFs at open time (fail closed). SketchUp uses the same user-facing messages but may proceed on rare gate-internal errors (fail open). Compare fallback.reason per host rather than assuming identical refusal behavior.
MIT License — see LICENSE for details.
Copyright (c) 2024-2026 BlueCollar-Systems