use duc::types;
pub struct DucDataScaler;
impl DucDataScaler {
pub fn scale_exported_data(exported_data: &mut types::ExportedDataState, scale: f64) {
for element_wrapper in &mut exported_data.elements {
Self::scale_element(&mut element_wrapper.element, scale);
}
for block_instance in &mut exported_data.block_instances {
if let Some(ref mut duplication) = block_instance.duplication_array {
duplication.row_spacing *= scale;
duplication.col_spacing *= scale;
}
}
if let Some(ref mut local_state) = exported_data.duc_local_state {
local_state.scroll_x *= scale;
local_state.scroll_y *= scale;
}
}
fn scale_element(element: &mut types::DucElementEnum, scale: f64) {
match element {
types::DucElementEnum::DucRectangleElement(rect) => {
Self::scale_element_base(&mut rect.base, scale);
}
types::DucElementEnum::DucEllipseElement(ellipse) => {
Self::scale_element_base(&mut ellipse.base, scale);
}
types::DucElementEnum::DucPolygonElement(polygon) => {
Self::scale_element_base(&mut polygon.base, scale);
}
types::DucElementEnum::DucTextElement(text) => {
Self::scale_element_base(&mut text.base, scale);
Self::scale_text_style(&mut text.style, scale);
}
types::DucElementEnum::DucLinearElement(linear) => {
Self::scale_linear_element_base(&mut linear.linear_base, scale);
}
types::DucElementEnum::DucArrowElement(arrow) => {
Self::scale_linear_element_base(&mut arrow.linear_base, scale);
}
types::DucElementEnum::DucFreeDrawElement(freedraw) => {
Self::scale_element_base(&mut freedraw.base, scale);
Self::scale_freedraw_element(freedraw, scale);
}
types::DucElementEnum::DucTableElement(table) => {
Self::scale_element_base(&mut table.base, scale);
Self::scale_table_element(table, scale);
}
types::DucElementEnum::DucImageElement(image) => {
Self::scale_element_base(&mut image.base, scale);
}
types::DucElementEnum::DucFrameElement(frame) => {
Self::scale_element_base(&mut frame.stack_element_base.base, scale);
}
types::DucElementEnum::DucPlotElement(plot) => {
Self::scale_element_base(&mut plot.stack_element_base.base, scale);
Self::scale_plot_element(plot, scale);
}
types::DucElementEnum::DucDocElement(doc) => {
Self::scale_element_base(&mut doc.base, scale);
Self::scale_doc_element(doc, scale);
}
types::DucElementEnum::DucEmbeddableElement(embeddable) => {
Self::scale_element_base(&mut embeddable.base, scale);
}
types::DucElementEnum::DucPdfElement(pdf) => {
Self::scale_element_base(&mut pdf.base, scale);
Self::scale_pdf_element(pdf, scale);
}
types::DucElementEnum::DucModelElement(model) => {
Self::scale_element_base(&mut model.base, scale);
}
}
}
fn scale_element_base(base: &mut types::DucElementBase, scale: f64) {
base.x *= scale;
base.y *= scale;
base.width *= scale;
base.height *= scale;
base.styles.roundness *= scale;
for stroke in &mut base.styles.stroke {
stroke.width *= scale;
}
}
fn scale_text_style(style: &mut types::DucTextStyle, scale: f64) {
style.font_size *= scale;
style.line_height *= scale as f32;
}
fn scale_linear_element_base(base: &mut types::DucLinearElementBase, scale: f64) {
Self::scale_element_base(&mut base.base, scale);
for point in &mut base.points {
point.x *= scale;
point.y *= scale;
}
if let Some(ref mut point) = base.last_committed_point {
point.x *= scale;
point.y *= scale;
}
for line in &mut base.lines {
if let Some(handle) = line.start.handle.as_mut() {
handle.x *= scale;
handle.y *= scale;
}
if let Some(handle) = line.end.handle.as_mut() {
handle.x *= scale;
handle.y *= scale;
}
}
}
fn scale_freedraw_element(freedraw: &mut types::DucFreeDrawElement, scale: f64) {
freedraw.size *= scale;
for point in &mut freedraw.points {
point.x *= scale;
point.y *= scale;
}
if let Some(ref mut point) = freedraw.last_committed_point {
point.x *= scale;
point.y *= scale;
}
if let Some(ref mut svg_path) = freedraw.svg_path {
*svg_path = Self::scale_svg_path(svg_path, scale);
}
}
fn scale_svg_path(path_data: &str, scale: f64) -> String {
let mut result = String::new();
let mut current_number = String::new();
let mut in_number = false;
for ch in path_data.chars() {
if ch.is_ascii_digit() || ch == '.' || (ch == '-' && !in_number) {
current_number.push(ch);
in_number = true;
} else {
if in_number {
if let Ok(num) = current_number.parse::<f64>() {
result.push_str(&format!("{}", num * scale));
} else {
result.push_str(¤t_number);
}
current_number.clear();
in_number = false;
}
result.push(ch);
}
}
if in_number {
if let Ok(num) = current_number.parse::<f64>() {
result.push_str(&format!("{}", num * scale));
} else {
result.push_str(¤t_number);
}
}
result
}
fn scale_table_element(table: &mut types::DucTableElement, scale: f64) {
let _ = (table, scale);
}
fn scale_doc_element(doc: &mut types::DucDocElement, scale: f64) {
doc.grid_config.gap_x *= scale;
doc.grid_config.gap_y *= scale;
}
fn scale_pdf_element(pdf: &mut types::DucPdfElement, scale: f64) {
pdf.grid_config.gap_x *= scale;
pdf.grid_config.gap_y *= scale;
}
fn scale_plot_element(plot: &mut types::DucPlotElement, scale: f64) {
plot.layout.margins.left *= scale;
plot.layout.margins.top *= scale;
plot.layout.margins.right *= scale;
plot.layout.margins.bottom *= scale;
}
pub fn transform_y_coordinate_to_pdf_system(y: f64, height: f64, page_height: f64) -> f64 {
page_height - (y + height)
}
pub fn transform_point_y_to_pdf_system(y: f64, page_height: f64) -> f64 {
page_height - y
}
}