///|
/// Build cpdf add-rectangle content operators after placement is resolved.
pub fn pdf_addtext_rectangle_ops(
x : Double,
y : Double,
width : Double,
height : Double,
colour : @colour.PdfContentColour,
outline : Bool,
line_width : Double,
extgstate_name : @core.PdfName?,
) -> Array[@content.PdfContentOp] {
let ops = [
@content.pdf_content_begin_artifact(),
Op_q,
Op_BMC(pdf_addtext_cpdf_stamp()),
pdf_addtext_colour_op(colour),
pdf_addtext_colour_op_stroke(colour),
]
if outline {
ops.push(Op_w(line_width))
}
match extgstate_name {
Some(name) => ops.push(Op_gs(name))
None => ()
}
ops.push(Op_re(x, y, width, height))
ops.push(if outline { Op_s } else { Op_f })
ops.push(Op_EMC)
ops.push(Op_Q)
ops.push(@content.pdf_content_end_artifact())
ops
}
///|
fn pdf_addtext_fontpack_text_ops(
fontpack : PdfFontPack,
unique_fontnames : ArrayView[@core.PdfName],
font_size : Double,
text : String,
) -> Array[@content.PdfContentOp] raise @core.PdfError {
let codepoints = pdf_codepoints_of_utf8(@utf8.encode(text))
let triples : Array[(Int, Int, PdfFont)] = Array(capacity=codepoints.length())
for codepoint in codepoints {
match fontpack.get_char(codepoint) {
Some(triple) => triples.push(triple)
None => ()
}
}
let ops : Array[@content.PdfContentOp] = Array(capacity=triples.length() * 2)
for run in pdf_fontpack_collate_runs(triples) {
guard run.length() > 0 else { continue }
let font_index = run[0].1
if font_index < 0 || font_index >= unique_fontnames.length() {
raise SoftError("bad add-text fontpack font name list")
}
let bytes = Array::make(run.length(), b'\x00')
for index, triple in run {
bytes[index] = @core.pdf_byte_of_int(triple.0)
}
ops.push(Op_Tf(unique_fontnames[font_index], font_size))
ops.push(Op_Tj(Bytes::from_array(bytes)))
}
ops
}
///|
fn pdf_addtext_font_text_ops_with_bytes(
fontpack : PdfFontPack?,
unique_fontname : @core.PdfName,
unique_fontnames : ArrayView[@core.PdfName],
font_size : Double,
text : String,
text_bytes : @core.PdfBytes,
) -> Array[@content.PdfContentOp] raise @core.PdfError {
match fontpack {
Some(fontpack) =>
pdf_addtext_fontpack_text_ops(fontpack, unique_fontnames, font_size, text)
None => [Op_Tf(unique_fontname, font_size), Op_Tj(text_bytes)]
}
}
///|
fn pdf_addtext_text_matrix(
x : Double,
y : Double,
base_rotation : Double,
horizontal_offset : Double,
vertical_offset : Double,
text_rotation : Double,
rotation_h_offset : Double,
rotation_v_offset : Double,
) -> @geometry.TransformMatrix {
@geometry.transform_matrix_of_transform([
Translate(
x - horizontal_offset + rotation_h_offset,
y - vertical_offset + rotation_v_offset,
),
Rotate(@geometry.point2(0.0, 0.0), base_rotation + text_rotation),
])
}
///|
fn pdf_addtext_text_ops_with_bytes(
fontpack : PdfFontPack?,
x : Double,
y : Double,
base_rotation : Double,
horizontal_offset : Double,
vertical_offset : Double,
outline : Bool,
line_width : Double,
unique_fontname : @core.PdfName,
unique_fontnames : ArrayView[@core.PdfName],
extgstate_name : @core.PdfName?,
colour : @colour.PdfContentColour,
font_size : Double,
text : String,
text_bytes : @core.PdfBytes,
text_rotation : Double,
rotation_h_offset : Double,
rotation_v_offset : Double,
) -> Array[@content.PdfContentOp] raise @core.PdfError {
let textops = pdf_addtext_font_text_ops_with_bytes(
fontpack, unique_fontname, unique_fontnames, font_size, text, text_bytes,
)
let ops = [
@content.pdf_content_begin_artifact(),
Op_q,
Op_BMC(pdf_addtext_cpdf_stamp()),
Op_cm(
pdf_addtext_text_matrix(
x, y, base_rotation, horizontal_offset, vertical_offset, text_rotation, rotation_h_offset,
rotation_v_offset,
),
),
Op_BT,
]
if outline {
ops.push(Op_w(line_width))
ops.push(Op_Tr(1))
} else {
ops.push(Op_Tr(0))
}
ops.push(pdf_addtext_colour_op(colour))
ops.push(pdf_addtext_colour_op_stroke(colour))
match extgstate_name {
Some(name) => ops.push(Op_gs(name))
None => ()
}
for op in textops {
ops.push(op)
}
ops.push(Op_ET)
ops.push(Op_EMC)
ops.push(Op_Q)
ops.push(@content.pdf_content_end_artifact())
ops
}
///|
/// Build cpdf add-text text-stamp content operators after placement is resolved.
///
/// This ports the source-level `cpdfaddtext.ml` `ops` helper, including
/// `/CPDFSTAMP` artifact wrapping, placement matrix, outline rendering mode,
/// colour operators, optional opacity graphics state, simple-font charcode
/// conversion, and fontpack run switching.
pub fn pdf_addtext_text_ops(
font : PdfFont?,
fontpack : PdfFontPack?,
x : Double,
y : Double,
base_rotation : Double,
horizontal_offset : Double,
vertical_offset : Double,
outline : Bool,
line_width : Double,
unique_fontname : @core.PdfName,
unique_fontnames : ArrayView[@core.PdfName],
extgstate_name : @core.PdfName?,
colour : @colour.PdfContentColour,
font_size : Double,
text : String,
text_rotation : Double,
rotation_h_offset : Double,
rotation_v_offset : Double,
) -> Array[@content.PdfContentOp] raise @core.PdfError {
let text_bytes = match font {
Some(font) => pdf_addtext_charcodes_of_utf8(font, text)
None => @utf8.encode(text)
}
pdf_addtext_text_ops_with_bytes(
fontpack, x, y, base_rotation, horizontal_offset, vertical_offset, outline, line_width,
unique_fontname, unique_fontnames, extgstate_name, colour, font_size, text, text_bytes,
text_rotation, rotation_h_offset, rotation_v_offset,
)
}