///|
pub(all) enum PdfContentOp {
Op_w(Double)
Op_J(Int)
Op_j(Int)
Op_M(Double)
Op_d(Array[Double], Double)
Op_ri(PdfName)
Op_i(Double)
Op_q
Op_Q
Op_cm(TransformMatrix)
Op_m(Double, Double)
Op_l(Double, Double)
Op_c(Double, Double, Double, Double, Double, Double)
Op_v(Double, Double, Double, Double)
Op_y(Double, Double, Double, Double)
Op_h
Op_re(Double, Double, Double, Double)
Op_S
Op_s
Op_f
Op_F
Op_fstar
Op_B
Op_Bstar
Op_b
Op_bstar
Op_n
Op_W
Op_Wstar
Op_BT
Op_ET
Op_Tc(Double)
Op_Tw(Double)
Op_Tz(Double)
Op_TL(Double)
Op_Tf(PdfName, Double)
Op_Tr(Int)
Op_Ts(Double)
Op_Td(Double, Double)
Op_TD(Double, Double)
Op_Tm(TransformMatrix)
Op_Tstar
Op_Tj(PdfBytes)
Op_TJ(PdfObject)
Op_quote(PdfBytes)
Op_double_quote(Double, Double, PdfBytes)
Op_d0(Double, Double)
Op_d1(Double, Double, Double, Double, Double, Double)
Op_G(Double)
Op_g(Double)
Op_RG(Double, Double, Double)
Op_rg(Double, Double, Double)
Op_K(Double, Double, Double, Double)
Op_k(Double, Double, Double, Double)
Op_gs(PdfName)
Op_CS(PdfName)
Op_cs(PdfName)
Op_SC(Array[Double])
Op_sc(Array[Double])
Op_SCN(Array[Double])
Op_scn(Array[Double])
Op_SCNName(PdfName, Array[Double])
Op_scnName(PdfName, Array[Double])
Op_sh(PdfName)
Op_Do(PdfName)
Op_InlineImage(PdfObject, PdfObject?, PdfBytes)
Op_MP(PdfName)
Op_DP(PdfName, PdfObject)
Op_BMC(PdfName)
Op_BDC(PdfName, PdfObject)
Op_EMC
Op_BX
Op_EX
Op_Unknown(PdfBytes)
} derive(Debug, Eq, ToJson)
///|
enum PdfContentLexeme {
ContentOperand(PdfObject)
ContentOperator(BytesView)
ContentComment
ContentEnd
} derive(Debug, Eq, ToJson)
///|
enum PdfContentInlineTextFilter {
PdfContentInlineAsciiHex
PdfContentInlineAscii85
} derive(Debug, Eq)
///|
fn pdf_content_ascii(text : String) -> PdfBytes {
@ascii.encode(text)
}
///|
fn pdf_content_name(text : String) -> PdfName {
pdf_name_of_bytes(pdf_content_ascii(text))
}
///|
let pdf_content_length_key_name : PdfName = pdf_content_name("/Length")
///|
let pdf_content_inline_l_key_name : PdfName = pdf_content_name("/L")
///|
let pdf_content_artifact_name : PdfName = pdf_content_name("/Artifact")
///|
let pdf_content_inline_image_begin_operator : PdfBytes = pdf_content_ascii("BI")
///|
let pdf_content_inline_image_data_operator : PdfBytes = pdf_content_ascii("ID")
///|
fn pdf_content_length_name() -> PdfName {
pdf_content_length_key_name
}
///|
fn pdf_content_inline_l_name() -> PdfName {
pdf_content_inline_l_key_name
}
///|
pub fn pdf_content_begin_artifact() -> PdfContentOp {
Op_BMC(pdf_content_artifact_name)
}
///|
pub fn pdf_content_end_artifact() -> PdfContentOp {
Op_EMC
}
///|
fn pdf_content_push_view(output : Array[Byte], view : BytesView) -> Unit {
for byte in view {
output.push(byte)
}
}
///|
fn pdf_content_push_object(
output : Array[Byte],
object : PdfObject,
) -> Unit raise PdfError {
pdf_content_push_view(output, pdf_write_object(object)[:])
}
///|
fn pdf_content_push_section(
output : Array[Byte],
operands : ArrayView[PdfObject],
operator : BytesView,
) -> Unit raise PdfError {
for operand in operands {
if output.length() > 0 {
output.push(32)
}
pdf_content_push_object(output, operand)
}
if output.length() > 0 {
output.push(32)
}
pdf_content_push_view(output, operator)
}
///|
fn pdf_content_number_object(value : Double) -> PdfObject {
PdfReal(value)
}
///|
fn pdf_content_matrix_operands(matrix : TransformMatrix) -> Array[PdfObject] {
[
pdf_content_number_object(matrix.a),
pdf_content_number_object(matrix.b),
pdf_content_number_object(matrix.c),
pdf_content_number_object(matrix.d),
pdf_content_number_object(matrix.e),
pdf_content_number_object(matrix.f),
]
}
///|
fn pdf_content_number_array(values : ArrayView[Double]) -> PdfObject {
PdfArray([ for value in values => pdf_content_number_object(value) ])
}
///|
fn pdf_content_number_operands(values : ArrayView[Double]) -> Array[PdfObject] {
[
for value in values => pdf_content_number_object(value)
]
}
///|
fn pdf_content_op_section(op : PdfContentOp) -> (Array[PdfObject], PdfBytes) {
match op {
Op_w(width) => ([pdf_content_number_object(width)], pdf_content_ascii("w"))
Op_J(cap) => ([PdfInteger(cap)], pdf_content_ascii("J"))
Op_j(join) => ([PdfInteger(join)], pdf_content_ascii("j"))
Op_M(limit) => ([pdf_content_number_object(limit)], pdf_content_ascii("M"))
Op_d(dashes, phase) =>
(
[pdf_content_number_array(dashes), pdf_content_number_object(phase)],
pdf_content_ascii("d"),
)
Op_ri(intent) => ([PdfNameObject(intent)], pdf_content_ascii("ri"))
Op_i(flatness) =>
([pdf_content_number_object(flatness)], pdf_content_ascii("i"))
Op_q => ([], pdf_content_ascii("q"))
Op_Q => ([], pdf_content_ascii("Q"))
Op_cm(matrix) =>
(pdf_content_matrix_operands(matrix), pdf_content_ascii("cm"))
Op_m(x, y) =>
(
[pdf_content_number_object(x), pdf_content_number_object(y)],
pdf_content_ascii("m"),
)
Op_l(x, y) =>
(
[pdf_content_number_object(x), pdf_content_number_object(y)],
pdf_content_ascii("l"),
)
Op_c(x1, y1, x2, y2, x3, y3) =>
(
[
pdf_content_number_object(x1),
pdf_content_number_object(y1),
pdf_content_number_object(x2),
pdf_content_number_object(y2),
pdf_content_number_object(x3),
pdf_content_number_object(y3),
],
pdf_content_ascii("c"),
)
Op_v(x2, y2, x3, y3) =>
(
[
pdf_content_number_object(x2),
pdf_content_number_object(y2),
pdf_content_number_object(x3),
pdf_content_number_object(y3),
],
pdf_content_ascii("v"),
)
Op_y(x1, y1, x3, y3) =>
(
[
pdf_content_number_object(x1),
pdf_content_number_object(y1),
pdf_content_number_object(x3),
pdf_content_number_object(y3),
],
pdf_content_ascii("y"),
)
Op_h => ([], pdf_content_ascii("h"))
Op_re(x, y, width, height) =>
(
[
pdf_content_number_object(x),
pdf_content_number_object(y),
pdf_content_number_object(width),
pdf_content_number_object(height),
],
pdf_content_ascii("re"),
)
Op_S => ([], pdf_content_ascii("S"))
Op_s => ([], pdf_content_ascii("s"))
Op_f => ([], pdf_content_ascii("f"))
Op_F => ([], pdf_content_ascii("F"))
Op_fstar => ([], pdf_content_ascii("f*"))
Op_B => ([], pdf_content_ascii("B"))
Op_Bstar => ([], pdf_content_ascii("B*"))
Op_b => ([], pdf_content_ascii("b"))
Op_bstar => ([], pdf_content_ascii("b*"))
Op_n => ([], pdf_content_ascii("n"))
Op_W => ([], pdf_content_ascii("W"))
Op_Wstar => ([], pdf_content_ascii("W*"))
Op_BT => ([], pdf_content_ascii("BT"))
Op_ET => ([], pdf_content_ascii("ET"))
Op_Tc(spacing) =>
([pdf_content_number_object(spacing)], pdf_content_ascii("Tc"))
Op_Tw(spacing) =>
([pdf_content_number_object(spacing)], pdf_content_ascii("Tw"))
Op_Tz(scale) =>
([pdf_content_number_object(scale)], pdf_content_ascii("Tz"))
Op_TL(leading) =>
([pdf_content_number_object(leading)], pdf_content_ascii("TL"))
Op_Tf(font, size) =>
(
[PdfNameObject(font), pdf_content_number_object(size)],
pdf_content_ascii("Tf"),
)
Op_Tr(mode) => ([PdfInteger(mode)], pdf_content_ascii("Tr"))
Op_Ts(rise) => ([pdf_content_number_object(rise)], pdf_content_ascii("Ts"))
Op_Td(tx, ty) =>
(
[pdf_content_number_object(tx), pdf_content_number_object(ty)],
pdf_content_ascii("Td"),
)
Op_TD(tx, ty) =>
(
[pdf_content_number_object(tx), pdf_content_number_object(ty)],
pdf_content_ascii("TD"),
)
Op_Tm(matrix) =>
(pdf_content_matrix_operands(matrix), pdf_content_ascii("Tm"))
Op_Tstar => ([], pdf_content_ascii("T*"))
Op_Tj(text) => ([PdfString(text)], pdf_content_ascii("Tj"))
Op_TJ(array) => ([array], pdf_content_ascii("TJ"))
Op_quote(text) => ([PdfString(text)], pdf_content_ascii("'"))
Op_double_quote(word_space, char_space, text) =>
(
[
pdf_content_number_object(word_space),
pdf_content_number_object(char_space),
PdfString(text),
],
pdf_content_ascii("\""),
)
Op_d0(width_x, width_y) =>
(
[pdf_content_number_object(width_x), pdf_content_number_object(width_y)],
pdf_content_ascii("d0"),
)
Op_d1(width_x, width_y, llx, lly, urx, ury) =>
(
[
pdf_content_number_object(width_x),
pdf_content_number_object(width_y),
pdf_content_number_object(llx),
pdf_content_number_object(lly),
pdf_content_number_object(urx),
pdf_content_number_object(ury),
],
pdf_content_ascii("d1"),
)
Op_G(gray) => ([pdf_content_number_object(gray)], pdf_content_ascii("G"))
Op_g(gray) => ([pdf_content_number_object(gray)], pdf_content_ascii("g"))
Op_RG(r, g, b) =>
(
[
pdf_content_number_object(r),
pdf_content_number_object(g),
pdf_content_number_object(b),
],
pdf_content_ascii("RG"),
)
Op_rg(r, g, b) =>
(
[
pdf_content_number_object(r),
pdf_content_number_object(g),
pdf_content_number_object(b),
],
pdf_content_ascii("rg"),
)
Op_K(c, m, y, k) =>
(
[
pdf_content_number_object(c),
pdf_content_number_object(m),
pdf_content_number_object(y),
pdf_content_number_object(k),
],
pdf_content_ascii("K"),
)
Op_k(c, m, y, k) =>
(
[
pdf_content_number_object(c),
pdf_content_number_object(m),
pdf_content_number_object(y),
pdf_content_number_object(k),
],
pdf_content_ascii("k"),
)
Op_gs(name) => ([PdfNameObject(name)], pdf_content_ascii("gs"))
Op_CS(name) => ([PdfNameObject(name)], pdf_content_ascii("CS"))
Op_cs(name) => ([PdfNameObject(name)], pdf_content_ascii("cs"))
Op_SC(values) =>
(pdf_content_number_operands(values), pdf_content_ascii("SC"))
Op_sc(values) =>
(pdf_content_number_operands(values), pdf_content_ascii("sc"))
Op_SCN(values) =>
(pdf_content_number_operands(values), pdf_content_ascii("SCN"))
Op_scn(values) =>
(pdf_content_number_operands(values), pdf_content_ascii("scn"))
Op_SCNName(name, values) =>
(
[..pdf_content_number_operands(values), PdfNameObject(name)],
pdf_content_ascii("SCN"),
)
Op_scnName(name, values) =>
(
[..pdf_content_number_operands(values), PdfNameObject(name)],
pdf_content_ascii("scn"),
)
Op_sh(name) => ([PdfNameObject(name)], pdf_content_ascii("sh"))
Op_Do(name) => ([PdfNameObject(name)], pdf_content_ascii("Do"))
Op_InlineImage(_, _, _) => ([], pdf_content_ascii(""))
Op_MP(tag) => ([PdfNameObject(tag)], pdf_content_ascii("MP"))
Op_DP(tag, properties) =>
([PdfNameObject(tag), properties], pdf_content_ascii("DP"))
Op_BMC(tag) => ([PdfNameObject(tag)], pdf_content_ascii("BMC"))
Op_BDC(tag, properties) =>
([PdfNameObject(tag), properties], pdf_content_ascii("BDC"))
Op_EMC => ([], pdf_content_ascii("EMC"))
Op_BX => ([], pdf_content_ascii("BX"))
Op_EX => ([], pdf_content_ascii("EX"))
Op_Unknown(bytes) => ([], bytes)
}
}
///|
fn pdf_content_push_inline_image_entry(
output : Array[Byte],
key : PdfName,
value : PdfObject,
) -> Unit raise PdfError {
output.push(32)
pdf_content_push_object(output, PdfNameObject(key))
output.push(32)
pdf_content_push_object(output, value)
}
///|
fn pdf_content_push_inline_image(
output : Array[Byte],
dictionary : PdfObject,
decode_parms : PdfObject?,
data : PdfBytes,
) -> Unit raise PdfError {
let compress_inline_image = pdf_content_inline_filter_is_empty(dictionary)
let (render_data, render_decode_parms, render_extra_entries) = if compress_inline_image {
let encoded = pdf_flate_encode(data)
(
encoded,
None,
[
(
pdf_content_inline_f_name(),
PdfNameObject(pdf_content_inline_fl_name()),
),
(pdf_content_inline_l_name(), PdfInteger(encoded.length())),
],
)
} else {
(data, decode_parms, [])
}
if output.length() > 0 {
output.push(32)
}
pdf_content_push_view(output, pdf_content_ascii("BI")[:])
match dictionary {
PdfDictionary(entries) =>
for entry in entries {
let (key, value) = entry
if !compress_inline_image ||
(
key != pdf_content_inline_filter_name() &&
key != pdf_content_inline_f_name() &&
key != pdf_content_inline_decode_parms_name() &&
key != pdf_content_inline_dp_name() &&
key != pdf_content_length_name() &&
key != pdf_content_inline_l_name()
) {
pdf_content_push_inline_image_entry(output, key, value)
}
}
_ => raise DictionaryExpected
}
for entry in render_extra_entries {
let (key, value) = entry
pdf_content_push_inline_image_entry(output, key, value)
}
match render_decode_parms {
Some(value) =>
pdf_content_push_inline_image_entry(
output,
pdf_content_inline_dp_name(),
value,
)
None => ()
}
pdf_content_push_view(output, pdf_content_ascii(" ID ")[:])
pdf_content_push_view(output, render_data[:])
pdf_content_push_view(output, pdf_content_ascii(" EI")[:])
}
///|
pub fn pdf_content_bytes_of_ops(
ops : ArrayView[PdfContentOp],
) -> PdfBytes raise PdfError {
let output : Array[Byte] = []
for op in ops {
match op {
Op_InlineImage(dictionary, decode_parms, data) =>
pdf_content_push_inline_image(output, dictionary, decode_parms, data)
Op_Unknown(bytes) => {
if output.length() > 0 {
output.push(32)
}
pdf_content_push_view(output, bytes[:])
}
_ => {
let (operands, operator) = pdf_content_op_section(op)
pdf_content_push_section(output, operands, operator)
}
}
}
Bytes::from_array(output)
}
///|
pub fn pdf_content_bytes_of_op(op : PdfContentOp) -> PdfBytes raise PdfError {
pdf_content_bytes_of_ops([op])
}
///|
pub fn pdf_string_of_content_ops(
ops : ArrayView[PdfContentOp],
) -> PdfBytes raise PdfError {
pdf_content_bytes_of_ops(ops)
}
///|
pub fn pdf_string_of_content_op(op : PdfContentOp) -> PdfBytes raise PdfError {
pdf_content_bytes_of_op(op)
}
///|
pub fn pdf_content_stream_of_ops(
ops : ArrayView[PdfContentOp],
) -> PdfObject raise PdfError {
let data = pdf_content_bytes_of_ops(ops)
pdf_stream(
PdfDictionary([(pdf_content_length_name(), PdfInteger(data.length()))]),
StreamGot(data),
)
}
///|
pub fn pdf_content_concat_stream_views(
streams : ArrayView[BytesView],
) -> PdfBytes {
let output : Array[Byte] = []
for stream in streams {
if output.length() > 0 {
output.push(32)
}
pdf_content_push_view(output, stream)
}
Bytes::from_array(output)
}
///|
pub fn pdf_content_concat_streams(streams : ArrayView[PdfBytes]) -> PdfBytes {
let output : Array[Byte] = []
for stream in streams {
if output.length() > 0 {
output.push(32)
}
pdf_content_push_view(output, stream[:])
}
Bytes::from_array(output)
}
///|
pub fn PdfDocument::parse_content_ops(
self : PdfDocument,
streams : ArrayView[PdfObject],
) -> Array[PdfContentOp] raise PdfError {
let raw_streams = self.pdf_content_raw_streams(streams)
pdf_parse_content_ops_from_view(pdf_content_concat_streams(raw_streams)[:])
}
///|
pub fn PdfDocument::parse_content_ops_with_resources(
self : PdfDocument,
resources : PdfObject,
streams : ArrayView[PdfObject],
) -> Array[PdfContentOp] raise PdfError {
let raw_streams = self.pdf_content_raw_streams(streams)
pdf_parse_content_ops_from_view_with_context(
pdf_content_concat_streams(raw_streams)[:],
Some(self),
resources,
)
}
///|
pub fn PdfDocument::parse_content_bytes_with_resources(
self : PdfDocument,
resources : PdfObject,
data : PdfBytes,
) -> Array[PdfContentOp] raise PdfError {
self.parse_content_view_with_resources(resources, data[:])
}
///|
pub fn PdfDocument::parse_content_view_with_resources(
self : PdfDocument,
resources : PdfObject,
data : BytesView,
) -> Array[PdfContentOp] raise PdfError {
pdf_parse_content_ops_from_view_with_context(data, Some(self), resources)
}
///|
fn PdfDocument::pdf_content_raw_streams(
self : PdfDocument,
streams : ArrayView[PdfObject],
) -> Array[PdfBytes] raise PdfError {
let raw_streams : Array[PdfBytes] = []
for stream_ref in streams {
match self.direct(stream_ref) {
PdfStreamObject(stream) =>
raw_streams.push(
pdf_stream_data_bytes(
self.pdf_decode_stream_value_direct(stream).data,
),
)
_ => raise ParseStreamExpected
}
}
raw_streams
}
///|
fn pdf_content_read_complex_object(
cursor : ByteCursor,
first : PdfLexeme,
) -> PdfObject raise PdfError {
let lexemes : Array[PdfLexeme] = [first]
let mut array_depth = 0
let mut dict_depth = 0
match first {
LexLeftSquare => array_depth = 1
LexLeftDict => dict_depth = 1
_ => ()
}
while array_depth > 0 || dict_depth > 0 {
let token = cursor.lex_pdf_token()
match token {
StopLexing | LexNone => raise ParseObjectExpected
LexLeftSquare => array_depth += 1
LexRightSquare => array_depth -= 1
LexLeftDict => dict_depth += 1
LexRightDict => dict_depth -= 1
_ => ()
}
lexemes.push(token)
}
pdf_parse_single_lexeme_object(lexemes)
}
///|
fn pdf_content_read_object(cursor : ByteCursor) -> PdfObject raise PdfError {
let token = cursor.lex_pdf_token()
match token {
StopLexing | LexNone => raise ParseObjectExpected
LexLeftSquare | LexLeftDict =>
pdf_content_read_complex_object(cursor, token)
_ => pdf_parse_single_lexeme_object([token])
}
}
///|
fn pdf_content_operator_or_literal(view : BytesView) -> PdfContentLexeme {
match view {
[116, 114, 117, 101] => ContentOperand(PdfBoolean(true))
[102, 97, 108, 115, 101] => ContentOperand(PdfBoolean(false))
[110, 117, 108, 108] => ContentOperand(PdfNull)
_ => ContentOperator(view)
}
}
///|
fn pdf_content_lex_next(cursor : ByteCursor) -> PdfContentLexeme raise PdfError {
cursor.drop_pdf_whitespace()
let value = cursor.peek_byte()
match value {
value if value == pdf_no_more => ContentEnd
37 => {
ignore(cursor.lex_pdf_comment())
ContentComment
}
47 | 40 | 91 | 60 => ContentOperand(pdf_content_read_object(cursor))
value if pdf_is_number_start_byte(value) =>
ContentOperand(pdf_content_read_object(cursor))
116 | 102 | 110 =>
pdf_content_operator_or_literal(cursor.read_pdf_regular_token_view())
_ => ContentOperator(cursor.read_pdf_regular_token_view())
}
}
///|
let pdf_content_inline_decode_parms_key_name : PdfName = pdf_content_name(
"/DecodeParms",
)
///|
let pdf_content_inline_dp_key_name : PdfName = pdf_content_name("/DP")
///|
let pdf_content_inline_filter_key_name : PdfName = pdf_content_name("/Filter")
///|
let pdf_content_inline_f_key_name : PdfName = pdf_content_name("/F")
///|
let pdf_content_inline_dctdecode_name_value : PdfName = pdf_content_name(
"/DCTDecode",
)
///|
let pdf_content_inline_dct_name_value : PdfName = pdf_content_name("/DCT")
///|
let pdf_content_inline_ascii_hexdecode_name_value : PdfName = pdf_content_name(
"/ASCIIHexDecode",
)
///|
let pdf_content_inline_ahx_name_value : PdfName = pdf_content_name("/AHx")
///|
let pdf_content_inline_ascii85decode_name_value : PdfName = pdf_content_name(
"/ASCII85Decode",
)
///|
let pdf_content_inline_a85_name_value : PdfName = pdf_content_name("/A85")
///|
let pdf_content_inline_runlengthdecode_name_value : PdfName = pdf_content_name(
"/RunLengthDecode",
)
///|
let pdf_content_inline_rl_name_value : PdfName = pdf_content_name("/RL")
///|
let pdf_content_inline_flatedecode_name_value : PdfName = pdf_content_name(
"/FlateDecode",
)
///|
let pdf_content_inline_fl_name_value : PdfName = pdf_content_name("/Fl")
///|
let pdf_content_inline_lzwdecode_name_value : PdfName = pdf_content_name(
"/LZWDecode",
)
///|
let pdf_content_inline_lzw_name_value : PdfName = pdf_content_name("/LZW")
///|
let pdf_content_inline_im_key_name : PdfName = pdf_content_name("/IM")
///|
let pdf_content_inline_image_mask_key_name : PdfName = pdf_content_name(
"/ImageMask",
)
///|
let pdf_content_inline_cs_key_name : PdfName = pdf_content_name("/CS")
///|
let pdf_content_inline_colorspace_key_name : PdfName = pdf_content_name(
"/ColorSpace",
)
///|
let pdf_content_inline_g_name : PdfName = pdf_content_name("/G")
///|
let pdf_content_inline_device_gray_name : PdfName = pdf_content_name(
"/DeviceGray",
)
///|
let pdf_content_inline_rgb_name : PdfName = pdf_content_name("/RGB")
///|
let pdf_content_inline_device_rgb_name : PdfName = pdf_content_name(
"/DeviceRGB",
)
///|
let pdf_content_inline_cmyk_name : PdfName = pdf_content_name("/CMYK")
///|
let pdf_content_inline_device_cmyk_name : PdfName = pdf_content_name(
"/DeviceCMYK",
)
///|
let pdf_content_inline_bpc_key_name : PdfName = pdf_content_name("/BPC")
///|
let pdf_content_inline_bits_per_component_key_name : PdfName = pdf_content_name(
"/BitsPerComponent",
)
///|
let pdf_content_inline_w_key_name : PdfName = pdf_content_name("/W")
///|
let pdf_content_inline_width_key_name : PdfName = pdf_content_name("/Width")
///|
let pdf_content_inline_h_key_name : PdfName = pdf_content_name("/H")
///|
let pdf_content_inline_height_key_name : PdfName = pdf_content_name("/Height")
///|
fn pdf_content_inline_decode_parms_name() -> PdfName {
pdf_content_inline_decode_parms_key_name
}
///|
fn pdf_content_inline_dp_name() -> PdfName {
pdf_content_inline_dp_key_name
}
///|
fn pdf_content_inline_filter_name() -> PdfName {
pdf_content_inline_filter_key_name
}
///|
fn pdf_content_inline_f_name() -> PdfName {
pdf_content_inline_f_key_name
}
///|
fn pdf_content_inline_dctdecode_name() -> PdfName {
pdf_content_inline_dctdecode_name_value
}
///|
fn pdf_content_inline_dct_name() -> PdfName {
pdf_content_inline_dct_name_value
}
///|
fn pdf_content_inline_ascii_hexdecode_name() -> PdfName {
pdf_content_inline_ascii_hexdecode_name_value
}
///|
fn pdf_content_inline_ahx_name() -> PdfName {
pdf_content_inline_ahx_name_value
}
///|
fn pdf_content_inline_ascii85decode_name() -> PdfName {
pdf_content_inline_ascii85decode_name_value
}
///|
fn pdf_content_inline_a85_name() -> PdfName {
pdf_content_inline_a85_name_value
}
///|
fn pdf_content_inline_runlengthdecode_name() -> PdfName {
pdf_content_inline_runlengthdecode_name_value
}
///|
fn pdf_content_inline_rl_name() -> PdfName {
pdf_content_inline_rl_name_value
}
///|
fn pdf_content_inline_flatedecode_name() -> PdfName {
pdf_content_inline_flatedecode_name_value
}
///|
fn pdf_content_inline_fl_name() -> PdfName {
pdf_content_inline_fl_name_value
}
///|
fn pdf_content_inline_lzwdecode_name() -> PdfName {
pdf_content_inline_lzwdecode_name_value
}
///|
fn pdf_content_inline_lzw_name() -> PdfName {
pdf_content_inline_lzw_name_value
}
///|
fn pdf_content_inline_filter_value(dictionary : PdfObject) -> PdfObject? {
match dictionary.lookup_immediate(pdf_content_inline_f_name()) {
Some(value) => Some(value)
None => dictionary.lookup_immediate(pdf_content_inline_filter_name())
}
}
///|
fn pdf_content_inline_lookup_orelse(
dictionary : PdfObject,
first : PdfName,
second : PdfName,
) -> PdfObject? {
match dictionary.lookup_immediate(first) {
Some(value) => Some(value)
None => dictionary.lookup_immediate(second)
}
}
///|
fn pdf_content_inline_int_orelse(
dictionary : PdfObject,
first : PdfName,
second : PdfName,
) -> Int? {
match pdf_content_inline_lookup_orelse(dictionary, first, second) {
Some(PdfInteger(value)) if value >= 0 => Some(value)
_ => None
}
}
///|
fn pdf_content_inline_image_mask(dictionary : PdfObject) -> Bool {
match
pdf_content_inline_lookup_orelse(
dictionary, pdf_content_inline_im_key_name, pdf_content_inline_image_mask_key_name,
) {
Some(PdfBoolean(true)) => true
_ => false
}
}
///|
fn pdf_content_inline_components(
document : PdfDocument?,
resources : PdfObject,
dictionary : PdfObject,
) -> Int? raise PdfError {
match
pdf_content_inline_lookup_orelse(
dictionary, pdf_content_inline_cs_key_name, pdf_content_inline_colorspace_key_name,
) {
Some(PdfNameObject(name)) =>
if name == pdf_content_inline_g_name ||
name == pdf_content_inline_device_gray_name {
Some(1)
} else if name == pdf_content_inline_rgb_name ||
name == pdf_content_inline_device_rgb_name {
Some(3)
} else if name == pdf_content_inline_cmyk_name ||
name == pdf_content_inline_device_cmyk_name {
Some(4)
} else {
match document {
Some(document) =>
Some(
document.colour_space_components(resources, PdfNameObject(name)),
)
None => None
}
}
Some(colour_space) =>
match document {
Some(document) =>
Some(document.colour_space_components(resources, colour_space))
None => None
}
None if pdf_content_inline_image_mask(dictionary) => Some(1)
_ => None
}
}
///|
fn pdf_content_inline_bits_per_component(dictionary : PdfObject) -> Int? {
match
pdf_content_inline_int_orelse(
dictionary, pdf_content_inline_bpc_key_name, pdf_content_inline_bits_per_component_key_name,
) {
Some(value) if value > 0 => Some(value)
None if pdf_content_inline_image_mask(dictionary) => Some(1)
_ => None
}
}
///|
fn pdf_content_inline_declared_data_length(dictionary : PdfObject) -> Int? {
pdf_content_inline_int_orelse(
dictionary, pdf_content_inline_l_key_name, pdf_content_length_key_name,
)
}
///|
fn pdf_content_inline_filter_is_empty(dictionary : PdfObject) -> Bool {
match pdf_content_inline_filter_value(dictionary) {
None | Some(PdfArray([])) => true
_ => false
}
}
///|
fn pdf_content_inline_image_data_length(
document : PdfDocument?,
resources : PdfObject,
dictionary : PdfObject,
) -> Int? raise PdfError {
if !pdf_content_inline_filter_is_empty(dictionary) {
pdf_content_inline_declared_data_length(dictionary)
} else {
let declared = pdf_content_inline_declared_data_length(dictionary)
let metadata_length = try {
match
(
pdf_content_inline_int_orelse(
dictionary, pdf_content_inline_w_key_name, pdf_content_inline_width_key_name,
),
pdf_content_inline_int_orelse(
dictionary, pdf_content_inline_h_key_name, pdf_content_inline_height_key_name,
),
pdf_content_inline_bits_per_component(dictionary),
pdf_content_inline_components(document, resources, dictionary),
) {
(Some(width), Some(height), Some(bits), Some(components)) => {
let row_bits = width * components * bits
let row_bytes = if row_bits % 8 == 0 {
row_bits / 8
} else {
row_bits / 8 + 1
}
Some(row_bytes * height)
}
_ => None
}
} catch {
error =>
match declared {
Some(_) => declared
None => raise error
}
}
match metadata_length {
Some(length) => Some(length)
None => declared
}
}
}
///|
fn pdf_content_filter_is_inline_dct(filter : PdfObject) -> Bool {
match filter {
PdfNameObject(name) =>
name == pdf_content_inline_dctdecode_name() ||
name == pdf_content_inline_dct_name()
PdfArray([PdfNameObject(name), ..]) =>
name == pdf_content_inline_dctdecode_name() ||
name == pdf_content_inline_dct_name()
_ => false
}
}
///|
fn pdf_content_filter_name_inline_text_filter(
name : PdfName,
) -> PdfContentInlineTextFilter? {
if name == pdf_content_inline_ascii_hexdecode_name() ||
name == pdf_content_inline_ahx_name() {
Some(PdfContentInlineAsciiHex)
} else if name == pdf_content_inline_ascii85decode_name() ||
name == pdf_content_inline_a85_name() {
Some(PdfContentInlineAscii85)
} else {
None
}
}
///|
fn pdf_content_filter_inline_text_filter(
filter : PdfObject,
) -> PdfContentInlineTextFilter? {
match filter {
PdfNameObject(name) => pdf_content_filter_name_inline_text_filter(name)
PdfArray([PdfNameObject(name), ..]) =>
pdf_content_filter_name_inline_text_filter(name)
_ => None
}
}
///|
fn pdf_content_filter_single_inline_text_filter(
filter : PdfObject,
) -> PdfContentInlineTextFilter? {
match filter {
PdfNameObject(name) => pdf_content_filter_name_inline_text_filter(name)
PdfArray([PdfNameObject(name)]) =>
pdf_content_filter_name_inline_text_filter(name)
_ => None
}
}
///|
fn pdf_content_filter_name_is_inline_run_length(name : PdfName) -> Bool {
name == pdf_content_inline_runlengthdecode_name() ||
name == pdf_content_inline_rl_name()
}
///|
fn pdf_content_filter_is_inline_run_length(filter : PdfObject) -> Bool {
match filter {
PdfNameObject(name) => pdf_content_filter_name_is_inline_run_length(name)
PdfArray([PdfNameObject(name), ..]) =>
pdf_content_filter_name_is_inline_run_length(name)
_ => false
}
}
///|
fn pdf_content_filter_is_single_inline_run_length(filter : PdfObject) -> Bool {
match filter {
PdfNameObject(name) => pdf_content_filter_name_is_inline_run_length(name)
PdfArray([PdfNameObject(name)]) =>
pdf_content_filter_name_is_inline_run_length(name)
_ => false
}
}
///|
fn pdf_content_filter_name_is_inline_flate(name : PdfName) -> Bool {
name == pdf_content_inline_flatedecode_name() ||
name == pdf_content_inline_fl_name()
}
///|
fn pdf_content_filter_is_inline_flate(filter : PdfObject) -> Bool {
match filter {
PdfNameObject(name) => pdf_content_filter_name_is_inline_flate(name)
PdfArray([PdfNameObject(name), ..]) =>
pdf_content_filter_name_is_inline_flate(name)
_ => false
}
}
///|
fn pdf_content_filter_is_single_inline_flate(filter : PdfObject) -> Bool {
match filter {
PdfNameObject(name) => pdf_content_filter_name_is_inline_flate(name)
PdfArray([PdfNameObject(name)]) =>
pdf_content_filter_name_is_inline_flate(name)
_ => false
}
}
///|
fn pdf_content_filter_name_is_inline_lzw(name : PdfName) -> Bool {
name == pdf_content_inline_lzwdecode_name() ||
name == pdf_content_inline_lzw_name()
}
///|
fn pdf_content_filter_is_inline_lzw(filter : PdfObject) -> Bool {
match filter {
PdfNameObject(name) => pdf_content_filter_name_is_inline_lzw(name)
PdfArray([PdfNameObject(name), ..]) =>
pdf_content_filter_name_is_inline_lzw(name)
_ => false
}
}
///|
fn pdf_content_filter_is_single_inline_lzw(filter : PdfObject) -> Bool {
match filter {
PdfNameObject(name) => pdf_content_filter_name_is_inline_lzw(name)
PdfArray([PdfNameObject(name)]) =>
pdf_content_filter_name_is_inline_lzw(name)
_ => false
}
}
///|
fn pdf_content_inline_image_uses_dct(dictionary : PdfObject) -> Bool {
match pdf_content_inline_filter_value(dictionary) {
Some(filter) => pdf_content_filter_is_inline_dct(filter)
None => false
}
}
///|
fn pdf_content_inline_image_text_filter(
dictionary : PdfObject,
) -> PdfContentInlineTextFilter? {
match pdf_content_inline_filter_value(dictionary) {
Some(filter) => pdf_content_filter_inline_text_filter(filter)
None => None
}
}
///|
fn pdf_content_inline_image_single_text_filter(
dictionary : PdfObject,
) -> PdfContentInlineTextFilter? {
match pdf_content_inline_filter_value(dictionary) {
Some(filter) => pdf_content_filter_single_inline_text_filter(filter)
None => None
}
}
///|
fn pdf_content_inline_image_uses_run_length(dictionary : PdfObject) -> Bool {
match pdf_content_inline_filter_value(dictionary) {
Some(filter) => pdf_content_filter_is_inline_run_length(filter)
None => false
}
}
///|
fn pdf_content_inline_image_uses_single_run_length(
dictionary : PdfObject,
) -> Bool {
match pdf_content_inline_filter_value(dictionary) {
Some(filter) => pdf_content_filter_is_single_inline_run_length(filter)
None => false
}
}
///|
fn pdf_content_inline_image_uses_flate(dictionary : PdfObject) -> Bool {
match pdf_content_inline_filter_value(dictionary) {
Some(filter) => pdf_content_filter_is_inline_flate(filter)
None => false
}
}
///|
fn pdf_content_inline_image_uses_single_flate(dictionary : PdfObject) -> Bool {
match pdf_content_inline_filter_value(dictionary) {
Some(filter) => pdf_content_filter_is_single_inline_flate(filter)
None => false
}
}
///|
fn pdf_content_inline_image_uses_lzw(dictionary : PdfObject) -> Bool {
match pdf_content_inline_filter_value(dictionary) {
Some(filter) => pdf_content_filter_is_inline_lzw(filter)
None => false
}
}
///|
fn pdf_content_inline_image_uses_single_lzw(dictionary : PdfObject) -> Bool {
match pdf_content_inline_filter_value(dictionary) {
Some(filter) => pdf_content_filter_is_single_inline_lzw(filter)
None => false
}
}
///|
fn pdf_content_read_inline_image_data(
cursor : ByteCursor,
) -> PdfBytes raise PdfError {
match cursor.peek_byte() {
value if pdf_is_whitespace_byte(value) => cursor.nudge()
_ => ()
}
let view = cursor.remaining_view()
let mut found = false
let mut index = 0
let mut data_length = 0
let mut skip_before_marker = 0
while !found && index + 1 < view.length() {
let is_marker = view[index].to_int() == 69 && view[index + 1].to_int() == 73
let before_ok = index == 0 ||
pdf_is_whitespace_byte(view[index - 1].to_int())
let after_index = index + 2
let after_ok = after_index >= view.length() ||
pdf_is_whitespace_byte(view[after_index].to_int())
if is_marker && before_ok && after_ok {
found = true
if index > 0 && pdf_is_whitespace_byte(view[index - 1].to_int()) {
data_length = index - 1
skip_before_marker = 1
} else {
data_length = index
skip_before_marker = 0
}
} else {
index += 1
}
}
if !found {
raise ParseEndStreamExpected
}
let data = cursor.read_view(data_length).to_owned()
if skip_before_marker > 0 {
ignore(cursor.read_view(skip_before_marker))
}
ignore(cursor.read_view(2))
data
}
///|
fn pdf_content_run_length_encoded_length(data : BytesView) -> Int? {
let mut index = 0
while index < data.length() {
let control = data[index].to_int()
index += 1
if control < 128 {
index += control + 1
} else if control > 128 {
index += 1
} else {
return Some(index)
}
}
None
}
///|
fn pdf_content_ascii_hex_encoded_length(data : BytesView) -> Int? {
for index in 0.. Int? {
let mut index = 0
while index + 1 < data.length() {
if data[index].to_int() == 126 && data[index + 1].to_int() == 62 {
return Some(index + 2)
}
index += 1
}
None
}
///|
fn pdf_content_text_encoded_inline_image_length(
data : BytesView,
filter : PdfContentInlineTextFilter,
) -> Int? {
match filter {
PdfContentInlineAsciiHex => pdf_content_ascii_hex_encoded_length(data)
PdfContentInlineAscii85 => pdf_content_ascii85_encoded_length(data)
}
}
///|
fn pdf_content_read_text_encoded_inline_image_data(
cursor : ByteCursor,
filter : PdfContentInlineTextFilter,
) -> PdfBytes raise PdfError {
match cursor.peek_byte() {
value if pdf_is_whitespace_byte(value) => cursor.nudge()
_ => ()
}
match
pdf_content_text_encoded_inline_image_length(
cursor.remaining_view(),
filter,
) {
Some(length) => {
let data = cursor.read_view(length).to_owned()
pdf_content_read_inline_image_end(cursor)
data
}
None => raise ParseEndStreamExpected
}
}
///|
fn pdf_content_read_text_encoded_inline_image_decoded(
cursor : ByteCursor,
filter : PdfContentInlineTextFilter,
) -> PdfBytes raise PdfError {
match cursor.peek_byte() {
value if pdf_is_whitespace_byte(value) => cursor.nudge()
_ => ()
}
match
pdf_content_text_encoded_inline_image_length(
cursor.remaining_view(),
filter,
) {
Some(length) => {
let encoded = cursor.read_view(length)
let decoded = match filter {
PdfContentInlineAsciiHex => pdf_ascii_hex_decode_view(encoded)
PdfContentInlineAscii85 => pdf_ascii85_decode_view(encoded)
}
pdf_content_read_inline_image_end(cursor)
decoded
}
None => raise ParseEndStreamExpected
}
}
///|
fn pdf_content_read_flate_inline_image_data(
cursor : ByteCursor,
) -> PdfBytes raise PdfError {
match cursor.peek_byte() {
value if pdf_is_whitespace_byte(value) => cursor.nudge()
_ => ()
}
let (_, length) = pdf_flate_decode_view_prefix(cursor.remaining_view())
let data = cursor.read_view(length).to_owned()
pdf_content_read_inline_image_end(cursor)
data
}
///|
fn pdf_content_read_flate_inline_image_decoded(
cursor : ByteCursor,
) -> PdfBytes raise PdfError {
match cursor.peek_byte() {
value if pdf_is_whitespace_byte(value) => cursor.nudge()
_ => ()
}
let (decoded, length) = pdf_flate_decode_view_prefix(cursor.remaining_view())
ignore(cursor.read_view(length))
pdf_content_read_inline_image_end(cursor)
decoded
}
///|
fn pdf_content_read_lzw_inline_image_data(
cursor : ByteCursor,
dictionary : PdfObject,
decode_parms : PdfObject?,
) -> PdfBytes raise PdfError {
match cursor.peek_byte() {
value if pdf_is_whitespace_byte(value) => cursor.nudge()
_ => ()
}
let with_decode_parms = match decode_parms {
Some(value) =>
dictionary.add_dict_entry(pdf_content_inline_dp_name(), value)
None => dictionary
}
let (_, length) = pdf_lzw_decode_view_prefix(
cursor.remaining_view(),
early_change=pdf_lzw_early_change(with_decode_parms),
)
let data = cursor.read_view(length).to_owned()
pdf_content_read_inline_image_end(cursor)
data
}
///|
fn pdf_content_read_lzw_inline_image_decoded(
cursor : ByteCursor,
) -> PdfBytes raise PdfError {
match cursor.peek_byte() {
value if pdf_is_whitespace_byte(value) => cursor.nudge()
_ => ()
}
let (decoded, length) = pdf_lzw_decode_view_prefix(cursor.remaining_view())
ignore(cursor.read_view(length))
pdf_content_read_inline_image_end(cursor)
decoded
}
///|
fn pdf_content_read_run_length_inline_image_data(
cursor : ByteCursor,
) -> PdfBytes raise PdfError {
match cursor.peek_byte() {
value if pdf_is_whitespace_byte(value) => cursor.nudge()
_ => ()
}
match pdf_content_run_length_encoded_length(cursor.remaining_view()) {
Some(length) => {
let data = cursor.read_view(length).to_owned()
pdf_content_read_inline_image_end(cursor)
data
}
None => raise ParseEndStreamExpected
}
}
///|
fn pdf_content_run_length_decode_view_prefix(
data : BytesView,
) -> (PdfBytes, Int) raise PdfError {
let output : Array[Byte] = []
let mut index = 0
while index < data.length() {
let control = data[index].to_int()
index += 1
if control < 128 {
let wanted = control + 1
if index + wanted > data.length() {
raise ParseEndStreamExpected
}
for i in 0.. 128 {
if index >= data.length() {
raise ParseEndStreamExpected
}
let value = data[index]
index += 1
for _ in 0..<(257 - control) {
output.push(value)
}
} else {
return (Bytes::from_array(output), index)
}
}
raise ParseEndStreamExpected
}
///|
fn pdf_content_read_run_length_inline_image_decoded(
cursor : ByteCursor,
) -> PdfBytes raise PdfError {
match cursor.peek_byte() {
value if pdf_is_whitespace_byte(value) => cursor.nudge()
_ => ()
}
let (decoded, length) = pdf_content_run_length_decode_view_prefix(
cursor.remaining_view(),
)
ignore(cursor.read_view(length))
pdf_content_read_inline_image_end(cursor)
decoded
}
///|
fn pdf_content_decode_inline_image_data(
dictionary : PdfObject,
decode_parms : PdfObject?,
encoded : PdfBytes,
) -> (PdfObject, PdfBytes) raise PdfError {
let with_decode_parms = match decode_parms {
Some(value) =>
dictionary.add_dict_entry(pdf_content_inline_dp_name(), value)
None => dictionary
}
let stream_dictionary = with_decode_parms.add_dict_entry(
pdf_content_length_name(),
PdfInteger(encoded.length()),
)
let decoded = pdf_decode_stream_until_unknown_value({
dictionary: stream_dictionary,
data: StreamGot(encoded),
})
let decoded_data = pdf_stream_data_bytes(decoded.data)
if pdf_stream_has_filter_value(decoded) {
(
decoded.dictionary
.remove_dict_entry(pdf_content_length_name())
.remove_dict_entry(pdf_content_inline_l_name()),
decoded_data,
)
} else {
(pdf_content_remove_inline_image_filter_metadata(dictionary), decoded_data)
}
}
///|
fn pdf_content_remove_inline_image_filter_metadata(
dictionary : PdfObject,
) -> PdfObject raise PdfError {
dictionary
.remove_dict_entry(pdf_content_inline_filter_name())
.remove_dict_entry(pdf_content_inline_f_name())
.remove_dict_entry(pdf_content_inline_decode_parms_name())
.remove_dict_entry(pdf_content_inline_dp_name())
.remove_dict_entry(pdf_content_length_name())
.remove_dict_entry(pdf_content_inline_l_name())
}
///|
fn pdf_content_read_sized_inline_image_data(
cursor : ByteCursor,
length : Int,
) -> PdfBytes raise PdfError {
match cursor.peek_byte() {
value if pdf_is_whitespace_byte(value) => cursor.nudge()
_ => ()
}
let data = cursor.read_view(length).to_owned() catch {
EndOfInput => raise ParseEndStreamExpected
error => raise error
}
pdf_content_read_inline_image_end(cursor)
data
}
///|
fn pdf_content_skip_whitespace(cursor : ByteCursor) -> Unit {
while pdf_is_whitespace_byte(cursor.peek_byte()) {
cursor.nudge()
}
}
///|
fn pdf_content_consume_next_inline_image_end(
cursor : ByteCursor,
) -> Bool raise PdfError {
let remaining = cursor.remaining_view()
if remaining.length() < 2 {
false
} else {
let limit = remaining.length() - 1
for index in 0.. Unit raise PdfError {
pdf_content_skip_whitespace(cursor)
let marker_start = cursor.position()
match (cursor.read_byte(), cursor.read_byte()) {
(Some(first), Some(second)) if first.to_int() == 69 && second.to_int() == 73 =>
()
_ => {
try! cursor.seek(marker_start)
if !pdf_content_consume_next_inline_image_end(cursor) {
raise ParseEndStreamExpected
}
}
}
}
///|
fn pdf_content_read_dct_inline_image_data(
cursor : ByteCursor,
) -> PdfBytes raise PdfError {
match cursor.peek_byte() {
value if pdf_is_whitespace_byte(value) => cursor.nudge()
_ => ()
}
let data = cursor.read_jpeg_data()
pdf_content_read_inline_image_end(cursor)
data
}
///|
fn pdf_content_read_inline_image(
cursor : ByteCursor,
document : PdfDocument?,
resources : PdfObject,
) -> PdfContentOp raise PdfError {
let entries : Array[(PdfName, PdfObject)] = []
let mut decode_parms : PdfObject? = None
let mut done = false
while !done {
match pdf_content_lex_next(cursor) {
ContentOperator(operator) if operator ==
pdf_content_inline_image_data_operator => done = true
ContentOperand(PdfNameObject(key)) =>
match pdf_content_lex_next(cursor) {
ContentOperand(value) =>
if key == pdf_content_inline_dp_name() ||
key == pdf_content_inline_decode_parms_name() {
decode_parms = Some(value)
} else {
entries.push((key, value))
}
_ => raise ContentOperandExpected
}
ContentComment => ()
_ => raise ContentOperandExpected
}
}
let dictionary = PdfDictionary(entries)
if pdf_content_inline_image_uses_dct(dictionary) {
Op_InlineImage(
dictionary,
decode_parms,
pdf_content_read_dct_inline_image_data(cursor),
)
} else {
match pdf_content_inline_image_text_filter(dictionary) {
Some(filter) =>
match
(
decode_parms,
pdf_content_inline_image_single_text_filter(dictionary),
) {
(None, Some(single_filter)) =>
Op_InlineImage(
pdf_content_remove_inline_image_filter_metadata(dictionary),
None,
pdf_content_read_text_encoded_inline_image_decoded(
cursor, single_filter,
),
)
_ => {
let encoded = pdf_content_read_text_encoded_inline_image_data(
cursor, filter,
)
let (decoded_dictionary, decoded) = pdf_content_decode_inline_image_data(
dictionary, decode_parms, encoded,
)
Op_InlineImage(decoded_dictionary, None, decoded)
}
}
None if pdf_content_inline_image_uses_run_length(dictionary) =>
if decode_parms is None &&
pdf_content_inline_image_uses_single_run_length(dictionary) {
Op_InlineImage(
pdf_content_remove_inline_image_filter_metadata(dictionary),
None,
pdf_content_read_run_length_inline_image_decoded(cursor),
)
} else {
let encoded = pdf_content_read_run_length_inline_image_data(cursor)
let (decoded_dictionary, decoded) = pdf_content_decode_inline_image_data(
dictionary, decode_parms, encoded,
)
Op_InlineImage(decoded_dictionary, None, decoded)
}
None if pdf_content_inline_image_uses_flate(dictionary) =>
if decode_parms is None &&
pdf_content_inline_image_uses_single_flate(dictionary) {
Op_InlineImage(
pdf_content_remove_inline_image_filter_metadata(dictionary),
None,
pdf_content_read_flate_inline_image_decoded(cursor),
)
} else {
let encoded = pdf_content_read_flate_inline_image_data(cursor)
let (decoded_dictionary, decoded) = pdf_content_decode_inline_image_data(
dictionary, decode_parms, encoded,
)
Op_InlineImage(decoded_dictionary, None, decoded)
}
None if pdf_content_inline_image_uses_lzw(dictionary) =>
if decode_parms is None &&
pdf_content_inline_image_uses_single_lzw(dictionary) {
Op_InlineImage(
pdf_content_remove_inline_image_filter_metadata(dictionary),
None,
pdf_content_read_lzw_inline_image_decoded(cursor),
)
} else {
let encoded = pdf_content_read_lzw_inline_image_data(
cursor, dictionary, decode_parms,
)
let (decoded_dictionary, decoded) = pdf_content_decode_inline_image_data(
dictionary, decode_parms, encoded,
)
Op_InlineImage(decoded_dictionary, None, decoded)
}
None =>
Op_InlineImage(
dictionary,
decode_parms,
match
pdf_content_inline_image_data_length(
document, resources, dictionary,
) {
Some(length) =>
pdf_content_read_sized_inline_image_data(cursor, length)
None => pdf_content_read_inline_image_data(cursor)
},
)
}
}
}
///|
fn pdf_content_operand_number(
operands : ArrayView[PdfObject],
index : Int,
) -> Double? {
if index >= operands.length() {
None
} else {
match operands[index] {
PdfReal(value) => Some(value)
PdfInteger(value) => Some(value.to_double())
_ => None
}
}
}
///|
fn pdf_content_operand_int(
operands : ArrayView[PdfObject],
index : Int,
) -> Int? {
if index >= operands.length() {
None
} else {
match operands[index] {
PdfInteger(value) => Some(value)
PdfReal(value) => Some(value.to_int())
_ => None
}
}
}
///|
fn pdf_content_operand_name(
operands : ArrayView[PdfObject],
index : Int,
) -> PdfName? {
if index >= operands.length() {
None
} else {
match operands[index] {
PdfNameObject(name) => Some(name)
_ => None
}
}
}
///|
fn pdf_content_operand_string(
operands : ArrayView[PdfObject],
index : Int,
) -> PdfBytes? {
if index >= operands.length() {
None
} else {
match operands[index] {
PdfString(bytes) => Some(bytes)
_ => None
}
}
}
///|
fn pdf_content_numbers_from_array(object : PdfObject) -> Array[Double]? {
match object {
PdfArray(items) => {
let output : Array[Double] = []
for item in items {
match item {
PdfReal(value) => output.push(value)
PdfInteger(value) => output.push(value.to_double())
_ => break None
}
} nobreak {
Some(output)
}
}
_ => None
}
}
///|
fn pdf_content_numbers_from_operands(
operands : ArrayView[PdfObject],
) -> Array[Double]? {
let output : Array[Double] = []
for operand in operands {
match operand {
PdfReal(value) => output.push(value)
PdfInteger(value) => output.push(value.to_double())
_ => break None
}
} nobreak {
Some(output)
}
}
///|
fn pdf_content_malformed_color_fallback() -> Array[Double] {
[0.0, 0.0, 0.0]
}
///|
fn pdf_content_numbers_or_malformed_color_fallback(
operands : ArrayView[PdfObject],
) -> Array[Double] {
match pdf_content_numbers_from_operands(operands) {
Some(values) => values
None => pdf_content_malformed_color_fallback()
}
}
///|
fn pdf_content_named_color_operands(
operands : ArrayView[PdfObject],
) -> (PdfName, Array[Double])? {
if operands.length() == 0 {
None
} else {
match operands[operands.length() - 1] {
PdfNameObject(name) => {
let numbers : Array[Double] = []
for i in 0..<(operands.length() - 1) {
match operands[i] {
PdfReal(value) => numbers.push(value)
PdfInteger(value) => numbers.push(value.to_double())
_ => break None
}
} nobreak {
Some((name, numbers))
}
}
_ => None
}
}
}
///|
fn pdf_content_named_color_operands_or_malformed_fallback(
operands : ArrayView[PdfObject],
) -> (PdfName, Array[Double])? {
match pdf_content_named_color_operands(operands) {
Some(named_color) => Some(named_color)
None =>
if operands.length() == 0 {
None
} else {
match operands[operands.length() - 1] {
PdfNameObject(name) =>
Some((name, pdf_content_malformed_color_fallback()))
_ => None
}
}
}
}
///|
fn pdf_content_tj_array_from_operand(object : PdfObject) -> PdfObject? {
match object {
PdfArray(items) => {
let output : Array[PdfObject] = []
for item in items {
match item {
PdfString(bytes) => output.push(PdfString(bytes))
PdfInteger(value) => output.push(PdfReal(value.to_double()))
PdfReal(value) => output.push(PdfReal(value))
_ => ()
}
}
Some(PdfArray(output))
}
_ => None
}
}
///|
fn pdf_content_section_unknown(
operands : ArrayView[PdfObject],
operator : BytesView,
) -> PdfContentOp raise PdfError {
let output : Array[Byte] = []
pdf_content_push_section(output, operands, operator)
Op_Unknown(Bytes::from_array(output))
}
///|
fn pdf_content_matrix_from_operands(
operands : ArrayView[PdfObject],
) -> TransformMatrix? {
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
pdf_content_operand_number(operands, 2),
pdf_content_operand_number(operands, 3),
pdf_content_operand_number(operands, 4),
pdf_content_operand_number(operands, 5),
) {
(Some(a), Some(b), Some(c), Some(d), Some(e), Some(f)) =>
Some({ a, b, c, d, e, f })
_ => None
}
}
///|
fn pdf_content_dash_op_from_operands(
operands : ArrayView[PdfObject],
) -> PdfContentOp? raise PdfError {
if operands.length() != 2 {
None
} else {
match (operands[0], pdf_content_operand_number(operands, 1)) {
(PdfArray(_), Some(phase)) =>
match pdf_content_numbers_from_array(operands[0]) {
Some(dashes) => Some(Op_d(dashes, phase))
None => raise NumberExpected
}
_ => None
}
}
}
///|
fn pdf_content_parse_known_section(
operands : ArrayView[PdfObject],
operator : BytesView,
) -> PdfContentOp? raise PdfError {
match operator {
[113] if operands.length() == 0 => Some(Op_q)
[81] if operands.length() == 0 => Some(Op_Q)
[104] if operands.length() == 0 => Some(Op_h)
[83] if operands.length() == 0 => Some(Op_S)
[115] if operands.length() == 0 => Some(Op_s)
[102] if operands.length() == 0 => Some(Op_f)
[70] if operands.length() == 0 => Some(Op_F)
[102, 42] if operands.length() == 0 => Some(Op_fstar)
[66] if operands.length() == 0 => Some(Op_B)
[66, 42] if operands.length() == 0 => Some(Op_Bstar)
[98] if operands.length() == 0 => Some(Op_b)
[98, 42] if operands.length() == 0 => Some(Op_bstar)
[110] if operands.length() == 0 => Some(Op_n)
[87] if operands.length() == 0 => Some(Op_W)
[87, 42] if operands.length() == 0 => Some(Op_Wstar)
[66, 84] if operands.length() == 0 => Some(Op_BT)
[69, 84] if operands.length() == 0 => Some(Op_ET)
[84, 42] if operands.length() == 0 => Some(Op_Tstar)
[69, 77, 67] if operands.length() == 0 => Some(Op_EMC)
[66, 88] if operands.length() == 0 => Some(Op_BX)
[69, 88] if operands.length() == 0 => Some(Op_EX)
[119] if operands.length() == 1 =>
match pdf_content_operand_number(operands, 0) {
Some(width) => Some(Op_w(width))
None => None
}
[74] if operands.length() == 1 =>
match pdf_content_operand_int(operands, 0) {
Some(cap) => Some(Op_J(cap))
None => None
}
[106] if operands.length() == 1 =>
match pdf_content_operand_int(operands, 0) {
Some(join) => Some(Op_j(join))
None => None
}
[77] if operands.length() == 1 =>
match pdf_content_operand_number(operands, 0) {
Some(limit) => Some(Op_M(limit))
None => None
}
[100] => pdf_content_dash_op_from_operands(operands)
[114, 105] if operands.length() == 1 =>
match pdf_content_operand_name(operands, 0) {
Some(intent) => Some(Op_ri(intent))
None => None
}
[105] if operands.length() == 1 =>
match pdf_content_operand_number(operands, 0) {
Some(flatness) => Some(Op_i(flatness))
None => None
}
[99, 109] if operands.length() == 6 =>
match pdf_content_matrix_from_operands(operands) {
Some(matrix) => Some(Op_cm(matrix))
None => None
}
[84, 109] if operands.length() == 6 =>
match pdf_content_matrix_from_operands(operands) {
Some(matrix) => Some(Op_Tm(matrix))
None => None
}
[109] if operands.length() == 2 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
) {
(Some(x), Some(y)) => Some(Op_m(x, y))
_ => None
}
[108] if operands.length() == 2 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
) {
(Some(x), Some(y)) => Some(Op_l(x, y))
_ => None
}
[99] if operands.length() == 6 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
pdf_content_operand_number(operands, 2),
pdf_content_operand_number(operands, 3),
pdf_content_operand_number(operands, 4),
pdf_content_operand_number(operands, 5),
) {
(Some(x1), Some(y1), Some(x2), Some(y2), Some(x3), Some(y3)) =>
Some(Op_c(x1, y1, x2, y2, x3, y3))
_ => None
}
[118] if operands.length() == 4 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
pdf_content_operand_number(operands, 2),
pdf_content_operand_number(operands, 3),
) {
(Some(x2), Some(y2), Some(x3), Some(y3)) => Some(Op_v(x2, y2, x3, y3))
_ => None
}
[121] if operands.length() == 4 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
pdf_content_operand_number(operands, 2),
pdf_content_operand_number(operands, 3),
) {
(Some(x1), Some(y1), Some(x3), Some(y3)) => Some(Op_y(x1, y1, x3, y3))
_ => None
}
[114, 101] if operands.length() == 4 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
pdf_content_operand_number(operands, 2),
pdf_content_operand_number(operands, 3),
) {
(Some(x), Some(y), Some(width), Some(height)) =>
Some(Op_re(x, y, width, height))
_ => None
}
[84, 99] if operands.length() == 1 =>
match pdf_content_operand_number(operands, 0) {
Some(spacing) => Some(Op_Tc(spacing))
None => None
}
[84, 119] if operands.length() == 1 =>
match pdf_content_operand_number(operands, 0) {
Some(spacing) => Some(Op_Tw(spacing))
None => None
}
[84, 122] if operands.length() == 1 =>
match pdf_content_operand_number(operands, 0) {
Some(scale) => Some(Op_Tz(scale))
None => None
}
[84, 76] if operands.length() == 1 =>
match pdf_content_operand_number(operands, 0) {
Some(leading) => Some(Op_TL(leading))
None => None
}
[84, 102] if operands.length() == 2 =>
match
(
pdf_content_operand_name(operands, 0),
pdf_content_operand_number(operands, 1),
) {
(Some(font), Some(size)) => Some(Op_Tf(font, size))
_ => None
}
[84, 114] if operands.length() == 1 =>
match pdf_content_operand_int(operands, 0) {
Some(mode) => Some(Op_Tr(mode))
None => None
}
[84, 115] if operands.length() == 1 =>
match pdf_content_operand_number(operands, 0) {
Some(rise) => Some(Op_Ts(rise))
None => None
}
[84, 100] if operands.length() == 2 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
) {
(Some(tx), Some(ty)) => Some(Op_Td(tx, ty))
_ => None
}
[84, 68] if operands.length() == 2 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
) {
(Some(tx), Some(ty)) => Some(Op_TD(tx, ty))
_ => None
}
[84, 106] if operands.length() == 1 =>
match pdf_content_operand_string(operands, 0) {
Some(text) => Some(Op_Tj(text))
None => None
}
[84, 74] if operands.length() == 1 =>
match pdf_content_tj_array_from_operand(operands[0]) {
Some(array) => Some(Op_TJ(array))
None => None
}
[39] if operands.length() == 1 =>
match pdf_content_operand_string(operands, 0) {
Some(text) => Some(Op_quote(text))
None => None
}
[34] if operands.length() == 3 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
pdf_content_operand_string(operands, 2),
) {
(Some(word_space), Some(char_space), Some(text)) =>
Some(Op_double_quote(word_space, char_space, text))
_ => None
}
[100, 48] if operands.length() == 2 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
) {
(Some(width_x), Some(width_y)) => Some(Op_d0(width_x, width_y))
_ => None
}
[100, 49] if operands.length() == 6 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
pdf_content_operand_number(operands, 2),
pdf_content_operand_number(operands, 3),
pdf_content_operand_number(operands, 4),
pdf_content_operand_number(operands, 5),
) {
(
Some(width_x),
Some(width_y),
Some(llx),
Some(lly),
Some(urx),
Some(ury),
) => Some(Op_d1(width_x, width_y, llx, lly, urx, ury))
_ => None
}
[71] if operands.length() == 1 =>
match pdf_content_operand_number(operands, 0) {
Some(gray) => Some(Op_G(gray))
None => None
}
[103] if operands.length() == 1 =>
match pdf_content_operand_number(operands, 0) {
Some(gray) => Some(Op_g(gray))
None => None
}
[82, 71] if operands.length() == 3 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
pdf_content_operand_number(operands, 2),
) {
(Some(r), Some(g), Some(b)) => Some(Op_RG(r, g, b))
_ => None
}
[114, 103] if operands.length() == 3 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
pdf_content_operand_number(operands, 2),
) {
(Some(r), Some(g), Some(b)) => Some(Op_rg(r, g, b))
_ => None
}
[75] if operands.length() == 4 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
pdf_content_operand_number(operands, 2),
pdf_content_operand_number(operands, 3),
) {
(Some(c), Some(m), Some(y), Some(k)) => Some(Op_K(c, m, y, k))
_ => None
}
[107] if operands.length() == 4 =>
match
(
pdf_content_operand_number(operands, 0),
pdf_content_operand_number(operands, 1),
pdf_content_operand_number(operands, 2),
pdf_content_operand_number(operands, 3),
) {
(Some(c), Some(m), Some(y), Some(k)) => Some(Op_k(c, m, y, k))
_ => None
}
[103, 115] if operands.length() == 1 =>
match pdf_content_operand_name(operands, 0) {
Some(name) => Some(Op_gs(name))
None => None
}
[67, 83] if operands.length() == 1 =>
match pdf_content_operand_name(operands, 0) {
Some(name) => Some(Op_CS(name))
None => None
}
[99, 115] if operands.length() == 1 =>
match pdf_content_operand_name(operands, 0) {
Some(name) => Some(Op_cs(name))
None => None
}
[83, 67] =>
Some(Op_SC(pdf_content_numbers_or_malformed_color_fallback(operands)))
[115, 99] =>
Some(Op_sc(pdf_content_numbers_or_malformed_color_fallback(operands)))
[83, 67, 78] =>
match pdf_content_named_color_operands_or_malformed_fallback(operands) {
Some((name, values)) => Some(Op_SCNName(name, values))
None =>
Some(
Op_SCN(pdf_content_numbers_or_malformed_color_fallback(operands)),
)
}
[115, 99, 110] =>
match pdf_content_named_color_operands_or_malformed_fallback(operands) {
Some((name, values)) => Some(Op_scnName(name, values))
None =>
Some(
Op_scn(pdf_content_numbers_or_malformed_color_fallback(operands)),
)
}
[115, 104] if operands.length() == 1 =>
match pdf_content_operand_name(operands, 0) {
Some(name) => Some(Op_sh(name))
None => None
}
[68, 111] if operands.length() == 1 =>
match pdf_content_operand_name(operands, 0) {
Some(name) => Some(Op_Do(name))
None => None
}
[77, 80] if operands.length() == 1 =>
match pdf_content_operand_name(operands, 0) {
Some(tag) => Some(Op_MP(tag))
None => None
}
[68, 80] if operands.length() == 2 =>
match pdf_content_operand_name(operands, 0) {
Some(tag) => Some(Op_DP(tag, operands[1]))
None => None
}
[66, 77, 67] if operands.length() == 1 =>
match pdf_content_operand_name(operands, 0) {
Some(tag) => Some(Op_BMC(tag))
None => None
}
[66, 68, 67] if operands.length() == 2 =>
match pdf_content_operand_name(operands, 0) {
Some(tag) => Some(Op_BDC(tag, operands[1]))
None => None
}
_ => None
}
}
///|
fn pdf_content_parse_section(
operands : ArrayView[PdfObject],
operator : BytesView,
) -> PdfContentOp raise PdfError {
match pdf_content_parse_known_section(operands, operator) {
Some(op) => op
None => pdf_content_section_unknown(operands, operator)
}
}
///|
pub fn pdf_parse_content_ops_from_bytes(
data : PdfBytes,
) -> Array[PdfContentOp] raise PdfError {
pdf_parse_content_ops_from_view(data[:])
}
///|
pub fn pdf_parse_content_ops_from_view(
data : BytesView,
) -> Array[PdfContentOp] raise PdfError {
pdf_parse_content_ops_from_view_with_context(data, None, PdfDictionary([]))
}
///|
fn pdf_parse_content_ops_from_view_with_context(
data : BytesView,
document : PdfDocument?,
resources : PdfObject,
) -> Array[PdfContentOp] raise PdfError {
let cursor = byte_cursor_of_view(data)
let ops : Array[PdfContentOp] = []
let operands : Array[PdfObject] = []
let mut done = false
while !done {
match pdf_content_lex_next(cursor) {
ContentEnd => done = true
ContentComment => ()
ContentOperand(object) => operands.push(object)
ContentOperator(operator) =>
if operator == pdf_content_inline_image_begin_operator &&
operands.length() == 0 {
ops.push(pdf_content_read_inline_image(cursor, document, resources))
} else {
ops.push(pdf_content_parse_section(operands, operator))
operands.clear()
}
}
}
if operands.length() > 0 {
raise ContentOperatorExpected
}
ops
}