Tcl/Tk 9 upgrade and additions¶
Rbc 0.5.0 targets Tcl/Tk 9 on Windows and Linux. This page summarizes the visible additions first, followed by the API, numerical and resource-management changes behind them. Tcl/Tk 8.x compatibility is not a goal of this fork. Build instructions and dependency details are in the documentation overview.
User-visible additions¶
This fork adds plotting, interaction and numerical features alongside the Tcl/Tk 9 API migration.
Track XOR markers, dividers and decimation¶
::rbc::TRACKGRAPH line, polygon and arc markers now accept -xor yes, using native XOR within the clipped
redraw pass in either renderer. Graphtoolbar zoom outlines can use it too. Optional
-trackseparatorcolor and -trackseparatorwidth graph options draw dividers at the separator centres,
following rows or inverted columns; the default empty colour keeps them hidden.
Line/strip -decimate auto uses the shared X span with the existing eligibility rules and full-detail
exports. The fast strip mapping path now attaches its reduced segments to the drawing pen, fixing dense
strips disappearing with decimation enabled in both stripcharts and trackgraphs. Regression coverage
checks visible extrema, vector updates and picking in both orientations.
Window-marker visibility and track support¶
Window markers now unmap their live child when hidden, emptied, moved completely outside the plot,
or associated with a hidden element, and remap it when visible again. ::rbc::TRACKGRAPH widgets accept window markers
with -track and -mapy in either orientation. They follow track placement and resizing, preserving
ordinary graph behaviour: partially overlapping children keep their full size and may extend beyond
the track. There is no internal window clipping container. See ::rbc::MARKER.
Configurable logarithmic bar baseline¶
Bar elements honor a positive graph -baseline on logarithmic Y axes, including automatic limits,
inverted graphs and exports. Non-positive settings retain the historical logarithmic baseline of 1.0.
Stack totals remain additive from zero. See ::rbc::BARELEMENT for details.
Static MinGW-w64 threading runtime¶
--enable-winpthreads-static embeds the genuine libwinpthread.a archive in the RBC DLL and checks
a linked probe for unwanted winpthreads imports. It is independent of --enable-cairo-static; combine
both options to embed Cairo dependencies and the threading runtime. The option is off by default
and requires a MinGW-w64 toolchain and target objdump. Windows system libraries remain dynamic.
Literal parentheses in vector names¶
Real and complex vectors accept names such as v(out) directly, with references such as
v(out)(1:20) selecting a range. Exact existing names take precedence over range interpretation.
Creation retains numeric size/range suffixes; -literal true permits literal names such as v(1).
Parenthesized names default to no Tcl array mapping; -variable can select a separate array name without
parentheses. Mathematical functions keep expression precedence; braces inside an expression disambiguate
a vector name such as {sin(x)}. Public C constructors and lookup APIs support the same names without
changing the stubs ABI. See ::rbc::vector for examples and the naming rules.
Tcl-only vector loading¶
package require rbc::vector loads vectors from the same shared library without initializing Tk or
loading argparse and graphtoolbar. Full package require rbc can follow without replacing vectors or
client subscriptions; the reverse loading order also works. C consumers can use Rbc_VectorInitStubs
with the updated stub library. make test-vector runs the package-loading and public C API tests
without a graphical display. Binary dependencies remain required. See ::rbc::vector for details.
Optional toolbar package¶
package require rbc loads the native widgets without loading argparse or the toolbar. Applications using
::rbc::graphtoolbar now need package require rbc::graphtoolbar, before any namespace import ::rbc::*.
The toolbar package requires the matching Rbc version and loads argparse. An installed argparse is preferred;
if it is missing, the bundled Tcl-only argparse 0.65 is used, so graph demos need no separate installation.
Errors from an installed argparse are still reported. The private fallback is not advertised by the package
index and is never loaded by native RBC or the vector core. Repeated requires preserve existing
widgets. Toolbar demos, tests, and documentation generation load this optional package explicitly.
Backward-compatible graph helpers¶
The historical graph.tcl helpers are available again after package require rbc, without requiring argparse.
Existing calls such as Rbc_ZoomStack .g and Rbc_Crosshairs .g work on native graphs. These helpers are retained
for backward compatibility; new applications should prefer rbc::graphtoolbar. Using both interaction systems
on the same graph is not recommended. Pending callbacks and helper state are cleaned up on widget destruction.
See GRAPHINST for the complete legacy command list and reserved binding/marker names.
X and Y error bands for lines and strips¶
Cartesian line and strip elements support -errorband x|y, filling between symmetric -xerror or
-yerror bounds, or the corresponding absolute low/high endpoints. The default none disables bands.
Independent -errorbandpattern, -errorbandforeground,
-errorbandbackground, -errorbandtile, and -errorbandopacity options reuse ordinary area-fill
styles and backend limitations. Solid opacity is supported by Cairo and SVG; native rendering and
PostScript ignore it. Linear and step bands preserve all source bounds despite symbol thinning or
trace decimation and split at invalid data. See ::rbc::LINEELEMENT for details and examples.
Symbols on reduced traces¶
Line, stripchart, and polar elements accept -symbolpoints all|reduced. The default all preserves
original-sample symbols. With positive -reduce, reduced restricts symbols, error bars and value labels to original
samples retained by trace simplification; generated smoothing vertices never acquire symbols. Exact
closest-point searches still include omitted samples. See ::rbc::LINEELEMENT for details.
A positive -maxsymbols further thins normal symbols, error bars and value labels together on screen and in SVG/PostScript exports. Active symbols and labels bypass this density limit.
MSVC builds on Windows¶
The win/makefile.vc build supports MSVC and Nmake with Tcl/Tk 9, including optional Cairo via
CAIRO=1 and CAIRODIR. It provides build, test, install and shell targets independently of the
MSYS2 build. Matching MSVC-built Tcl/Tk source trees and libraries are required; Cairo runtime
DLLs and their dependencies must be available when loading RBC. See win/README.md for commands.
Polar/Smith grid configuration¶
Polar/Smith tick lists, label anchors, label formatter commands, and -smithgrid are now grid component
options. Use graphPath grid configure and graphPath grid cget. They are no longer accepted by the graph
constructor or graph-level configure/cget. The graph retains -representation and -aspect.
::rbc::polar .p -representation smith
.p grid configure -smithgrid admittance -smithrealmajorticks {0 0.5 1 2}
Option-database patterns likewise include the grid component, for example option add
*Polar.grid.AngleMajorTicks {0 90 180 270}. Polar grids are now visible by default, including Smith charts.
Grid -hide yes hides both grid lines and their coordinate labels on screen and in exports. The toolbar keeps
its -smithgrid constructor convenience option and reads subsequent changes from the grid component. See
::rbc::GRID for full option tables and formatter details.
Optional Cairo rendering¶
Configure with --enable-cairo to build the antialiased renderer. Cairo-enabled builds default to
-renderer cairo; builds without Cairo default to -renderer native. Applications can select either
available renderer explicitly or through Tk’s option database.
::rbc::graph .g -renderer cairo -antialias default
.g element create signal -data {0 0 1 2 2 1} -symbol none
.g configure -renderer native
Cairo covers line and strip traces, symbols, error bars, bars, grid and axis lines, ticks, legend symbols, and supported marker geometry, bitmaps and photos. Text glyphs remain native, as do XOR crosshairs, window markers, Tk relief drawing and unsupported image types. Snapshots use the selected renderer; PostScript and Windows metafile output retain their existing exporters.
Cairo improves edge quality but is not a universal speed improvement. Native rendering remains useful for dense geometry; image-heavy workloads can favour Cairo. Windows marker passes share a drawing target, and compatible marker strokes reuse their Cairo context while retaining separate drawing operations.
The automated test runner defaults to native through the option database. Dedicated renderer tests select
Cairo explicitly. Manual tests and demos use the compiled default unless they request another renderer.
Benchmark scripts have their own explicit -renderer and -antialias settings and CSV comparison tools.
Display decimation and streaming updates¶
Line and strip elements support -decimate none|auto; none remains the default. Eligible monotonic
waveforms retain first/minimum/maximum/last representatives in each physical data-X pixel, preserving
narrow extrema rather than averaging them away. Source data and PostScript resolution remain unchanged.
With auto, the activation threshold is 4 source points per plot pixel for Cairo and 8 for native.
Renderer changes remap the data. The persistent cache supports axis changes, ranged Y updates and
monotonic tail appends, while unsupported data combinations use the full or fallback mapping paths.
Graph interaction and toolbar¶
graphtoolbar provides zooming, panning, closest-point annotations, legend controls and configurable
pointer appearance. Windows touchpad scrolling is supported alongside mouse-wheel zoom. Consecutive
axis-scroll actions retain their selected axis when rescaling moves it away from the pointer.
Crosshair annotations refresh beneath a stationary pointer when streaming data or axis mapping changes. Current-coordinate annotations stay beside the pointer; closest-point annotations repeat the search. Annotation boxes are recalculated after zooming, including with inverted axes.
Graph widgets emit <<RbcGraphChanged>> after relevant display changes. The toolbar combines refresh
requests into an idle callback and respects temporary suspension during zooming, panning and menus.
Windows crosshair motion was corrected to avoid flicker. Symbols crossing the plot boundary are clipped
to the visible area instead of disappearing while still partially visible.
Graph widgets also provide <<RbcAxisChanged>> for successful axis configuration or changed effective
limits, and <<RbcAxisLimitsChanged>> for numeric limit changes alone. Both queue one list of affected
axis names in %d after display, including initial limits. Applications can use these events to synchronize
plots or update controls without reacting to unrelated redraws. The broader event includes log/linear
switching, tick configuration and styling; synchronization handlers must account for queued feedback.
Custom closest-point annotations¶
The toolbar’s -closestcommand accepts a Tcl command prefix receiving element x y info and returning
annotation text. Configuring it adds Custom to the available formats; -coordclosestmark custom
selects it. Empty results suppress the annotation. Ordinary coordinates follow the element’s mapped
axes; Polar coordinates are Cartesian components. Smith charts supply normalized admittance for an
admittance grid, or normalized impedance for impedance and combined grids. The information dictionary
retains the closest-search fields, including the source index.
Built-in closest annotations display the element’s nonempty -label, falling back to its name.
Toolbar control mode now uses a Crosshairs menu button instead of two comboboxes, with the same mode
and format choices as context control mode. Polar formats include polar (radians) and polardegrees
(degrees). Format changes refresh the annotation without requiring another pointer movement.
Complex vectors¶
The vector subsystem now supports both real and complex numeric vectors. Complex vectors are created explicitly
with -type complex, and Tcl-level complex values use the form {real imag}:
::rbc::vector create z -type complex
z set {{1 2} {3 -4} {5 0}}
Complex vectors are supported by most vector instance operations and by the vector expression engine, including
arithmetic, complex exponentiation, trigonometric and logarithmic functions, projections such as real,
imag, abs, and arg, and complex statistical reductions.
Operations that require an ordering of values remain real-only. In particular, sort and normalize are not
supported for complex vectors.
Traditional graph, barchart, and stripchart X/Y element data remain real-valued. Polar elements can attach a
complex vector directly through -cdata, and the spline subsystem provides complex-vector parametric natural
and quadratic interpolation.
Applications can still explicitly derive real projections such as real, imag, abs, or arg when a
traditional Cartesian graph or scalar spline is required.
The public C API was extended with typed vector access, including Rbc_VectorType, Rbc_Complex,
Rbc_CreateVectorWithType(), Rbc_VectorComplexData(), Rbc_ResetComplexVector(), and
Rbc_VectorChanged(). The original real-vector API remains available for compatibility.
Polar and Smith charts¶
This fork adds the polar graph widget for plotting Cartesian complex-plane data with either a conventional
Polar grid or a Smith-chart representation.
Polar elements accept real lists or vectors through -xdata and -ydata, paired lists through -data,
or first-class complex vectors through -cdata. With the default -datacoordinates cartesian, X and Y
are real and imaginary components. With -datacoordinates polar, X supplies angles in radians and Y
supplies radii; conversion to Cartesian coordinates occurs internally. Source lists and vectors remain
unchanged. Polar input coordinates cannot be combined with -cdata or error-bar data options.
Complex data can be interpreted as:
reflection coefficient with
-cdataformat gamma;physical impedance with
-cdataformat impedance;physical admittance with
-cdataformat admittance.
The -z0 option specifies the positive reference impedance used for impedance/admittance conversion.
Smith charts support impedance, admittance, or combined contour grids, configurable major/minor normalized contour values, and Tcl callbacks for formatting real and imaginary contour labels.
Polar grids provide independently configurable angular major/minor spokes, angular label callbacks, radial label formatting through the mapped X axis, and configurable label anchoring.
Polar and Smith grid geometry follows the axes selected by grid -mapx/-mapy.
Unless -aspect is explicitly configured, Polar widgets automatically maintain equal physical scale for X and
Y data units. This keeps circles circular even when the mapped numerical X/Y ranges have different spans.
Polar grid rendering remains meaningful when the origin is outside the current viewport. Radial circles which intersect the viewport are retained, angular spokes are clipped to the visible Cartesian area, and angular labels move from the normal circular layout to the visible ends of their spokes when no complete centered circle is available.
Radial labels remain tied to the positive zero-degree ray and are displayed whenever their corresponding
{radius,0} point is visible, even when the Polar origin itself is outside the viewport.
Polar autoscaling also supplies a neutral fallback range when a grid-mapped axis has no contributing visible element data, allowing the Polar grid to remain usable when the widget is empty or all plotted elements are hidden.
Smith reactive labels likewise adapt to zoomed views. When the complete unit circle is no longer visible, major reactance and susceptance labels are moved to the first visible boundary of their corresponding contour instead of disappearing with their normal unit-circle label position.
Natural/cubic and quadratic smoothing on Polar elements is parametric, allowing vertical paths, non-monotonic-X paths and loops. Catmull-Rom smoothing remains parametric as well.
Missing, non-finite, logarithmically invalid, or singular impedance/admittance points split a trace into continuous runs. Smoothing is performed independently on those runs and never bridges a gap.
element closest on a Polar widget additionally reports radius and angle. The angle field now uses
radians in [0, 2*pi), including for Cartesian and complex-vector input; this deliberately replaces
the previous degree result. The origin has angle zero, and returned X/Y coordinates remain Cartesian.
Polar grid angular labels and their formatting callback continue to use degrees. In Smith representation,
closest results also report Gamma and normalized and physical impedance and admittance quantities.
Polar/Smith grid rendering, labels, custom formatter callbacks and smoothed element traces are supported by PostScript output as well as on-screen drawing.
Area closure and transparency¶
Line and Polar elements support -areaclose baseline|chord|origin. The default baseline retains the
bottom-of-plot closure; chord joins the endpoints directly, and origin closes through Cartesian
{0 0}. These choices control the fill polygon without adding segments to the visible trace. They apply
to solid, stippled and tiled areas, and the same closure geometry is used in PostScript.
Bar elements and bar pens support -fillopacity (default 1.0). Cairo and SVG support partial opacity
for solid and stippled bar fills and legend swatches. Zero disables filling on every backend; native
drawing and PostScript render nonzero values as opaque. Borders, error bars, and labels remain unaffected.
-areaopacity controls solid fills (-areapattern solid) in Cairo and SVG, from 0.0 (invisible) to 1.0
(opaque, the default). It does not change lines, symbols, stipples or image tiles. Photo tiles retain
their own per-pixel alpha, including partial transparency.
Native rendering accepts but ignores -areaopacity, and native image tiles use binary transparency
masks. PostScript also ignores the option and retains opaque solid fills; standard PostScript cannot
express general alpha blending. These area options are available on line and Polar elements, not bars
or strip elements.
Plot-only element hiding¶
Line, stripchart, and bar elements now support the -hideplot option.
Unlike -hide, which removes an element from the graph display list, -hideplot yes suppresses plotting while
leaving the element in the display list. Its legend entry therefore remains available, making it possible for
applications to hide and restore plotted data without rebuilding or reordering the legend.
A plot-hidden element is also excluded from automatic axis limits, closest-element searches, element hit testing, and PostScript element output. Plot-hidden bars are additionally excluded from bar grouping and stacking calculations.
-hide and -hideplot are independent, so changing the normal visibility of an element does not alter its
-hideplot state.
Circles, ellipses and arc markers¶
The new arc marker supports full circles/ellipses, open curves, filled chords and pie sectors.
-coords {x1 y1 x2 y2} specifies opposite corners of the ellipse bounding rectangle. -start sets
the starting angle and -extent the signed sweep in degrees; their defaults are 0 and 360.
Positive sweeps run counterclockwise from the display’s positive X direction. The box is mapped
before constructing the ellipse, preserving its displayed shape on logarithmic or inverted axes.
Equal displayed width and height produce a circle.
-style arc draws the curve only, chord connects the endpoints directly, and pieslice connects
them through the centre. The default is pieslice. Full sweeps have no radial seam. Fill and outline
colors, foreground/background color pairs, stipples, line width, dashes, caps, joins and XOR follow
polygon-marker conventions. Common marker options, clipping, picking and bindings are supported.
See ::rbc::MARKER for the complete interface.
.g marker create arc -coords {2 2 6 6} -fill lightblue -outline navy
.g marker create arc -coords {2 2 6 6} -start 30 -extent 120 -style pieslice -fill orange
.g marker create arc -coords {2 2 6 6} -start 30 -extent 120 -style chord -fill lightblue
.g marker create arc -coords {2 2 6 6} -start 30 -extent 120 -style arc -outline red -linewidth 2
The private renderer interface now provides Rbc_RenderArc() and Rbc_RenderFillArc() with a shared
mapped ellipse description. Cairo draws curved paths, SVG emits elliptical arc commands, and PostScript
emits transformed arc/arcn paths. These backends clip the original curve without adding boundary
edges, preserve continuous dashes through clipped portions, and keep stroke widths and stipple patterns
independent of the ellipse aspect ratio. SVG and PostScript arc export do not require Cairo.
Native rendering, including XOR, and hit testing retain flattened geometry with a 0.15-pixel chord-error target and an 8192-segment limit. At extreme zoom, picking can differ from the curved path; native dashes can restart after leaving and re-entering the plot.
tests/benchmark/markers.tcl includes separate ellipse-fill, ellipse-outline, open-arc, chord-fill and
pieslice-fill workloads in all profiles. They report creation, already-mapped redraw and axis-remap
timings for native and Cairo renderers. See tests/benchmark/README.md for case names and commands.
Bar alignment and error-bar positioning¶
Bar elements now support -baralign center|left|right and -baroffset value. These options control how the
full bar or group interval is positioned relative to each data X coordinate. Offsets are expressed in X-axis
data units. The defaults, center and 0.0, preserve existing placement.
In aligned mode, alignment applies to the full group width before subdivision into individual bars. Different
alignments and offsets within a group are supported in aligned, overlap and stacked modes, allowing gaps,
additional overlap or staggered stacks. Group membership still uses the original X coordinates and axis pair.
Bar elements also support -errorbarposition data|bar:
data, the default, preserves historical placement: errors use the original data coordinates plus-baroffsetin X.barpositions errors at the final bar centre in X and applies the accumulated stacking displacement in Y. Alignment, offsets and group-slot placement are included.
The same translation applies to symmetric errors and explicit low/high bounds, without modifying their source lists or vectors. Translation occurs in data coordinates before axis mapping, and automatic axis limits include the translated error endpoints.
.g element configure first second -baralign left -baroffset 0.25 -errorbarposition bar
Arrowheads for line markers¶
Line markers now support arrowheads through the -arrow and -arrowshape options.
-arrow accepts none, first, last, or both, allowing an arrowhead to be drawn at either or both ends
of a line marker. -arrowshape {a b c} controls the arrowhead geometry using screen distances.
.g marker create line -name direction -coords {0 0 5 4 10 2} -outline red -linewidth 2 -arrow last
.g marker configure direction -arrow both -arrowshape {8 10 3}
Arrowheads use the line marker’s -outline color, and the line shaft is shortened to the arrowhead neck so
that it does not extend through the filled arrowhead.
The drawing implementation was also corrected for X11/Linux. Arrowheads are concave polygons, so they are now passed to the native polygon renderer with the correct non-convex geometry and without the duplicate closing vertex. This keeps arrow rendering consistent across supported platforms.
Bar geometry from element closest¶
The element closest operation now provides additional geometry information when the selected element is a bar.
In addition to the normal name, index, x, y, and dist entries, the result array contains:
lefttoprightbottom
These values are the physical widget coordinates of the final mapped bar rectangle that is actually drawn. They therefore reflect the current bar mode: stacked bars return the selected stacked segment, while aligned and overlapping bars return the adjusted rectangle belonging to the selected element.
The values remain physical widget coordinates when -invertxy is enabled: left and right always describe
physical X coordinates, while top and bottom always describe physical Y coordinates.
This makes element closest directly usable for bar highlighting, overlays, annotations, and interactive
interfaces without requiring applications to reconstruct bar geometry themselves.
Custom element value labels¶
Value labels accept -valueoffset {dx dy} on elements and pens. Signed integer pixel offsets move
the label anchor right/down, independently of axis inversion and text rotation. The default {0 0}
preserves existing placement in both renderers and PostScript.
Elements and named pens now accept -valuecommand, a Tcl command prefix receiving the graph pathname,
element name, source index, X and Y. Its result replaces the -showvalues label on screen and in PostScript.
Empty results hide individual labels; clearing the option restores -valueformat.
Vector polyline simplification¶
rbc::vector::simplify x y destX destY tolerance (also rbc::vector simplify) reduces a polyline
into two existing real vectors using Douglas-Peucker simplification. Tolerance is a Euclidean distance
in data coordinates, measured to finite replacement segments. Endpoints and point order are retained;
in-place output is supported without replacing vector identities or graph bindings. This headless
operation is independent of graph rendering decimation. See ::rbc::vector simplify and the interactive
demos/simplify1.tcl example.
Vector FFT and inverse FFT¶
Real and complex vectors provide fft and ifft instance operations. Results are written into an
existing complex vector or two existing real vectors. Vector types and C identities remain fixed;
compatible input/output overlap is supported. The full spectrum uses the conventional negative forward
sign and a 1/N-normalized inverse. Power-of-two lengths are required, with explicit -length auto|size
zero padding. No external FFT dependency or Tk initialization is needed. See ::rbc::VECINST for syntax,
frequency-bin ordering, normalization and sampling requirements.
FFT frequency bins and windows¶
Existing real vectors provide fftfreq length ?-delta interval? ?-onesided boolean? and
window type length ?-periodic boolean?. Frequency axes match full FFT ordering or its nonnegative
half. Window types are rectangular, Hann, Hamming, Blackman and Bartlett; periodic form is the default,
with symmetric form available explicitly. Generate windows at the original sample count before padding,
and frequency bins at the actual transform length. Neither operation creates vectors or changes types.
See ::rbc::VECINST for formulas, examples and amplitude/energy normalization.
Implementation modernization¶
The migration replaces obsolete Tcl/Tk interfaces, widens collection sizes and indexes, and improves configuration rollback, numerical boundaries and resource lifetime management.
Tcl 9 command and object API¶
Converted command implementations to the Tcl 9 object-based command interface.
Updated command callbacks to use
Tcl_Sizeargument counts where appropriate.Migrated command creation to
Tcl_CreateObjCommand2()for Tcl 9 large-argument support.Replaced remaining old string-based command and result handling with
Tcl_Obj-based APIs.Removed obsolete command parsing infrastructure inherited from the original BLT/Rbc implementation.
Reworked operation dispatch tables and argument validation around object-based parsing.
Improved const-correctness throughout Tcl-facing APIs and removed casts that previously discarded
const.Removed several local copies or emulations of Tcl internal parsing structures and functions.
64-bit and Tcl_Size support¶
A large part of the original code assumed that collection sizes, vector lengths and indexes fit in an
int. These assumptions were systematically removed.
Converted vector lengths, indexes and capacities to
Tcl_Size.Converted spline point counts and interpolation indexes to
Tcl_Size.Converted graph element point indexes and data-index mappings to
Tcl_Size.Converted error-bar index mappings and element-to-data mappings to
Tcl_Size.Updated sorting, searching, closest-point and line-reduction code for large indexes.
Updated chain/list traversal code where sizes or indexes could exceed the old 32-bit assumptions.
Fixed vector binary-reading and vector mathematical operations for Tcl 9 size semantics.
Added overflow checks before converting between
Tcl_Size,size_t, integers and allocation sizes.Added allocation-overflow guards for dynamically sized arrays throughout graph, spline and vector code.
This removes a large class of silent truncation and overflow problems that were possible with large datasets.
Modern Tk option handling¶
The graph subsystem previously relied heavily on the legacy Tk configuration API. Most of it has been replaced with the modern Tk option-table interface.
The following subsystems were migrated to Tk_OptionSpec/Tk_OptionTable based configuration:
graph widgets
axes
legends
grid
crosshairs
pens
markers
line elements
stripchart elements
bar elements
PostScript options
Legacy configuration tables and their associated processing functions were removed after the new implementations were activated.
Custom option types were added or rewritten for complex Rbc values such as:
vectors
axes
pens
tags
element styles
states
coordinates
padding and margins
format strings
graph-specific enumerations
Configuration processing was also made transactional where needed. Invalid option changes now preserve the previous valid object state instead of leaving partially modified graph objects.
The EPS canvas item remains on Tk_ConfigSpec/Tk_ConfigureWidget() because the public Tk 9 Tk_ItemType
canvas-item interface still exposes the legacy configuration mechanism.
Component option-database lookup¶
Graph components such as elements, markers, pens, axes, the legend, grid, crosshairs, and PostScript settings are not ordinary Tk child widgets, but they participate in Tk’s option database using component resource names and classes.
The previous implementation created and destroyed a temporary Tk child window whenever a pseudo-component was
initialized so that Tk_InitOptions() could perform the appropriate name/class lookup. With large numbers of
objects, particularly markers or elements, this made component creation dominated by Tk window-management
overhead.
Each graph now owns a single anonymous Tk option-proxy window which is reused for pseudo-component option lookup. Before initializing a component, the proxy is temporarily given the component’s resource name and class and is then passed to Tk’s normal option-table machinery.
This preserves the existing option-database hierarchy and precedence, including both class-wide resources such as:
option add *Graph.TextMarker.Foreground darkgreen
and resources for particular named components such as:
option add *Graph.annotation.foreground purple
without constructing a real Tk child for every component.
The proxy is anonymous and is not entered into Tk’s pathname hierarchy. It exists only for the lifetime of its graph and is destroyed with the graph. Explicit component options continue to override option-database defaults normally.
Removing the temporary-window creation path substantially reduces the cost of creating large numbers of graph objects while retaining the established option-database behavior.
Graph object and resource lifetime¶
Configuration modernization exposed a number of ownership and rollback problems that were corrected at the same time.
Reworked creation, configuration and destruction paths for graph components.
Improved rollback after failed configurations.
Corrected ownership of dynamically allocated option values.
Fixed temporary Tk image creation and destruction.
Corrected resource cleanup for legends, markers, pens and elements.
Hardened vector mathematical operations against ownership and aliasing problems.
Removed dead initialization and cleanup paths inherited from the old configuration system.
Removed substantial amounts of obsolete and unreachable compatibility code.
Axis and coordinate-system modernization¶
The axis implementation received extensive numerical and behavioral cleanup.
Hardened coordinate mapping against integer overflow and extreme coordinate ranges.
Widened intermediate geometry calculations before converting to Tk/X11 integer coordinates.
Added safe handling for rotated-axis dimensions.
Added validation for non-finite configuration values.
Hardened generated tick calculations against invalid or degenerate ranges.
Added guards against ill-defined tick spacing and numerical overflow.
Corrected axis scrolling and
-scrollcommandbehavior.Corrected tick-label command callback handling.
Improved option validation and rollback for axis configuration.
Hardened user-controlled formatting options and removed unsafe formatting operations.
Logarithmic axes were also substantially corrected:
Logarithmic axes now use well-defined positive-domain semantics.
Invalid/non-positive points are excluded instead of being mapped through invalid logarithms.
Line elements are split at invalid log-domain points instead of drawing across discontinuities.
Bar charts correctly handle logarithmic axis mapping.
Stacked bars were corrected for logarithmic scales.
Extreme logarithmic ranges are handled more safely.
Smoothing no longer bridges invalid log-domain gaps.
Line, bar and element processing¶
The internal representation and processing of graph elements were extensively updated.
Modernized element option handling.
Reworked vector association using object-based APIs.
Updated element state, tag, pen, style and axis handling.
Fixed error-bar mapping and data-index tracking.
Corrected closest-point and closest-segment calculations.
Corrected element binding/tag behavior.
Fixed line-reduction routines and their index handling.
Hardened construction of mapped point arrays and drawing traces.
Replaced internal uses of narrow X11 rectangle structures where larger internal coordinates were required.
Added explicit handling of
NaNand infinite values in plotted data.Corrected bar handling of non-finite data.
Corrected several element formatting and
-valueformatpaths.Fixed step-generation behavior.
Corrected line
-tracebehavior.Added optional screen-density decimation for large line and strip elements through -decimate none|auto.
Automatic line and strip decimation preserves the first, minimum, maximum, and last source representatives associated with each physical data-X pixel rather than averaging dense waveform data.
Added density-based selection so sparse data continues through the normal mapping path while dense eligible traces can avoid mapping and drawing millions of redundant screen points.
Added a persistent data-domain decimation cache for finite, monotonic-X line and strip data. The cache survives ordinary axis remapping and supports increasing, decreasing, and equal X coordinates as well as
-invertxyand descending axes.Added conservative fallback paths for discontinuities, logarithmically invalid data, non-monotonic paths, symbols, value labels, error data, multiple styles, and other combinations that require full source geometry.
Added incremental maintenance of persistent line and strip decimation summaries for ranged Y-vector updates and monotonic tail growth.
Vector
appendandindex ++endnow provide exact ranged tail notifications, allowing persistent display caches and cached real-vector extrema to be extended without rescanning the unchanged source prefix.Pure tail growth can preserve the decimation cache even when vector capacity growth relocates its backing storage. Shrinkage, changes inside the cached X prefix, non-monotonic growth, arbitrary storage replacement, and unknown/full changes retain conservative invalidation semantics.
Accelerated exact
ELEMENT closest -interpolate nosearches for decimated monotonic-X lines while preserving exact source-point results.Screen-density decimation affects window rendering only. PostScript output continues to use full source resolution.
Spline subsystem¶
The spline subsystem was subsequently extended with direct complex-vector parametric interpolation.
Added
spline parametric natural source result samples.Added
spline parametric quadratic source result samples.Parametric source and result vectors are first-class complex Rbc vectors.
Parametric splines use cumulative two-dimensional chord length and do not require either Cartesian coordinate to be monotonic.
Vertical paths, reversing paths and loop-like trajectories are supported.
Consecutive duplicate source points are rejected because they create a zero-length parameter interval.
Parametric generation is transactional and supports source/result aliasing.
The original scalar real-vector spline interface remains unchanged.
Vector subsystem¶
Vector handling was updated substantially beyond the minimum required for compilation with Tcl 9.
Added Tcl 9 sized vector indexing.
Converted sorting indexes to
Tcl_Size.Removed global state from vector sorting operations.
Updated vector arithmetic and mathematical operations.
Corrected vector duplication and overwrite behavior.
Corrected binary-read operations.
Hardened allocation and capacity calculations.
Improved parsing and const-correctness.
Removed legacy parser dependencies.
Improved ownership of temporary data used by mathematical operations.
Added stricter handling of invalid and non-finite input.
Added first-class complex vectors, complex expression arithmetic and mathematical functions, typed public C API access, and precise ranged in-place update notification while retaining compatibility with the existing real-vector interface.
Added cached real-vector range maintenance so repeated clients do not rescan unchanged vectors merely to obtain minimum and maximum values.
Added ranged vector-change notifications. Mapped Tcl-array writes and ordinary vector
indexwrites report the affected source interval when an existing real-vector range is modified in place.Added
Rbc_VectorChangedRange(Rbc_Vector *, Tcl_Size first, Tcl_Size last)to the public C/stubs API so C producers can report precise in-place source modifications without changing vector storage or ownership.Ranged real-vector updates maintain cached extrema incrementally when possible and conservatively fall back to a complete range scan when a modified interval invalidates an existing global extremum.
Retained
Rbc_VectorChanged()as the full/unknown-range notification interface for callers that cannot provide a precise changed interval.
Geometry, text and drawing¶
Many drawing routines inherited assumptions from old X11 APIs where coordinates and dimensions were commonly stored in narrow integer types.
The modernization:
widened internal geometry calculations;
added checked conversion at native drawing boundaries;
hardened rotated text and bounding-box calculations;
updated text-layout processing;
hardened shadows, halos and graph-layout coordinate arithmetic;
corrected clipping and projection calculations;
updated polygon, rectangle and region processing;
added guards around fixed-size polygon and symbol allocations;
corrected point-in-region and projection helpers;
fixed drawing-boundary issues discovered on both Windows and Linux.
The intent is to keep high-precision or wide internal calculations for as long as possible and narrow them only when calling APIs that inherently require integer coordinates.
Image and bitmap handling¶
The image-processing code was significantly updated for current Tk behavior.
Updated photo-image access and processing.
Corrected temporary image lifetime management.
Updated bitmap rotation and scaling code.
Unified bitmap-region operations across platforms.
Corrected Unix image handling.
Corrected Windows bitmap representation and mask generation.
Hardened bitmap allocation and size calculations.
Isolated native bitmap-handle access behind Rbc Windows helper functions.
Named-font changes¶
Graph widgets now register Tk’s world-change callback. Reconfiguring a named font refreshes cached text-marker geometry, title and axis layout, legends and value-label drawing resources, including external legends and named/active pens. Redraws are scheduled through the normal idle mechanism. Explicit pixel sizes and configured axis limits are preserved. See Named fonts and display scaling.
PDF output¶
Graph, barchart, stripchart and polar widgets support pdf cget, pdf configure and pdf output.
The exporter writes single-page PDF 1.4 directly through the shared rendering abstraction, without Cairo
or an external converter. Paths, arcs, symbols, clipping, transparency, images and window snapshots are
supported. TrueType and ordinary OpenType/CFF fonts are embedded with Unicode maps for searching/copying,
including mathematical superscripts/subscripts and fallback characters. Font lookup follows Tk 9 font attributes
using GDI on Windows and Fontconfig on X11. PDF -embedfonts defaults to true; disabling it selects
standard Helvetica/Times/Courier fonts and Windows-1252 text, with an error for unsupported characters.
SVG offers the same option, defaulting to false. Enabling it embeds native fonts and fallback faces as CSS
webfonts while preserving Unicode text; viewers must support CSS webfonts and data URLs.
Unsupported or restricted fonts and missing glyphs report an error. Output is a binary file or Tcl bytearray. See ::rbc::PDF.
SVG output¶
Graph widgets now provide svg cget, svg configure, and svg output, with independent width,
height and decoration settings. SVG export uses vector geometry and editable text and does not
require Cairo. Solid area opacity and photo-marker alpha are preserved. Photos are embedded as PNG;
bitmap markers and symbols use vector shapes. Stipple fills use vector patterns, and photo area tiles
embed repeating PNG images with alpha. Non-photo Tk images are rasterized with recovered transparency;
mapped window markers embed native pixel snapshots. Capture failures report an error before opening
a file. See ::rbc::SVG for commands, options and capture limitations.
PostScript output¶
The PostScript subsystem was modernized and hardened alongside the graph code.
PostScript drawing now passes through the common renderer interface: strokes, fills, symbols, text, images, bitmap masks, window snapshots, relief borders, plot backgrounds and clipping. This includes normal/active elements, markers, legends, axis labels, and polar/Smith labels. The existing PostScript backend, prolog, font/color mapping and public command are retained; export does not require Cairo. Page setup, orientation, EPS metadata and file output remain in the PostScript subsystem. Screen text rendering is unchanged.
This is an internal refactoring, not a new export format. PostScript still ignores area opacity; image-tiled line areas export only their configured background. Existing bitmap masks, drawing order and window-snapshot fallback behavior are preserved.
Updated PostScript option handling.
Updated image generation and bitmap handling.
Corrected PostScript writer behavior.
Replaced unsafe formatting paths.
Hardened formatting and buffer handling.
Updated coordinate and size handling for the modernized graph structures.
Windows drawing backend¶
The Windows drawing implementation received a substantial cleanup.
Obsolete compatibility code and dead drawing implementations were removed, and the remaining native drawing code was reorganized behind an Rbc-owned Windows abstraction.
Rbc code outside the Windows backend no longer accesses Tk’s private Windows drawable structures directly.
Operations such as:
acquiring and releasing a drawable
HDC;extracting an
HBITMAPfrom a Tk pixmap;wrapping an
HBITMAPas a pixmap;wrapping a native
HDC;mapping an
HWNDto the required drawable representation;setting Windows GDI raster operations
are now isolated behind Rbc_Win* helper functions.
This reduced the former widespread dependency on:
TkWinDrawableTkWinBitmapTkWinDCTkWinDCStateTkWinGetDrawableDC()TkWinReleaseDrawableDC()TWD_*
to a single Windows implementation unit, rbcWinDraw.c.
Windows rendering performance¶
The Windows graph renderer was also optimized to reduce repeated GDI setup for large drawing workloads.
Several older drawing paths performed native device-context, pen, brush, or bitmap setup separately for every individual primitive. This was particularly expensive for large scatter plots, bar charts, error bars, and collections of graph markers.
The Windows backend now batches or shares native drawing state where the original drawing semantics permit it:
independent line and error-bar segments are grouped into
PolyPolyline()calls;polygon-based symbols use batched native polygon and polyline drawing;
square and circle symbol rendering uses dedicated Windows fast paths;
raised bars share an acquired drawable
HDCand precomputed 3-D border colors instead of repeatedly entering Tk’s per-rectangle drawing path;opaque stippled bars use a reusable monochrome pattern brush and
PatBlt()instead of creating temporary bitmap state for every rectangle;compatible consecutive line-marker and polygon-outline markers are combined into segment batches while preserving marker display-list order;
solid fill-only polygon markers share their destination
HDCand brush across a compatible run;compatible bitmap markers share both source and destination device-context setup;
compatible text-marker runs reuse an acquired destination
HDCwhile continuing to use Tk’s font renderer.
The fast paths are deliberately conservative. XOR drawing, dashed or otherwise incompatible line styles, marker arrowheads, masked or rotated bitmap cases, mixed polygon fill/outline cases, and other operations whose semantics depend on individual drawing order continue through the normal drawing paths.
Batching never reorders visible graph objects. A pending batch is flushed whenever an incompatible object or another visible marker class is encountered, preserving the graph’s existing stacking and overlap semantics.
These changes affect the Windows native renderer only. The X11 drawing paths and PostScript output retain their existing behavior.
Remaining private Tk dependencies¶
Complete elimination of private Tk interfaces is currently not practical without either changes in Tk itself or a significant drawing-backend redesign.
The remaining dependencies are deliberately isolated:
rbcText.cuses Tk’s internalTkDrawAngledChars()functionality for rotated text. Tk does not currently provide equivalent functionality through its public API.rbcWinDraw.cusestkWinInt.hto bridge between Tk drawables and native Windows GDI objects.
No other graph, element, image or general Rbc code needs to know about Tk’s Windows-private drawable structures.
Compiler diagnostics caused by known attribute mismatches inside the private Tk headers are suppressed only around those specific includes; warnings remain enabled for Rbc’s own source code.
C safety and hardening¶
The Tcl/Tk 9 work also included a wider C safety audit.
Replaced unsafe
sprintf()usage with bounded or object-based formatting.Added validation for user-controlled numeric formatting strings.
Added multiplication and allocation-overflow checks.
Added range checks before narrowing floating-point or wide integer values.
Added explicit handling of
NaNand infinity.Removed undefined or questionable integer-overflow paths.
Improved
constcorrectness.Removed mutations through pointers to constant data.
Fixed uninitialized index/data-mapping cases.
Removed obsolete K&R-era and compatibility code where encountered.
Removed dead
#ifdef notdefand otherwise unreachable implementations where they no longer served a purpose.
Regression testing¶
The modernization was accompanied by a substantial expansion of the test suite.
New regression coverage was added for areas including:
option configuration and rollback;
axes and axis bindings;
markers;
element options and bindings;
legends;
vectors and vector arithmetic;
splines;
non-finite values;
logarithmic axes;
bar charts;
PostScript output;
bitmap and image handling;
formatting options;
error bars;
closest-point calculations;
coordinate and integer-boundary cases.
Manual graph tests and demos were also repeatedly exercised during the migration.
The resulting code has been tested on both Windows and Linux with Tcl/Tk 9.x.
Remaining compatibility interfaces¶
The remaining use of legacy or private Tk interfaces is intentional:
the EPS canvas item uses the configuration API still required by Tk’s public custom-canvas-item interface;
rotated text uses Tk’s unsupported angled-text API;
the Windows drawing adapter uses Tk’s private drawable representation.
These remaining interfaces can only be removed cleanly if equivalent public Tk APIs become available or if the relevant rendering code is replaced with an independent backend.
Copyright (c) George Yashin