Glyph

Arrange — alignment, distribution, transform, boolean

The Arrange menu and the Transform toolbar group (which nests the Align dropdown) cover every geometric transform; boolean ops have their own Boolean toolbar group (a flyout listing all four with their hotkeys), plus the Edit menu, the right-click context menu, and the U/D/I/X keys directly (see below).

Alignment and distribution

When 2+ shapes are selected, the alignment buttons light up:

Transform

With a selection, the Properties panel shows an inline Transform section — no modal dialogs. Type a value and press Enter (or click the button); the panel stays open so you can repeat (e.g. Rotate +90 twice):

Array… (Arrange → Array… or the toolbar), Polar array… (Arrange) and Chamfer / Fillet corners… (Arrange) remain their own parameter dialogs.

The component library also carries two shapes Clewin offers as direct tools: a Regular polygon (any number of sides, with the radius measured to a corner or to an edge — the across-flats dimension a hexagon is usually specified by) and a Trapezoid (independent top and bottom widths, plus a top offset that turns the isosceles shape into a right trapezoid). They are components rather than drawing tools on purpose: both shapes are defined by numbers, so typing them beats dragging and correcting, and a placed one stays editable from the Properties panel.

Polar array repeats the selection around a centre instead of along a lattice: give a centre, a number of copies and a swept angle. A full 360° sweep spaces the copies evenly all the way round — 4 copies land at 0/90/180/270, so the last one does not sit on top of the first. A partial sweep (say 90°) fans them across that arc with the first and last copies ON the endpoints. Rotate each copy with the arc is on by default, which is what a radial test structure wants; turn it off and each copy keeps its original angle while only its position revolves, which is what alignment marks and labels need. It works on shapes and on placed instances — unlike the rectangular Array, which sends a selected instance to promote-to-AREF instead. GDS has no radial array primitive, so every copy is a separate object rather than one array record; the count is capped at 2000 and the dialog shows the resulting angular step live. One undo step.

Generate identifiers… (Arrange) stamps systematic labels in one undo step — the no-scripting replacement for Clewin's label function. Array labels mode writes an A1..H12 grid (rows × cols, configurable pitch, alpha/numeric row & column schemes, prefix, A1/1A order) across a die array; Mask ID block mode stacks large human-readable lines (project / designer / version / mask turn). Both use the normal text + font pipeline, so the labels flatten to polygons on GDS export like any other text.

Search & replace cell references

Ctrl+Shift+F (or Edit → Search & replace cell refs…) opens a dialog that rewrites every SREF/AREF whose target is the "from" cell to point at the "to" cell instead. The dialog shows a live count of how many refs will be affected before you commit. Scope is the whole document.

Find shapes & instances

Ctrl+F (or Edit → Find shapes & instances…) opens a searchable list of shapes and instances. Predicate grammar (terms separated by space = AND):

Scope is a three-way toggle:

Click any row to centre the viewport on it and select it — for a match owned by a cell other than the active one (either multi-cell scope), this also enters that cell (KLayout-style "show as new top") so the match is visible and editable, and the breadcrumb reflects the new context. Select all selects every match in the active cell at once (cross-cell matches aren't included, since canvas selection is per-cell). (You can also select every shape on a layer from the Layers panel — hover a row and click the marquee icon.)

Convert path to polygon (Arrange → Convert path to polygon)

Design-rule width/spacing/area checks and the boolean/layer operations above all work on filled polygon area — a path shape (a centreline plus a width) is invisible to them, so a routed trace can carry a sub-minimum width or overlap a keep-out layer and neither DRC nor a layer boolean will ever see it. Select one or more widened paths and run this to replace each with a boundary polygon tracing its exact stroked outline — same layer, same datatype, joints mitred and end caps honoured (flush / round / square) exactly as the path already drew. A path carrying custom per-end extensions (GDS PATHTYPE 4) is extended along its centreline before stroking, so the polygon has the same footprint a GDS reader would draw for the original path rather than shrinking by the extension at each end. Once converted, the geometry is checkable and boolean-able like any other polygon.

Every selected path lands in exactly one outcome, and the toast accounts for all of them:

Any non-path shapes in the selection pass through untouched and aren't counted. Single undo step for the whole selection.

Close open contours (Arrange → Close open contours…)

Outlines drawn in AutoCAD are very often not polygons — they are separate LINE and ARC entities whose endpoints happen to meet. They look correct on screen, but they enclose no area, so they export to GDS as PATH records and expose nothing. The failure is invisible until the mask comes back blank.

This command chains those open paths into filled polygons, merges duplicate or overlapping segments, and drops zero-length remnants.

It also runs automatically on every DXF, DWG and SVG import, on by default. A Close open contours & heal geometry checkbox appears on the DWG and SVG import dialogs (DXF has no import dialog, so the Heal imported geometry toggle in Edit → Settings decides on its own); untick it to import the file exactly as drawn. GDS, OASIS and CIF are never healed — they carry a real area primitive, so an open path there is a path you meant, not a CAD export artifact. Whichever way it's set, the import tells you how many open segments it found — with healing on, it also states what changed (contours closed, gaps bridged, duplicate segments merged, zero-length segments dropped); with healing off, it names the count and points you at this dialog or the Settings toggle. A genuinely clean file says nothing.

Two settings, both of which exist because neither has a safe universal value:

Chaining never crosses a layer or datatype boundary, and never touches a path that already has a width. Every removal is counted and reported. A chain that stays open keeps the paths it came from, but exact-duplicate and overlapping segments are merged away and zero-length remnants are dropped — the manual Arrange → Close open contours… command runs this as a single undo step.

Layer operations (Arrange → Layer operations…)

The selection-based booleans above replace whatever you select. Layer operations runs the same four ops (union / difference / intersect / XOR) between two whole layers instead, and is non-destructive: input layers A and B are left untouched, and the result is stamped onto a separate output layer — pick an existing layer or type a new layer/datatype number inline to create one on the spot. It refuses to run if the output layer is also input A or input B (writing back onto a source layer would just pile the result on top of the geometry that produced it) or if the output layer is locked.

Grow and Shrink size a single layer by a distance instead — layer B is ignored and a Distance (µm) box replaces it. This is true morphological sizing with round corners (a Minkowski offset), the same construction the design-rule checker uses, which is what stops a shrink from filling in a concave notch — a shrink that quietly welded a dumbbell's thin neck back into solid metal is the exact bug this avoids. Because the band construction costs roughly eight times a boolean on the same layer, grow/shrink is capped by input vertices (200 000) rather than shape count; past that it refuses immediately instead of grinding.

Tick Flatten instances first to expand every SREF/AREF in the active cell before collecting each side's shapes — off, only the active cell's own shapes on that layer are used, so geometry that only exists inside an instance is invisible to the op (same rule DRC uses, §8 below). Large jobs run on the same cancellable background worker as the selection-based booleans, above a 10 000-vertex threshold. The whole operation — including creating the output layer if it didn't exist — is one undo step.

CIF export and import (File → Export ▸ Export CIF…)

CIF (Caltech Intermediate Form) is Clewin's third interchange format. Glyph reads it (File → Open…, or drag a .cif in) and writes it (File → Export ▸ Export CIF…).

Coordinates are written in nanometres via CIF's DS n 1 10 scale, and layers are named L{layer}D{datatype} — the convention KLayout uses — so a layer number and its datatype stay distinct instead of merging.

What CIF cannot carry, stated plainly rather than lost quietly:

Geometry, hierarchy and layer assignment are checked against KLayout and gdstk on every release (npm run validate:cif); the four points above are the losses on that geometry path.

Opening a CleWin library. A CleWin structure library is itself a .cif, and it carries each symbol's parameter declarations and its source script inside CIF comments. Glyph reads them: open the file and the imported symbol shows the parameters CleWin declared — name, default and the valid range — in the Properties panel, along with a Show source script toggle. The layer colours CleWin stored are picked up too, so an imported stack is not uniformly grey.

Those parameters are read-only, and the panel says so. Glyph does not run the C script that consumed them, so the geometry in the file is already generated and changing a number here could not rebuild it. You get the geometry, and you get a record of how it was made — which is enough to redraw or re-parameterise it in Glyph deliberately, and honest about what it is not. Imported script text is stored and displayed only; Glyph never executes it.

Saving a CleWin library back out round-trips its parameter surface. Until v0.94.0, Export CIF… silently dropped an imported symbol's declared parameters and script text — the geometry above's "only losses" claim was wrong for exactly this field, since it was never on that list at all. Exporting a cell that carries CleWin-declared parameters now re-emits its (C5Param …) declarations and (CleScript …) text verbatim, so a colleague still using CleWin sees the same Properties → Parameters tab and script on reopening. This is passthrough of the same read-only values described above, not new editing capability — a parameter you cannot change in Glyph before saving, you still cannot change by round-tripping through Glyph.

Layer colours also round-trip now (R32-4). Every export writes a (CleWin: idx num/fill frame) comment for each declared layer (when the document has at least one cell — the records ride inside the first symbol, so a cell-less document emits none), fill from Layer.color and frame from Layer.edgeColor (falling back to the fill colour when no edge colour is set) — not only for layers that were originally read from a CleWin file. This closes the one gap the CleWin-import feature left open: previously a colour picked up on import, or set in Glyph, was silently dropped again on export. This is judged only against Glyph's own reader, never claimed as verified against a real CleWin install — the decode this write-back mirrors was itself inferred from observed files, not probed through CleWin (see the CleWin-import paragraph above), so treat it as a faithful Glyph round trip, not a guarantee about what a real CleWin will show. Two colour states do NOT survive the round trip (C32-V1): a pure-black fill (#000000) reads back as the default #cccccc (the importer deliberately rejects black — a CleWin file's black usually means "unset"); and an edge colour set exactly equal to the fill reads back as no edge colour (an equal fill/frame pair is how "no independent frame colour" is encoded, so the two states are indistinguishable in the file) — note the latter also moves that layer off the edge-framed render path after a round trip. Pick an edge colour that differs from the fill, and avoid pure black, if the distinction matters.

OASIS export and import (File → Export ▸ Export OASIS…)

OASIS (SEMI P39) is the modern, more compact companion to GDSII used in foundry flows. Glyph reads it (File → Open…, or drag a .oas/.oasis file in) and writes it (File → Export ▸ Export OASIS…, or pick a .oas filename in Save as…).

Output is compressed by default. .oas is never bound for save-in-place — Ctrl+S on a document opened from OASIS falls through to Save as… instead of overwriting it — because the OASIS writer is lossy in two small, deliberate ways: a round-capped path exports with a squared cap instead (OASIS has no round-cap concept); and bitmaps and construction shapes are dropped, the same exclusion every Glyph writer applies. Text size, font and PRESENTATION justification now survive an OASIS round trip — OASIS's TEXT record has no field for any of them, so they ride as element properties alongside the string, layer, texttype and position, and are read back the same way, so a GDS → OASIS → GDS trip no longer resizes your labels.

DXF export (File → Export ▸ Export DXF…)

Glyph writes AutoCAD R2000 ($ACADVER = AC1015) — the oldest widely supported DXF flavour that still carries blocks, arrayed inserts and constant-width LWPOLYLINE, so the file opens in essentially anything that reads DXF. See "DXF import" below (§15) for the read side of this exchange — this section is the write side, documented on its own because until now it had no section at all.

Coordinates are written verbatim in world nanometres, and the header declares $INSUNITS = 12 (nanometres) — the same "1 unit = 1 nm" convention as CIF's DS scale above, chosen so every coordinate is an exact integer rather than a rounded fraction. A file Glyph writes reopens (in Glyph, or any tool that honours $INSUNITS) at the same physical size.

Boundaries and boxes become closed LWPOLYLINEs; paths become open ones with a constant width. A boundary/box outline drops its own repeated closing vertex (the closed flag already implies the wrap edge) and writes exactly; a path carries its GDS width in LWPOLYLINE's constant-width group — DXF's own "ribbon path" model, matching a GDS PATH's width exactly. A path's end-cap style (pathType) has no DXF counterpart and is lost: every exported path reads back flush-capped regardless of how it was drawn. Zero-width paths still export, as a zero-width polyline.

Layers keep the (layer, datatype) pair distinct, via the same L{layer}D{datatype} naming CIF uses above ({Name}_L{layer}D{datatype} when the layer has a real name, so the human label survives alongside the pair) — DXF's own symbol table has no datatype, so without this two rows sharing a layer number would collapse into one DXF layer. A hidden Glyph layer is written switched off (a negative colour index), never dropped, and a locked layer carries the LAYER table's own locked flag.

Layer colour is quantized to the AutoCAD Color Index (ACI) — genuinely lossy, not a close approximation. DXF R2000's LAYER record has no true-colour field (that arrived with R2004's group 420), so each layer's #rrggbb is snapped to the nearest entry — by squared RGB distance — of a small, fixed 16-swatch palette (ACI 1–9, four mid-palette accents at 30/90/140/200, and three greys at 250/252/254), never the full 256-slot ACI ramp. Measured on a real export: #00ffaa and #ffee00 land on ACI 4 (cyan, #00ffff) and ACI 2 (yellow, #ffff00) respectively — both read back exactly as those two saturated swatches, nowhere near the original hue. A mid-range slot is worse twice over: #4488ff (a mid blue) lands on ACI 140, but Glyph's own DXF reader reconstructs ACI 10–249 from AutoCAD's real (Measured: slot 30 differs by 1/255 — visually identical; 90/140/200 differ materially. — C38-V1) hue-ramp layout (24 hues × 10 shades) rather than from this writer's own 16-entry table, so reopening the very file Glyph just wrote does not even recover the swatch the writer picked — only a different approximation of the same ACI number. There is no side channel to preserve the original hex, unlike CIF's inert (CleWin: …) comment trick above; hand off a .lyp/.csv layer map alongside the DXF (File → Layer setup ▸ Export layer map) if the recipient needs your house colours.

References become blocks and inserts. An SREF becomes a block INSERT, preserving position, rotation, mirror and scale exactly — DXF's INSERT carries all four, unlike CIF's call, so no reference is ever flattened for scale reasons the way a magnified CIF reference is. A rectangular, axis-aligned AREF becomes a native arrayed INSERT (DXF's own row/column/ spacing groups); anything sheared or rotated off-axis is expanded instance-by-instance instead, up to 20 000 instances — past that only the four corner instances are written, with a 999 comment at the top of the file recording that the array was truncated (the same policy Export SVG… and Export figure… use for an oversized array).

Text collapses to a plain TEXT entity in the STANDARD style — font, letter spacing and PRESENTATION justification are not concepts Glyph maps onto anything in DXF, so they are dropped; position, rotation and size (as the TEXT height) are kept exactly, with the justification already baked into the insertion point so the text lands in the right place even though the justification groups themselves are never written.

Construction shapes, bitmaps and Cell.dimensions are excluded — the same contract as every other Glyph writer.

Structural validity (never colour, which is cosmetic by nature here) is checked against the independent ezdxf Python library's Auditor on every release (npm run validate:dxf), which treats an auto-fix as a failure, not just a hard error — a round trip through Glyph's own DXF reader is deliberately never used as that check, since a lossy writer and a lossy reader can agree with each other while both are wrong.

Grid presets (Shift + a number key)

Ten snap steps live on the number keys, Shift+1 through Shift+0. Pressing one switches the grid to that fixed step and turns snapping on; the step is shown in a brief toast so a keypress never changes the grid silently. The current preset is ticked in View → Grid preset, which also lists all ten with their values. One caveat: under the KLayout keyboard preset, Shift+8 is the same physical keystroke as that preset's * (show full hierarchy), so grid preset 8 is unbound there — nine presets on keys, with the ticked menu still reaching all ten.

Edit the ten values in Settings → Advanced → Grid presets. They are in nanometres — a grid is an exact integer distance, and rounding it through a display unit would change it. Reset restores the default ladder (1 nm to 100 µm).

They take Shift because the bare number keys belong to the KLayout keyboard preset's hierarchy levels, and both migrant habits are worth keeping. Every one of the ten is remappable in Edit → Keyboard shortcuts… like any other command.

< and > step the live grid to the next finer/coarser stored preset without needing to remember which slot it is in — the same idea as KLayout's increase/decrease-grid keys. At either end of the ladder they clamp rather than wrapping around. Both are also in View → Grid preset and remappable like any other command.

EPS figure export (File → Export ▸ Export EPS…)

File → Export ▸ Export EPS… writes an Encapsulated PostScript figure — the vector page format Clewin emits and every LaTeX toolchain consumes. It uses the publication look by default (white ground, solid fills, outlines, a scale bar and a legend), because reaching for EPS means making a figure for a paper.

Its one advantage over SVG is that the figure has a real printed size: it is written at a width in millimetres, so it lands in your document at a known width instead of at whatever the importing tool guesses. For full control over the annotations, use File → Export ▸ Export figure… instead and pick a .eps filename there — when its Size is set to Print, the mm width you enter is the EPS page width.

Two things PostScript cannot do:

What survives each format

A quick-reference for "if I hand this file to someone else, what changes?" — each cell states the honest behaviour of that format's own writer, not a goal. GDS is the baseline every other row is measured against, since it's Glyph's native, lossless round trip (bitmaps, construction shapes and Cell.dimensions are the one universal exception — every writer below excludes all three, so that column isn't repeated per row).

Format Geometry Layer pairs (layer + datatype) Colours Text styling Refs / arrays
GDS Exact — Glyph's own native, lossless format. Exact — layer + datatype ARE the format's own key. None — GDS carries no colour field at all; hand off a layer map (§15) for your palette separately. Position/rotation/size/PRESENTATION preserved; an imported TTF/OTF font is even embedded whole, in a private __GLYPH_FONTS__ cell other tools ignore (§12). Exact — SREF/AREF are native GDS records, hierarchy intact.
OASIS Exact, except a round path cap exports squared (no round-cap primitive). Exact — native layer/datatype (+ texttype) fields. None — OASIS has no colour field either; reopening shows Glyph's own auto-assigned default palette, not yours. Size, font and PRESENTATION justification do survive, riding as S_GDS_PROPERTY element properties. Exact — native placement and array records.
CIF Near-exact — a widened path is stroked to its outline (the shape is right, "this is a path" isn't); zero-width paths stay wires. Exact — L{layer}D{datatype} naming (see above). Preserved, but only through Glyph's own reader — an inert (CleWin: …) comment other CIF tools ignore. Dropped — becomes a plain label; font, size and alignment are lost. Position/rotation/mirror preserved; a magnified (≠1×) reference is flattened into its parent.
DXF Exact outlines; a path's end-cap style is lost (always reads back flush-capped). Exact — same L{layer}D{datatype} naming as CIF (see above). Lossy — quantized onto a fixed 16-entry AutoCAD Color Index by nearest RGB; exact hex is never recovered. Dropped — becomes a plain TEXT entity, STANDARD style; position/rotation/size are kept, font/spacing/justification are not. SREF exact; an axis-aligned rectangular AREF becomes a native arrayed INSERT; anything sheared/rotated is expanded instance-by-instance (capped at 20 000).
SVG Exact, but always flattened — SREF/AREF fully expanded, hidden layers dropped. Not preserved as pairs — becomes flat coloured shapes; only the colour (not the original layer number) can round-trip, via "Split colours into layers" on reimport. Preserved exactly, including opacity (fill-opacity). Emitted as SVG <text> in a monospace font — position/rotation kept, exact glyph outlines are not (flatten to boundaries first). None — always flattened; an over-budget array draws a footprint outline plus a bounded sample of instances instead of every one.
EPS Exact, flattened the same way as SVG (shares the same flattener). Not preserved — flattened to coloured fills; EPS is export-only, there's no reimport path to preserve them for. Preserved but flattened — a translucent layer is composited onto the page background at write time, so an on-screen overlap blend is lost. Set in a PostScript base-14 font (Courier), always printed upright regardless of the shape's own rotation; non-ASCII characters become ?. None — always flattened, same as SVG.

Recipes (Edit → Recipes…)

A recipe is a saved, ordered list of editor commands you can re-run on any document — "run the design-rule check, then export per layer", every time, the same way. Add steps from the action picker, reorder them, save the recipe to a file, and load it again later. It is plain data: nothing in a recipe file is executed as code.

Steps can now carry parameters. Two actions run without opening their dialog when you fill in their fields:

Leaving a step's fields blank keeps the old behaviour: the action opens its dialog when the recipe reaches it, exactly as before. So a recipe you saved earlier runs identically today.

A step that names a parameter the action does not have, or gives it the wrong type, stops the recipe and says which step and why — it is not skipped. That matters most when nobody is watching: a step that quietly did nothing would let the run report success over a layout that is wrong.

Recipes are not atomic. Each step dispatches its own commands, so undo unwinds a recipe one step at a time rather than all at once.

Objects panel

The Objects tab in the left panel lists everything in the cell you are editing — every polygon, path, text, bitmap, instance and array — with its kind, its (layer, datatype), and its size. Click a row to select that object and frame it. Type in the filter box to narrow the list by kind, layer, id or note.

It is the fastest way to answer "which object is on the wrong layer" on a symbol that renders wrong. A few details worth knowing:

There is no per-object show/hide. Visibility is per layer and per cell; hiding an individual object would cost drawing speed on every frame for every design, and selecting the object plus isolating its layer covers most of the same need.

Alignment marks across a mask series (Verify → Place alignment marks… / Check mark alignment…)

Place alignment marks… puts one mark type at a list of wafer coordinates on every layer you tick, as a single undo step — so a five-mask series gets its marks from one action instead of twenty-five placements that have to agree by hand.

Emission is tone-aware. On a clear-field level the mark is drawn as geometry. On a level whose field tone is dark, the same mark is emitted as a clear window — the mark shape knocked out of a surround — because that is what prints the same image on a dark field. Drawing solid geometry there would print its complement, and the aligner would not find its mark. The dialog says which of the selected levels are dark-field before you commit.

Check mark alignment… is read-only: it finds small shapes on each layer, clusters them into marks, matches marks across layers, and reports any site where the layers disagree by more than 1 µm or where a layer is missing a mark the others have. It expands SREF/AREF instances first, so a mark that lives inside a sub-cell on one level and is drawn directly on another is still compared. On a document too large to expand (a full wafer step-and-repeat) it falls back to the active cell's own shapes and says so in the report rather than narrowing silently.

It is purely geometric, so it works on marks that were drawn by hand, imported from a foundry file, or copied between documents — nothing has to be tagged as a mark.

Updated 2026-08-28

Open Glyph — free, no install Your files never leave your computer.
Open Glyph →