///|
fn pdf_type_initial_state(
lmargin : Double,
tmargin : Double,
) -> PdfTypeTypesetState {
{
xpos: lmargin,
ypos: tmargin,
width_table: [],
font: None,
font_id: None,
font_size: 0.0,
dest: None,
mcid: -1,
ops: [],
fonts: [],
page_font_numbers: [],
page_annotations: [],
dest_rectangles: [],
pages: [],
tags: [],
tags_out: [],
}
}
///|
fn PdfTypeTypesetState::next_mcid(self : PdfTypeTypesetState) -> Int {
self.mcid += 1
self.mcid
}
///|
fn PdfTypeTypesetState::write_page(
self : PdfTypeTypesetState,
document : PdfDocument,
process_struct_tree : Bool,
paper : @geometry.PaperSize,
) -> Unit raise @core.PdfError {
let ops = if process_struct_tree {
@content.pdf_content_add_artifacts(self.ops)
} else {
[
for op in self.ops => op
]
}
self.pages.push({
content: if ops.length() == 0 {
[]
} else {
[pdf_content_stream_of_ops(ops)]
},
mediabox: @page.pdf_page_rectangle_of_paper(paper),
resources: pdf_type_make_resources(self.page_font_numbers),
rotate: Rotate0,
rest: pdf_type_make_annotations(document, self.page_annotations),
})
self.tags_out.push([ for tag in self.tags => tag ])
self.tags = []
}
///|
fn PdfTypeTypesetState::write_destination_annotations(
self : PdfTypeTypesetState,
) -> Unit {
match self.dest {
Some((destination, contents)) =>
if self.dest_rectangles.length() > 0 {
let annotations : Array[@syntax.PdfObject] = []
let mut index = self.dest_rectangles.length()
while index > 0 {
index -= 1
annotations.push(
pdf_type_annotation_object(
destination,
contents,
self.dest_rectangles[index],
),
)
}
for annotation in self.page_annotations {
annotations.push(annotation)
}
self.page_annotations = annotations
}
None => ()
}
self.dest = None
self.dest_rectangles = []
}
///|
fn PdfTypeTypesetState::write_font(
self : PdfTypeTypesetState,
document : PdfDocument,
id : String,
font : PdfFont,
font_size : Double,
) -> Unit raise @core.PdfError {
let object_number = match pdf_type_lookup_font_object(self.fonts, id) {
Some(number) => number
None => {
let number = document.write_font(font)
self.fonts.push((id, number))
number
}
}
self.width_table = pdf_type_font_widths(font, font_size)
self.font = Some(font)
self.font_id = Some(id)
self.font_size = font_size
self.page_font_numbers.push(object_number)
self.ops.push(Op_Tf(pdf_type_font_resource_name(object_number), font_size))
}
///|
fn PdfTypeTypesetState::write_text(
self : PdfTypeTypesetState,
text : @core.PdfBytes,
page_height : Double,
) -> Unit raise @core.PdfError {
let text_width = pdf_type_width_of_bytes(self.width_table, text)
self.ops.push(Op_q)
self.ops.push(
Op_cm(@geometry.transform_translate(self.xpos, page_height - self.ypos)),
)
self.ops.push(Op_BT)
self.ops.push(Op_Tj(text))
self.ops.push(Op_ET)
self.ops.push(Op_Q)
match self.dest {
Some(_) =>
self.dest_rectangles.push(
(
self.xpos,
page_height - self.ypos,
self.xpos + text_width,
page_height - self.ypos + self.font_size,
),
)
None => ()
}
self.xpos = self.xpos + text_width
}
///|
fn PdfTypeTypesetState::new_page(
self : PdfTypeTypesetState,
document : PdfDocument,
process_struct_tree : Bool,
lmargin : Double,
tmargin : Double,
paper : @geometry.PaperSize,
) -> Unit raise @core.PdfError {
self.write_page(document, process_struct_tree, paper)
self.page_font_numbers = []
self.page_annotations = []
self.ops = []
self.mcid = -1
match (self.font_id, self.font) {
(Some(id), Some(font)) =>
self.write_font(document, id, font, self.font_size)
_ => ()
}
self.xpos = lmargin
self.ypos = tmargin + self.font_size
}
///|
fn PdfTypeTypesetState::write_element(
self : PdfTypeTypesetState,
document : PdfDocument,
process_struct_tree : Bool,
lmargin : Double,
tmargin : Double,
paper : @geometry.PaperSize,
page_height : Double,
element : PdfTypeElement,
) -> Unit raise @core.PdfError {
match element {
PdfTypeText(text) => self.write_text(text, page_height)
PdfTypeFont(id, font, font_size) =>
self.write_font(document, id, font, font_size)
PdfTypeHGlue(length) => self.xpos = self.xpos + length
PdfTypeVGlue(length) => self.ypos = self.ypos + length
PdfTypeNewLine => {
self.xpos = lmargin
self.ypos = self.ypos + self.font_size * 1.3
}
PdfTypeNewPage =>
self.new_page(document, process_struct_tree, lmargin, tmargin, paper)
PdfTypeBeginDocument => self.ypos = tmargin + self.font_size
PdfTypeBeginDest(destination, contents) =>
self.dest = Some((destination, contents))
PdfTypeEndDest => self.write_destination_annotations()
PdfTypeTag(tag, number) => {
self.tags.push((tag, number))
self.ops.push(
Op_BDC(
pdf_type_name("/" + tag),
PdfDictionary([(pdf_type_name("/MCID"), PdfInteger(self.next_mcid()))]),
),
)
}
PdfTypeEndTag => self.ops.push(Op_EMC)
}
}