///|
/// Flat representation of PDF content stream operators.
///
/// Text strings and unknown operators are stored as raw PDF bytes. Inline images
/// carry their image dictionary, optional decode parameters, and image data; the
/// parser decodes supported inline-image filters when it can do so safely.
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)
///|
fn pdf_content_ascii(text : String) -> PdfBytes {
@ascii.encode(text)
}
///|
fn pdf_content_name(text : String) -> PdfName {
@core.pdf_name_of_bytes(pdf_content_ascii(text))
}
///|
let pdf_content_artifact_name : PdfName = pdf_content_name("/Artifact")
///|
let pdf_content_begin_artifact_name : PdfName = pdf_content_name(
"/BeginArtifact",
)
///|
let pdf_content_end_artifact_name : PdfName = pdf_content_name("/EndArtifact")
///|
/// Return the marked-content operation that begins a PDF/UA artifact.
pub fn pdf_content_begin_artifact() -> PdfContentOp {
Op_BMC(pdf_content_artifact_name)
}
///|
/// Return the marked-content operation that ends the current PDF/UA artifact.
pub fn pdf_content_end_artifact() -> PdfContentOp {
Op_EMC
}
///|
/// Mark unmarked content operations as PDF/UA artifacts.
///
/// This ports `cpdftype.ml`'s `add_artifacts` pass. Existing marked-content
/// sections entered with `BDC` are preserved as real content; unmarked runs are
/// wrapped in `/Artifact BMC ... EMC`. Back-channel `/BeginArtifact` and
/// `/EndArtifact` markers are converted to ordinary artifact marked content.
pub fn pdf_content_add_artifacts(
ops : ArrayView[PdfContentOp],
) -> Array[PdfContentOp] {
let output : Array[PdfContentOp] = Array(capacity=ops.length() + 2)
let mut in_content = false
let mut in_artifact = false
for op in ops {
match op {
Op_BMC(name) if name == pdf_content_begin_artifact_name => {
in_artifact = true
output.push(Op_BMC(pdf_content_artifact_name))
}
Op_BMC(name) if name == pdf_content_end_artifact_name => {
in_artifact = false
output.push(Op_EMC)
}
Op_BDC(_, _) => {
if in_artifact {
output.push(Op_EMC)
}
in_content = true
in_artifact = false
output.push(op)
}
Op_EMC => {
in_content = false
output.push(op)
}
_ => {
if !(in_content || in_artifact) {
in_artifact = true
output.push(Op_BMC(pdf_content_artifact_name))
}
output.push(op)
}
}
}
if in_artifact {
output.push(Op_EMC)
}
output
}