diff --git a/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/StyleEngineForIText.java b/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/StyleEngineForIText.java index 2ed8d676f..2ecbc1ee5 100644 --- a/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/StyleEngineForIText.java +++ b/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/StyleEngineForIText.java @@ -738,6 +738,12 @@ else if ( FoBreakBeforeAttribute.Value.COLUMN.toString().equals( breakBefore ) ) } } + // writing-mode + String writingMode = ele.getStyleWritingModeAttribute(); + if ( StringUtils.isNotEmpty( writingMode ) ){ + paragraphProperties.setWritingMode( writingMode ); + } + super.visit( ele ); } @@ -1134,6 +1140,12 @@ else if ( TableAlignAttribute.Value.RIGHT.toString().equals( align ) ) tableProperties.setMayBreakBetweenRows( mayBreakBetweenRows ); } + // writing-mode + String writingMode = ele.getStyleWritingModeAttribute(); + if ( StringUtils.isNotEmpty( writingMode ) ){ + tableProperties.setWritingMode( writingMode ); + } + super.visit( ele ); } diff --git a/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/stylable/StylableParagraph.java b/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/stylable/StylableParagraph.java index f9075d3d1..8cf3e5143 100644 --- a/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/stylable/StylableParagraph.java +++ b/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/stylable/StylableParagraph.java @@ -29,6 +29,7 @@ import com.lowagie.text.Font; import com.lowagie.text.Paragraph; import com.lowagie.text.pdf.BaseFont; +import com.lowagie.text.pdf.PdfWriter; import fr.opensagres.odfdom.converter.core.utils.ODFUtils; import fr.opensagres.odfdom.converter.pdf.internal.styles.Style; import fr.opensagres.odfdom.converter.pdf.internal.styles.StyleBreak; @@ -146,6 +147,19 @@ public void applyStyles( Style style ) { super.setKeepTogether( keepTogether ); } + + // Support for writing mode i.e. LTR OR RTL + String writingMode = paragraphProperties.getWritingMode(); + if (writingMode != null && writingMode.equals("rl-tb")) + { + // RTL + super.setRunDirection(PdfWriter.RUN_DIRECTION_RTL); + } + else + { + // LTR + super.setRunDirection(PdfWriter.RUN_DIRECTION_LTR); + } } } diff --git a/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/stylable/StylableTable.java b/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/stylable/StylableTable.java index d97687d79..f6c1db6b2 100644 --- a/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/stylable/StylableTable.java +++ b/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/stylable/StylableTable.java @@ -27,6 +27,7 @@ import com.lowagie.text.Element; import com.lowagie.text.pdf.PdfPCell; +import com.lowagie.text.pdf.PdfWriter; import fr.opensagres.odfdom.converter.pdf.internal.styles.Style; import fr.opensagres.odfdom.converter.pdf.internal.styles.StyleTableProperties; import fr.opensagres.odfdom.converter.pdf.internal.styles.StyleTableRowProperties; @@ -221,6 +222,13 @@ public void applyStyles( Style style ) { super.setKeepTogether( !mayBreakBetweenRows ); } + // Support for writing mode i.e. LTR OR RTL + String writingMode = tableProperties.getWritingMode(); + if ( writingMode != null && writingMode.equals("rl-tb")) + { + // RTL + super.setRunDirection(PdfWriter.RUN_DIRECTION_RTL); + } } StyleTableRowProperties tableRowProperties = style.getTableRowProperties(); if ( tableRowProperties != null ) diff --git a/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/styles/StyleParagraphProperties.java b/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/styles/StyleParagraphProperties.java index ecaed6574..321ce2ed0 100644 --- a/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/styles/StyleParagraphProperties.java +++ b/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/styles/StyleParagraphProperties.java @@ -79,6 +79,8 @@ public class StyleParagraphProperties private Float textIndent; + private String writingMode; + public StyleParagraphProperties() { } @@ -185,6 +187,11 @@ public void merge( StyleParagraphProperties paragraphProperties ) { textIndent = paragraphProperties.getTextIndent(); } + + if (paragraphProperties.getWritingMode() != null) + { + writingMode = paragraphProperties.getWritingMode(); + } } public int getAlignment() @@ -416,4 +423,14 @@ public void setTextIndent( Float textIndent ) { this.textIndent = textIndent; } + + public String getWritingMode() + { + return writingMode; + } + + public void setWritingMode( String writingMode ) + { + this.writingMode = writingMode; + } } diff --git a/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/styles/StyleTableProperties.java b/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/styles/StyleTableProperties.java index d4fdd0c10..8c656d113 100644 --- a/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/styles/StyleTableProperties.java +++ b/thirdparties-extension/fr.opensagres.odfdom.converter.pdf.openpdf/src/main/java/fr/opensagres/odfdom/converter/pdf/internal/styles/StyleTableProperties.java @@ -48,6 +48,8 @@ public class StyleTableProperties private Float width; + private String writingMode; + public StyleTableProperties() { } @@ -98,6 +100,10 @@ public void merge( StyleTableProperties tableProperties ) { width = tableProperties.getWidth(); } + if ( tableProperties.getWritingMode() != null ) + { + writingMode = tableProperties.getWritingMode(); + } } public int getAlignment() @@ -189,4 +195,12 @@ public void setWidth( Float width ) { this.width = width; } + + public String getWritingMode() { + return writingMode; + } + + public void setWritingMode(String writingMode) { + this.writingMode = writingMode; + } } diff --git a/thirdparties-extension/fr.opensagres.poi.xwpf.converter.core/src/main/java/fr/opensagres/poi/xwpf/converter/core/styles/XWPFStylesDocument.java b/thirdparties-extension/fr.opensagres.poi.xwpf.converter.core/src/main/java/fr/opensagres/poi/xwpf/converter/core/styles/XWPFStylesDocument.java index 977295f52..84db49fd6 100644 --- a/thirdparties-extension/fr.opensagres.poi.xwpf.converter.core/src/main/java/fr/opensagres/poi/xwpf/converter/core/styles/XWPFStylesDocument.java +++ b/thirdparties-extension/fr.opensagres.poi.xwpf.converter.core/src/main/java/fr/opensagres/poi/xwpf/converter/core/styles/XWPFStylesDocument.java @@ -35,6 +35,8 @@ import java.util.List; import java.util.Map; +import fr.opensagres.poi.xwpf.converter.core.styles.paragraph.ParagraphRunDirectionProvider; +import fr.opensagres.poi.xwpf.converter.core.styles.table.TableRunDirectionValueProvider; import org.apache.poi.ooxml.POIXMLDocumentPart; import org.apache.poi.xwpf.usermodel.ParagraphAlignment; import org.apache.poi.xwpf.usermodel.UnderlinePatterns; @@ -53,6 +55,7 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocDefaults; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFont; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumPr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPrBase; @@ -448,6 +451,11 @@ public Color getBackgroundColor( CTPPrBase pPr ) return ParagraphBackgroundColorValueProvider.INSTANCE.getValue( pPr ); } + /*enabling bidirectional support*/ + public CTOnOff getParagraphRunDirection(XWPFParagraph docxParagraph) { + return ParagraphRunDirectionProvider.INSTANCE.getValue( docxParagraph, this ); + } + /** * @param paragraph * @return @@ -786,6 +794,12 @@ public TableWidth getTableWidth( CTTbl table ) this ); } + /*enabling bidirectional support*/ + public CTOnOff getTableRunDirection(XWPFTable table ) + { + return TableRunDirectionValueProvider.INSTANCE.getValue( table, this ); + } + public ParagraphAlignment getTableAlignment( XWPFTable table ) { return TableAlignmentValueProvider.INSTANCE.getValue( table, this ); diff --git a/thirdparties-extension/fr.opensagres.poi.xwpf.converter.core/src/main/java/fr/opensagres/poi/xwpf/converter/core/styles/paragraph/ParagraphRunDirectionProvider.java b/thirdparties-extension/fr.opensagres.poi.xwpf.converter.core/src/main/java/fr/opensagres/poi/xwpf/converter/core/styles/paragraph/ParagraphRunDirectionProvider.java new file mode 100644 index 000000000..aa7c19848 --- /dev/null +++ b/thirdparties-extension/fr.opensagres.poi.xwpf.converter.core/src/main/java/fr/opensagres/poi/xwpf/converter/core/styles/paragraph/ParagraphRunDirectionProvider.java @@ -0,0 +1,16 @@ +package fr.opensagres.poi.xwpf.converter.core.styles.paragraph; + + +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPrBase; + +/*enabling bidirectional support -> paragraph direction*/ +public class ParagraphRunDirectionProvider extends AbstractParagraphValueProvider { + + public static final ParagraphRunDirectionProvider INSTANCE = new ParagraphRunDirectionProvider(); + + @Override + public CTOnOff getValue(CTPPrBase ppr) { + return ppr == null || !ppr.isSetBidi() ? null : ppr.getBidi(); + } +} \ No newline at end of file diff --git a/thirdparties-extension/fr.opensagres.poi.xwpf.converter.core/src/main/java/fr/opensagres/poi/xwpf/converter/core/styles/table/TableRunDirectionValueProvider.java b/thirdparties-extension/fr.opensagres.poi.xwpf.converter.core/src/main/java/fr/opensagres/poi/xwpf/converter/core/styles/table/TableRunDirectionValueProvider.java new file mode 100644 index 000000000..bae1ce9b2 --- /dev/null +++ b/thirdparties-extension/fr.opensagres.poi.xwpf.converter.core/src/main/java/fr/opensagres/poi/xwpf/converter/core/styles/table/TableRunDirectionValueProvider.java @@ -0,0 +1,25 @@ +package fr.opensagres.poi.xwpf.converter.core.styles.table; + +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPrBase; + +/*enabling bidirectional support -> table run direction*/ +public class TableRunDirectionValueProvider extends AbstractTableValueProvider { + + public static final TableRunDirectionValueProvider INSTANCE = new TableRunDirectionValueProvider(); + + @Override + public CTOnOff getValue(CTTblPr tblPr) { + return getTableRunDirection(tblPr); + } + + @Override + public CTOnOff getValue(CTTblPrBase tblPr) { + return getTableRunDirection(tblPr); + } + + private CTOnOff getTableRunDirection(CTTblPrBase tblPr) { + return tblPr == null || !tblPr.isSetBidiVisual() ? null : tblPr.getBidiVisual(); + } +} \ No newline at end of file diff --git a/thirdparties-extension/fr.opensagres.poi.xwpf.converter.pdf.openpdf/src/main/java/fr/opensagres/poi/xwpf/converter/pdf/internal/PdfMapper.java b/thirdparties-extension/fr.opensagres.poi.xwpf.converter.pdf.openpdf/src/main/java/fr/opensagres/poi/xwpf/converter/pdf/internal/PdfMapper.java index 6ebd61710..150d2c026 100644 --- a/thirdparties-extension/fr.opensagres.poi.xwpf.converter.pdf.openpdf/src/main/java/fr/opensagres/poi/xwpf/converter/pdf/internal/PdfMapper.java +++ b/thirdparties-extension/fr.opensagres.poi.xwpf.converter.pdf.openpdf/src/main/java/fr/opensagres/poi/xwpf/converter/pdf/internal/PdfMapper.java @@ -34,6 +34,7 @@ import java.util.Map; import java.util.logging.Logger; +import com.lowagie.text.pdf.PdfWriter; import org.apache.poi.xwpf.usermodel.IBodyElement; import org.apache.poi.xwpf.usermodel.ParagraphAlignment; import org.apache.poi.xwpf.usermodel.UnderlinePatterns; @@ -61,6 +62,7 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLvl; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPrBase; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPTab; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr; @@ -104,6 +106,7 @@ import fr.opensagres.poi.xwpf.converter.core.styles.paragraph.ParagraphIndentationLeftValueProvider; import fr.opensagres.poi.xwpf.converter.core.utils.DxaUtil; import fr.opensagres.poi.xwpf.converter.core.utils.StringUtils; +import fr.opensagres.poi.xwpf.converter.core.utils.XWPFUtils; import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions; import fr.opensagres.poi.xwpf.converter.pdf.internal.elements.StylableAnchor; import fr.opensagres.poi.xwpf.converter.pdf.internal.elements.StylableDocument; @@ -333,13 +336,25 @@ protected IITextContainer startVisitParagraph( XWPFParagraph docxParagraph, List } + /*enabling bidirectional support -> paragraph direction*/ + CTOnOff bidi = stylesDocument.getParagraphRunDirection(docxParagraph); + if(isRTLLayoutSet(bidi)){ + pdfParagraph.setRunDirection(PdfWriter.RUN_DIRECTION_RTL); + }else{ + pdfParagraph.setRunDirection(PdfWriter.RUN_DIRECTION_LTR); + } + // text-align ParagraphAlignment alignment = stylesDocument.getParagraphAlignment( docxParagraph ); if ( alignment != null ) { switch ( alignment ) { + /* please refer -> https://docs.microsoft.com/en-us/globalization/input/text-justification*/ case LEFT: + case LOW_KASHIDA: + case MEDIUM_KASHIDA: + case HIGH_KASHIDA: pdfParagraph.setAlignment( Element.ALIGN_LEFT ); break; case RIGHT: @@ -354,6 +369,9 @@ protected IITextContainer startVisitParagraph( XWPFParagraph docxParagraph, List default: break; } + } else { + /*enabling bidirectional support -> if by default Alignment of Paragraph is Undefined, set it to left*/ + pdfParagraph.setAlignment(Element.ALIGN_LEFT); } // background-color @@ -449,6 +467,10 @@ protected IITextContainer startVisitParagraph( XWPFParagraph docxParagraph, List return pdfParagraph; } + private boolean isRTLLayoutSet(CTOnOff bidiProperty){ + return XWPFUtils.isCTOnOff(bidiProperty); + } + @Override protected void endVisitParagraph( XWPFParagraph docxParagraph, IITextContainer pdfParentContainer, IITextContainer pdfParagraphContainer ) @@ -1105,6 +1127,14 @@ private StylableTable createPDFTable( XWPFTable table, float[] colWidths, IIText } pdfPTable.setLockedWidth( true ); + boolean isRightToLeftTable = false; + /*enabling bidirectional support -> Table layout/run direction(based on layout)*/ + CTOnOff bidiVisual = stylesDocument.getTableRunDirection(table); + if(isRTLLayoutSet(bidiVisual)){ + isRightToLeftTable = true; + pdfPTable.setRunDirection(PdfWriter.RUN_DIRECTION_RTL); + } + // Table alignment ParagraphAlignment alignment = stylesDocument.getTableAlignment( table ); if ( alignment != null ) @@ -1126,13 +1156,23 @@ private StylableTable createPDFTable( XWPFTable table, float[] colWidths, IIText default: break; } + } else { + if (isRightToLeftTable) { + pdfPTable.setHorizontalAlignment(Element.ALIGN_RIGHT); + } else { + pdfPTable.setHorizontalAlignment(Element.ALIGN_LEFT); + } } // Table indentation Float indentation = stylesDocument.getTableIndentation( table ); if ( indentation != null ) { - pdfPTable.setPaddingLeft( indentation ); + if (isRightToLeftTable) { + pdfPTable.setPaddingRight(indentation); + } else { + pdfPTable.setPaddingLeft(indentation); + } } return pdfPTable; }