Repository: typst/typst
File: crates/typst-svg/src/lib.rs (Rust)

Code before:
    }

    /// Render a frame with the given transform.
    fn render_frame(&mut self, state: &State, frame: &Frame) {
        self.xml.start_element("g");

        for (pos, item) in frame.items() {
            let state = state.pre_translate(*pos);
            match item {
                FrameItem::Group(group) => self.render_group(&state, group),
                FrameItem::Text(text) => self.render_text(&state, text),
                FrameItem::Shape(shape, _) => self.render_shape(&state, shape),
                FrameItem::Image(image, size, _) => {
                    self.render_image(&state, image, size)
                }
                FrameItem::Link(dest, size) => self.render_link(&state, dest, *size),
                FrameItem::Tag(_) => {}
            };
        }

        self.xml.end_element();
    }

    /// Render a group. If the group has `clips` set to true, a clip path will
    /// be created.
    fn render_group(&mut self, state: &State, group: &GroupItem) {
        self.xml.start_element("g");
        self.xml.write_attribute("class", "typst-group");

        let state = match group.frame.kind() {
            FrameKind::Soft => state.pre_concat(group.transform),
            FrameKind::Hard => {
                let transform = state.transform.pre_concat(group.transform);
                if !transform.is_identity() {
                    self.xml.write_attribute("transform", &SvgMatrix(transform));
                }
                state
                    .with_transform(Transform::identity())
                    .with_size(group.frame.size())
            }
        };

        if let Some(label) = group.label {
            self.xml.write_attribute("data-typst-label", &label.resolve());
        }

        if let Some(clip_curve) = &group.clip {
            let offset = Point::new(state.transform.tx, state.transform.ty);
            let hash = hash128(&(&clip_curve, &offset));
            let id = self
                .clip_paths

Review comment (suggestion):
could this use the `deferred` mechanism? I remember that we talked about this, but not the conclusion.

Code after:
            self.xml.end_element();
        }
    }

    /// Render a frame with the given transform.
    fn render_frame(&mut self, state: &State, frame: &Frame) {
        for (pos, item) in frame.items() {
            let state = state.pre_translate(*pos);
            match item {
                FrameItem::Group(group) => self.render_group(&state, group),
                FrameItem::Text(text) => self.render_text(&state, text),
                FrameItem::Shape(shape, _) => self.render_shape(&state, shape),
                FrameItem::Image(image, size, _) => {
                    self.render_image(&state, image, size)
                }
                FrameItem::Link(dest, size) => self.render_link(&state, dest, *size),
                FrameItem::Tag(_) => {}
            };
        }
    }

    /// Render a group. If the group has `clips` set to true, a clip path will
    /// be created.
    fn render_group(&mut self, state: &State, group: &GroupItem) {
        let mut started_group = false;
        let mut group_writer = LazyCell::new(|| {
            started_group = true;
            self.xml.start_element("g");
            &mut self.xml
        });

        let state = match group.frame.kind() {
            FrameKind::Soft => state.pre_concat(group.transform),
            FrameKind::Hard => {
                // Always generate a group for hard frames.
                group_writer.deref_mut();

                let transform = state.transform.pre_concat(group.transform);
                if !transform.is_identity() {
                    group_writer.write_attribute("transform", &SvgMatrix(transform));
                }
                state
                    .with_transform(Transform::identity())
                    .with_size(group.frame.size())
            }
        };

        if let Some(label) = group.label {
            group_writer.write_attribute("data-typst-label", &label.resolve());
        }