///|
fn pdf_addtext_degrees_to_radians(degrees : Double) -> Double {
degrees * @math.PI / 180.0
}
///|
/// Convert cpdf add-text's explicit rotation enum to content rotation radians.
pub fn pdf_addtext_rotation_radians(rotation : PdfAddTextRotation) -> Double {
match rotation {
PdfAddTextRot0 => 0.0
PdfAddTextRot90 => pdf_addtext_degrees_to_radians(270.0)
PdfAddTextRot180 => pdf_addtext_degrees_to_radians(180.0)
PdfAddTextRot270 => pdf_addtext_degrees_to_radians(90.0)
}
}
///|
/// Return cpdf's rotation-dependent text origin offset.
pub fn pdf_addtext_rotation_offsets(
position : @geometry.PdfPosition,
rotation : PdfAddTextRotation,
text_width : Double,
) -> (Double, Double) {
match position {
PdfPositionTopLeft(_, _) =>
match rotation {
PdfAddTextRot0 | PdfAddTextRot90 => (0.0, 0.0)
PdfAddTextRot180 => (text_width, 0.0)
PdfAddTextRot270 => (0.0, -text_width)
}
PdfPositionTop(_) =>
match rotation {
PdfAddTextRot0 => (0.0, 0.0)
PdfAddTextRot90 => (text_width / 2.0, 0.0)
PdfAddTextRot180 => (text_width, 0.0)
PdfAddTextRot270 => (text_width / 2.0, -text_width)
}
PdfPositionTopRight(_, _) =>
match rotation {
PdfAddTextRot0 => (0.0, 0.0)
PdfAddTextRot90 | PdfAddTextRot180 => (text_width, 0.0)
PdfAddTextRot270 => (text_width, -text_width)
}
PdfPositionRight(_) | PdfPositionPosRight(_, _) =>
match rotation {
PdfAddTextRot0 => (0.0, 0.0)
PdfAddTextRot90 => (text_width, text_width / 2.0)
PdfAddTextRot180 => (text_width, 0.0)
PdfAddTextRot270 => (text_width, -text_width / 2.0)
}
PdfPositionBottomRight(_, _) =>
match rotation {
PdfAddTextRot0 => (0.0, 0.0)
PdfAddTextRot90 => (text_width, text_width)
PdfAddTextRot180 => (text_width, 0.0)
PdfAddTextRot270 => (text_width, 0.0)
}
PdfPositionBottom(_) =>
match rotation {
PdfAddTextRot0 => (0.0, 0.0)
PdfAddTextRot90 => (text_width / 2.0, text_width)
PdfAddTextRot180 => (text_width, 0.0)
PdfAddTextRot270 => (text_width / 2.0, 0.0)
}
PdfPositionBottomLeft(_, _) =>
match rotation {
PdfAddTextRot0 => (0.0, 0.0)
PdfAddTextRot90 => (0.0, text_width)
PdfAddTextRot180 => (text_width, 0.0)
PdfAddTextRot270 => (0.0, 0.0)
}
PdfPositionLeft(_) | PdfPositionPosLeft(_, _) =>
match rotation {
PdfAddTextRot0 => (0.0, 0.0)
PdfAddTextRot90 => (0.0, text_width / 2.0)
PdfAddTextRot180 => (text_width, 0.0)
PdfAddTextRot270 => (0.0, -text_width / 2.0)
}
PdfPositionCentre | PdfPositionPosCentre(_, _) =>
match rotation {
PdfAddTextRot0 => (0.0, 0.0)
PdfAddTextRot90 => (text_width / 2.0, text_width / 2.0)
PdfAddTextRot180 => (text_width, 0.0)
PdfAddTextRot270 => (text_width / 2.0, -(text_width / 2.0))
}
PdfPositionDiagonal | PdfPositionReverseDiagonal => (0.0, 0.0)
}
}
///|
/// Adjust cpdf add-text offsets for diagonal and reverse-diagonal placement.
pub fn pdf_addtext_diagonal_offsets(
bounds : @geometry.PdfRectangle,
position : @geometry.PdfPosition,
rotation : PdfAddTextRotation,
text_width : Double,
horizontal_offset : Double,
vertical_offset : Double,
base_rotation : Double,
) -> (Double, Double) {
match position {
PdfPositionDiagonal | PdfPositionReverseDiagonal => {
let rotate = if rotation == PdfAddTextRot180 {
base_rotation + @math.PI
} else {
base_rotation
}
let horizontal = -(@math.cos(@math.PI / 2.0 - rotate) * vertical_offset)
let vertical = @math.sin(@math.PI / 2.0 - rotate) * vertical_offset
if rotation == PdfAddTextRot180 {
let angle = @math.atan(
(bounds.max_y - bounds.min_y) / (bounds.max_x - bounds.min_x),
)
let dx = @math.cos(angle) * text_width
let dy = @math.sin(angle) * text_width
match position {
PdfPositionDiagonal => (horizontal - dx, vertical - dy)
PdfPositionReverseDiagonal => (horizontal - dx, vertical + dy)
_ => (horizontal, vertical)
}
} else {
(horizontal, vertical)
}
}
_ => (horizontal_offset, vertical_offset)
}
}
///|
/// Return cpdf's initial `(horizontal, vertical)` offset for a multi-line
/// add-text paragraph.
pub fn pdf_addtext_initial_line_offsets(
position : @geometry.PdfPosition,
line_count : Int,
line_spacing : Double,
font_size : Double,
) -> (Double, Double) {
let line_delta = (line_count - 1).to_double()
let paragraph_height = line_spacing * font_size * line_delta
let vertical = match position {
PdfPositionBottomLeft(_, _)
| PdfPositionBottom(_)
| PdfPositionBottomRight(_, _) => -paragraph_height
PdfPositionLeft(_) | PdfPositionRight(_) => -(paragraph_height / 2.0)
PdfPositionDiagonal | PdfPositionReverseDiagonal =>
-(paragraph_height / 2.0)
_ => 0.0
}
(0.0, vertical)
}
///|
/// Return cpdf's per-line `(horizontal, vertical)` advance for add-text.
pub fn pdf_addtext_line_advance(
rotation : PdfAddTextRotation,
line_spacing : Double,
font_size : Double,
) -> (Double, Double) {
let advance = line_spacing * font_size
match rotation {
PdfAddTextRot90 | PdfAddTextRot270 => (advance, 0.0)
PdfAddTextRot0 | PdfAddTextRot180 => (0.0, advance)
}
}