Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/docx-typed-measure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@betteroffice/rust-crates": patch
---

Measure paragraphs through a typed path instead of serializing to JSON per call.
10 changes: 10 additions & 0 deletions crates/docx-layout/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ pub mod session;
pub mod table_grid;
pub mod table_row_break;

mod typed_measure;

use wasm_bindgen::prelude::*;

#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -556,6 +558,14 @@ pub fn measure_paragraph_json_resident(input: &str) -> Result<String, String> {
MEASURE_FONTS.with(|store| ooxml_text::measure_paragraph_json(&store.borrow(), input))
}

/// Typed form of [`measure_paragraph_json_resident`] against the same font
/// store, skipping both JSON round trips.
pub(crate) fn measure_paragraph_typed_resident(
request: &ooxml_text::MeasureRequest<'_>,
) -> Result<ooxml_text::ParagraphExtentOut, ooxml_text::MeasureError> {
MEASURE_FONTS.with(|store| ooxml_text::measure_paragraph_typed(&store.borrow(), request))
}

/// wasm wrapper over [`ooxml_text::FontStore::outline_glyph_json`]: the outline
/// of a registered font's glyph, in font design units, as JSON:
/// `{"upem":2048,"cmds":[{"t":"M","x":..,"y":..},{"t":"L","x":..,"y":..},
Expand Down
55 changes: 18 additions & 37 deletions crates/docx-layout/src/measure_blocks.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::{BTreeMap, HashMap};

use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use serde_json::Value;

use crate::table_grid::{resolve_cell_grid, resolve_table_column_widths, resolve_table_width_px};
use crate::types::{
Expand All @@ -15,15 +15,13 @@ const DEFAULT_CELL_PADDING_X: f64 = 7.0;
const DEFAULT_CELL_PADDING_Y: f64 = 0.0;
const ANCHOR_PROXIMITY: usize = 4;

#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
struct FloatingZone {
left_margin: f64,
right_margin: f64,
top_y: f64,
bottom_y: f64,
#[serde(skip_serializing_if = "std::ops::Not::not")]
full_width_block: bool,
#[derive(Clone, Debug)]
pub(crate) struct FloatingZone {
pub(crate) left_margin: f64,
pub(crate) right_margin: f64,
pub(crate) top_y: f64,
pub(crate) bottom_y: f64,
pub(crate) full_width_block: bool,
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -463,34 +461,16 @@ fn measure_paragraph_with_context(
if !content_width.is_finite() || content_width <= 0.0 {
return Ok(synthetic_paragraph_extent(paragraph, content_width));
}
let mut envelope = json!({
"block": LayoutBlock::Paragraph(paragraph.clone()),
"maxWidth": content_width,
"fontChains": config.font_chains,
"authoritativeShaping": config.authoritative_shaping,
});
let fields = envelope
.as_object_mut()
.expect("measurement envelope object");
if !config.defaults.is_null() {
fields.insert("defaults".to_owned(), config.defaults.clone());
}
if !config.compat.is_null() {
fields.insert("compat".to_owned(), config.compat.clone());
}
if let Some(zones) = floating_zones {
fields.insert(
"floatingZones".to_owned(),
serde_json::to_value(zones).expect("floating zones serialize"),
);
fields.insert("paragraphYOffset".to_owned(), json!(cumulative_y));
match crate::typed_measure::measure_paragraph(
paragraph,
content_width,
config,
floating_zones,
cumulative_y,
) {
Some(extent) => Ok(extent),
None => Ok(synthetic_paragraph_extent(paragraph, content_width)),
}
let Ok(extent) = crate::measure_paragraph_json_resident(&envelope.to_string()) else {
return Ok(synthetic_paragraph_extent(paragraph, content_width));
};
serde_json::from_str(&extent)
.map_err(|error| format!("parse paragraph extent: {error}"))
.or_else(|_| Ok(synthetic_paragraph_extent(paragraph, content_width)))
}

const SYNTHETIC_ADVANCE_EM: f64 = 1.0;
Expand Down Expand Up @@ -1264,6 +1244,7 @@ fn cell_border_height(cell: &crate::types::TableCell) -> f64 {
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;

#[test]
fn measures_non_text_blocks_without_host_callbacks() {
Expand Down
Loading
Loading