LCharacter Reference Manual & Broadcasting CG Overlay Guide
The LCharacter class is the high-performance vector graphics and Character Generator (CG) overlay engine of the now2sdk framework, derived from the base LObject class. It composites broadcasting overlays (lower-thirds, scoreboards, scrolling tickers, logos, lens flares, animated image sequences, live and transparent video elements) directly onto transparent RGBA frames using the Cairo 2D graphics API, with optional CPU or GPU rasterization.
It supports static and dynamic text wrapping, shape rendering with borders, gradients, and alpha transparency, horizontal/vertical scrolling crawls, vertical rolling tickers, custom images, image sequences, loopable transparent videos, dynamic live sources (CGo1), lens flares, declarative grouping, and complete XML template serialization for show playback.
1. Architectural Concept & Core Compositing Pipeline
graph TD
A[Item Creation: addItem] --> B[Cairo ARGB32 Surface - 1920x1080]
B --> C{Item Type Dispatch}
C -->|LCGTextItem| D[Static / Wrapped Text + Outline + Shadow]
C -->|LCGCrawlItem| E[Cached Text Surface + Scrolling Animation]
C -->|LCGTickerItem| F[Vertical Roll with Smooth Transitions]
C -->|LCGImageItem| G[PNG / JPG with Crop + Stretch Modes]
C -->|LCGImageSeqItem| H[FPS-Locked Image Sequence Playback]
C -->|LCGVideoItem| I[FFmpeg Decode + Loop - ProRes 4444 / WebM alpha]
C -->|LCGLiveItem| J[Live Source Registry - LLive Sink]
C -->|LCGRectItem| K[Vector Rectangle - Solid / Gradient]
C -->|LCGCircleItem| L[Vector Circle / Ellipse Shape]
C -->|LCGFlareItem| M[Animated Multi-Ray Lens Flare]
D & E & F & G & H & I & J & K & L & M --> N[Dynamic Tag Processor]
N -->|dateTime countdown countup| O[Refreshed Text]
O --> P[Cairo Compositor]
P --> Q[Group Transforms - x, y, show]
Q --> R[Item Transform - rotation, anchorX, anchorY]
R --> S[BGRA -> YUVA420P Conversion]
S --> T[distributeVideoFrame -> LPreview / LMixer / LOutput / LRecorder]
Key Subsystems:
- Cairo-Powered Compositor: All graphic operations (text shaping, vector shapes, alpha blending, gradient fills, drop shadows, rounded corners, outline strokes) are executed through the Cairo 2D library on an internal
CAIRO_FORMAT_ARGB32surface. This guarantees pixel-perfect, resolution-independent rendering with hardware-accelerated backend support when available. - Transparent Frame Output: Each rendered frame is converted from BGRA into
AV_PIX_FMT_YUVA420P(with alpha channel), so the overlay may be safely multiplied onto any underlying video layer (file, mixer, live source) without bleeding. - Internal Playback Thread: A dedicated worker thread (driven by
m_fps) callsrenderCompositionwheneverm_isDirtyis set or any dynamic item is detected (video, crawl, ticker, animated movement, dynamic text tags). This guarantees smooth motion at the configured composite FPS (default50.0). - Cairo Surface Caching: Crawl text, PNG images, and decoded video frames are cached internally per item to eliminate redundant rasterization between frames.
- UTF-8 Text Rendering with Auto-Shrink: Multi-byte character sets (Turkish, Arabic, Chinese, etc.) are correctly shaped via UTF-8 splitting.
autoShrinkautomatically reduces font size when text exceeds the bounding box width. - Dynamic Tag Engine: Text fields support runtime interpolation of
dateTime,countdown, andcountupmacros. Tags are re-evaluated each frame, enabling live time readouts, sports clocks, and broadcast timers. - Live Source Registry: A globally accessible static registry binds a named
LLive*instance to one or moreLCGLiveItemoverlays. Items automatically receive the most recent decoded frame from their associated live source via an internal sink chain. - Group Transform Layer: Items can be aggregated into groups (
LCGGroup). The group'sxandyoffsets, plus the item's ownrotation/anchorX/anchorY, are applied additively on top of each item's local coordinates.
2. API Reference & Key Methods
📌 Ingestion & Item Addition
LCGTextItem* addItem(std::string id, int x, int y, int w, int h, LCGTextProps props);
LCGCrawlItem* addItem(std::string id, int x, int y, int w, int h, LCGCrawlProps props);
LCGTickerItem* addItem(std::string id, int x, int y, int w, int h, LCGTickerProps props);
LCGImageItem* addItem(std::string id, int x, int y, int w, int h, LCGImageProps props);
LCGImageSeqItem* addItem(std::string id, int x, int y, int w, int h, LCGImageSeqProps props);
LCGVideoItem* addItem(std::string id, int x, int y, int w, int h, LCGVideoProps props);
LCGRectItem* addItem(std::string id, int x, int y, int w, int h, LCGRectProps props);
LCGCircleItem* addItem(std::string id, int x, int y, int w, int h, LCGCircleProps props);
LCGFlareItem* addItem(std::string id, int x, int y, int w, int h, LCGFlareProps props);
LCGLiveItem* addItem(std::string id, int x, int y, int w, int h, LCGLiveProps props);
Adds an overlay element to the canvas. Each addItem is an overloaded method that returns a pointer to the specific item subclass (LCGTextItem, LCGCrawlItem, etc.). The pointer can then be modified directly to mutate x, y, w, h, alpha, show, or its props/*Props struct, without calling updateItem.
For LCGImageItem, if w or h is <= 0, the item adopts the source image's intrinsic dimensions. For LCGVideoItem, the same rule is applied using the first decoded video frame's dimensions. For all other items, w<=0 or h<=0 falls back to the canvas size (1920 × 1080).
For LCGVideoItem, the decoder opens synchronously inside addItem. If the file cannot be opened, has no video stream, or fails to decode the first frame, the function returns nullptr.
For LCGLiveItem, a hidden internal LCGLiveSink is created and stored under the item's id. The render thread attaches the sink to whatever LLive* is currently stored in LCGLiveProps::source — pass the LLive* directly when adding the item, no separate registration is required. The item will surface frames only when that source produces them.
📌 Modification, Transform & Lifecycle
void updateItem(std::string id, int x, int y, int w, int h, float alpha, bool show, LCGTextProps props);
void updateItem(std::string id, int x, int y, int w, int h, float alpha, bool show, LCGCrawlProps props);
void updateItem(std::string id, int x, int y, int w, int h, float alpha, bool show, LCGTickerProps props);
void updateItem(std::string id, int x, int y, int w, int h, float alpha, bool show, LCGImageProps props);
void updateItem(std::string id, int x, int y, int w, int h, float alpha, bool show, LCGImageSeqProps props);
void updateItem(std::string id, int x, int y, int w, int h, float alpha, bool show, LCGVideoProps props);
void updateItem(std::string id, int x, int y, int w, int h, float alpha, bool show, LCGRectProps props);
void updateItem(std::string id, int x, int y, int w, int h, float alpha, bool show, LCGCircleProps props);
void updateItem(std::string id, int x, int y, int w, int h, float alpha, bool show, LCGFlareProps props);
void updateItem(std::string id, int x, int y, int w, int h, float alpha, bool show, LCGLiveProps props);
Updates an existing item's coordinates, bounding box, alpha opacity (0.0f to 1.0f), visibility, and style props in a single call. Type-specific overloads exist for all 10 element types.
void setItemTransform(std::string id, float rotation, float anchorX, float anchorY);
Sets per-item rotation in degrees (clockwise) and an anchor point (anchorX, anchorY from 0.0f to 1.0f, relative to the item's w × h box) around which the rotation is applied.
LCGItem* getItem(std::string id);
int getItemCount() const;
LCGItem* getItemByIndex(int index);
Resolves items: getItem(id) retrieves by ID (must cast to the proper subclass to access props); getItemCount() returns total items in the canvas; getItemByIndex(i) returns the i-th item by z-order.
void showItem(std::string id_or_group, bool show);
void remove(const std::string& id);
void clear();
void forceUpdate();
void setFPS(double fps);
showItemtoggles theshowflag on either an item or a group (matching byid).remove(id)erases the item and deletes its underlying memory. ForLCGLiveItem, the bound sink is detached from itsLLive*source and destroyed.clear()removes all items and groups and frees their resources. Use this before loading a complete fresh template.forceUpdate()marks the canvas dirty so the next playback tick re-renders.setFPS(double fps)sets the compositing frame rate (default50.0).
📌 Video Format Configuration
void setVideoFormat(const videoFormatProps& props);
void getVideoFormat(videoFormatProps& props) const;
Mirrors LMixer::setVideoFormat. Sets or queries the canvas resolution, frame rate, and pixel format used for compositing. Call this before adding items if you need a non-default canvas size — the first addItem call lazily allocates the Cairo surface to match.
📌 Frame-Based Playback Timing & Markers
void setTotalFrames(int n);
int getTotalFrames() const;
double getDurationSeconds() const;
void setInStopFrame(int f);
int getInStopFrame() const;
void setOutStartFrame(int f);
int getOutStartFrame() const;
void setLoopFrame(int f);
int getLoopFrame() const;
void forceUpdate();
setTotalFrames(n)sets the total timeline length in frames.getDurationSeconds()returns the equivalent duration at the configuredm_fps(default50.0).- Three independent in/out/loop markers: each accepts a frame index, or
-1to disable. They are used by the playback thread and bysetItemBakedFrameslookups. forceUpdate()marks the canvas dirty and triggers an immediate re-render on the next tick.
📌 Keyframe Animation & Pre-Baked Frames
void setItemBakedFrames(std::string id,
const std::vector<LCGFrameState>& states,
const std::vector<LCGTextProps>& props);
void setItemBakedFrames(std::string id,
const std::vector<LCGFrameState>& states,
const std::vector<LCGCrawlProps>& props);
void setItemBakedFrames(std::string id,
const std::vector<LCGFrameState>& states,
const std::vector<LCGTickerProps>& props);
void setItemBakedFrames(std::string id,
const std::vector<LCGFrameState>& states,
const std::vector<LCGImageProps>& props);
void setItemBakedFrames(std::string id,
const std::vector<LCGFrameState>& states,
const std::vector<LCGImageSeqProps>& props);
void setItemBakedFrames(std::string id,
const std::vector<LCGFrameState>& states,
const std::vector<LCGVideoProps>& props);
void setItemBakedFrames(std::string id,
const std::vector<LCGFrameState>& states,
const std::vector<LCGRectProps>& props);
void setItemBakedFrames(std::string id,
const std::vector<LCGFrameState>& states,
const std::vector<LCGCircleProps>& props);
void setItemBakedFrames(std::string id,
const std::vector<LCGFrameState>& states,
const std::vector<LCGFlareProps>& props);
void setItemBakedFrames(std::string id,
const std::vector<LCGFrameState>& states,
const std::vector<LCGLiveProps>& props);
Loads a fully pre-baked animation timeline into the item. Each entry in states describes the transform (x, y, w, h, alpha, show, rotation, anchorX, anchorY) at a specific frame index; the matching props entry carries the type-specific style for that frame. The playback thread samples these arrays directly without recomputing keyframe easing.
The companion types are:
struct LCGFrameState {
int x = 0, y = 0, w = 0, h = 0;
float alpha = 1.0f;
bool show = true;
float rotation = 0.0f;
float anchorX = 0.5f;
float anchorY = 0.5f;
};
enum class LCGAnimProp { PosX, PosY, Width, Height, Alpha, Rotation, AnchorX, AnchorY };
enum class LCGEasing { Linear, EaseIn, EaseOut, EaseInOut };
using LCGValue = std::variant<float, int, std::string, LCGColor>;
struct LCGKeyframe {
int frame = 0;
LCGAnimProp prop = LCGAnimProp::PosX;
LCGValue value{};
LCGEasing easing = LCGEasing::Linear;
float cp1x = -1.f, cp1y = -1.f, cp2x = -1.f, cp2y = -1.f;
};
Per-item keyframe API on every LCGItem subclass:
void addKeyframe(int frame, LCGAnimProp prop, LCGValue value,
LCGEasing easing = LCGEasing::Linear);
void updateKeyframe(int frame, LCGAnimProp prop, LCGValue newValue);
void removeKeyframe(int frame, LCGAnimProp prop);
void removeKeyframesForProp(LCGAnimProp prop);
void clearKeyframes();
const std::vector<LCGKeyframe>& getKeyframes() const;
Initializer-list setter proxies for compact timeline authoring:
item->addkeyframes = { kf(0, PosX, 50),
kf(50, PosX, 1920, EaseInOut) };
item->updatekeyframes = { kf(50, PosX, 1980) };
item->removekeyframes = { kf(50, PosX) };
addKeyframeappends or replaces the keyframe at(frame, prop). The optionalcp1x/cp1y/cp2x/cp2yfields override the easing preset with explicit cubic Bezier control points (set any of them to-1.fto fall back to the preset).updateKeyframechanges the value of an existing keyframe; the frame index and prop must already exist.removeKeyframeremoves a single keyframe;removeKeyframesForPropwipes every keyframe for oneLCGAnimProp;clearKeyframeswipes everything.getKeyframes()returns the read-only vector the engine samples every frame.
📌 Playback Sequence Control
void setPlaybackSequence(int totalFrames, int inStopFrame,
int outStartFrame, int loopFrame,
bool hasLoop);
void startPlayback();
void stopPlayback();
void shutdownPlayback(); // hard stop: joins the playback thread
void seekPlayback(int frame);
int getPlaybackFrame() const;
bool isPlaying() const;
bool isPlaybackFinished() const;
setPlaybackSequencearms the playback thread with the total timeline length and the three markers. Pass any marker as-1to disable that boundary.startPlayback()spins up the dedicated playback worker thread (separate from the live render thread).stopPlayback()requests a soft stop — the worker exits at the next safe checkpoint.shutdownPlayback()performs a hard stop: it joins the playback thread before the engine destructor runs. Call this on the application side before removing the layer from a parentLMixer; otherwise the worker keeps pushing frames into a sink that the mixer has already freed.seekPlayback(frame)jumps the playback cursor without restarting the thread.getPlaybackFrame(),isPlaying(),isPlaybackFinished()query the live state.
📌 XML Configuration Save & Load
void saveToXMLFile(const std::string& filePath);
void loadFromXMLFile(const std::string& filePath);
void insertFromXMLFile(const std::string& filePath);
saveToXMLFileserializes the current canvas state — items, groups, coordinates, props — into a single XML file.loadFromXMLFileperforms a full reset, then loads the XML template as the new canvas contents.insertFromXMLFilemerges items from the XML template into the existing canvas without clearing it (allows layer-based composition from multiple templates).
XML persistence makes it trivial to author complex on-air branding templates in a desktop tool and reload them at runtime during a show playback.
📌 Grouping Operations
std::string group(const std::vector<std::string>& itemIDs);
void unGroup(const std::string& groupID);
void deleteGroup(const std::string& groupID);
int groupItemCount(const std::string& groupID);
LCGItem* getGroupItemByIndex(const std::string& groupID, int index);
std::string getGroup(const std::string& itemID);
LCGGroup* getGroupObject(const std::string& groupID);
int getGroupCount() const;
LCGGroup* getGroupByIndex(int index);
group(itemIDs)aggregates multiple items into a singleLCGGroup. It returns an auto-generated group ID (group1,group2, ...). If an item was already in another group, it is removed from its prior group first.unGroup(groupID)dissolves a group: every member'spGroupis set tonullptr. Items remain in the canvas but become independent.deleteGroup(groupID)destroys every item belonging to the group in addition to the group itself.getGroupItemByIndex,groupItemCount,getGroup,getGroupObject,getGroupCount,getGroupByIndexprovide rich per-group and per-item traversal.getGroupObject(groupID)retrieves the group pointer — useful for moving the whole cluster by mutatingx/y, or forshow = falseto hide all members at once.
3. Base Element Properties: LCGItem & Group Class: LCGGroup
LCGItem Base Class
All items added to LCharacter (LCGTextItem, LCGCrawlItem, etc.) inherit the base properties of LCGItem. These parameters can be read or modified directly on the item pointer:
| Field | Type | Default Value | Description |
|---|---|---|---|
id |
std::string |
"" |
Unique identifier for the element. |
x |
float |
0.0f |
Current horizontal coordinate in pixels. |
y |
float |
0.0f |
Current vertical coordinate in pixels. |
startX |
float |
0.0f |
Default starting horizontal coordinate (reference / reset position). |
startY |
float |
0.0f |
Default starting vertical coordinate (reference / reset position). |
w |
int |
0 |
Width of the bounding box in pixels. |
h |
int |
0 |
Height of the bounding box in pixels. |
show |
bool |
true |
Visibility switch (true to render, false to hide). |
alpha |
float |
1.0f |
Opacity scale factor (0.0f to 1.0f). |
pGroup |
LCGGroup* |
nullptr |
Pointer to the parent group object (or nullptr if independent). |
move |
std::string |
"None" |
Motion style key: "None", "Horizontal", "Vertical". |
speed |
float |
0.0f |
Animation/motion velocity factor (pixels per frame). |
loop |
bool |
true |
If true, items entering the off-canvas area wrap around (used for crawls/loops). |
rotation |
float |
0.0f |
Item rotation in degrees, applied via setItemTransform. |
anchorX |
float |
0.5f |
Horizontal rotation pivot (normalized 0.0f to 1.0f). |
anchorY |
float |
0.5f |
Vertical rotation pivot (normalized 0.0f to 1.0f). |
inTrack |
int |
-1 |
Input track index that routes this item's video into the global mixer bus. -1 = unassigned. |
outTrack |
int |
-1 |
Output track index that consumes this item's video from the bus. -1 = unassigned. |
bakedStates |
std::vector<LCGFrameState> |
{} |
Pre-baked per-frame transforms loaded by setItemBakedFrames. |
keyframes |
std::vector<LCGKeyframe> |
{} |
Live keyframe timeline sampled every render tick. Mutate via the keyframe methods below. |
LCGGroup Class
Defines a collection of elements that can be moved or toggled as a single unit:
| Field | Type | Default Value | Description |
|---|---|---|---|
id |
std::string |
"" |
Unique group identifier. |
show |
bool |
true |
Group visibility switch. When false, all member items are skipped during rendering. |
x |
float |
0.0f |
Group horizontal offset in pixels (added on top of each item's local x). |
y |
float |
0.0f |
Group vertical offset in pixels (added on top of each item's local y). |
w |
float |
0.0f |
Group bounding box width in pixels (informational; not enforced during rendering). |
h |
float |
0.0f |
Group bounding box height in pixels (informational; not enforced during rendering). |
items |
std::vector<LCGItem*> |
{} |
Vector of items inside the group. |
4. Subclass Items & Property Structs
To mutate a specific item, modify its props / *Props struct on the pointer returned by addItem or getItem (cast the base LCGItem* to the appropriate subclass first):
📌 LCGTextItem (Static / Dynamic Text)
Defines a text block layout:
class NOW2SDK_EXPORT LCGTextItem : public LCGItem {
public:
LCGTextProps props; // Text properties struct
};
LCGTextProps Struct
| Field | Type | Default Value | Description |
|---|---|---|---|
text |
std::string |
"" |
Text contents. Supports dynamic tags: %dateTime::...%, %countdown::SEC::FORMAT%, %countup::SEC::FORMAT%. |
font |
std::string |
"Arial" |
Font family name (must be available to the system font loader). |
fontSize |
int |
24 |
Font size in pixels. |
color |
LCGColor |
"#FFFFFF" |
Font hex color. |
textAlpha |
int |
255 |
Font opacity (0 to 255). |
letterSpacing |
float |
0.0f |
Spacing between characters (in pixels). |
autoShrink |
bool |
false |
Shrinks font size automatically if the text exceeds bounding width. |
padding |
int |
0 |
Inner padding in pixels. |
outlineSize |
int |
0 |
Text outline stroke size in pixels (0 disables). |
outlineColor |
LCGColor |
"#000000" |
Text outline stroke color. |
hAlign |
std::string |
"Left" |
Horizontal alignment: "Left", "Center", "Right". |
vAlign |
std::string |
"Center" |
Vertical alignment: "Top", "Center", "Bottom". |
bgType |
std::string |
"None" |
Background type: "None", "Color", "Gradient". |
bgColor |
LCGColor |
"#000000" |
Solid background fill color. |
bgGradientStartColor |
LCGColor |
"#FF0000" |
Gradient starting color (top). |
bgGradientEndColor |
LCGColor |
"#000000" |
Gradient ending color (bottom). |
bgAlpha |
int |
255 |
Background block opacity (0 to 255). |
bgRadius |
int |
0 |
Corner rounding radius for the background box in pixels (0 = square). |
bgShadowOffsetX |
float |
0.0f |
Background drop shadow horizontal offset. |
bgShadowOffsetY |
float |
0.0f |
Background drop shadow vertical offset. |
bgShadowAlpha |
int |
0 |
Background drop shadow opacity (0 to 255). |
bgShadowColor |
LCGColor |
"#000000" |
Background drop shadow color. |
borderColor |
LCGColor |
"#FFFFFF" |
Background box border outline color. |
borderSize |
int |
0 |
Background box border outline thickness in pixels (0 disables). |
borderAlpha |
int |
255 |
Background box border outline opacity. |
textShadowOffsetX |
float |
0.0f |
Text character drop shadow horizontal offset. |
textShadowOffsetY |
float |
0.0f |
Text character drop shadow vertical offset. |
textShadowAlpha |
int |
0 |
Text character shadow opacity (0 to 255). |
textShadowColor |
LCGColor |
"#000000" |
Text character shadow color. |
📌 LCGCrawlItem (Scrolling News Tickers)
Defines a continuous text crawl marquee. The text content, fonts, colors, alignment, outline, shadow, padding, background and panel border are all carried by LCGCrawlProps, which inherits directly from LCGTextProps. Crawl-only motion and separator fields are appended at the bottom of the same struct.
class NOW2SDK_EXPORT LCGCrawlItem : public LCGItem {
public:
LCGCrawlProps crawlProps; // Crawl ticker properties
};
struct NOW2SDK_EXPORT LCGCrawlProps : public LCGTextProps {
// crawl-specific fields appended below — see table
};
Text Source — crawlProps.text
crawlProps.textis the string the crawler prints. Place every ticker line in this field.- Lines may be separated by
\nor the literal|character (the engine treats both as line breaks). - The text supports every dynamic tag documented in Section 5:
%dateTime::FORMAT%,%countdown::SEC::FORMAT%,%countup::SEC::FORMAT%. Tags are re-evaluated on every render frame. - In addition, the base
loopflag (bool, defaulttrue) is inherited fromLCGItemand applies to crawls: whentruethe text chain is appended with the separator indefinitely so the crawl never visibly ends.
LCGCrawlProps — Complete Property Reference
The table below lists every field you can set on a crawl. Inherited fields from LCGTextProps are marked [Inherited], crawl-only fields are marked [Crawl-only]:
| Field | Type | Default | Group | Description |
|---|---|---|---|---|
text |
std::string |
"" |
[Inherited] | Crawler text. Multi-line content via \n or |. Supports %dateTime::%, %countdown::%, %countup::% tags. |
font |
std::string |
"Arial" |
[Inherited] | Font family name (must be available to the system font loader). |
fontSize |
int |
24 |
[Inherited] | Font size in pixels. |
color |
LCGColor |
"#FFFFFF" |
[Inherited] | Font hex color. |
textAlpha |
int |
255 |
[Inherited] | Font opacity (0 to 255). |
letterSpacing |
float |
0.0f |
[Inherited] | Spacing between characters (in pixels). |
autoShrink |
bool |
false |
[Inherited] | Shrinks font size automatically if the text exceeds bounding width. |
padding |
int |
0 |
[Inherited] | Inner padding (in pixels) applied to the bounding box. |
outlineSize |
int |
0 |
[Inherited] | Text outline stroke size in pixels (0 disables). |
outlineColor |
LCGColor |
"#000000" |
[Inherited] | Text outline stroke color. |
hAlign |
std::string |
"Left" |
[Inherited] | Horizontal alignment of the text segment inside the bounding box: "Left", "Center", "Right". |
vAlign |
std::string |
"Center" |
[Inherited] | Vertical alignment inside the bounding box: "Top", "Center", "Bottom". |
bgType |
std::string |
"None" |
[Inherited] | Background type behind the crawl: "None", "Color", "Gradient". |
bgColor |
LCGColor |
"#000000" |
[Inherited] | Solid background fill color. |
bgGradientStartColor |
LCGColor |
"#FF0000" |
[Inherited] | Gradient starting color (top edge). |
bgGradientEndColor |
LCGColor |
"#000000" |
[Inherited] | Gradient ending color (bottom edge). |
bgAlpha |
int |
255 |
[Inherited] | Background block opacity (0 to 255). |
bgRadius |
int |
0 |
[Inherited] | Corner rounding radius for the background box (0 = square). |
bgShadowOffsetX |
float |
0.0f |
[Inherited] | Background drop shadow horizontal offset. |
bgShadowOffsetY |
float |
0.0f |
[Inherited] | Background drop shadow vertical offset. |
bgShadowAlpha |
int |
0 |
[Inherited] | Background drop shadow opacity (0 to 255). |
bgShadowColor |
LCGColor |
"#000000" |
[Inherited] | Background drop shadow color. |
borderColor |
LCGColor |
"#FFFFFF" |
[Inherited] | Background box border outline color. |
borderSize |
int |
0 |
[Inherited] | Background box border outline thickness in pixels (0 disables). |
borderAlpha |
int |
255 |
[Inherited] | Background box border outline opacity. |
textShadowOffsetX |
float |
0.0f |
[Inherited] | Text character drop shadow horizontal offset. |
textShadowOffsetY |
float |
0.0f |
[Inherited] | Text character drop shadow vertical offset. |
textShadowAlpha |
int |
0 |
[Inherited] | Text character shadow opacity (0 to 255). |
textShadowColor |
LCGColor |
"#000000" |
[Inherited] | Text character shadow color. |
textMove |
std::string |
"Horizontal" |
[Crawl-only] | Scroll direction: "Horizontal" or "Vertical". |
textSpeed |
float |
50.0f |
[Crawl-only] | Pixels-per-frame offset. Positive scrolls right / down, negative scrolls left / up. |
separatorImage |
std::string |
"" |
[Crawl-only] | Path to image file used as separator between text repetitions. |
textSeparator |
std::string |
" *** " |
[Crawl-only] | Text used as separator if separatorImage is empty. |
separatorPadding |
int |
10 |
[Crawl-only] | Padding space (in pixels) added around the separator image or text. |
loop(inherited fromLCGItem,bool, defaulttrue): whentruethe text chain is appended with the separator indefinitely so the crawl has no visible end.
Format Example
LCGCrawlProps crawl;
crawl.text = "::: NOW2SDK CAIRO GRAPHICS ENGINE ::: %dateTime::HH:mm:ss% ::: "
"BREAKING %countdown::120::mm:ss% :::"; // multi-segment + dynamic tags
crawl.textMove = "Horizontal";
crawl.textSpeed = -4.0f;
crawl.textSeparator = " ★ ";
crawl.separatorPadding = 12;
crawl.font = "Arial";
crawl.fontSize = 30;
crawl.color = "#FFFF00";
crawl.bgType = "Solid";
crawl.bgColor = "#111111";
crawl.bgAlpha = 220;
The crawl pre-renders the full text + separator chain into an internal Cairo surface on the first frame, then blits-and-translates this cached surface every frame for high-performance rendering.
📌 LCGTickerItem (Vertical Rolling Page Tickers)
Defines a multi-line vertical slide-roll ticker. Every text appearance field lives in LCGTickerProps, which inherits directly from LCGTextProps. Ticker-only motion/transition fields are appended at the bottom of the same struct.
class NOW2SDK_EXPORT LCGTickerItem : public LCGItem {
public:
LCGTickerProps tickerProps; // Rolling ticker properties
};
struct NOW2SDK_EXPORT LCGTickerProps : public LCGTextProps {
// ticker-specific fields appended below — see table
};
Text Source — tickerProps.text
tickerProps.textis the string the ticker rolls. Place each headline/page in this field.- Pages are separated by the
\nnewline character — every non-empty line becomes an independent page that the ticker cycles through. - The text supports every dynamic tag documented in Section 5:
%dateTime::FORMAT%,%countdown::SEC::FORMAT%,%countup::SEC::FORMAT%. Tags are re-evaluated on every render frame, even between transitions.
LCGTickerProps — Complete Property Reference
The table below lists every field you can set on a ticker. Inherited fields from LCGTextProps are marked [Inherited], ticker-only fields are marked [Ticker-only]:
| Field | Type | Default | Group | Description |
|---|---|---|---|---|
text |
std::string |
"" |
[Inherited] | Pages to display, separated by \n. Supports %dateTime::%, %countdown::%, %countup::% tags. |
font |
std::string |
"Arial" |
[Inherited] | Font family name (must be available to the system font loader). |
fontSize |
int |
24 |
[Inherited] | Font size in pixels. |
color |
LCGColor |
"#FFFFFF" |
[Inherited] | Font hex color. |
textAlpha |
int |
255 |
[Inherited] | Font opacity (0 to 255). |
letterSpacing |
float |
0.0f |
[Inherited] | Spacing between characters (in pixels). |
autoShrink |
bool |
false |
[Inherited] | Shrinks font size automatically if the text exceeds bounding width. |
padding |
int |
0 |
[Inherited] | Inner padding (in pixels) applied to the bounding box. |
outlineSize |
int |
0 |
[Inherited] | Text outline stroke size in pixels (0 disables). |
outlineColor |
LCGColor |
"#000000" |
[Inherited] | Text outline stroke color. |
hAlign |
std::string |
"Left" |
[Inherited] | Horizontal alignment of the page text inside the bounding box: "Left", "Center", "Right". |
vAlign |
std::string |
"Center" |
[Inherited] | Vertical alignment inside the bounding box: "Top", "Center", "Bottom". |
bgType |
std::string |
"None" |
[Inherited] | Background type behind the ticker: "None", "Color", "Gradient". |
bgColor |
LCGColor |
"#000000" |
[Inherited] | Solid background fill color. |
bgGradientStartColor |
LCGColor |
"#FF0000" |
[Inherited] | Gradient starting color (top edge). |
bgGradientEndColor |
LCGColor |
"#000000" |
[Inherited] | Gradient ending color (bottom edge). |
bgAlpha |
int |
255 |
[Inherited] | Background block opacity (0 to 255). |
bgRadius |
int |
0 |
[Inherited] | Corner rounding radius for the background box (0 = square). |
bgShadowOffsetX |
float |
0.0f |
[Inherited] | Background drop shadow horizontal offset. |
bgShadowOffsetY |
float |
0.0f |
[Inherited] | Background drop shadow vertical offset. |
bgShadowAlpha |
int |
0 |
[Inherited] | Background drop shadow opacity (0 to 255). |
bgShadowColor |
LCGColor |
"#000000" |
[Inherited] | Background drop shadow color. |
borderColor |
LCGColor |
"#FFFFFF" |
[Inherited] | Background box border outline color. |
borderSize |
int |
0 |
[Inherited] | Background box border outline thickness in pixels (0 disables). |
borderAlpha |
int |
255 |
[Inherited] | Background box border outline opacity. |
textShadowOffsetX |
float |
0.0f |
[Inherited] | Text character drop shadow horizontal offset. |
textShadowOffsetY |
float |
0.0f |
[Inherited] | Text character drop shadow vertical offset. |
textShadowAlpha |
int |
0 |
[Inherited] | Text character shadow opacity (0 to 255). |
textShadowColor |
LCGColor |
"#000000" |
[Inherited] | Text character shadow color. |
textMove |
std::string |
"Up" |
[Ticker-only] | Rolling direction between pages: "Up" (default) or "Down". |
textMoveDuration |
float |
5.0f |
[Ticker-only] | Dwell time, in seconds, each line stays visible before triggering the transition. The transition itself is a fixed 0.5-second smooth slide. |
Format Example
LCGTickerProps ticker;
ticker.text = "Headline One\n"
"Headline Two\n"
"BREAKING %dateTime::HH:mm:ss%\n"
"Round %countup::600::mm:ss% elapsed"; // multi-page with dynamic tags
ticker.font = "Arial";
ticker.fontSize = 32;
ticker.color = "#FFFFFF";
ticker.bgType = "Color";
ticker.bgColor = "#001133";
ticker.bgAlpha = 230;
ticker.textMove = "Up";
ticker.textMoveDuration = 4.0f; // each page visible 4 s
Empty lines are skipped during rendering; if all lines evaluate to empty, a single empty placeholder line is drawn so the ticker box is never fully blank.
📌 LCGImageItem (Static Raster Image Overlay)
Defines a static raster image overlay with cropping, aspect-lock, and stretch support:
class NOW2SDK_EXPORT LCGImageItem : public LCGItem {
public:
LCGImageProps imageProps; // Image path and fit settings
};
LCGImageProps Struct
| Field | Type | Default Value | Description |
|---|---|---|---|
path |
std::string |
"" |
Path to local image file (.png, .jpg, .bmp, .webp, .tga) that will be loaded and scaled into the item bounds. PNGs are decoded natively via Cairo; other formats use FFmpeg. |
cropLeft |
int |
0 |
Pixels cropped from the left edge of the source image before scaling. |
cropTop |
int |
0 |
Pixels cropped from the top edge of the source image. |
cropRight |
int |
0 |
Pixels cropped from the right edge of the source image. |
cropBottom |
int |
0 |
Pixels cropped from the bottom edge of the source image. |
stretchMode |
int |
0 |
Layout mode: 0 Stretch, 1 Fit (letter-box), 2 Fill (crop-to-fit), 3 Original (no scale, draw 1:1). |
aspectLock |
bool |
true |
If true, the source aspect ratio is preserved when scaling into the item box. |
bgType |
std::string |
"None" |
Background panel behind the image: "None", "Color", "Gradient". |
bgColor |
LCGColor |
"#FFFFFF" |
Solid panel fill color. |
bgGradientStartColor |
LCGColor |
"#FFFFFF" |
Gradient starting color (top edge). |
bgGradientEndColor |
LCGColor |
"#000000" |
Gradient ending color (bottom edge). |
bgAlpha |
int |
255 |
Background panel opacity (0 to 255). |
bgRadius |
int |
0 |
Panel corner rounding radius (and image clip radius) in pixels. |
borderColor |
LCGColor |
"#FFFFFF" |
Border outline color. |
borderSize |
int |
0 |
Border outline thickness in pixels (0 disables). |
borderAlpha |
int |
255 |
Border outline opacity. |
bgShadowOffsetX |
float |
0.0f |
Background drop shadow horizontal offset. |
bgShadowOffsetY |
float |
0.0f |
Background drop shadow vertical offset. |
bgShadowAlpha |
int |
0 |
Background drop shadow opacity (0 to 255). |
bgShadowColor |
LCGColor |
"#000000" |
Background drop shadow color. |
📌 LCGImageSeqItem (Image Sequence / Stop-Motion Animation)
Loads all image files from a directory (*.png, *.jpg, *.jpeg, *.bmp, *.webp) and plays them back as a frame-locked sequence:
class NOW2SDK_EXPORT LCGImageSeqItem : public LCGItem {
public:
LCGImageSeqProps seqProps;
};
LCGImageSeqProps Struct
| Field | Type | Default Value | Description |
|---|---|---|---|
folder |
std::string |
"" |
Directory containing the sorted image sequence frames. Files are sorted alphabetically before playback. If the folder changes between updateItem calls, the frame list is rebuilt from scratch. |
fps |
double |
25.0 |
Playback frame rate of the sequence. Independent of the canvas m_fps. |
loop |
bool |
true |
If true, playback wraps back to the first frame after the last. If false, the last frame is held when the sequence ends. |
cropLeft |
int |
0 |
Pixels cropped from the left edge of each frame before scaling. |
cropTop |
int |
0 |
Pixels cropped from the top edge of each frame. |
cropRight |
int |
0 |
Pixels cropped from the right edge of each frame. |
cropBottom |
int |
0 |
Pixels cropped from the bottom edge of each frame. |
stretchMode |
int |
0 |
Layout mode: 0 Stretch, 1 Fit (letter-box), 2 Fill (crop-to-fit), 3 Original. |
aspectLock |
bool |
true |
If true, source aspect ratio is preserved when scaling into the item box. |
bgType |
std::string |
"None" |
Background panel behind the sequence: "None", "Color", "Gradient". |
bgColor |
LCGColor |
"#FFFFFF" |
Solid panel fill color. |
bgGradientStartColor |
LCGColor |
"#FFFFFF" |
Gradient starting color (top). |
bgGradientEndColor |
LCGColor |
"#000000" |
Gradient ending color (bottom). |
bgAlpha |
int |
255 |
Background panel opacity (0 to 255). |
bgRadius |
int |
0 |
Panel corner rounding radius (and image clip radius) in pixels. |
borderColor |
LCGColor |
"#FFFFFF" |
Border outline color. |
borderSize |
int |
0 |
Border outline thickness in pixels (0 disables). |
borderAlpha |
int |
255 |
Border outline opacity. |
bgShadowOffsetX |
float |
0.0f |
Background drop shadow horizontal offset. |
bgShadowOffsetY |
float |
0.0f |
Background drop shadow vertical offset. |
bgShadowAlpha |
int |
0 |
Background drop shadow opacity (0 to 255). |
bgShadowColor |
LCGColor |
"#000000" |
Background drop shadow color. |
📌 LCGVideoItem (Loopable Transparent Video)
Defines a loopable transparent video overlay:
class NOW2SDK_EXPORT LCGVideoItem : public LCGItem {
public:
LCGVideoProps videoProps;
};
LCGVideoProps Struct
| Field | Type | Default Value | Description |
|---|---|---|---|
path |
std::string |
"" |
Path to local transparent video file (.mov with alpha, .webm with alpha, ProRes 4444, etc.) that loops inside the item bounds. The decoder is opened synchronously inside addItem and returns nullptr if the file or video stream cannot be opened. |
cropLeft |
int |
0 |
Pixels cropped from the left edge of each decoded frame before scaling. |
cropTop |
int |
0 |
Pixels cropped from the top edge of each decoded frame. |
cropRight |
int |
0 |
Pixels cropped from the right edge of each decoded frame. |
cropBottom |
int |
0 |
Pixels cropped from the bottom edge of each decoded frame. |
stretchMode |
int |
0 |
Layout mode: 0 Stretch, 1 Fit (letter-box), 2 Fill (crop-to-fit), 3 Original. |
aspectLock |
bool |
true |
If true, decoded frame aspect ratio is preserved when scaling into the item box. |
bgType |
std::string |
"None" |
Background panel behind the video: "None", "Color", "Gradient". |
bgColor |
LCGColor |
"#FFFFFF" |
Solid panel fill color. |
bgGradientStartColor |
LCGColor |
"#FFFFFF" |
Gradient starting color (top). |
bgGradientEndColor |
LCGColor |
"#000000" |
Gradient ending color (bottom). |
bgAlpha |
int |
255 |
Background panel opacity (0 to 255). |
bgRadius |
int |
0 |
Panel corner rounding radius in pixels. |
borderColor |
LCGColor |
"#FFFFFF" |
Border outline color. |
borderSize |
int |
0 |
Border outline thickness in pixels (0 disables). |
borderAlpha |
int |
255 |
Border outline opacity. |
bgShadowOffsetX |
float |
0.0f |
Background drop shadow horizontal offset. |
bgShadowOffsetY |
float |
0.0f |
Background drop shadow vertical offset. |
bgShadowAlpha |
int |
0 |
Background drop shadow opacity (0 to 255). |
bgShadowColor |
LCGColor |
"#000000" |
Background drop shadow color. |
The decoder reads packets in the playback loop using the active m_fps value, scales each frame into BGRA, premultiplies alpha, and blits into the Cairo surface.
📌 LCGLiveItem (Live Source Overlay)
Binds to a registered LLive* source by name and displays its most recently decoded frame:
class NOW2SDK_EXPORT LCGLiveItem : public LCGItem {
public:
LCGLiveProps liveProps;
};
LCGLiveProps Struct
| Field | Type | Default Value | Description |
|---|---|---|---|
source |
LLive* |
nullptr |
Direct pointer to the LLive source this overlay should display. The render thread attaches the item's internal sink to source automatically on the next frame. If nullptr, the item renders empty. Pass the LLive* directly (object-based binding) — no separate registry call is needed. |
cropLeft |
int |
0 |
Pixels cropped from the left edge of each cached live frame before scaling. |
cropTop |
int |
0 |
Pixels cropped from the top edge of each cached live frame. |
cropRight |
int |
0 |
Pixels cropped from the right edge of each cached live frame. |
cropBottom |
int |
0 |
Pixels cropped from the bottom edge of each cached live frame. |
stretchMode |
int |
0 |
Layout mode: 0 Stretch, 1 Fit (letter-box), 2 Fill (crop-to-fit), 3 Original. |
aspectLock |
bool |
true |
If true, source aspect ratio is preserved when scaling into the item box. |
bgType |
std::string |
"None" |
Background panel behind the live frame: "None", "Color", "Gradient". |
bgColor |
LCGColor |
"#FFFFFF" |
Solid panel fill color. |
bgGradientStartColor |
LCGColor |
"#FFFFFF" |
Gradient starting color (top). |
bgGradientEndColor |
LCGColor |
"#000000" |
Gradient ending color (bottom). |
bgAlpha |
int |
255 |
Background panel opacity (0 to 255). |
bgRadius |
int |
0 |
Panel corner rounding radius in pixels. |
borderColor |
LCGColor |
"#FFFFFF" |
Border outline color. |
borderSize |
int |
0 |
Border outline thickness in pixels (0 disables). |
borderAlpha |
int |
255 |
Border outline opacity. |
bgShadowOffsetX |
float |
0.0f |
Background drop shadow horizontal offset. |
bgShadowOffsetY |
float |
0.0f |
Background drop shadow vertical offset. |
bgShadowAlpha |
int |
0 |
Background drop shadow opacity (0 to 255). |
bgShadowColor |
LCGColor |
"#000000" |
Background drop shadow color. |
XML persistence note:
saveToXMLFilewrites the boundLLive*address as a hex<sourcePtr>tag for in-process round-trip reference. AfterloadFromXMLFile, everyLCGLiveItem'ssourcefield is reset tonullptrbecause runtime pointers cannot be reconstructed from disk. Re-bind by callingaddItemorupdateItemwith the newLLive*after the load.
Each LCGLiveItem internally allocates an LCGLiveSink (LSink derivative) which is attached to the named LLive. The sink caches the latest decoded frame in a thread-safe manner; LCGLiveItem blits the cached frame each render tick.
📌 LCGRectItem (Vector Rectangle Shape)
Defines a vector rectangle block:
class NOW2SDK_EXPORT LCGRectItem : public LCGItem {
public:
LCGRectProps rectProps; // Rectangle styling properties
};
LCGRectProps Struct
| Field | Type | Default Value | Description |
|---|---|---|---|
bgType |
std::string |
"Solid" |
Fill type: "Solid" or "Gradient". |
bgColor |
LCGColor |
"#FFFFFF" |
Solid color fill. |
bgGradientStartColor |
LCGColor |
"#FFFFFF" |
Gradient starting color. |
bgGradientEndColor |
LCGColor |
"#000000" |
Gradient ending color. |
bgAlpha |
int |
255 |
Opacity (0 to 255). |
bgRadius |
int |
0 |
Corner rounding radius in pixels. |
borderColor |
LCGColor |
"#FFFFFF" |
Border outline color. |
borderSize |
int |
0 |
Border outline thickness in pixels. |
borderAlpha |
int |
255 |
Border outline opacity. |
bgShadowOffsetX |
float |
0.0f |
Background drop shadow horizontal offset. |
bgShadowOffsetY |
float |
0.0f |
Background drop shadow vertical offset. |
bgShadowAlpha |
int |
0 |
Background drop shadow opacity. |
bgShadowColor |
LCGColor |
"#000000" |
Background drop shadow color. |
📌 LCGCircleItem (Vector Circle / Ellipse Shape)
Defines a vector circle or ellipse. Same property surface as LCGRectItem with bgRadius reinterpreted as a percentage (0–100) of the shortest side for elliptical curvature:
class NOW2SDK_EXPORT LCGCircleItem : public LCGItem {
public:
LCGCircleProps circleProps;
};
LCGCircleProps Struct
| Field | Type | Default Value | Description |
|---|---|---|---|
bgType |
std::string |
"Solid" |
Fill type: "Solid" or "Gradient". |
bgColor |
LCGColor |
"#FFFFFF" |
Solid color fill. |
bgGradientStartColor |
LCGColor |
"#FFFFFF" |
Gradient starting color. |
bgGradientEndColor |
LCGColor |
"#000000" |
Gradient ending color. |
bgAlpha |
int |
255 |
Opacity (0 to 255). |
borderColor |
LCGColor |
"#FFFFFF" |
Border outline color. |
borderSize |
int |
0 |
Border outline thickness in pixels. |
borderAlpha |
int |
255 |
Border outline opacity. |
bgShadowOffsetX |
float |
0.0f |
Background drop shadow horizontal offset. |
bgShadowOffsetY |
float |
0.0f |
Background drop shadow vertical offset. |
bgShadowAlpha |
int |
0 |
Background drop shadow opacity. |
bgShadowColor |
LCGColor |
"#000000" |
Background drop shadow color. |
📌 LCGFlareItem (Animated Multi-Ray Lens Flare)
Generates an animated light-flare effect with a configurable number of rays, hotspot, fade, and sweep direction:
class NOW2SDK_EXPORT LCGFlareItem : public LCGItem {
public:
LCGFlareProps flareProps;
};
LCGFlareProps Struct
| Field | Type | Default Value | Description |
|---|---|---|---|
rayLength |
float |
200.0f |
Half-width of the flare's bounding box along the ray axis (pixels). |
wingStrength |
float |
20.0f |
Half-height of the rays perpendicular to the ray axis (pixels). |
centerHotspot |
float |
0.35f |
Center hotspot size as a fraction of rayLength (0.0 to 1.0). |
centerStretch |
float |
1.0f |
Horizontal stretch factor of the hotspot (0.1 to 10.0; 1.0 = perfect circle). |
cropLeft |
int |
0 |
Pixels hidden on the left edge of the rendered flare. |
cropTop |
int |
0 |
Pixels hidden on the top edge of the rendered flare. |
cropRight |
int |
0 |
Pixels hidden on the right edge of the rendered flare. |
cropBottom |
int |
0 |
Pixels hidden on the bottom edge of the rendered flare. |
brightness |
int |
220 |
Peak brightness (0 to 255). |
rotationSpeed |
float |
30.0f |
Rotation speed in degrees per second. |
angle |
int |
1 |
Number of duplicated rays spaced equally around 360° (1 to 12). |
horizontalFade |
float |
0.2f |
Per-edge horizontal fade (0.0 to 0.5). |
verticalFade |
float |
0.1f |
Per-edge vertical fade (0.0 to 0.5). |
color |
LCGColor |
"#FFEE88" |
Flare tint color. |
flowDirection |
int |
0 |
Sweep direction: 0 L→R, 1 R→L, 2 T→B, 3 B→T. Active when directionEnable = true. |
directionSpeed |
int |
2000 |
Time to traverse from one end to the other (milliseconds). |
directionLoopDelay |
float |
1.0f |
Wait time before the next sweep, in seconds. |
directionEnable |
bool |
false |
Toggles the flow animation around the canvas. |
5. Dynamic Tag Engine (Live Timers, Clocks & Counters)
Any text field on LCGTextItem, LCGCrawlItem, or LCGTickerItem (props.text / crawlProps.text / tickerProps.text) supports runtime interpolation through three tag families. The engine's processDynamicTags(itemId, rawText) is invoked once per render frame on every text-bearing item — there is no need to call updateItem to refresh the displayed value.
Reset rule: changing any of (itemId, type, targetSeconds, formatString) for a given tag restarts the timer from zero.
📌 dateTime:: — Live Clock & Calendar
Insert a literal dateTime::FORMAT token (surrounded by % on both sides) anywhere in the text field. The engine replaces it on every frame.
- Tokens (case-insensitive):
yyyy(4-digit year),MM(month),dd(day),HH/hh(24-hour hour),mm(minute),ss(second),ii(centisecond, 0–99). - Separators allowed inside the format:
:,-,or none.
LCGTextProps lowerThirdLine;
lowerThirdLine.text = std::string("ON AIR ") + "%dateTime::HH:mm:ss%"; // live broadcast clock
lowerThirdLine.text = std::string("Recorded: ") + "%dateTime::yyyy:MM:dd HH:mm:ss%"; // full stamp
LCGTextItem* liveClock = m_lCG->addItem("live_clock", 1500, 50, 380, 50, lowerThirdLine);
📌 countdown:: — Sports / Show Timer
Format: %countdown::INITIAL_SECONDS::FORMAT%
The engine starts a wall-clock timer the first time it sees this tag for a given (itemId, type, target, format) tuple. As soon as the timer hits zero it stays at 00:00.
Supported output formats: HH:mm:ss, mm:ss:ii, mm:ss, ss:ii, ss. Anything else falls back to mm:ss.
LCGTextProps gameClock;
gameClock.text = "Time Left: %countdown::90::mm:ss%"; // 90-second countdown, mm:ss
gameClock.text = "Round 2: %countdown::180::HH:mm:ss%"; // 3-minute round, HH:mm:ss
LCGTextItem* clock = m_lCG->addItem("game_clock", 100, 100, 400, 60, gameClock);
📌 countup:: — Elapsed Timer
Format: %countup::TARGET_SECONDS::FORMAT%
Counts up from zero and clamps at the target value (then freezes). Useful for on-air elapsed-time readouts.
LCGTextProps elapsed;
elapsed.text = "Elapsed: %countup::600::mm:ss%"; // counts up to 10 minutes, then holds
elapsed.font = "Arial"; elapsed.fontSize = 32; elapsed.color = "#FFFFFF";
LCGTextItem* showTimer = m_lCG->addItem("show_timer", 100, 200, 400, 60, elapsed);
6. Mixer & Live Source Integration Example
The following C++ example demonstrates how to integrate LCharacter inside LMixer to overlay branding elements (logo, scrolling crawl, lower-third with live countdown, animated image sequence, transparent video bumper, and live camera inset) on top of a video playback.
mainwindow.cpp
#include "mainwindow.h"
#include "now2sdk.h"
#include "LFile.h"
#include "LMixer.h"
#include "LPreview.h"
#include "LCharacter.h"
#include "LLive.h"
#include <QTimer>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
m_lFile(new LFile()),
m_lMixer(new LMixer()),
m_lCG(new LCharacter()),
m_lLive(new LLive()),
m_lPreview(new LPreview())
{
// 1. Configure Mixer Resolution (1080p50)
videoFormatProps format;
format.setVideoFormat = vF::HD1080_50p;
m_lMixer->setVideoFormat(format);
// 2. Add Background Video Layer (z-index: 0)
m_lMixer->addLayer("video_bg", m_lFile, 0, 0, 0, 255, 1920, 1080);
// 4. Add CG Character Generator Overlay Layer (z-index: 1)
m_lMixer->addLayer("cg_overlay", m_lCG, 1, 0, 0, 255, 1920, 1080);
// 5. Configure Preview Widget
m_lPreview->setProps("ui_framework", "qt");
m_lPreview->previewEnable(ui->programView, true, true);
m_lPreview->previewObject(m_lMixer);
// 6. Lock the composite FPS (50p for PAL, 60p for NTSC)
m_lCG->setFPS(50.0);
// 7. Load file and play
m_lFile->fileNameSet("/media/background.mp4");
m_lFile->play();
}
MainWindow::~MainWindow() {
m_lFile->stop();
delete m_lPreview;
delete m_lLive;
delete m_lFile;
delete m_lMixer;
delete m_lCG;
}
// ─── 1. Lower-Third with Live Countdown Clock ─────────────────────────────
void MainWindow::showLowerThird() {
m_lCG->remove("lt_bg");
m_lCG->remove("lt_title");
m_lCG->remove("lt_desc");
// Gradient background block
LCGRectProps bg;
bg.bgType = "Gradient";
bg.bgGradientStartColor = "#0055ff";
bg.bgGradientEndColor = "#020215";
bg.bgAlpha = 240;
bg.bgRadius = 12;
bg.bgShadowOffsetX = 4.0f;
bg.bgShadowOffsetY = 6.0f;
bg.bgShadowAlpha = 160;
bg.bgShadowColor = "#000000";
m_lCG->addItem("lt_bg", 150, 800, 700, 140, bg);
// Header
LCGTextItem* title = m_lCG->addItem("lt_title", 150, 800, 700, 70, LCGTextProps{});
title->props.text = "ALİ SABER";
title->props.font = "Courier New";
title->props.fontSize = 36;
title->props.color = "#FFFFFF";
title->props.outlineSize = 1;
title->props.outlineColor = "#000000";
title->props.hAlign = "Left";
title->props.padding = 20;
// Subtitle — interpolates the live timer on each frame
LCGTextItem* desc = m_lCG->addItem("lt_desc", 150, 870, 700, 60, LCGTextProps{});
desc->props.text = "Lead Broadcast Engineer | %countdown::90::mm:ss%";
desc->props.font = "Courier New";
desc->props.fontSize = 22;
desc->props.color = "#55AAFF";
desc->props.hAlign = "Left";
desc->props.padding = 20;
desc->props.autoShrink = true;
m_lCG->forceUpdate();
}
// ─── 2. Scrolling Crawl Ticker ─────────────────────────────────────────────
void MainWindow::showNewsTicker() {
m_lCG->remove("ticker");
LCGCrawlProps crawl;
crawl.text = "::: NOW2SDK CAIRO GRAPHICS ENGINE DEMO ::: EXTREMELY LOW LATENCY RASTERIZATION :::";
crawl.font = "Arial";
crawl.fontSize = 30;
crawl.color = "#FFFF00";
crawl.bgType = "Solid";
crawl.bgColor = "#111111";
crawl.bgAlpha = 220;
crawl.textMove = "Horizontal";
crawl.textSpeed = -4.0f; // negative = scroll left
m_lCG->addItem("ticker", 0, 980, 1920, 80, crawl);
m_lCG->forceUpdate();
}
// ─── 3. Vertical Rolling Ticker with Multiple Pages ────────────────────────
void MainWindow::showVerticalTicker() {
m_lCG->remove("vticker");
LCGTickerProps ticker;
ticker.text = "Headline One\nHeadline Two\nHeadline Three\nBreaking News";
ticker.font = "Arial";
ticker.fontSize = 32;
ticker.color = "#FFFFFF";
ticker.bgType = "Color";
ticker.bgColor = "#001133";
ticker.bgAlpha = 230;
ticker.textMove = "Up";
ticker.textMoveDuration = 4.0f; // each page visible for 4 s
m_lCG->addItem("vticker", 1620, 100, 280, 800, ticker);
m_lCG->forceUpdate();
}
// ─── 4. Stop-Motion Image Sequence Loader ─────────────────────────────────
void MainWindow::showImageSequence() {
m_lCG->remove("seq");
LCGImageSeqProps seq;
seq.folder = "/media/frames/intro";
seq.fps = 30.0;
seq.loop = true;
seq.aspectLock = true;
seq.stretchMode = 1; // Fit (letter-box)
m_lCG->addItem("seq", 760, 380, 400, 320, seq);
m_lCG->forceUpdate();
}
// ─── 5. Transparent Video Bumper (ProRes 4444 / WebM alpha) ───────────────
void MainWindow::showTransparentBumper() {
m_lCG->remove("bumper");
LCGVideoProps vid;
vid.path = "/media/bumper_alpha.mov";
vid.aspectLock = true;
vid.stretchMode = 0; // Stretch
vid.loop = true;
m_lCG->addItem("bumper", 0, 0, 1920, 1080, vid);
m_lCG->forceUpdate();
}
// ─── 5b. Static Raster Image (logo PNG with rounded clip + border) ──────
void MainWindow::showLogo() {
m_lCG->remove("logo");
LCGImageProps logo;
logo.path = "/media/brand/logo.png";
logo.stretchMode = 0; // Stretch
logo.aspectLock = true;
logo.bgRadius = 16; // rounded clip mask
logo.borderSize = 2;
logo.borderColor = "#FFFFFF";
logo.borderAlpha = 255;
logo.bgShadowOffsetX = 3.0f;
logo.bgShadowOffsetY = 3.0f;
logo.bgShadowAlpha = 160;
logo.bgShadowColor = "#000000";
m_lCG->addItem("logo", 50, 50, 220, 80, logo); // 50,50 = top-left coords
m_lCG->forceUpdate();
}
// ─── 5c. Vector Circle Element (round badge with gradient) ──────────────
void MainWindow::showCircleBadge() {
m_lCG->remove("badge");
LCGCircleProps circle;
circle.bgType = "Gradient";
circle.bgColor = "#FFFFFF";
circle.bgGradientStartColor = "#FF5500";
circle.bgGradientEndColor = "#880000";
circle.bgAlpha = 230;
circle.borderSize = 3;
circle.borderColor = "#FFFFFF";
circle.borderAlpha = 255;
m_lCG->addItem("badge", 1820, 60, 80, 80, circle);
m_lCG->forceUpdate();
}
// ─── 5d. Lens Flare (animated 6-ray flare with hotspot) ─────────────────
void MainWindow::showLensFlare() {
m_lCG->remove("flare");
LCGFlareProps flare;
flare.rayLength = 240.0f;
flare.wingStrength = 28.0f;
flare.centerHotspot = 0.40f;
flare.centerStretch = 1.0f;
flare.brightness = 230;
flare.rotationSpeed = 40.0f; // degrees / second
flare.angle = 6; // 6 rays around 360°
flare.horizontalFade = 0.2f;
flare.verticalFade = 0.1f;
flare.color = "#FFEE88";
flare.directionEnable = true;
flare.flowDirection = 0; // L -> R
flare.directionSpeed = 2500;
flare.directionLoopDelay = 0.5f;
m_lCG->addItem("flare", 760, 420, 400, 240, flare);
m_lCG->forceUpdate();
}
// ─── 6. Live Camera Inset (LLive source pulled live) ──────────────────────
void MainWindow::showLiveInset() {
// 1. Pick a real device / channel / format reported by the SDK, then Start() capture.
int devCount = 0; m_lLive->DeviceGetCount(devCount);
if (devCount > 0) {
std::string devName, devDesc;
m_lLive->DeviceGetByIndex(0, devName, devDesc);
m_lLive->DeviceSet(0); // select device 0
int chCount = 0; m_lLive->DeviceChannelGetCount(0, chCount);
if (chCount > 0) m_lLive->DeviceChannelSet(0); // select channel 0
videoFormatProps vidFormat; std::string fmtName;
int fmtCount = 0; m_lLive->DeviceFormatVideoGetCount(0, 0, fmtCount);
if (fmtCount > 0) m_lLive->DeviceFormatVideoSet(0); // first available mode
m_lLive->Start(); // start the capture thread
}
m_lCG->remove("livecam");
// 2. Object-based binding: just hand the LLive* to LCGLiveProps.source.
// No registry call required — the engine attaches the sink on the next
// render frame and detaches it on remove() / clear() / destruction.
LCGLiveProps live;
live.source = m_lLive; // direct LLive* binding
live.aspectLock = true;
live.stretchMode = 1; // Fit
live.borderSize = 4;
live.borderColor = "#FFCC00";
live.borderAlpha = 255;
live.bgRadius = 24;
m_lCG->addItem("livecam", 1480, 700, 360, 240, live);
m_lCG->forceUpdate();
}
// ─── 7. Group Multiple Items for Bulk Translation ─────────────────────────
void MainWindow::groupLowerThird() {
std::vector<std::string> ids = { "lt_bg", "lt_title", "lt_desc" };
std::string gid = m_lCG->group(ids);
LCGGroup* g = m_lCG->getGroupObject(gid);
if (g) { g->x = 0; g->y = 0; } // anchor to current position
m_lCG->forceUpdate();
}
// ─── 8. Save / Load CG Templates to XML ───────────────────────────────────
void MainWindow::exportTemplate() {
m_lCG->saveToXMLFile("/templates/lower_third_branding.xml");
}
void MainWindow::importTemplate() {
m_lCG->loadFromXMLFile("/templates/lower_third_branding.xml");
m_lCG->forceUpdate();
}
// ─── 9. Clear CG overlays ─────────────────────────────────────────────────
void MainWindow::clearOverlays() {
m_lCG->remove("lt_bg");
m_lCG->remove("lt_title");
m_lCG->remove("lt_desc");
m_lCG->remove("ticker");
m_lCG->remove("vticker");
m_lCG->remove("seq");
m_lCG->remove("bumper");
m_lCG->remove("logo");
m_lCG->remove("badge");
m_lCG->remove("flare");
m_lCG->remove("livecam");
m_lCG->forceUpdate();
}