///|
fn pdf_page_stamp_half(value : Double) -> Double {
value / 2.0
}
///|
fn pdf_page_stamp_shift_of_position(
topline : Bool,
midline : Bool,
stamp_width : Double,
stamp_height : Double,
page_width : Double,
page_height : Double,
position : @geometry.PdfPosition,
) -> (Double, Double) {
let dy = if midline {
stamp_height / 2.0
} else if topline {
stamp_height
} else {
0.0
}
match position {
PdfPositionPosCentre(x, y) => (x - pdf_page_stamp_half(stamp_width), y - dy)
PdfPositionPosLeft(x, y) => (x, y - dy)
PdfPositionPosRight(x, y) => (x - stamp_width, y - dy)
PdfPositionTop(offset) =>
(
pdf_page_stamp_half(page_width) - pdf_page_stamp_half(stamp_width),
page_height - offset - stamp_height - dy,
)
PdfPositionTopLeft(x, y) => (x, page_height - stamp_height - y - dy)
PdfPositionTopRight(x, y) =>
(page_width - stamp_width - x, page_height - stamp_height - y - dy)
PdfPositionLeft(offset) =>
(
offset,
pdf_page_stamp_half(page_height) -
pdf_page_stamp_half(stamp_height) -
dy,
)
PdfPositionBottomLeft(x, y) => (x, y - dy)
PdfPositionBottom(offset) =>
(
pdf_page_stamp_half(page_width) - pdf_page_stamp_half(stamp_width),
offset - dy,
)
PdfPositionBottomRight(x, y) => (page_width - stamp_width - x, y - dy)
PdfPositionRight(offset) =>
(
page_width - stamp_width - offset,
pdf_page_stamp_half(page_height) -
pdf_page_stamp_half(stamp_height) -
dy,
)
PdfPositionDiagonal | PdfPositionReverseDiagonal | PdfPositionCentre =>
(
pdf_page_stamp_half(page_width) - pdf_page_stamp_half(stamp_width),
pdf_page_stamp_half(page_height) -
pdf_page_stamp_half(stamp_height) -
dy,
)
}
}
///|
fn PdfDocument::pdf_page_stamp_box(
self : PdfDocument,
page : @page.PdfPage,
box_name : @core.PdfName,
) -> @geometry.PdfRectangle raise @core.PdfError {
self.parse_rectangle(
if box_name == pdf_page_mediabox_key() {
page.mediabox
} else {
match self.lookup_direct(box_name, page.rest) {
Some(box) => box
None => page.mediabox
}
},
)
}
///|
fn pdf_page_stamp_scale_to_fit_factor(
x_magnification : Double,
y_magnification : Double,
) -> Double {
if x_magnification < 0.999 && y_magnification < 0.999 {
if x_magnification > y_magnification {
x_magnification
} else {
y_magnification
}
} else if x_magnification >= 1.001 && y_magnification >= 1.001 {
if x_magnification > y_magnification {
y_magnification
} else {
x_magnification
}
} else if x_magnification >= 1.001 {
y_magnification
} else {
x_magnification
}
}
///|
fn pdf_page_stamp_scale_to_fit_matrix(
stamp_box : @geometry.PdfRectangle,
target_box : @geometry.PdfRectangle,
relative_to_box : @core.PdfName,
) -> @geometry.TransformMatrix raise @core.PdfError {
let stamp_width = stamp_box.max_x - stamp_box.min_x
let stamp_height = stamp_box.max_y - stamp_box.min_y
let target_width = target_box.max_x - target_box.min_x
let target_height = target_box.max_y - target_box.min_y
if stamp_width == 0.0 || stamp_height == 0.0 {
raise BadNumberArgument("stamp_pages: zero-sized stamp page is invalid")
}
let scale = pdf_page_stamp_scale_to_fit_factor(
target_width / stamp_width,
target_height / stamp_height,
)
let dx = target_box.min_x + (target_width - stamp_width * scale) / 2.0
let dy = target_box.min_y + (target_height - stamp_height * scale) / 2.0
let ops : Array[@geometry.TransformOp] = [Translate(dx, dy)]
if relative_to_box != pdf_page_mediabox_key() {
ops.push(Translate(target_box.min_x, target_box.min_y))
}
ops.push(
Scale(@geometry.point2(stamp_box.min_x, stamp_box.min_y), scale, scale),
)
@geometry.transform_matrix_of_ops(ops)
}
///|
fn pdf_page_stamp_position_matrix(
stamp_box : @geometry.PdfRectangle,
target_box : @geometry.PdfRectangle,
relative_to_box : @core.PdfName,
position : @geometry.PdfPosition,
topline : Bool,
midline : Bool,
) -> @geometry.TransformMatrix {
let stamp_width = stamp_box.max_x - stamp_box.min_x
let stamp_height = stamp_box.max_y - stamp_box.min_y
let target_width = target_box.max_x - target_box.min_x
let target_height = target_box.max_y - target_box.min_y
let (dx, dy) = pdf_page_stamp_shift_of_position(
topline, midline, stamp_width, stamp_height, target_width, target_height, position,
)
let ops : Array[@geometry.TransformOp] = []
if relative_to_box != pdf_page_mediabox_key() {
ops.push(Translate(target_box.min_x, target_box.min_y))
}
ops.push(Translate(dx, dy))
@geometry.transform_matrix_of_ops(ops)
}