mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-03 06:51:50 -06:00
M12: doc comments for the functions around this change
This commit is contained in:
@@ -1004,6 +1004,9 @@ impl Layouter<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// The height a value takes at width `w` in the context's font and paragraph: its text as
|
||||
/// measured, a picture scaled to `w` keeping its shape, nothing for a line, a rectangle or
|
||||
/// no value.
|
||||
fn value_height(&self, v: &Value, w: f64, ctx: &Ctx) -> f64 {
|
||||
match v {
|
||||
Value::Text(t) => text::measure_height(&text::plain(t), w, &ctx.para, &Face::of(&ctx.font), &|id| self.embed(id)),
|
||||
@@ -1013,6 +1016,10 @@ impl Layouter<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Where a field's caption goes and the room it takes there: its reserve, else the height
|
||||
/// of its text above or below, or beside it its text's width plus 2pt, at most 60% of
|
||||
/// `inner_w`. An inline caption goes on the left. `None` for a button, a caption that takes
|
||||
/// no space, or one with neither text nor a reserve.
|
||||
fn caption_reserve(&self, f: &Field, inner_w: f64, ctx: &Ctx) -> Option<(Placement, f64)> {
|
||||
let cap = f.caption.as_ref()?;
|
||||
if !cap.presence.occupies() || f.ui == Ui::Button {
|
||||
@@ -1037,6 +1044,9 @@ impl Layouter<'_> {
|
||||
Some((placement, reserve))
|
||||
}
|
||||
|
||||
/// The height of a field at `inner_w`: its widget (a check box's size, or its lines of text,
|
||||
/// grown to hold a long value, plus padding and the widget margin), plus a caption above or
|
||||
/// below it. A caption beside it makes it at least as tall as the caption's text.
|
||||
fn field_height(&self, f: &Field, inner_w: f64, ctx: &Ctx) -> f64 {
|
||||
let font = ctx.font.apply(&f.common.font);
|
||||
let lines = if f.multiline { 3.0 } else { 1.0 };
|
||||
@@ -1089,6 +1099,8 @@ impl Layouter<'_> {
|
||||
text::measure_height(&text::plain(value.trim_end()), w, &ctx.para, &Self::field_text_face(f, &font), &|_| String::new())
|
||||
}
|
||||
|
||||
/// The height of an exclusion group's fields at `inner_w`, by the group's layout: stacked
|
||||
/// top to bottom, at their own positions, or packed in rows.
|
||||
fn group_height(&self, g: &ExclGroup, inner_w: f64, ctx: &Ctx, depth: usize) -> f64 {
|
||||
let nodes: Vec<Node> = g.fields.iter().map(|f| Node::Field(Box::new(f.clone()))).collect();
|
||||
match g.layout {
|
||||
@@ -1457,6 +1469,9 @@ impl Layouter<'_> {
|
||||
self.push(Item::Image { rect: fitted, data: Arc::new(data.to_vec()), content_type: content_type.to_string() })
|
||||
}
|
||||
|
||||
/// The widget name for a field or group named `base`, cleaned (dots become underscores,
|
||||
/// control characters go): the first use is the name itself, later ones `name_2`, `name_3`
|
||||
/// and so on.
|
||||
fn unique_name(&mut self, base: &str) -> String {
|
||||
let base = clean_name(base);
|
||||
let n = self.names.entry(base.clone()).or_insert(0);
|
||||
|
||||
@@ -40,6 +40,8 @@ pub fn measure(s: &str) -> Option<f64> {
|
||||
Some((v * k).clamp(-100_000.0, 100_000.0))
|
||||
}
|
||||
|
||||
/// The attribute `name` of `n` read as a measurement in points (see [`measure`]); `None`
|
||||
/// when it is missing or unreadable.
|
||||
fn attr_measure(n: XmlNode, name: &str) -> Option<f64> {
|
||||
n.attribute(name).and_then(measure)
|
||||
}
|
||||
@@ -51,6 +53,7 @@ fn scale(v: &str) -> Option<f64> {
|
||||
(v.is_finite() && v > 0.0).then(|| (v / 100.0).clamp(0.01, 10.0))
|
||||
}
|
||||
|
||||
/// The first child element of `n` named `name` (by local name, in any namespace).
|
||||
fn child<'a, 'd>(n: XmlNode<'a, 'd>, name: &str) -> Option<XmlNode<'a, 'd>> {
|
||||
n.children().find(|c| c.is_element() && c.tag_name().name() == name)
|
||||
}
|
||||
|
||||
@@ -509,6 +509,9 @@ impl Emitter<'_> {
|
||||
Some(r)
|
||||
}
|
||||
|
||||
/// Write a new image XObject for a picture, tagged with its `hash`: a JPEG as it is, a PNG
|
||||
/// or GIF decoded to samples with a soft mask for any transparency. `None`, with a warning,
|
||||
/// when the picture can't be read or is another kind.
|
||||
fn new_image_xobject(&mut self, data: &[u8], content_type: &str, hash: &[u8; 32]) -> Option<ObjRef> {
|
||||
let what = if content_type.is_empty() { "picture" } else { content_type };
|
||||
let mut d = Dict::new();
|
||||
|
||||
@@ -13,14 +13,18 @@ use crate::layout::WidgetKind;
|
||||
use crate::model::*;
|
||||
use crate::script::{NodeKind, Overrides, apply_overrides, fields_by_som, form_tree, overrides, rerender, set_overrides};
|
||||
|
||||
/// The widgets laid out on `page`, in order.
|
||||
fn widgets(page: &Page) -> Vec<&Widget> {
|
||||
page.items.iter().filter_map(|i| if let Item::Widget(w) = i { Some(w.as_ref()) } else { None }).collect()
|
||||
}
|
||||
|
||||
/// The text of each text span laid out on `page`, in order.
|
||||
fn texts(page: &Page) -> Vec<String> {
|
||||
page.items.iter().filter_map(|i| if let Item::Text(s) = i { Some(s.text.clone()) } else { None }).collect()
|
||||
}
|
||||
|
||||
/// Measurements in points, inches, millimeters and centimeters convert to points, a bare
|
||||
/// number is points, and an `em` length, a non-number or a NaN is `None`.
|
||||
#[test]
|
||||
fn measurements_convert_to_points() {
|
||||
assert_eq!(measure("72pt"), Some(72.0));
|
||||
@@ -137,6 +141,9 @@ fn horizontally_scaled_text_is_written_with_tz_inside_its_own_graphics_state() {
|
||||
assert!(ops.lines().filter(|l| l.contains(" Tj ") && !l.contains(" Tz ")).all(|l| l.starts_with("BT ")), "{ops}");
|
||||
}
|
||||
|
||||
/// The sample template parses without warnings into what the layout uses: its page areas,
|
||||
/// page-number draws, rich-text title, field font, caption and widget border, check box,
|
||||
/// date field, radio group, table columns and page break all come through.
|
||||
#[test]
|
||||
fn the_template_parses_with_fonts_captions_and_rich_text() {
|
||||
let (tpl, warnings) = parse(&template(2)).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user