Reference Documentation

CXTF
Coordinates Exchange Text-Format

A plain-text format for hierarchical 2D and 3D vector graphics and map data: human-readable, explicitly structured, and built for seamless exchange between applications. One command per line, no hidden state, no surprises.

About CXTF

Coordinates Exchange Text-Format (CXTF) is a line-based text format for exchanging hierarchical 2D or 3D geometric data for vector maps and any other graphics with styling information. It provides a human-readable way to represent vector graphics including paths, shapes, colours, gradients, and hierarchical organisation. The format was developed by Stefan Gies from 1992 onwards, evolving from an earlier binary precursor (CH5) into its current human-readable form.

Designed for

Interoperability between vector graphics applications — easy parsing and generation — preservation of visual styling (colours, gradients, strokes, fills) — hierarchical document structure (layers, groups).

Syntax

CXTF uses a line-oriented, space-delimited syntax. Each line contains exactly one command followed by its parameters. Comments begin with ~ and the rest of that line is ignored.

command parameter1 parameter2 … parameterN

Commands are typically 1–2 characters long and case-sensitive (with a few case-insensitive exceptions). Parameters are separated by spaces: numbers (integers or floats) for coordinates and values, strings for names and text, and colours in BGR(A) format.

A backslash \ at the end of a line is a continuation marker — the next line is appended to the current one without inserting a line break. The pipe character | is an explicit line separator equivalent to a newline, allowing multiple commands on the same physical line.

Strings (titles, layer names, group names) must encode special characters using $XX hex escaping: $ | = ; ~ \ / # @ & " CR LF. Because | acts as a line separator, it must be encoded as $7C inside string values.

Colours

Colours are specified in BGRA order (Blue Green Red Alpha, 0–255). The alpha channel is optional and defaults to 255 (fully opaque). The alternative commands -c and -f accept colours in RGBA order — these exist so third-party exporters that work natively in RGB do not need to swap channels before writing CXTF.

Dimensionality

The dimensionality of coordinate vectors is set once in the file header with the $ command:

$ 2 ~ 2D: vectors are X Y $ 3 ~ 3D: vectors are X Y Z (Z is ignored by the 2D renderer)

Parameters typed DimVector in the command reference change their value count with dimensionality — 2 values in 2D, 3 values in 3D. These are exclusively the geometry coordinate commands (p, s, l, L, z, Z, H, M and related). Parameters typed Vector are always a fixed 2-value pair regardless of $ — this applies to transformation commands (O, S, U) and structural commands (<, >).

The Bézier commands z/Z have two DimVector anchor points before the endpoint. In 3D each gains a Z component, shifting the position of all subsequent parameters — unlike every other command where vectors are at the end.

Since format version 6.3, the Z component of a DimVector is optional in 3D files. The Z value persists within a group: the polygon or polyline start point (p or s) establishes the initial Z, and all subsequent points (l, z, Z etc.) inherit it until a new explicit Z value appears. Z is reset at each new group. This makes contour-line data significantly more compact — the elevation only needs to be stated once per contour line.

File Extensions

CXTF content is typically stored in one of two forms. A plain .cxtf file contains only the vector data; any referenced images, textures, symbols and fonts must reside alongside it on the file system or server. A .cxzip archive bundles the .cxtf file together with all its resources into a single standard ZIP file. The main CXTF file inside the archive is always named __main.cxtf; the original filename is recorded within it via the ofn command.

Image Resources

Images, textures and symbols referenced in a CXTF file are identified by their basename only — the directory path is stripped at parse time. All image basenames within a project must therefore be unique regardless of extension: having both photo.jpg and photo.png in the same project is not permitted.

The GGG command (formerly GG) applies colour filtering to an image. To avoid recalculating the filter every time the file is opened, the adjusted result is written alongside the source as a PNG with a suffixed second extension: photo.jpg becomes Adjusted/photo.jpg.png. When this pre-computed file is present — either on disk or inside a .cxzip archive — it is loaded directly in preference to the original, making large projects with many filtered images open instantly.

Style Model

Of all CXTF commands, only c (stroke colour) and f (fill colour) are stateful — their values persist across subsequent elements until explicitly changed. Since version 6.3, the Z coordinate of DimVector parameters in 3D files follows the same principle: once set by the element start point (p or s), it is carried forward within the group until a new explicit Z value appears. Every other property command (cp, w, t, fg, fh, n, U, O, R, S, zr and so on) is a modifier applied to the immediately preceding element, group, folder, image or symbol. This keeps the format explicit and predictable: no style inheritance cascades through the hierarchy.

Design Philosophy

  • Text-based — human-readable and editable in any text editor
  • Explicit — every style and coordinate is stated directly
  • Sequential — commands are processed in order
  • Hierarchical — Project → Folders → Groups → Elements, with a separate Image Overlay hierarchy
  • Stateful — stroke colour (c) and fill colour (f) persist across elements until changed; all other modifiers apply to the immediately preceding element
  • Extensible — new commands can be added while maintaining backward compatibility

Typical File Structure

CXTF ~ File header ? Title ~ Document title v 6 1 ~ Format version V Application Name ~ Exporting application F 0 -1 1 Layer Name ~ Layer definitions F 1 0 1 Sub Layer ~ (Id ParentId Visible Name) * Group Name ~ Group start c B G R [A] ~ Stroke colour (alpha optional, default 255) f B G R [A] ~ Fill colour (alpha optional, default 255) p X Y ~ Polygon start l X Y ~ Line to point z B1x B1y B2x B2y X Y ~ Bezier curve

Browse the Documentation

Quickstart

Include the renderer script and place a <cxtf-view> tag anywhere in your HTML. No build step, no dependencies.

<!-- 1. Load the renderer (once, anywhere in the page) -->
<script src="docs/cxtf-renderer.js" defer></script>

<!-- 2. Place the viewer -->
<cxtf-view src="mymap.cxtf"
            width="600" height="400"></cxtf-view>

That is all that is required. The component renders inside a Shadow DOM canvas and fires a cxtf-ready event when loaded.

The defer attribute on the script tag ensures the custom element is defined before any <cxtf-view> tags in the document are connected.

Inline vs src

There are two ways to supply CXTF content to the component. Use one or the other — not both on the same element.

src attribute — load from file

Fetches a .cxtf or .cxzip file from the server. The path is relative to the page URL. A CORS header (Access-Control-Allow-Origin) is required if loading cross-origin.

When a .cxzip archive is loaded, the component unpacks it in the browser using the built-in DecompressionStream API (no external libraries required), reads __main.cxtf as the main file, and resolves all resource references (images, textures, symbols, fonts) directly from the archive as blob URLs.

<cxtf-view src="examples/mymap.cxtf"
            width="800" height="500"
            centered="true"></cxtf-view>

Inline content — embed CXTF directly

Place CXTF text as the text content of the element. Suitable for small, self-contained examples or when serving static HTML without separate asset files.

<cxtf-view width="400" height="300">
CXTF
? Inline example
$ 2
b 30 30 30

* Box
c 100 160 80
f 60 100 50 180
p 0 0
l 20 0
l 20 15
l 0 15
L 0 0
</cxtf-view>
Do not set both src and inline text content on the same element. If src is present it takes precedence and the text content is ignored.

Attributes

All attributes except src, width, and height are boolean and take the literal string values "true" or "false".

AttributeTypeDefaultDescription
src string URL of the .cxtf file to load. Omit to use inline text content instead.
width integer 600 Initial canvas width in CSS pixels. The canvas scales with devicePixelRatio for sharp rendering on HiDPI displays.
height integer 400 Initial canvas height in CSS pixels.
centered boolean false When true, the viewport is centred on the focus point. When false, the origin is the top-left corner.
interactive boolean false Enables mouse-wheel zoom and right-click (or touch) pan. Disable for static embeds.
transparent boolean true When true (default), the checkered transparency background is suppressed and the CXTF background colour is drawn at its own alpha. Set "false" to show a checkerboard for transparent areas.
xray boolean false Outline-only (X-ray) render mode. All fills are suppressed; only stroke outlines are drawn.
cross boolean false Draws a crosshair at the focus point. Useful for debugging centred viewports.
nodes boolean false When true, folders and groups that are invisible by default (# marker in CXTF) are shown in the tree panel. Does not affect canvas rendering.

All attributes with their default values:

<cxtf-view
  src=""               <!-- omit for inline content -->
  width="600"
  height="400"
  centered="false"
  interactive="false"
  transparent="true"
  xray="false"
  cross="false"
  nodes="false"></cxtf-view>

Packaging as .cxzip

A .cxzip file is a standard ZIP archive (DEFLATE compression, no Zip64) containing a CXTF project and all its resources in one portable file. The component loads it identically to a plain .cxtf — just point the src attribute at the archive.

<cxtf-view src="maps/myproject.cxzip"
            width="800" height="500"
            centered="true"></cxtf-view>

Archive structure

PathDescription
__main.cxtf The main CXTF file. Always this exact name. The original filename is recorded inside it via the ofn command.
foo.jpg
bar.png …
Image resources in the archive root. All image basenames must be unique regardless of extension — photo.jpg and photo.png in the same archive is not permitted.
Adjusted/foo.jpg.png Pre-adjusted version of foo.jpg produced by the GGG (formerly GG) colour-filtering command. When present, this takes priority over the root entry so the adjusted image is used directly without recalculating the filter at load time.
font.ttf … Font resources, always in the archive root (no subdirectory).

Resource resolution order

For each image reference the component checks in this order:

  • Is there an Adjusted/ entry whose name matches (e.g. Adjusted/foo.jpg.png for a reference to foo.jpg)? → use that blob URL.
  • Otherwise use the root entry matching the basename (e.g. foo.jpg).

Fonts and all other resources are always resolved from the archive root.

The DecompressionStream API used for unpacking is available in all modern browsers (Chrome 80+, Firefox 113+, Safari 16.4+). No external ZIP library is required.

With Tree

The <cxtf-tree> companion component renders a visibility-toggle tree panel linked to a <cxtf-view> by ID. It includes folder/group checkboxes, an image overlay section, a font list, and a built-in search box.

Connect them with the for attribute matching the viewer's id:

<div style="display:flex; border:1px solid #ccc;">

  <!-- Tree panel: for= must match the cxtf-view id -->
  <cxtf-tree for="mymap"
              style="width:220px; flex-shrink:0;"></cxtf-tree>

  <!-- Viewer -->
  <cxtf-view id="mymap"
              src="mymap.cxtf"
              width="600" height="400"
              centered="true"
              interactive="true"></cxtf-view>

</div>

<cxtf-tree> listens for the cxtf-ready event on the linked viewer. It can be placed anywhere in the document — it does not need to be adjacent to the viewer.

Toggling a checkbox in the tree calls node.visible = … on the parsed tree and then view.refresh() to redraw immediately.

The tree component uses its own Shadow DOM and stylesheet (cxtf-viewer.css is its companion CSS). Load that stylesheet in your page <head> for correct rendering.

Live example

Events

All three events bubble and are dispatched on the <cxtf-view> element itself, so you can listen on a parent container. All three are dispatched asynchronously (via setTimeout), so listeners registered in a script loaded after cxtf-renderer.js are guaranteed to receive them.

EventdetailDescription
cxtf-ready { tree, view } Fired after a successful parse and first render. tree is the parsed project tree; view is the component element itself.
cxtf-error { src, filename, kind, detail } Fired on fatal load or parse failure. kind is one of "not-found" (HTTP 404), "network" (other fetch failure), or "empty" (file loaded but parsed to an empty tree). src is the original URL; detail carries additional diagnostic information. The canvas displays an error message automatically.
cxtf-warning { kind, message, paths } Fired for non-fatal issues. Currently used when image assets fail to load; kind is "images", paths is an array of the resolved URLs that failed, and message is a human-readable summary. The canvas shows placeholder cross-outs on affected nodes.

Usage example

const view = document.getElementById('mymap');

view.addEventListener('cxtf-ready', e => {
  const { tree, view } = e.detail;
  console.log('Loaded:', tree.meta.title ?? tree.meta.ofn);
  console.log('Dimensions:', tree.meta.dims);
});

view.addEventListener('cxtf-error', e => {
  const { filename, kind } = e.detail;
  const msg = {
    'not-found': `"${filename}" not found`,
    'network':   `"${filename}" could not be fetched`,
    'empty':     `"${filename}" has no renderable content`,
  }[kind] ?? `Error loading "${filename}"`;
  showError(msg);
});

view.addEventListener('cxtf-warning', e => {
  if (e.detail.kind === 'images')
    console.warn('Failed images:', e.detail.paths);
});

JavaScript API

After a cxtf-ready event (or once the element is in the DOM), the following properties and methods are available directly on the element reference.

Properties

PropertyTypeDescription
.zoom number (r/w) Current zoom factor. Range 0.05 – 500. Setting triggers an immediate re-render. Each mouse-wheel step multiplies by 21/8 ≈ 1.091.
.focusPoint { x, y } (r/w) The point in CXTF coordinate space that maps to the canvas centre (when centered="true") or top-left origin. Setting triggers an immediate re-render.
.tree object (r) The parsed project tree. Available after cxtf-ready. Key sub-objects: tree.root (folder hierarchy), tree.meta (title, author, version, dims, …), tree.images.
.cxtfText string (r) The raw CXTF source text that was parsed — whether loaded via src or supplied inline.

Methods

MethodDescription
.refresh() Re-renders the canvas with the current view state. Call after manually modifying node.visible on tree nodes or any other state that affects rendering.
.setInteractive(bool) Enables or disables mouse-wheel zoom, drag pan, and touch gestures at runtime. Cleans up any in-progress drag or touch gesture when disabling. Equivalent to toggling the interactive attribute.
.exportPng(filename?) Renders the current view to a PNG at full canvas resolution and triggers a browser download. filename is optional — if omitted it defaults to the project's original filename (from the ofn command) with a .png extension.

Usage example

const view = document.getElementById('mymap');

view.addEventListener('cxtf-ready', () => {

  // Zoom in 2× and centre on a specific point
  view.zoom = 2.0;
  view.focusPoint = { x: 100, y: 80 };

  // Hide a specific folder by name
  function findNode(node, name) {
    if (node.name === name) return node;
    for (const child of node.children ?? []) {
      const found = findNode(child, name);
      if (found) return found;
    }
  }
  const labels = findNode(view.tree.root, 'Labels');
  if (labels) { labels.visible = false; view.refresh(); }

  // Export to PNG
  document.getElementById('save-btn')
    .addEventListener('click', () => view.exportPng('mymap.png'));

});

Known Limitations

The following CXTF commands are parsed but not yet rendered by the web component. Files using these features will load without error; the commands are silently ignored.

CommandDescriptionNote
fh Fill hatch pattern GDI+ hatch styles — no direct Canvas 2D equivalent
ffg Combined fill-style shorthand Combines c + f + fg + fh; depends on fh
zr Zoom-range visibility Show/hide groups outside a min/max zoom range
J Inline image element Image placed inside a group (distinct from G background overlay)
cp Extended line properties Cap, join, dash — overlaps with w optional parameters
cg Line/stroke gradient No direct Canvas 2D equivalent for stroke gradients
triangle, quadrangle, ellipse, box Primitive shapes (ElementType 60–63) Parsed but not rendered
GGG contrast / mix Image colour adjustment parameters Opacity and inverted flag are applied; contrast, mix mode and per-channel curves are parsed but not rendered
Key Name Section Remarks
📄
ABNF Grammar
Formal syntax definition of the CXTF format in Augmented Backus–Naur Form. Useful for implementing parsers and validators.
CXTF.abnf
Download
📦
Command & Enumeration Reference
Full machine-readable documentation of all CXTF commands, parameters, and enumerations. The data that powers this site.
CXTF_Documentation.json.gz  · 
Download