///|
let pdf_impose_matrix_key_name : @core.PdfName = pdf_page_name("/Matrix")
///|
fn pdf_impose_pattern_name_used(
used_names : ArrayView[@core.PdfName],
name : @core.PdfName,
) -> Bool {
for used_name in used_names {
if used_name == name {
break true
}
} nobreak {
false
}
}
///|
fn pdf_impose_pattern_add_used(
used_names : Array[@core.PdfName],
name : @core.PdfName,
) -> Unit {
if !pdf_impose_pattern_name_used(used_names, name) {
used_names.push(name)
}
}
///|
fn PdfDocument::pdf_impose_patterns_used_with_scn(
self : PdfDocument,
content : ArrayView[@syntax.PdfObject],
resources : @syntax.PdfObject,
) -> Array[@core.PdfName] raise @core.PdfError {
let used_names : Array[@core.PdfName] = []
match self.lookup_direct(pdf_page_pattern_resource_name, resources) {
Some(_) => {
let ops = self.parse_content_ops_with_resources(resources, content)
for op in ops {
match op {
Op_scnName(name, []) | Op_SCNName(name, []) =>
pdf_impose_pattern_add_used(used_names, name)
_ => ()
}
}
}
None => ()
}
used_names
}
///|
fn pdf_impose_xobject_done(done : ArrayView[Int], number : Int) -> Bool {
for item in done {
if item == number {
break true
}
} nobreak {
false
}
}
///|
fn PdfDocument::pdf_impose_change_pattern_object(
self : PdfDocument,
matrix : @geometry.TransformMatrix,
pattern : @syntax.PdfObject,
) -> @syntax.PdfObject raise @core.PdfError {
let old_pattern = self.direct(pattern)
let existing = self.parse_matrix(pdf_impose_matrix_key_name, old_pattern)
let new_matrix = @geometry.transform_matrix_compose(matrix, existing)
PdfIndirect(
self.add_object(
old_pattern.add_dict_entry(
pdf_impose_matrix_key_name,
pdf_object_of_matrix(new_matrix),
),
),
)
}
///|
fn PdfDocument::pdf_impose_change_pattern_matrices_resources(
self : PdfDocument,
matrix : @geometry.TransformMatrix,
resources : @syntax.PdfObject,
names_used_with_scn : ArrayView[@core.PdfName],
xobjects_done : Array[Int],
) -> @syntax.PdfObject raise @core.PdfError {
match self.lookup_direct(pdf_page_xobject_key(), resources) {
Some(PdfDictionary(entries)) =>
for entry in entries {
match entry.1 {
PdfIndirect(number) =>
self.pdf_impose_change_pattern_matrices_xobject(
matrix,
entry.1,
number,
xobjects_done,
)
_ => raise DictionaryExpected
}
}
_ => ()
}
match self.lookup_direct(pdf_page_pattern_resource_name, resources) {
Some(PdfDictionary(patterns)) => {
let entries : Array[(@core.PdfName, @syntax.PdfObject)] = []
for entry in patterns {
let (name, pattern) = entry
if pdf_impose_pattern_name_used(names_used_with_scn, name) {
entries.push(
(name, self.pdf_impose_change_pattern_object(matrix, pattern)),
)
} else {
entries.push(entry)
}
}
resources.add_dict_entry(
pdf_page_pattern_resource_name,
PdfDictionary(entries),
)
}
_ => resources
}
}
///|
fn PdfDocument::pdf_impose_change_pattern_matrices_xobject(
self : PdfDocument,
matrix : @geometry.TransformMatrix,
xobject : @syntax.PdfObject,
xobject_number : Int,
xobjects_done : Array[Int],
) -> Unit raise @core.PdfError {
if pdf_impose_xobject_done(xobjects_done, xobject_number) {
()
} else {
xobjects_done.push(xobject_number)
let direct_xobject = self.direct(xobject)
match self.lookup_direct(pdf_page_subtype_key(), direct_xobject) {
Some(PdfNameObject(name)) if name == pdf_page_type_form() => {
let resources = match
self.lookup_direct(pdf_page_resources_key(), direct_xobject) {
Some(value) => value
None => PdfDictionary([])
}
let used = self.pdf_impose_patterns_used_with_scn(
[direct_xobject],
resources,
)
match self.lookup_direct(pdf_page_resources_key(), direct_xobject) {
Some(_) => {
let updated_resources = self.pdf_impose_change_pattern_matrices_resources(
matrix, resources, used, xobjects_done,
)
self.add_object_given_number(
xobject_number,
direct_xobject.add_dict_entry(
pdf_page_resources_key(),
updated_resources,
),
)
}
None => ()
}
}
_ => ()
}
}
}
///|
fn PdfDocument::pdf_impose_change_pattern_matrices_page(
self : PdfDocument,
matrix : @geometry.TransformMatrix,
page : @page.PdfPage,
) -> @page.PdfPage raise @core.PdfError {
let used = self.pdf_impose_patterns_used_with_scn(
page.content,
page.resources,
)
let xobjects_done : Array[Int] = []
{
..page,
resources: self.pdf_impose_change_pattern_matrices_resources(
matrix,
page.resources,
used,
xobjects_done,
),
}
}
///|
/// Rewrite pattern matrices used by a page after applying a page transform.
pub fn PdfDocument::change_pattern_matrices_page(
self : PdfDocument,
matrix : @geometry.TransformMatrix,
page : @page.PdfPage,
) -> @page.PdfPage raise @core.PdfError {
self.pdf_impose_change_pattern_matrices_page(matrix, page)
}
///|
/// Compatibility wrapper matching cpdfpage's `change_pattern_matrices_page`.
pub fn pdf_change_pattern_matrices_page(
document : PdfDocument,
matrix : @geometry.TransformMatrix,
page : @page.PdfPage,
) -> @page.PdfPage raise @core.PdfError {
document.change_pattern_matrices_page(matrix, page)
}