Text Block¶
This example renders a multiline text object at a stable screen position.
Preview¶
Run And Adapt¶
Commands below assume a Datoviz source checkout and start at the repository root. Use your configured build environment; Python routes additionally require local bindings.
| Route | Availability | Command or action |
|---|---|---|
| C | Canonical native source | just example-c features/text_block (build and run), or rerun ./build/examples/c/features/text_block |
| Python | Available; direct-engine adaptation | python3 -m examples.python.gallery.features.text_block |
| Browser | Live WebGPU route | Open live example |
This example is approved as a starting point for user code and coding agents. Keep the object lifetimes and data shapes intact while adapting the data and styling.
What To Look For¶
The text object keeps style, layout, placement, and the whole paragraph string together. The example uses an MSDF atlas renderer, explicit text size, line height, line gap, and a top-left screen placement inside the panel. Text blocks are useful for annotations, compact notes, and status messages that should remain legible independent of data coordinates.
Source¶
#!/usr/bin/env python3
"""Retained multiline text block in panel screen coordinates."""
from __future__ import annotations
import ctypes
import datoviz as dvz
from examples.python.gallery import common as ex
def main() -> None:
scene, figure, panel = ex.scene_panel()
text = dvz.dvz_text(panel, 0)
if not text:
raise RuntimeError("dvz_text() failed")
style = dvz.dvz_text_style()
style.size_px = 24.0
style.renderer = dvz.DVZ_TEXT_RENDERER_MSDF_ATLAS
style.color[:] = (ex.TEXT.r, ex.TEXT.g, ex.TEXT.b, ex.TEXT.a)
if dvz.dvz_text_set_style(text, ctypes.byref(style)) != 0:
raise RuntimeError("dvz_text_set_style() failed")
layout = dvz.dvz_text_layout()
layout.line_height = 1.18
layout.line_gap_px = 6.0
if dvz.dvz_text_set_layout(text, ctypes.byref(layout)) != 0:
raise RuntimeError("dvz_text_set_layout() failed")
placement = dvz.dvz_text_placement()
placement.mode = dvz.DVZ_TEXT_PLACEMENT_SCREEN
placement.anchor = dvz.DVZ_SCENE_ANCHOR_PANEL_TOP_LEFT
placement.position[:] = (138.0, 245.0, 0.0)
placement.text_anchor[:] = (0.0, 0.0)
placement.has_text_anchor = True
if dvz.dvz_text_set_placement(text, ctypes.byref(placement)) != 0:
raise RuntimeError("dvz_text_set_placement() failed")
content = (
b"Retained text can hold a compact note that reads\n"
b"like ordinary prose across multiple explicit lines.\n"
b"The whole paragraph remains one scene-owned string,\n"
b"so placement, style, and updates stay together."
)
if dvz.dvz_text_set_string(text, content) != 0:
raise RuntimeError("dvz_text_set_string() failed")
ex.run(scene, figure, "Text Block")
if __name__ == "__main__":
main()
/*
* Copyright (c) 2021 Cyrille Rossant and contributors. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project root for details.
* SPDX-License-Identifier: MIT
*/
/* This example renders a retained multiline text object at a stable screen position.
*
* What to look for: the text object keeps style, layout, placement, and the whole paragraph string
* together. The example uses an MSDF atlas renderer, explicit text size, line height, line gap,
* and a top-left screen placement inside the panel. Text blocks are useful for annotations,
* compact notes, and status messages that should remain legible independent of data coordinates.
*
* Scenario: features_text_block
* Style: features, graphite_cyan, 1280x720 window target
*
* Build: just example-c features/text_block
* Run: ./build/examples/c/features/text_block --live
* Smoke: ./build/examples/c/features/text_block --png
*/
/*************************************************************************************************/
/* Includes */
/*************************************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "datoviz/scene.h"
#include "example_style.h"
#include "runner/scenario_runner.h"
/*************************************************************************************************/
/* Forward declarations */
/*************************************************************************************************/
DvzScenarioSpec dvz_example_text_block_scenario(void);
/*************************************************************************************************/
/* Constants */
/*************************************************************************************************/
#define WIDTH EXAMPLE_WINDOW_WIDTH
#define HEIGHT EXAMPLE_WINDOW_HEIGHT
/*************************************************************************************************/
/* Helpers */
/*************************************************************************************************/
/**
* Add a compact multiline annotation block.
*
* @param panel target panel
* @return true on success
*/
static bool _add_text_block(DvzPanel* panel)
{
DvzText* text = dvz_text(panel, 0);
if (text == NULL)
return false;
DvzColor color = example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_TEXT);
DvzTextStyle style = dvz_text_style();
style.size_px = 24.0f;
style.renderer = DVZ_TEXT_RENDERER_MSDF_ATLAS;
style.color[0] = color.r;
style.color[1] = color.g;
style.color[2] = color.b;
style.color[3] = color.a;
if (dvz_text_set_style(text, &style) != 0)
return false;
DvzTextLayout layout = dvz_text_layout();
layout.line_height = 1.18f;
layout.line_gap_px = 6.0f;
if (dvz_text_set_layout(text, &layout) != 0)
return false;
DvzTextPlacement placement = dvz_text_placement();
placement.mode = DVZ_TEXT_PLACEMENT_SCREEN;
placement.anchor = DVZ_SCENE_ANCHOR_PANEL_TOP_LEFT;
placement.position[0] = 138.0;
placement.position[1] = 245.0;
placement.position[2] = 0.0;
placement.text_anchor[0] = 0.0f;
placement.text_anchor[1] = 0.0f;
placement.has_text_anchor = true;
if (dvz_text_set_placement(text, &placement) != 0)
return false;
return dvz_text_set_string(
text,
"Retained text can hold a compact note that reads\n"
"like ordinary prose across multiple explicit lines.\n"
"The whole paragraph remains one scene-owned string,\n"
"so placement, style, and updates stay together.") == 0;
}
/*************************************************************************************************/
/* Scenario callbacks */
/*************************************************************************************************/
/**
* Initialize the retained text-block scenario.
*
* @param ctx scenario context
* @param out_user scenario state output
* @return true on success
*/
static bool _scenario_init(DvzScenarioContext* ctx, void** out_user)
{
if (ctx == NULL)
return false;
if (out_user != NULL)
*out_user = NULL;
ctx->figure = dvz_figure(ctx->scene, ctx->width, ctx->height, 0);
if (ctx->figure == NULL)
return false;
DvzPanel* panel = dvz_panel_full(ctx->figure);
if (panel == NULL)
return false;
example_graphite_cyan_set_panel_background(panel);
return _add_text_block(panel);
}
/**
* Return the text-block scenario specification.
*
* @return scenario specification
*/
DvzScenarioSpec dvz_example_text_block_scenario(void)
{
return (DvzScenarioSpec){
.id = "features_text_block",
.title = "Text Block",
.width = WIDTH,
.height = HEIGHT,
.fps = 60.0,
.requirements = DVZ_SCENARIO_REQ_TEXT_VISUAL,
.init = _scenario_init,
};
}
/*************************************************************************************************/
/* Functions */
/*************************************************************************************************/
/**
* Run the retained text-block feature example through the native scenario runner.
*
* @param argc command-line argument count
* @param argv command-line argument vector
* @return process exit code
*/
#ifndef DVZ_EXAMPLE_NO_MAIN
int main(int argc, char** argv)
{
DvzScenarioSpec spec = dvz_example_text_block_scenario();
return dvz_scenario_run_native_cli(&spec, argc, argv) == 0 ? 0 : 1;
}
#endif
Example details
- ID:
features_text_block - Category:
feature - Lane:
features - Status:
supported - Source:
examples/c/features/text_block.c - Approved adaptation starter:
yes - Python source:
examples/python/gallery/features/text_block.py - Python adaptation: Available; direct-engine adaptation
- Browser support: Live in browser
- WebGPU live route:
examples/webgpu/live.html?id=features_text_block - Browser capability tags:
text,glyph-atlas - Validation:
smoke+screenshot
Data
| Field | Value |
|---|---|
kind |
synthetic |
