///|
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 : 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 : PdfRectangle,
position : 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 : 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)
}
}
///|
fn pdf_addtext_rotation_adjustment_offsets(
rotation : PdfAddTextRotation,
adjustment : Double,
) -> (Double, Double) {
match rotation {
PdfAddTextRot0 => (0.0, adjustment)
PdfAddTextRot90 => (adjustment, 0.0)
PdfAddTextRot180 => (0.0, -adjustment)
PdfAddTextRot270 => (-adjustment, 0.0)
}
}
///|
/// Return cpdf's `(horizontal, vertical)` baseline shift for midline/topline
/// add-text placement.
pub fn pdf_addtext_baseline_offsets(
font : PdfFont?,
font_size : Double,
position : PdfPosition,
rotation : PdfAddTextRotation,
midline : Bool,
topline : Bool,
) -> (Double, Double) {
if midline {
match font {
Some(PdfFontStandard({ font, .. })) =>
pdf_addtext_rotation_adjustment_offsets(
rotation,
font_size *
pdf_standard14_baseline_adjustment(font).to_double() /
1000.0,
)
Some(PdfFontSimple({ fontdescriptor: Some(descriptor), .. })) =>
pdf_addtext_rotation_adjustment_offsets(
rotation,
font_size * descriptor.capheight / 2.0 / 1000.0,
)
_ => (0.0, 0.0)
}
} else if topline {
match font {
Some(PdfFontStandard({ font, .. })) => {
let adjustment = font_size *
pdf_standard14_baseline_adjustment(font).to_double() *
2.0 /
1000.0
match position {
PdfPositionDiagonal | PdfPositionReverseDiagonal => (0.0, adjustment)
_ => pdf_addtext_rotation_adjustment_offsets(rotation, adjustment)
}
}
Some(PdfFontSimple({ fontdescriptor: Some(descriptor), .. })) => {
let adjustment = font_size * descriptor.capheight / 1000.0
match position {
PdfPositionDiagonal | PdfPositionReverseDiagonal => (0.0, adjustment)
_ => pdf_addtext_rotation_adjustment_offsets(rotation, adjustment)
}
}
_ => (0.0, 0.0)
}
} else {
(0.0, 0.0)
}
}