#pdflite/geometry

    moonbitlang/pdflite/geometry defines PDF units, paper sizes, 2D points, and affine transform matrices. The root package re-exports these helpers for page construction, but this package is the focused place for geometry-only code.

    flowchart LR Units[PdfUnit] --> Paper[PaperSize] Paper --> PageBox[page MediaBox] Point[Point2] --> Matrix[TransformMatrix] Ops[TransformOp list] --> Matrix Matrix --> PointOut[transformed point]

    #Checked Examples

    ///|
    test "paper sizes and units are explicit" {
    if @geometry.paper_a4.unit() != Millimetre {
    fail("A4 is stored in millimetres")
    }
    if @geometry.unit_points(1.0, Inch) != 72.0 {
    fail("one inch is 72 PDF points")
    }
    let landscape = @geometry.paper_a4.landscape()
    if landscape.width() != 297.0 || landscape.height() != 210.0 {
    fail("landscape swaps paper width and height")
    }
    }

    ///|
    test "transforms apply to points and render as PDF matrices" {
    let moved = @geometry.transform_translate(5.0, -10.0).apply(
    @geometry.point2(10.0, 20.0),
    )
    if moved.x != 15.0 || moved.y != 10.0 {
    fail("translation should move the point")
    }
    inspect(
    @geometry.transform_string_of_matrix(
    @geometry.transform_translate(5.0, -10.0),
    ),
    content="1, 0, 0, 1, 5, -10",
    )
    }

    #Package Notes

    • PaperSize keeps both dimensions and their original unit.
    • TransformMatrix uses the PDF six-number affine matrix layout.
    • TransformOp preserves CamlPDF-style transform-list ordering for callers that build or inspect transformation pipelines.

    #Pedantic Boundaries

    • This package owns unit conversion and affine transform math only. It does not inspect page dictionaries, content streams, or resources.
    • Units are explicit: PaperSize stores its source unit, while page code converts to PDF points when constructing /MediaBox.
    • Transform matrices follow PDF's six-number convention (a b c d e f). Composition order must be tested with points, not only by comparing matrix fields.
    • Singular matrices raise the shared PdfError::MatrixNotInvertable through the core dependency.

    #Verification Notes

    • README examples are blackbox tests for public geometry APIs.
    • Use exact assertions for simple unit conversions and tolerance-based tests for rotations or decompositions.
    • Run moon test geometry/README.mbt.md after editing this file.
    • Run moon info before review; this README should not change geometry/pkg.generated.mbti.

    PdfError

    Error variants raised by pdflite parsing, writing, filtering, text, and encryption APIs.

    The variants intentionally stay specific enough for tests and callers to distinguish malformed input classes, while most public APIs expose them through the ordinary raise PdfError flow.

    PaperSize

    pub(all) struct PaperSize {
    unit : PdfUnit
    width : Double
    height : Double
    } derive(Eq, ToJson,
    Debug
    )

    A paper size expressed in a declared unit.

    Width and height are stored as given; conversion to PDF points happens at page-construction boundaries.

    PaperSize::equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PaperSize::equal(PaperSize, PaperSize) -> Bool

    PaperSize::height

    fn PaperSize::height(self : PaperSize) -> Double

    Returns the paper height in this size's unit.

    PaperSize::landscape

    fn PaperSize::landscape(self : PaperSize) -> PaperSize

    Returns the same paper dimensions with width and height swapped.

    PaperSize::not_equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PaperSize::not_equal(x : PaperSize, y : PaperSize) -> Bool

    PaperSize::to_json

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PaperSize::to_json(PaperSize) -> Json

    PaperSize::to_repr

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PaperSize::to_repr(PaperSize) ->
    Repr

    PaperSize::unit

    fn PaperSize::unit(self : PaperSize) -> PdfUnit

    Returns the unit used by this paper size.

    PaperSize::width

    fn PaperSize::width(self : PaperSize) -> Double

    Returns the paper width in this size's unit.

    PdfCalculatedPosition

    pub(all) struct PdfCalculatedPosition {
    x : Double
    y : Double
    rotation : Double
    } derive(Eq, ToJson,
    Debug
    )

    Absolute placement calculated from a position keyword and page bounds.

    PdfCalculatedPosition::equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfCalculatedPosition::equal(PdfCalculatedPosition, PdfCalculatedPosition) -> Bool

    PdfCalculatedPosition::not_equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfCalculatedPosition::not_equal(x : PdfCalculatedPosition, y : PdfCalculatedPosition) -> Bool

    PdfCalculatedPosition::to_json

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfCalculatedPosition::to_json(PdfCalculatedPosition) -> Json

    PdfCalculatedPosition::to_repr

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfCalculatedPosition::to_repr(PdfCalculatedPosition) ->
    Repr

    PdfCoordRectangle

    pub(all) struct PdfCoordRectangle {
    x : Double
    y : Double
    width : Double
    height : Double
    } derive(Eq, ToJson,
    Debug
    )

    A cpdf coordinate rectangle: origin plus width and height.

    PdfCoordRectangle::equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfCoordRectangle::equal(PdfCoordRectangle, PdfCoordRectangle) -> Bool

    PdfCoordRectangle::not_equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfCoordRectangle::not_equal(x : PdfCoordRectangle, y : PdfCoordRectangle) -> Bool

    PdfCoordRectangle::to_json

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfCoordRectangle::to_json(PdfCoordRectangle) -> Json

    PdfCoordRectangle::to_repr

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfCoordRectangle::to_repr(PdfCoordRectangle) ->
    Repr

    PdfPosition

    pub(all) enum PdfPosition {
    PdfPositionPosCentre(Double, Double)
    PdfPositionPosLeft(Double, Double)
    PdfPositionPosRight(Double, Double)
    PdfPositionTop(Double)
    PdfPositionTopLeft(Double, Double)
    PdfPositionTopRight(Double, Double)
    PdfPositionLeft(Double)
    PdfPositionBottomLeft(Double, Double)
    PdfPositionBottom(Double)
    PdfPositionBottomRight(Double, Double)
    PdfPositionRight(Double)
    PdfPositionDiagonal
    PdfPositionReverseDiagonal
    PdfPositionCentre
    } derive(Eq, ToJson,
    Debug
    )

    Position keywords used by cpdf-style text and layout operations.

    PdfPosition::equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfPosition::equal(PdfPosition, PdfPosition) -> Bool

    PdfPosition::not_equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfPosition::not_equal(x : PdfPosition, y : PdfPosition) -> Bool

    PdfPosition::to_json

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfPosition::to_json(PdfPosition) -> Json

    PdfPosition::to_repr

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfPosition::to_repr(PdfPosition) ->
    Repr

    PdfRectangle

    pub(all) struct PdfRectangle {
    min_x : Double
    min_y : Double
    max_x : Double
    max_y : Double
    } derive(Eq, ToJson,
    Debug
    )

    A normalized rectangle in PDF user-space coordinates.

    min_x and min_y are always the lower bounds, and max_x and max_y are always the upper bounds. Parsers normalize PDF rectangle arrays whose coordinates are written in the opposite order.

    PdfRectangle::equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfRectangle::equal(PdfRectangle, PdfRectangle) -> Bool

    PdfRectangle::not_equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfRectangle::not_equal(x : PdfRectangle, y : PdfRectangle) -> Bool

    PdfRectangle::to_json

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfRectangle::to_json(PdfRectangle) -> Json

    PdfRectangle::to_repr

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfRectangle::to_repr(PdfRectangle) ->
    Repr

    PdfUnit

    pub(all) enum PdfUnit {
    PdfPoint
    Inch
    Centimetre
    Millimetre
    } derive(Eq, ToJson,
    Debug
    )

    Units accepted by page and geometry helpers.

    PDF coordinates are ultimately expressed in points, but the public API keeps common paper and layout units explicit at call sites.

    PdfUnit::equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfUnit::equal(PdfUnit, PdfUnit) -> Bool

    PdfUnit::not_equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfUnit::not_equal(x : PdfUnit, y : PdfUnit) -> Bool

    PdfUnit::to_json

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfUnit::to_json(PdfUnit) -> Json

    PdfUnit::to_repr

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfUnit::to_repr(PdfUnit) ->
    Repr

    Point2

    pub(all) struct Point2 {
    x : Double
    y : Double
    } derive(Eq, ToJson,
    Debug
    )

    A two-dimensional point in PDF user-space coordinates.

    Point2::equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn Point2::equal(Point2, Point2) -> Bool

    Point2::not_equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn Point2::not_equal(x : Point2, y : Point2) -> Bool

    Point2::to_json

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn Point2::to_json(Point2) -> Json

    Point2::to_repr

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn Point2::to_repr(Point2) ->
    Repr

    TransformDecomposition

    pub(all) struct TransformDecomposition {
    scale : Double
    aspect : Double
    rotation : Double
    shear : Double
    translate_x : Double
    translate_y : Double
    } derive(Eq, ToJson,
    Debug
    )

    The decomposed components of an affine transform matrix.

    Values are expressed as scale, aspect ratio, rotation, shear, and translation components suitable for recomposition.

    TransformDecomposition::equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn TransformDecomposition::equal(TransformDecomposition, TransformDecomposition) -> Bool

    TransformDecomposition::not_equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn TransformDecomposition::not_equal(x : TransformDecomposition, y : TransformDecomposition) -> Bool

    TransformDecomposition::to_json

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn TransformDecomposition::to_json(TransformDecomposition) -> Json

    TransformDecomposition::to_repr

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn TransformDecomposition::to_repr(TransformDecomposition) ->
    Repr

    TransformMatrix

    pub(all) struct TransformMatrix {
    a : Double
    b : Double
    c : Double
    d : Double
    e : Double
    f : Double
    } derive(Eq, ToJson,
    Debug
    )

    A PDF affine transform matrix.

    The fields correspond to PDF's six-operand matrix [a b c d e f], where a point is transformed as x' = a*x + c*y + e and y' = b*x + d*y + f.

    TransformMatrix::apply

    fn TransformMatrix::apply(self : TransformMatrix, point : Point2) -> Point2

    Applies this matrix to a point.

    TransformMatrix::debug_string

    fn TransformMatrix::debug_string(self : TransformMatrix) -> String

    Formats a matrix as its six comma-separated operands.

    TransformMatrix::decompose

    Decomposes this matrix into scale, aspect, rotation, shear, and translation components.

    Non-finite and underflowed intermediate values are normalized to zero so the result is stable for malformed or degenerate matrices.

    TransformMatrix::equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn TransformMatrix::equal(TransformMatrix, TransformMatrix) -> Bool

    TransformMatrix::invert

    Returns the inverse of this matrix.

    Raises PdfError::MatrixNotInvertable when the matrix determinant is zero or too small to produce a finite inverse.

    TransformMatrix::not_equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn TransformMatrix::not_equal(x : TransformMatrix, y : TransformMatrix) -> Bool

    TransformMatrix::to_json

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn TransformMatrix::to_json(TransformMatrix) -> Json

    TransformMatrix::to_repr

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn TransformMatrix::to_repr(TransformMatrix) ->
    Repr

    TransformOp

    pub(all) enum TransformOp {
    Scale(Point2, Double, Double)
    Rotate(Point2, Double)
    Translate(Double, Double)
    ShearX(Point2, Double)
    ShearY(Point2, Double)
    } derive(Eq, ToJson,
    Debug
    )

    A high-level affine transform operation.

    Operation lists preserve CamlPDF's transform model; they can be rendered for diagnostics or lowered to TransformMatrix for application to points.

    TransformOp::debug_string

    fn TransformOp::debug_string(self : TransformOp) -> String

    Formats one transform operation in CamlPDF-compatible debug text.

    TransformOp::equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn TransformOp::equal(TransformOp, TransformOp) -> Bool

    TransformOp::not_equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn TransformOp::not_equal(x : TransformOp, y : TransformOp) -> Bool

    TransformOp::to_json

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn TransformOp::to_json(TransformOp) -> Json

    TransformOp::to_repr

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn TransformOp::to_repr(TransformOp) ->
    Repr

    paper_a0

    let paper_a0 : PaperSize

    ISO A0 paper, 841 mm by 1189 mm.

    paper_a1

    let paper_a1 : PaperSize

    ISO A1 paper, 594 mm by 841 mm.

    paper_a10

    let paper_a10 : PaperSize

    ISO A10 paper, 26 mm by 37 mm.

    paper_a2

    let paper_a2 : PaperSize

    ISO A2 paper, 420 mm by 594 mm.

    paper_a3

    let paper_a3 : PaperSize

    ISO A3 paper, 297 mm by 420 mm.

    paper_a4

    let paper_a4 : PaperSize

    ISO A4 paper, 210 mm by 297 mm.

    paper_a5

    let paper_a5 : PaperSize

    ISO A5 paper, 148 mm by 210 mm.

    paper_a6

    let paper_a6 : PaperSize

    ISO A6 paper, 105 mm by 148 mm.

    paper_a7

    let paper_a7 : PaperSize

    ISO A7 paper, 74 mm by 105 mm.

    paper_a8

    let paper_a8 : PaperSize

    ISO A8 paper, 52 mm by 74 mm.

    paper_a9

    let paper_a9 : PaperSize

    ISO A9 paper, 37 mm by 52 mm.

    paper_size_make

    fn paper_size_make(unit : PdfUnit, width : Double, height : Double) -> PaperSize

    Creates a paper size from a unit, width, and height.

    paper_uslegal

    let paper_uslegal : PaperSize

    US Legal paper, 8.5 inches by 14 inches.

    paper_usletter

    let paper_usletter : PaperSize

    US Letter paper, 8.5 inches by 11 inches.

    pdf_calculate_position

    fn pdf_calculate_position(ignore_distance : Bool, text_width : Double, bounds : PdfRectangle, position : PdfPosition) -> PdfCalculatedPosition

    Calculate the absolute placement for text of text_width in bounds.

    When ignore_distance is true, edge-distance values in the position are treated as zero, matching cpdf's calculate_position behavior.

    point2

    fn point2(x : Double, y : Double) -> Point2

    Creates a two-dimensional point.

    transform_append

    fn transform_append(after : ArrayView[TransformOp], before : ArrayView[TransformOp]) -> Array[TransformOp]

    Concatenates two transform operation lists.

    The after operations are placed before the before operations to preserve the same ordering used by CamlPDF transform lists.

    transform_apply

    fn transform_apply(ops : ArrayView[TransformOp], point : Point2) -> Point2

    Compatibility alias for applying a transform operation list to a point.

    transform_apply_matrix

    fn transform_apply_matrix(matrix : TransformMatrix, point : Point2) -> Point2

    Applies a matrix to a point.

    transform_apply_ops

    fn transform_apply_ops(ops : ArrayView[TransformOp], point : Point2) -> Point2

    Applies a transform operation list to a point.

    transform_compose_op

    fn transform_compose_op(op : TransformOp, ops : ArrayView[TransformOp]) -> Array[TransformOp]

    Adds one operation to the front of an operation list, merging with the first operation when the two adjacent operations are compatible.

    Compatible adjacent translations, scales about the same origin, rotations about the same origin, and shears about the same origin are combined to keep operation lists compact.

    transform_decompose

    fn transform_decompose(matrix : TransformMatrix) -> TransformDecomposition

    Decomposes a matrix into scale, aspect, rotation, shear, and translation.

    transform_identity

    fn transform_identity() -> Array[TransformOp]

    Returns an empty transform operation list, representing identity.

    transform_identity_matrix

    let transform_identity_matrix : TransformMatrix

    The identity affine transform matrix.

    transform_matrix_compose

    fn transform_matrix_compose(after : TransformMatrix, before : TransformMatrix) -> TransformMatrix

    Composes two matrices so before is applied first and after second.

    transform_matrix_invert

    fn transform_matrix_invert(matrix : TransformMatrix) -> TransformMatrix raise
    PdfError

    Returns the inverse of a matrix.

    Raises PdfError::MatrixNotInvertable when the matrix cannot be inverted.

    transform_matrix_of_op

    fn transform_matrix_of_op(op : TransformOp) -> TransformMatrix

    Lowers one high-level transform operation to a matrix.

    transform_matrix_of_ops

    fn transform_matrix_of_ops(ops : ArrayView[TransformOp]) -> TransformMatrix

    Lowers an operation list to one composed matrix.

    transform_matrix_of_transform

    fn transform_matrix_of_transform(ops : ArrayView[TransformOp]) -> TransformMatrix

    Compatibility alias for lowering a transform operation list to a matrix.

    transform_recompose

    fn transform_recompose(parts : TransformDecomposition) -> TransformMatrix

    Recomposes a matrix from decomposed transform components.

    transform_recompose_components

    fn transform_recompose_components(scale : Double, aspect : Double, rotation : Double, shear : Double, translate_x : Double, translate_y : Double) -> TransformMatrix

    Recomposes a matrix from individual decomposition fields.

    transform_rotate

    fn transform_rotate(origin : Point2, angle : Double) -> TransformMatrix

    Creates a rotation matrix around origin.

    angle is measured in radians.

    transform_scale

    fn transform_scale(origin : Point2, sx : Double, sy : Double) -> TransformMatrix

    Creates a scale matrix around origin.

    transform_shear_x

    fn transform_shear_x(origin : Point2, factor : Double) -> TransformMatrix

    Creates an X-shear matrix around origin.

    transform_shear_y

    fn transform_shear_y(origin : Point2, factor : Double) -> TransformMatrix

    Creates a Y-shear matrix around origin.

    transform_string_of_matrix

    fn transform_string_of_matrix(matrix : TransformMatrix) -> String

    Formats a matrix as its six comma-separated operands.

    transform_string_of_op

    fn transform_string_of_op(op : TransformOp) -> String

    Formats one transform operation in CamlPDF-compatible debug text.

    transform_string_of_ops

    fn transform_string_of_ops(ops : ArrayView[TransformOp]) -> String

    Formats a transform operation list in display order.

    CamlPDF prints the most recently composed operation first, so this walks the input list in reverse.

    transform_string_of_transform

    fn transform_string_of_transform(ops : ArrayView[TransformOp]) -> String

    Compatibility alias for formatting a transform operation list.

    transform_translate

    fn transform_translate(tx : Double, ty : Double) -> TransformMatrix

    Creates a translation matrix.

    unit_centimetres

    fn unit_centimetres(value : Double, unit : PdfUnit) -> Double

    Converts a value from unit to centimetres.

    The PdfPoint path preserves CamlPDF's historical conversion constant for compatibility with existing output.

    unit_inches

    fn unit_inches(value : Double, unit : PdfUnit) -> Double

    Converts a value from unit to inches.

    unit_millimetres

    fn unit_millimetres(value : Double, unit : PdfUnit) -> Double

    Converts a value from unit to millimetres.

    unit_points

    fn unit_points(value : Double, unit : PdfUnit) -> Double

    Converts a value from unit to PDF points.