Skip to main content

atmos/os_lib/layout/
resize_observer.rs

1//! Resize Observer 寸法計算モジュール (W3C Resize Observer Level 1)
2//!
3//! 要素のボーダーボックス、コンテンツボックス、およびデバイスピクセル単位寸法の
4//! 導出と、差分検知(`has_size_changed`)を提供する。
5
6/// `ResizeObserver.observe()` の `box` オプション
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum ResizeObserverBoxOptions {
9    ContentBox,
10    BorderBox,
11    DevicePixelContentBox,
12}
13
14impl ResizeObserverBoxOptions {
15    pub fn parse(s: &str) -> Self {
16        match s.trim() {
17            "border-box" => Self::BorderBox,
18            "device-pixel-content-box" => Self::DevicePixelContentBox,
19            _ => Self::ContentBox, // 既定値
20        }
21    }
22}
23
24/// 算出された各ボックス寸法
25#[derive(Debug, Clone, Copy, PartialEq)]
26pub struct ResizeBoxDimensions {
27    pub border_box_inline_size: f64,
28    pub border_box_block_size: f64,
29    pub content_box_inline_size: f64,
30    pub content_box_block_size: f64,
31    pub device_pixel_content_box_inline_size: f64,
32    pub device_pixel_content_box_block_size: f64,
33    pub content_rect_x: f64,
34    pub content_rect_y: f64,
35    pub content_rect_width: f64,
36    pub content_rect_height: f64,
37}
38
39/// 各種パディングとボーダーから各ボックス寸法を計算する
40#[allow(clippy::too_many_arguments)]
41pub fn compute_resize_boxes(
42    border_w: f64,
43    border_h: f64,
44    padding_top: f64,
45    padding_right: f64,
46    padding_bottom: f64,
47    padding_left: f64,
48    border_top: f64,
49    border_right: f64,
50    border_bottom: f64,
51    border_left: f64,
52) -> ResizeBoxDimensions {
53    let content_w =
54        (border_w - padding_left - padding_right - border_left - border_right).max(0.0);
55    let content_h =
56        (border_h - padding_top - padding_bottom - border_top - border_bottom).max(0.0);
57    let content_x = padding_left + border_left;
58    let content_y = padding_top + border_top;
59
60    // AtmOS では window.devicePixelRatio が 1.0 固定
61    let dpr = 1.0;
62
63    ResizeBoxDimensions {
64        border_box_inline_size: border_w.max(0.0),
65        border_box_block_size: border_h.max(0.0),
66        content_box_inline_size: content_w,
67        content_box_block_size: content_h,
68        device_pixel_content_box_inline_size: content_w * dpr,
69        device_pixel_content_box_block_size: content_h * dpr,
70        content_rect_x: content_x,
71        content_rect_y: content_y,
72        content_rect_width: content_w,
73        content_rect_height: content_h,
74    }
75}
76
77/// 前回の寸法と今回の寸法の間で変化があったかを判定
78#[inline]
79pub fn has_size_changed(
80    last_inline: f64,
81    last_block: f64,
82    current_inline: f64,
83    current_block: f64,
84) -> bool {
85    (last_inline - current_inline).abs() >= 1e-5 || (last_block - current_block).abs() >= 1e-5
86}