Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions bbb_presentation_video/renderer/presentation.py
Copy link
Contributor

@kepstin kepstin Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change appears to be unrelated.

For compatibility reasons with older BBB versions, the pan/zoom of a slide needs to be preserved when switching back to a previously used slide. There is a lot of code in the tool which is there just to preserve the pan/zoom and this change is a hack job that causes that code to still run, but no longer be functional.

Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ def update_slide(self, event: events.SlideEvent) -> None:
if self.presentation is not None:
self.presentation_slide[self.presentation] = self.slide
self.slide_changed = True
# Pan and zoom resets when switching slides
self.pan = Position(0.0, 0.0)
self.zoom = Size(1.0, 1.0)
self.pan_zoom_changed = True
print(f"\tPresentation: slide: {self.slide}")

def update_pan_zoom(self, event: events.PanZoomEvent) -> None:
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
11 changes: 7 additions & 4 deletions bbb_presentation_video/renderer/tldraw/shape/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,14 @@ def show_layout_by_lines(
*,
padding: float = 0,
do_path: bool = False,
line_height_multiplier: float = 1.0,
) -> None:
"""Show a Pango Layout line by line to manually handle CSS-style line height."""
# TODO: With Pango 1.50 this can be replaced with Pango.attr_line_height_new_absolute

font = layout.get_font_description()
# Assuming CSS "line-height: 1;" - i.e. line height = font size
line_height = font.get_size() / Pango.SCALE
# CSS line-height as a multiplier of font size (1.0 = tldraw v1, 1.35 = tldraw v2)
line_height = font.get_size() / Pango.SCALE * line_height_multiplier

ctx.save()
ctx.translate(padding, padding)
Expand Down Expand Up @@ -145,14 +146,16 @@ def show_layout_by_lines(
ctx.restore()


def get_layout_size(layout: Pango.Layout, *, padding: float = 0) -> Size:
def get_layout_size(
layout: Pango.Layout, *, padding: float = 0, line_height_multiplier: float = 1.0
) -> Size:
# TODO: Once we switch to Pango 1.50 and use Pango.attr_line_height_new_absolute this can
# be replaced with a call to layout.get_size()
layout_size = layout.get_size()
width = layout_size[0] / Pango.SCALE
lines = layout.get_line_count()
font = layout.get_font_description()
line_height = font.get_size() / Pango.SCALE
line_height = font.get_size() / Pango.SCALE * line_height_multiplier
height = lines * line_height
return Size(width + padding * 2, height + padding * 2)

Expand Down
24 changes: 14 additions & 10 deletions bbb_presentation_video/renderer/tldraw/shape/text_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
)

TEXT_OUTLINE_WIDTH: float = 2.0
# tldraw v2 line height multiplier (from bbb-export-annotations/shapes/TextShape.js)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please find a reference in the actual client rendering code, not the bbb-export-annotations code.

V2_LINE_HEIGHT: float = 1.35

CairoSomeSurface = TypeVar("CairoSomeSurface", bound=cairo.Surface)

Expand All @@ -53,21 +55,23 @@ def finalize_v2_text(
# be blended with alpha afterwards
ctx.push_group()

layout = create_pango_layout(ctx, style, font_size)
# Use the shape's width to constrain text wrapping, matching the tldraw client
text_width = shape.size.width if shape.size.width > 0 else None
layout = create_pango_layout(ctx, style, font_size, width=text_width)
layout.set_text(shape.text, -1)

# Draw text border (outside stroke)
ctx.save()
ctx.set_source_rgb(*CANVAS)
ctx.set_line_width(TEXT_OUTLINE_WIDTH * 2)
ctx.set_line_join(cairo.LINE_JOIN_ROUND)
show_layout_by_lines(ctx, layout, padding=4, do_path=True)
show_layout_by_lines(ctx, layout, padding=4, do_path=True, line_height_multiplier=V2_LINE_HEIGHT)
ctx.stroke()
ctx.restore()

# Draw text
ctx.set_source_rgb(*stroke)
show_layout_by_lines(ctx, layout, padding=4)
show_layout_by_lines(ctx, layout, padding=4, line_height_multiplier=V2_LINE_HEIGHT)

# Composite result with opacity applied
ctx.pop_group_to_source()
Expand Down Expand Up @@ -100,7 +104,7 @@ def finalize_v2_label(
)
layout.set_text(shape.label, -1)

label_size = get_layout_size(layout, padding=4)
label_size = get_layout_size(layout, padding=4, line_height_multiplier=V2_LINE_HEIGHT)
bounds = shape.size

if offset is None:
Expand All @@ -123,13 +127,13 @@ def finalize_v2_label(
ctx.set_source_rgb(*CANVAS)
ctx.set_line_width(TEXT_OUTLINE_WIDTH * 2)
ctx.set_line_join(cairo.LINE_JOIN_ROUND)
show_layout_by_lines(ctx, layout, padding=4, do_path=True)
show_layout_by_lines(ctx, layout, padding=4, do_path=True, line_height_multiplier=V2_LINE_HEIGHT)
ctx.stroke()
ctx.restore()

# Draw the original text on top
ctx.set_source_rgb(*stroke)
show_layout_by_lines(ctx, layout, padding=4)
show_layout_by_lines(ctx, layout, padding=4, line_height_multiplier=V2_LINE_HEIGHT)

# Composite result with opacity applied
ctx.pop_group_to_source()
Expand Down Expand Up @@ -166,14 +170,14 @@ def finalize_frame_name(

layout.set_text(shape.label, -1)

label_size = get_layout_size(layout, padding=4)
label_size = get_layout_size(layout, padding=4, line_height_multiplier=V2_LINE_HEIGHT)

x = 0
y = -20
ctx.translate(x, y)
ctx.set_source_rgba(stroke.r, stroke.g, stroke.b, style.opacity)

show_layout_by_lines(ctx, layout, padding=4)
show_layout_by_lines(ctx, layout, padding=4, line_height_multiplier=V2_LINE_HEIGHT)

ctx.restore()

Expand All @@ -200,7 +204,7 @@ def finalize_sticky_text_v2(
layout.set_text(shape.text, -1)

# Calculate vertical position to center the text
_, text_height = get_layout_size(layout, padding=STICKY_PADDING)
_, text_height = get_layout_size(layout, padding=STICKY_PADDING, line_height_multiplier=V2_LINE_HEIGHT)
x, y = ctx.get_current_point()

if shape.verticalAlign is AlignStyle.MIDDLE:
Expand All @@ -212,4 +216,4 @@ def finalize_sticky_text_v2(
ctx.set_source_rgba(
STICKY_TEXT_COLOR.r, STICKY_TEXT_COLOR.g, STICKY_TEXT_COLOR.b, style.opacity
)
show_layout_by_lines(ctx, layout, padding=STICKY_PADDING)
show_layout_by_lines(ctx, layout, padding=STICKY_PADDING, line_height_multiplier=V2_LINE_HEIGHT)
18 changes: 10 additions & 8 deletions bbb_presentation_video/renderer/tldraw/utils.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes made here break compatibility with processing recordings made with tldraw v1. Recording processing needs to be backwards compatible.

Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,13 @@ class SizeStyle(Enum):

FONT_SIZES: Dict[SizeStyle, float] = {
SizeStyle.SMALL: 28,
SizeStyle.S: 26,
SizeStyle.MEDIUM: 48,
SizeStyle.M: 36,
SizeStyle.LARGE: 96,
SizeStyle.L: 54,
SizeStyle.XL: 64,
# tldraw v2 text font sizes (from bbb-export-annotations/shapes/Shape.js)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please find a reference in the BBB client code for the font sizes, not bbb-export-annotations.

SizeStyle.S: 18,
SizeStyle.M: 24,
SizeStyle.L: 36,
SizeStyle.XL: 44,
}

STICKY_FONT_SIZES: Dict[SizeStyle, float] = {
Expand Down Expand Up @@ -273,12 +274,13 @@ class FontStyle(Enum):

FONT_FACES: Dict[FontStyle, str] = {
FontStyle.SCRIPT: "Caveat Brush",
FontStyle.SANS: "Source Sans Pro",
FontStyle.ERIF: "Crimson Pro",
FontStyle.SERIF: "Crimson Pro",
FontStyle.MONO: "Source Code Pro",
FontStyle.DRAW: "Caveat Brush",
FontStyle.ARIAL: "Arial",
# tldraw v2 fonts (from bigbluebutton-html5 whiteboard/service.js)
FontStyle.SANS: "IBM Plex Sans",
FontStyle.SERIF: "IBM Plex Serif",
FontStyle.MONO: "IBM Plex Mono",
FontStyle.DRAW: "Shantell Sans",
}


Expand Down
Loading