Skip to main content

ass_renderer/layout/
context.rs

1//! Layout context for positioning calculations
2
3use super::{Alignment, TextMetrics};
4
5/// Layout context for positioning calculations
6pub struct LayoutContext {
7    pub screen_width: f32,
8    pub screen_height: f32,
9    pub margin_left: f32,
10    pub margin_right: f32,
11    pub margin_vertical: f32,
12    pub play_res_x: f32,
13    pub play_res_y: f32,
14}
15
16impl LayoutContext {
17    pub fn new(screen_width: f32, screen_height: f32) -> Self {
18        Self {
19            screen_width,
20            screen_height,
21            margin_left: 0.0,
22            margin_right: 0.0,
23            margin_vertical: 0.0,
24            play_res_x: screen_width,
25            play_res_y: screen_height,
26        }
27    }
28
29    /// Calculate position for text with given alignment and metrics
30    pub fn calculate_position(&self, alignment: Alignment, metrics: &TextMetrics) -> (f32, f32) {
31        // In ASS/SSA, the position is where the text glyph paths start
32        // For proper centering, we need to account for text dimensions
33
34        // Calculate horizontal position (left edge of text bounding box)
35        let x = match alignment {
36            Alignment::BottomLeft | Alignment::MiddleLeft | Alignment::TopLeft => {
37                // Left alignment - text starts at left margin
38                self.margin_left
39            }
40            Alignment::BottomCenter | Alignment::Center | Alignment::TopCenter => {
41                // Center alignment - center the text horizontally
42                // This should put the left edge at center minus half width
43                (self.screen_width / 2.0) - (metrics.width / 2.0)
44            }
45            Alignment::BottomRight | Alignment::MiddleRight | Alignment::TopRight => {
46                // Right alignment - text ends at right margin
47                self.screen_width - self.margin_right - metrics.width
48            }
49        };
50
51        // Calculate vertical position (top edge of text bounding box)
52        // The glyphs are drawn from their top-left corner typically
53        let y = match alignment {
54            Alignment::TopLeft | Alignment::TopCenter | Alignment::TopRight => {
55                // Top alignment - text at top margin
56                self.margin_vertical
57            }
58            Alignment::MiddleLeft | Alignment::Center | Alignment::MiddleRight => {
59                // Middle alignment - center vertically
60                (self.screen_height / 2.0) - (metrics.height / 2.0)
61            }
62            Alignment::BottomLeft | Alignment::BottomCenter | Alignment::BottomRight => {
63                // Bottom alignment - text bottom at bottom margin
64                self.screen_height - self.margin_vertical - metrics.height
65            }
66        };
67
68        (x, y)
69    }
70
71    /// Apply PlayResX/PlayResY scaling
72    pub fn apply_play_res_scaling(&self, x: f32, y: f32) -> (f32, f32) {
73        let scale_x = self.screen_width / self.play_res_x;
74        let scale_y = self.screen_height / self.play_res_y;
75        (x * scale_x, y * scale_y)
76    }
77}