Rbc - Refactored BLT Components for Tcl/Tk 9

RBC preview

Rbc extends Tcl/Tk 9 with scientific plots, interactive graph controls, real and complex vectors, spline interpolation, and window and image utilities. Graphs update automatically when their attached vectors change. All types of plots and graphical elements support SVG, PostScript and PDF export. All three exporters work without Cairo.

This repository maintains and extends Rbc for Tcl/Tk 9.0. The current package version is 0.8.1.

Components

  • graph - Cartesian plots with line elements, symbols, multiple axes, error bars, markers, legends, and PostScript output.

  • barchart - Bar plots with normal, aligned, stacked, and overlapping presentations.

  • stripchart - Plots using independent line segments, suitable for waveform and continuously updated data displays.

  • polar - Complex-plane plots with polar or Smith-chart grids. Data coordinates remain Cartesian; elements can use real X/Y vectors or complex vectors directly.

  • graphtoolbar - A TclOO megawidget providing graph interaction, including zooming, panning, crosshairs, closest-point information, legend interaction, and context controls.

  • vector - Real and complex double-precision vectors, with numerical operations and automatic notification of attached graph elements.

  • spline - Natural cubic and shape-preserving quadratic interpolation, including parametric interpolation of complex vectors.

  • winop - Window operations and image-processing utilities.

Eligible dense line and strip elements support -decimate auto. The reduction preserves waveform extrema and reuses cached summaries across axis changes, ranged value updates, and monotonic tail appends.

An optional Cairo backend adds antialiased plotting. Cairo-enabled builds select it by default; applications can choose -renderer native for workloads where native drawing is faster. Text continues to use Tk in either mode.

Rbc contains selected components derived from BLT. It is not a complete replacement for the BLT toolkit.

Interactive examples

In this section you can see the usage of the package in a few examples from demo folder. There is shown dynamic interaction between native Tk widgets and Rbc graphtoolbar megawidget, as well as live graph update following vectors changes:

Fast Fourier Transform (fft1.tcl)

fft1_live_demo

Douglas-Peucker simplification (simplify1.tcl)

simplify1_live_demo

Combined scatter and disribution plots (combined1.tcl)

combined1_live_demo

Detailed description and demonstration of graphtoolbar megawidget could be found in related documentation section

Requirements

Running Rbc

  • Tcl and Tk 9.0/9.1

  • The optional toolbar prefers an installed argparse package. If none is available, it uses the bundled Tcl-only argparse 0.65; no separate installation is required for the graph demos.

  • A graphical environment supported by the Tk installation.

The build environments described here are Linux with X11 Tk and Windows with MSYS2/UCRT64 or MSVC. Tcl/Tk 8.x compatibility is not a target of this fork.

package require rbc loads Tk, the native Rbc widgets and commands, and the legacy graph.tcl helpers, without requiring argparse.

The global Rbc_ActiveLegend, Rbc_Crosshairs, Rbc_ResetCrosshairs, Rbc_ZoomStack, Rbc_ClosestPoint, Rbc_PrintKey, and Rbc_PostScriptDialog commands are retained for backward compatibility. They are not enabled until called on a graph. For new applications, prefer the optional toolbar below. Using these helpers together with ``rbc::graphtoolbar`` on the same graph is not recommended, because their bindings and interaction state can interfere. Separate widgets may use separate interaction systems. See Legacy graph helpers in the graph documentation for usage and cleanup behavior. Load the optional toolbar explicitly, before importing Rbc commands:

package require rbc::graphtoolbar
namespace import ::rbc::*

This also loads the matching rbc package and argparse (installed, or the bundled Tcl-only fallback when missing). Applications using graphtoolbar must add this require; the command name remains ::rbc::graphtoolbar. Requiring the toolbar repeatedly preserves existing widgets.

The bundled argparse source and MIT licence are installed alongside graphtoolbar.tcl. Its origin and version are recorded in argparse-README.txt. Errors from an installed argparse package are reported rather than replaced by the fallback. Plain package require rbc and rbc::vector remain independent of argparse; the bundled copy is not advertised as a separate installed package.

For vector-only use in tclsh, load the Tcl-only package instead:

package require rbc::vector
::rbc::vector create samples
samples set {1 2 3}

This uses the same binary without initializing Tk, requiring a display, or loading argparse. Loading package require rbc afterward adds the GUI while preserving existing vectors. The binary’s linked dependencies must still be installed; building still requires the usual Tcl/Tk development files. Direct load now initializes only the vector core; use package require rbc for the full package. External C extensions can use Rbc_VectorInitStubs from the updated stub library for this Tcl-only path.

The full tests and documentation generation need a working graphical display. The vector-only test target does not.

Building Rbc

  • A C compiler and linker compatible with the selected Tcl/Tk build.

  • GNU Make and a Unix-style shell.

  • Tcl/Tk development files, including tclConfig.sh and tkConfig.sh.

  • Matching Tk private headers.

  • On Linux, the X11 and Fontconfig development headers and libraries (for example, libx11-dev and libfontconfig1-dev on Debian/Ubuntu). PDF/SVG font discovery uses Fontconfig, independently of Cairo. Configure uses pkg-config; custom installations can set FONTCONFIG_CFLAGS and FONTCONFIG_LIBS. Windows uses GDI without an additional font library.

  • For --enable-cairo, Cairo 1.12 or newer with its platform backend and development headers. Configure uses pkg-config unless both CAIRO_CFLAGS and CAIRO_LIBS are supplied.

Rbc still uses a small number of private Tk interfaces. Retain the matching Tk source tree unless the development installation provides all required private headers. The configure script uses the source location recorded in tkConfig.sh when locating these headers.

Keep the corresponding Tcl source tree available as well when using the provided development targets: the Makefile sets TCL_LIBRARY from the source location recorded in tclConfig.sh.

The repository includes a generated configure script. Autoconf is needed only when regenerating it after changes to the build configuration.

Building from source

Obtain the sources:

git clone https://github.com/georgtree/rbc-tk9.git
cd rbc-tk9

The examples below build in the repository root. Replace the Tcl/Tk paths with paths for your installation or build trees.

--with-tcl and --with-tk take the directories containing tclConfig.sh and tkConfig.sh, not the configuration filenames themselves.

Install argparse for the same Tcl interpreter before running toolbar demos, toolbar tests, benchmarks, or generating the complete documentation. Native Rbc widgets and vector-only use do not need argparse.

Linux

For example, using Tcl/Tk build trees and a user-local installation prefix:

./configure \
    --with-tcl=/path/to/tcl9.0/unix \
    --with-tk=/path/to/tk9.0/unix \
    --prefix="$HOME/.local" \
    --enable-cairo

make -j4
make test

make install

The Tcl/Tk directories can instead refer to installed configuration files, provided that the required headers and source locations remain accessible.

The selected Tcl/Tk shared libraries must also be discoverable by the system dynamic loader. The Makefile supplies the build-directory environment for its test and shell targets.

Windows with MSVC

The Nmake build in win supports Tcl/Tk 9 and optional Cairo. It requires MSVC-built Tcl/Tk source trees and matching libraries; use MSVC Cairo libraries rather than MSYS2 import archives. See the MSVC build instructions for dependency setup, CAIRO=1, testing, and installation. Autoconf flags below apply to the Unix/MSYS2 build, not to Nmake.

Windows with MSYS2/UCRT64

Run the following commands in an MSYS2 UCRT64 shell, using Tcl and Tk built with a compatible toolchain and architecture:

./configure \
    --with-tcl=/path/to/tcl9.0/win \
    --with-tk=/path/to/tk9.0/win \
    --prefix=/ucrt64 \
    --enable-cairo

make -j4
make test

make install

Ensure that the selected Tcl/Tk DLLs, Cairo DLLs and their dependencies, and compiler runtime DLLs are available through PATH. Use Cairo and pkg-config from the same UCRT64 toolchain as Tcl/Tk and Rbc.

The UCRT64 shell does not automatically determine Rbc’s installation prefix. Specify --prefix=/ucrt64 when that is the intended destination.

Configure options and renderer defaults

Option

Effect

--enable-cairo

Builds Cairo support and makes cairo the default renderer. Requires cairo-xlib on Linux or cairo-win32 on Windows.

--disable-cairo

Builds without Cairo; native is the renderer default. This is also the configure default when neither flag is supplied.

--enable-cairo-static

Enables Cairo and links its non-system dependencies from static archives into the RBC shared library. Requires GCC and GNU-compatible linker options.

--disable-cairo-static

Disables forced static linking of Cairo dependencies. This is the default; Cairo support is controlled separately by --enable-cairo.

--enable-winpthreads-static

Embeds the MinGW-w64 winpthreads runtime in the DLL. Independent of Cairo; disabled by default. Requires genuine libwinpthread.a and target objdump.

--enable-symbols

Builds with debugging symbols for crash diagnosis.

--with-tcl=DIR, --with-tk=DIR

Select directories containing the matching Tcl/Tk configuration files.

--prefix=DIR

Selects the installation prefix.

The examples above enable Cairo. Omit --enable-cairo, or replace it with --disable-cairo, for a native-only build. If Cairo is requested but its headers or platform backend cannot be linked, configure fails rather than silently building without it.

For a nonstandard Cairo installation, set PKG_CONFIG_PATH to its pkg-config directory, or supply both CAIRO_CFLAGS and CAIRO_LIBS to configure. Inspect config.log if the backend link check fails. After changing build features in an existing build directory, run make clean and rebuild.

Choose a renderer for one graph, or set an application-wide default before creating widgets:

::rbc::graph .g -renderer native
.g configure -renderer cairo -antialias default

foreach class {Graph Barchart Stripchart Polar} {
    option add *${class}.renderer native
}

Explicit widget options take precedence over the option database. -renderer cairo is unavailable in native-only builds. Cairo is not uniformly faster: dense traces, symbols and error bars may favour native rendering; image-heavy workloads may favour Cairo. Use the benchmark suite to compare the workloads relevant to your application.

Linking Cairo statically

The Autoconf build supports linking Cairo and its non-system dependencies into the RBC DLL on MSYS2/UCRT64 or shared library on Linux:

./configure \
    --with-tcl=/path/to/tcl/config-directory \
    --with-tk=/path/to/tk/config-directory \
    --enable-cairo-static

make
make test

--enable-cairo-static also enables Cairo support and makes it the default renderer. It cannot be combined with --disable-cairo. RBC itself remains a shared library; do not use --disable-shared for this purpose.

Configure obtains the dependency list using pkg-config --static and selects exact static archive names for non-system libraries. Operating-system libraries remain dynamically linked. The link check verifies that the selected archives can be incorporated into a shared library.

This option does not download or build dependencies. Missing archives or unresolved dependencies cause configuration to fail; inspect config.log for the linker diagnostics.

MSYS2/UCRT64

To also eliminate the RBC DLL’s libwinpthread-1.dll import, add the separate option:

./configure --enable-cairo-static --enable-winpthreads-static
make clean
make
objdump -p tcl9rbc050.dll | rg 'DLL Name:'

Retain your usual --with-tcl, --with-tk, and other configure arguments. Winpthreads is not supplied by Windows. This option forces inclusion of the genuine libwinpthread.a archive before other libraries, including compiler-added thread references, and defines WINPTHREAD_STATIC for RBC compilation. Configure links a test DLL and checks its imports using the target objdump; no test binary is executed. A missing archive, failed link, remaining winpthreads import, or failed inspection stops configuration. For cross-compilation, set OBJDUMP to the target tool (for example x86_64-w64-mingw32-objdump). Custom archive locations can be supplied with LDFLAGS=-L/path/to/lib.

--enable-winpthreads-static works independently of Cairo and is rejected on non-MinGW builds. --disable-winpthreads-static retains the normal runtime linkage. It does not eliminate imports from other DLLs: if Cairo itself is shared, Cairo may still require its own winpthreads DLL. Always inspect the final RBC DLL and its remaining non-system dependencies. Windows system and UCRT imports remain normal. This configure option does not apply to the MSVC win/makefile.vc build.

Use Cairo, its dependencies and GCC from the same UCRT64 environment as the RBC build. Static libraries must be genuine .a archives; .dll.a import libraries still require external DLLs.

The build defines CAIRO_WIN32_STATIC_BUILD, links the C++ standard library and Iconv statically, and selects static GCC runtime support. These are needed by the MSYS2 Cairo dependency chain, including its DirectWrite and font libraries.

The static-Cairo build has been compiled and tested on MSYS2/UCRT64. The resulting RBC DLL is larger because it contains code previously supplied by dependency DLLs.

Inspect the DLL’s direct imports after building:

objdump -p tcl9rbc050.dll | rg 'DLL Name:'

Cairo and the dependencies selected as static archives should no longer appear as DLL imports. Windows system libraries and any remaining dynamically linked runtime libraries are still required. A larger file alone does not establish that every dependency was linked statically.

Static Cairo on Linux

Cairo and the non-system dependency archives must support incorporation into a shared library, normally by being built with -fPIC. Distribution-provided static archives are not necessarily suitable. The configure check attempts a shared-library link to detect incompatible archives.

The static-Cairo build retains dynamic linking for standard system libraries, including X11/XCB and the C runtime. Tcl/Tk remains a runtime requirement.

For a separately built Cairo dependency installation, select its pkg-config metadata:

PKG_CONFIG_PATH=/path/to/static-prefix/lib/pkgconfig \
    ./configure \
    --with-tcl=/path/to/tcl/config-directory \
    --with-tk=/path/to/tk/config-directory \
    --enable-cairo-static

Inspect the resulting shared library’s direct dependencies:

readelf -d ./librbc*.so | rg NEEDED

Rebuilding and deployment

Use a separate build directory, or run make clean after reconfiguring, when switching between shared and static Cairo dependencies. The Windows compilation flags differ between these modes.

Updating a statically included dependency requires rebuilding RBC. Static linking changes packaging, not renderer behavior: applications can still select -renderer native or -renderer cairo. Required Tcl scripts and packages must still be installed.

Installation locations

With the default directory layout, installation places:

  • The package library, pkgIndex.tcl, runtime scripts, and supporting resources in PREFIX/lib/rbc0.8.1.

  • Demos in PREFIX/lib/rbc0.8.1/demos.

  • Manual pages in PREFIX/share/man/mann.

HTML documentation, image resources and the license are installed in PREFIX/share/rbc0.8.1/doc. Override DOC_INSTALL_DIR to choose a different location.

If --prefix is omitted, the build system normally inherits the prefix from the selected Tcl configuration.

For other configure options, run:

./configure --help

Uninstalling

From the configured build directory, run:

make uninstall

Use the same directory overrides and DESTDIR as for installation. For example:

make uninstall DESTDIR=/path/to/staging

Uninstall removes the RBC package directory (including its stub archive, scripts and demos), installed executables, public headers (rbc.h, rbcVector.h, rbcDecls.h), rbcStubLib.c, manual pages and HTML documentation resources. It preserves shared include, bin and manual-page directories and unrelated files in them. Documentation files are removed individually; empty documentation directories are then removed. A custom DOC_INSTALL_DIR may therefore contain unrelated files without those files being deleted. Use the same source version and configured build used for installation so the file lists match; uninstall does not track files installed by other versions.

Creating an installation archive

After configuring the desired build, run:

make dist
# Optional ZIP archive, convenient for Windows Explorer:
make dist-zip

These GNU make targets build RBC and stage the same files as ``make install``, including the library, pkgIndex.tcl, runtime resources, demos, public headers, stub library, manual pages and HTML documentation with its images. They do not create a source archive or write into the configured installation prefix. They use the generated documentation already present in docs/; run make doc first if it needs updating.

Output defaults to dist/rbc0.8.1.tar.gz (and dist/rbc0.8.1.zip for dist-zip) in the build directory. The archive directly contains lib/, include/, share/, and any installed bin/ files. Extract it into the intended installation prefix, or merge these directories into that prefix. For example, for an MSYS2 UCRT64 installation, merge them into C:/msys64/ucrt64, not into its lib subdirectory.

Configured subdirectory choices such as lib64 are preserved. All installation directories must be under --prefix; an external directory produces an error because it cannot be represented in a single relocatable archive. DESTDIR is not included in archive paths. The archive contains the current build’s binaries and requires matching platform, architecture, Tcl/Tk and any dynamically linked dependencies; it does not bundle them.

For separately named release builds:

make dist-zip DIST_NAME=rbc0.8.1-windows-x86_64 DIST_ROOT=/path/to/releases

make dist-clean removes that distribution’s staging directory and archives. Source releases can be obtained from the repository’s GitHub source archives.

Packaging regression tests (no Tk or compiler needed):

tclsh tests/build/installDist.test

The tests use GNU make, a POSIX shell, install and tar; ZIP checks also require zip and unzip.

Loading the package

Start the Tcl/Tk interpreter associated with your build and run:

package require rbc

To check the versions in use:

puts "Tcl: [info patchlevel]"
puts "Tk:  [package provide Tk]"
puts "Rbc: [package provide rbc]"

If Rbc is installed outside Tcl’s normal package search locations, add its library directory before loading it:

lappend auto_path /path/to/prefix/lib
package require rbc

When using the optional toolbar or benchmarks, the same applies to argparse if it is installed separately.

When installing a prebuilt package, preserve the complete package directory, including pkgIndex.tcl, the shared library, graph.tcl, graphtoolbar.tcl, PostScript prologs, and bitmap resources. Copying only the DLL or shared library is not sufficient.

Using an uninstalled build

From the Rbc build directory:

make shell

This starts the configured Tcl interpreter with the build directory in its package search path. Then load Rbc normally:

package require rbc

Running tests

Run the automated test suite from the build directory:

make test

This target builds the package and the public C API test extension, then runs tests/all.tcl with the appropriate build environment. The automated runner sets native as the option-database default to preserve the existing pixel tests. Dedicated renderer tests explicitly select Cairo and verify the compiled default. Manual tests and demos retain the build default: Cairo when enabled, native otherwise.

Run the Tcl-only package-loading, public vector C API, literal-name, namespace, rename, and expression callback tests without a display:

make test-vector

This runs tests/vectorAll.tcl. GUI upgrade/load-order tests run in the normal make test suite and are skipped by the headless runner. Regenerate your Makefile with ./config.status after updating Makefile.in.

The suite uses tcltest. Pass test selection options through TESTFLAGS.

For example, run the line-decimation test file:

make test TESTFLAGS="-file RBC.graph.element.decimate.A.test"

Or select tests by name:

make test TESTFLAGS="-match RBC.graph.element.decimate.*"

On a headless Linux system, an X11 virtual display can be used if Xvfb is installed:

xvfb-run -a make test

Review the test summary and any skipped-test constraints. The manualtests directory contains additional visual and interactive checks that are separate from the automated suite.

Running demos

From an in-tree build, start the demo browser with:

make shell SCRIPT=demos/demos.tcl

The browser launches individual demos when their thumbnails are selected.

An individual demo can also be started directly:

make shell SCRIPT=demos/graph1.tcl

After installation, use the matching Tcl/Tk 9 interpreter:

wish9.0 /path/to/prefix/lib/rbc0.8.1/demos/demos.tcl

The executable may instead be named wish, depending on the Tcl/Tk installation. On Windows, use the corresponding wish.exe.

The demos locate their supporting files relative to their own script directory. Keep the demo scripts, images, bitmaps, stipples, and helper scripts together.

The current demos cover graphs, bar charts, stripcharts, symbols, spline interpolation, and window/image operations.

Rendering benchmarks

Performance benchmarks are separate from the correctness tests. They can create large data sets and should be run deliberately.

In addition to Rbc and argparse, the benchmark scripts require the Tcllib packages csv, report, and struct::matrix.

Run the small smoke profile from an in-tree build:

make shell SCRIPT="tests/benchmark/run.tcl -profile smoke"

Run the standard benchmark suite:

make shell SCRIPT="tests/benchmark/run.tcl -profile standard"

Run a focused line/strip comparison and save CSV results:

make shell SCRIPT="tests/benchmark/run.tcl -profile standard -benchmarks line,strip -renderer cairo -antialias default -csv-dir benchmark-results"

Benchmarks explicitly default to -renderer native -antialias default, independently of the build default. Select -renderer cairo for the Cairo comparison and keep results from different builds and power conditions separate.

The suite includes line, strip, symbol, error-bar, bar, marker, and mixed workloads. For individual line-benchmark measurements and options, see the benchmark README.

Documentation

The generated HTML documentation is available online:

The repository also includes generated HTML under docs/ and manual pages as docs/*.n. Open docs/index.html to browse the local HTML documentation.

Regenerating documentation

Documentation generation requires:

  • A working Rbc build and its runtime dependencies.

  • The Tcl ruff package with Sphinx and nroff output support.

  • Tcllib’s fileutil and textutil::adjust packages.

  • Python Sphinx, with sphinx-build available through PATH.

  • ditaa and its Java runtime when rendering diagrams that use the configured diagram generator.

The published documentation uses a modified Ruff package that is not currently public. Other Ruff versions may produce different output or lack the required output formats.

From an in-tree build, run:

make doc

The target builds the binaries and refreshes the build-directory Tcl runtime files before loading RBC, so changes to library/graphtoolbar.tcl are reflected without running make install first.

The generator reads the .ruff sources and Tcl API documentation, writes Sphinx sources under docs/sphinx, builds HTML under docs, and generates the .n manual pages.

Write documentation tables once, in Markdown. docs/tableHelpers.tcl expands the README and every selected namespace’s _ruff_preamble before Ruff runs. Each table keeps its Markdown form for Sphinx/HTML and receives a wrapped, boxed literal form for nroff, selected with generated #ruffopt guards. Existing format restrictions and fenced code examples are preserved. Preambles are restored after generation, including on errors.

Do not maintain a second hand-written nroff copy of a table. Tables may have any column count that fits the default 120-character width (including borders, excluding source indentation). Columns are sized automatically; long cells wrap. Alignment markers are accepted, while the nroff cells are left-aligned. Escape literal pipes as \| or put them inside inline code. Table rows must have the same column count as the header. This preprocessing covers namespace preambles and the README; it does not rewrite procedure bodies or TclOO method documentation.

The helper regression tests require only Tcl, Tcllib and tcltest:

tclsh9.0 tests/RBC.docs.tables.A.test

Review the generator output and resulting pages before publishing. The current generator prints Sphinx diagnostics, so the Make command’s exit status alone is not a complete documentation-build check.

README.md supplies the shared introduction and build instructions. docs/startPage.ruff reads that file as the documentation preamble.

Reporting problems

Please use the issue tracker.

For build or runtime problems, include:

  • The Rbc version or commit.

  • Operating system and architecture.

  • Tcl/Tk versions and, on Windows, the compiler/MSYS2 environment.

  • Configure options and the relevant error output.

  • A small Tcl script reproducing the problem, when applicable.

For rendering problems, include a screenshot and the relevant graph, element, pen, or marker options.

History and acknowledgments

Rbc originated as a refactoring of selected components from version 2.4z of the BLT toolkit, developed by George Howlett and other contributors.

Samuel Green, Nicholas Hudson, Stanton Sievers, and Jarrod Stormo carried out the original Rbc project at Rose-Hulman Institute of Technology during 2008–2009. The project adapted commonly used BLT components for Tcl/Tk 8.5 and was associated with the GDAT graphical data-analysis project.

Subsequent work included additional maintenance, demo improvements, and C stubs support. The stubs implementation includes work by Ashok P. Nadkarni.

Emiliano Gavilán adapted Rbc for Tcl/Tk 9.0. This repository is based on his Rbc Tcl/Tk 9 repository.

George Yashin maintains this fork and its further Tcl/Tk 9 modernization, new functionality, tests, performance improvements, and documentation.

The project also acknowledges the Tcl/Tk developers, the maintainers of the Tcl Extension Architecture build system, and the contributors whose code and resources remain part of Rbc.