Skip to content

fix(pptx): a right-to-left line's paired punctuation is not mirrored #545

Description

@DemchaAV

Opening a PPTX with a right-to-left line shows a parenthesis facing the way it was typed rather than the way it reads. The same document as a PDF is correct.

Source line (direction(AUTO), resolved RTL from the first strong letter):

2026 שנה טובה (AUTO resolves from the first strong letter)

PDF(AUTO resolves from the first strong letter), parentheses facing the phrase.
PPTX)AUTO resolves from the first strong letter at the left, ( before 2026 at the right.

Mechanism

PptxParagraphFragmentRenderHandler puts a right-to-left line through per-span absolute frames, and it places them correctly — from the produced slide:

frame x text
142pt )
147pt AUTO resolves from the first strong letter
368pt שנה טובה (
430pt 2026

The positions are the engine's resolved visual order. What is missing is the mirroring: the PDF backend mirrors paired punctuation at its own seam (BidiMirroring.mirror, UAX #9 L4), the PPTX backend hands PowerPoint the logical, unmirrored character and relies on PowerPoint to do it — which it cannot, because each span sits in its own frame with no direction declared. rtl="1" is never written on a paragraph anywhere in the backend (0 occurrences), so a frame holding a lone ) has nothing to resolve it against and draws it as typed.

Suggested fix

Write rtl="1" on the paragraph of a frame whose span is right-to-left, rather than mirroring in the backend. The stored text then stays logical — which is what keeps copy-paste and PowerPoint's own Arabic shaping working — and PowerPoint mirrors for display exactly as the algorithm says. Mirroring in the backend would also work visually but would bake mirrored characters into the text a user copies out.

Worth checking in the same pass: the em-dashes in a mixed line (שלום עולם — GraphCompose 2.2.0 — ועוד מילים) sit on the wrong side of their frames for the same reason — a neutral at a frame edge with no base direction.

Recorded in the capability matrix by #544.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions