Repository: typst/typst
File: crates/typst-library/src/layout/ratio.rs (Rust)

Code before:
/// Here the block width is set to `{250pt}` (just to demonstrate the use of
/// ratio with containers), and inside of it the rectangle width is set to
/// `{25%}`, which means "get 25% of the width of the innermost container" (240
/// ⋅ 0.25 = 60). The reason it shows `{50pt}` instead of `{60pt}` is due to
/// the default value of inset. If we set it to `{0pt}`, then we will get
/// the expected result (although the number will be cramped):
///
/// ```example
/// #block(width: 240pt, {
///   rect(width: 25%, inset: 0pt, layout(size => size.width))
/// })
/// ```
///
/// If you are trying to use the page width/height's value as the base for the
/// ratio, then the value is equal to the width/height of the page minus the
/// margins (left and right for width, top and bottom for height). To force
/// Typst to use the full length you have a few options (this highly depends on
/// your exact use case):
///
/// 1. set page margins to `{0pt}` (`#set page(margin: 0pt)`)
/// 2. multiply by a full length value (`{21cm * 69%}`)
/// 3. use padding which will negate the margins (`#pad(x: -2.5cm, ...)`)
/// 4. use page [background](page.background)/[foreground](page.foreground)
///    field that doesn't use the margins (note that it will render the content
///    outside of the document flow, see [place] to control the content
///    position)
///
/// However, within your own code, you can use ratios as you'd like. You can
/// multiply ratio by ratio, [length], [relative length](relative), [angle],
/// [int], [float], and [fraction].
///
/// # Example
/// ```example
/// #set align(center)
/// #scale(x: 150%)[
///   Scaled apart.
/// ]
/// ```
#[ty(cast)]
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Ratio(Scalar);

impl Ratio {
    /// A ratio of `0%` represented as `0.0`.
    pub const fn zero() -> Self {
        Self(Scalar::ZERO)
    }

    /// A ratio of `100%` represented as `1.0`.
    pub const fn one() -> Self {
        Self(Scalar::ONE)

Review comment (suggestion):
I see now that this feels a bit out of place... Perhaps we could keep this level of detail to relative length docs instead, and link to it explicitly (e.g. "see (link) for more details").

Code after:
/// they enclose.
///
/// # Scripting
/// Within your own code, you can use ratios as you like. You can multiply them
/// with various other types as shown below:
///
/// |  Multiply by    |  Example                | Result          |
/// |-----------------|-------------------------|-----------------|
/// | [`ratio`]       | `{27% * 10%}`           | `{2.7%}`        |
/// | [`length`]      | `{27% * 100pt}`         | `{27pt}`        |
/// | [`relative`]    | `{27% * (10% + 100pt)}` | `{2.7% + 27pt}` |
/// | [`angle`]       | `{27% * 100deg}`        | `{27deg}`       |
/// | [`int`]         | `{27% * 2}`             | `{54%}`         |
/// | [`float`]       | `{27% * 0.37037}`       | `{10%}`         |
/// | [`fraction`]    | `{27% * 3fr}`           | `{0.81fr}`      |
///
/// When ratios are displayed in the document, they are rounded to two
/// significant digits for readability.
#[ty(cast)]
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Ratio(Scalar);

impl Ratio {
    /// A ratio of `0%` represented as `0.0`.
    pub const fn zero() -> Self {
        Self(Scalar::ZERO)
    }

    /// A ratio of `100%` represented as `1.0`.
    pub const fn one() -> Self {
        Self(Scalar::ONE)
    }

    /// Create a new ratio from a value, where `1.0` means `100%`.
    pub const fn new(ratio: f64) -> Self {
        Self(Scalar::new(ratio))
    }

    /// Get the underlying ratio.
    pub const fn get(self) -> f64 {
        (self.0).get()
    }

    /// Whether the ratio is zero.
    pub fn is_zero(self) -> bool {
        self.0 == 0.0
    }

    /// Whether the ratio is one.
    pub fn is_one(self) -> bool {
        self.0 == 1.0