Author: fanningpj
Date: Sat Oct 14 14:31:52 2023
New Revision: 1912963

URL: http://svn.apache.org/viewvc?rev=1912963&view=rev
Log:
[bug-67735] Add Complex scripts support in XWPFRun. Thanks to Mohammed 
Alhaddar. This closes #536

Modified:
    poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java
    
poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java

Modified: 
poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java?rev=1912963&r1=1912962&r2=1912963&view=diff
==============================================================================
--- 
poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java 
(original)
+++ 
poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java 
Sat Oct 14 14:31:52 2023
@@ -252,7 +252,7 @@ public class XWPFRun implements ISDTCont
      * Whether the bold property shall be applied to all non-complex script
      * characters in the contents of this run when displayed in a document
      *
-     * @return {@code true} if the bold property is applied
+     * @return {@code true} if the bold property for non-complex scripts is 
applied
      */
     @Override
     public boolean isBold() {
@@ -261,7 +261,19 @@ public class XWPFRun implements ISDTCont
     }
 
     /**
-     * Whether the bold property shall be applied to all non-complex script
+     * Whether the bold property shall be applied to the complex
+     * characters in the contents of this run when displayed in a document.
+     *
+     * @return {@code true} if the bold property for complex scripts is applied
+     * @since POI 5.2.5
+     */
+    public boolean isComplexScriptBold() {
+        CTRPr pr = getRunProperties(false);
+        return pr != null && pr.sizeOfBCsArray() > 0 && 
isCTOnOff(pr.getBCsArray(0));
+    }
+
+    /**
+     * Whether the bold property shall be applied to the non-complex
      * characters in the contents of this run when displayed in a document.
      * <p>
      * This formatting property is a toggle property, which specifies that its
@@ -281,8 +293,7 @@ public class XWPFRun implements ISDTCont
      * applied to non-complex script characters.
      * </p>
      *
-     * @param value {@code true} if the bold property is applied to
-     *              this run
+     * @param value {@code true} if the bold property is applied for 
non-complex characters.
      */
     @Override
     public void setBold(boolean value) {
@@ -292,6 +303,36 @@ public class XWPFRun implements ISDTCont
     }
 
     /**
+     * Whether the bold property shall be applied to the complex
+     * characters in the contents of this run when displayed in a document.
+     * <p>
+     * This formatting property is a toggle property, which specifies that its
+     * behavior differs between its use within a style definition and its use 
as
+     * direct formatting. When used as part of a style definition, setting this
+     * property shall toggle the current state of that property as specified up
+     * to this point in the hierarchy (i.e. applied to not applied, and vice
+     * versa). Setting it to {@code false} (or an equivalent) shall
+     * result in the current setting remaining unchanged. However, when used as
+     * direct formatting, setting this property to true or false shall set the
+     * absolute state of the resulting property.
+     * </p>
+     * <p>
+     * If this element is not present, the default value is to leave the
+     * formatting applied at previous level in the style hierarchy. If this
+     * element is never applied in the style hierarchy, then bold shall not be
+     * applied to the complex characters.
+     * </p>
+     *
+     * @param value {@code true} if the bold property is applied for complex 
characters
+     * @since POI 5.2.5
+     */
+    public void setComplexScriptBold(boolean value) {
+        CTRPr pr = getRunProperties(true);
+        CTOnOff bold = pr.sizeOfBCsArray() > 0 ? pr.getBCsArray(0) : 
pr.addNewBCs();
+        bold.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
+    }
+
+    /**
      * Get text color. The returned value is a string in the hex form 
"RRGGBB". This can be <code>null</code>.
      */
     public String getColor() {
@@ -362,7 +403,7 @@ public class XWPFRun implements ISDTCont
      * Whether the italic property should be applied to all non-complex script
      * characters in the contents of this run when displayed in a document.
      *
-     * @return {@code true} if the italic property is applied
+     * @return {@code true} if the italic property is applied for non-complex 
characters.
      */
     @Override
     public boolean isItalic() {
@@ -371,8 +412,20 @@ public class XWPFRun implements ISDTCont
     }
 
     /**
-     * Whether the bold property shall be applied to all non-complex script
-     * characters in the contents of this run when displayed in a document
+     * Whether the italic property should be applied to the complex
+     * characters in the contents of this run when displayed in a document.
+     *
+     * @return {@code true} if the italic property is applied for complex 
characters.
+     * @since POI 5.2.5
+     */
+    public boolean isComplexScriptItalic() {
+        CTRPr pr = getRunProperties(false);
+        return pr != null && pr.sizeOfICsArray() > 0 && 
isCTOnOff(pr.getICsArray(0));
+    }
+
+    /**
+     * Whether the italic property shall be applied to the non-complex
+     * characters in the contents of this run when displayed in a document.
      * <p>
      * This formatting property is a toggle property, which specifies that its
      * behavior differs between its use within a style definition and its use 
as
@@ -389,8 +442,7 @@ public class XWPFRun implements ISDTCont
      * element is never applied in the style hierarchy, then bold shall not be
      * applied to non-complex script characters.
      *
-     * @param value {@code true} if the italic property is applied to
-     *              this run
+     * @param value {@code true} if the italic property is applied for 
non-complex characters.
      */
     @Override
     public void setItalic(boolean value) {
@@ -400,6 +452,34 @@ public class XWPFRun implements ISDTCont
     }
 
     /**
+     * Whether the italic property shall be applied to the complex
+     * characters in the contents of this run when displayed in a document.
+     * <p>
+     * This formatting property is a toggle property, which specifies that its
+     * behavior differs between its use within a style definition and its use 
as
+     * direct formatting. When used as part of a style definition, setting this
+     * property shall toggle the current state of that property as specified up
+     * to this point in the hierarchy (i.e. applied to not applied, and vice
+     * versa). Setting it to {@code false} (or an equivalent) shall
+     * result in the current setting remaining unchanged. However, when used as
+     * direct formatting, setting this property to true or false shall set the
+     * absolute state of the resulting property.
+     * <p>
+     * If this element is not present, the default value is to leave the
+     * formatting applied at previous level in the style hierarchy. If this
+     * element is never applied in the style hierarchy, then italic shall not 
be
+     * applied to the complex characters.
+     *
+     * @param value {@code true} if the italic property is applied for complex 
characters.
+     * @since POI 5.2.5
+     */
+    public void setComplexScriptItalic(boolean value) {
+        CTRPr pr = getRunProperties(true);
+        CTOnOff italic = pr.sizeOfICsArray() > 0 ? pr.getICsArray(0) : 
pr.addNewICs();
+        italic.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
+    }
+
+    /**
      * Get the underline setting for the run.
      *
      * @return the Underline pattern applied to this run
@@ -849,7 +929,7 @@ public class XWPFRun implements ISDTCont
     }
 
     /**
-     * Specifies the font size which shall be applied to all non complex script
+     * Specifies the font size which shall be applied to the non-complex
      * characters in the contents of this run when displayed.
      *
      * @return value representing the font size (can be null if size not set)
@@ -861,11 +941,31 @@ public class XWPFRun implements ISDTCont
         return bd == null ? null : bd.doubleValue();
     }
 
+    /**
+     * Specifies the font size which shall be applied to the complex script
+     * characters in the contents of this run when displayed.
+     *
+     * @return value representing the font size for the complex scripts (can 
be null if size not set)
+     * @since POI 5.2.5
+     */
+    public Double getComplexScriptFontSizeAsDouble() {
+        BigDecimal bd = getComplexScriptFontSizeAsBigDecimal(1);
+        return bd == null ? null : bd.doubleValue();
+    }
+
+
     private BigDecimal getFontSizeAsBigDecimal(int scale) {
         CTRPr pr = getRunProperties(false);
         return (pr != null && pr.sizeOfSzArray() > 0)
-            ? 
BigDecimal.valueOf(Units.toPoints(POIXMLUnits.parseLength(pr.getSzArray(0).xgetVal()))).divide(BigDecimal.valueOf(4),
 scale, RoundingMode.HALF_UP)
-            : null;
+                ? 
BigDecimal.valueOf(Units.toPoints(POIXMLUnits.parseLength(pr.getSzArray(0).xgetVal()))).divide(BigDecimal.valueOf(4),
 scale, RoundingMode.HALF_UP)
+                : null;
+    }
+
+    private BigDecimal getComplexScriptFontSizeAsBigDecimal(int scale) {
+        CTRPr pr = getRunProperties(false);
+        return (pr != null && pr.sizeOfSzCsArray() > 0)
+                ? 
BigDecimal.valueOf(Units.toPoints(POIXMLUnits.parseLength(pr.getSzCsArray(0).xgetVal()))).divide(BigDecimal.valueOf(4),
 scale, RoundingMode.HALF_UP)
+                : null;
     }
 
     /**
@@ -890,8 +990,30 @@ public class XWPFRun implements ISDTCont
     }
 
     /**
-     * Specifies the font size which shall be applied to all non complex script
+     * Specifies the font size which shall be applied to the currently 
specified complex
+     * script characters in the contents of this run when displayed.
+     * <p>
+     * If this element is not present, the default value is to leave the value
+     * applied at previous level in the style hierarchy. If this element is
+     * never applied in the style hierarchy, then any appropriate font size may
+     * be used for the non-complex characters.
+     * </p>
+     *
+     * @param size The font size as number of point measurements.
+     * @see #setComplexScriptFontSize(double)
+     * @since POI 5.2.5
+     */
+    public void setComplexScriptFontSize(int size) {
+        CTRPr pr = getRunProperties(true);
+        BigInteger bint = BigInteger.valueOf(size);
+        CTHpsMeasure ctCsSize = pr.sizeOfSzCsArray() > 0 ? pr.getSzCsArray(0) 
: pr.addNewSzCs();
+        ctCsSize.setVal(bint.multiply(BigInteger.valueOf(2)));
+    }
+
+    /**
+     * Specifies the font size which shall be applied to the currently 
specified non-complex
      * characters in the contents of this run when displayed.
+     *
      * <p>
      * If this element is not present, the default value is to leave the value
      * applied at previous level in the style hierarchy. If this element is
@@ -911,6 +1033,29 @@ public class XWPFRun implements ISDTCont
         ctSize.setVal(bd.multiply(BigDecimal.valueOf(2)).setScale(0, 
RoundingMode.HALF_UP).toBigInteger());
     }
 
+
+    /**
+     * Specifies the font size which shall be applied to the currently 
specified complex
+     * characters in the contents of this run when displayed.
+     *
+     * <p>
+     * If this element is not present, the default value is to leave the value
+     * applied at previous level in the style hierarchy. If this element is
+     * never applied in the style hierarchy, then any appropriate font size may
+     * be used for the non-complex characters.
+     * </p>
+     *
+     * @param size The font size as number of point measurements.
+     * @see #setFontSize(int)
+     * @since POI 5.2.5
+     */
+    public void setComplexScriptFontSize(double size) {
+        CTRPr pr = getRunProperties(true);
+        BigDecimal bd = BigDecimal.valueOf(size);
+        CTHpsMeasure ctCsSize = pr.sizeOfSzCsArray() > 0 ? pr.getSzCsArray(0) 
: pr.addNewSzCs();
+        ctCsSize.setVal(bd.multiply(BigDecimal.valueOf(2)).setScale(0, 
RoundingMode.HALF_UP).toBigInteger());
+    }
+
     /**
      * This element specifies the amount by which text shall be raised or
      * lowered for this run in relation to the default baseline of the
@@ -1250,7 +1395,7 @@ public class XWPFRun implements ISDTCont
     public void setStyle(String styleId) {
         CTRPr pr = getCTR().getRPr();
         if (null == pr) {
-           pr = getCTR().addNewRPr();
+            pr = getCTR().addNewRPr();
         }
         CTString style = pr.sizeOfRStyleArray() > 0 ? pr.getRStyleArray(0) : 
pr.addNewRStyle();
         style.setVal(styleId);

Modified: 
poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java?rev=1912963&r1=1912962&r2=1912963&view=diff
==============================================================================
--- 
poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java
 (original)
+++ 
poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java
 Sat Oct 14 14:31:52 2023
@@ -146,6 +146,20 @@ class TestXWPFRun {
     }
 
     @Test
+    void testSetGetComplexBold() {
+        CTRPr rpr = ctRun.addNewRPr();
+        rpr.addNewBCs().setVal(STOnOff1.ON);
+
+        XWPFRun run = new XWPFRun(ctRun, irb);
+        assertTrue(run.isComplexScriptBold());
+
+        run.setComplexScriptBold(false);
+        // Implementation detail: POI natively prefers <w:b w:val="false"/>,
+        // but should correctly read val="0" and val="off"
+        assertEquals("off", rpr.getBCsArray(0).getVal());
+    }
+
+    @Test
     void testSetGetItalic() {
         CTRPr rpr = ctRun.addNewRPr();
         rpr.addNewI().setVal(STOnOff1.ON);
@@ -158,6 +172,18 @@ class TestXWPFRun {
     }
 
     @Test
+    void testSetGetItalicComplex() {
+        CTRPr rpr = ctRun.addNewRPr();
+        rpr.addNewICs().setVal(STOnOff1.ON);
+
+        XWPFRun run = new XWPFRun(ctRun, irb);
+        assertTrue(run.isComplexScriptItalic());
+
+        run.setComplexScriptItalic(false);
+        assertEquals("off", rpr.getICsArray(0).getVal());
+    }
+
+    @Test
     void testSetGetStrike() {
         CTRPr rpr = ctRun.addNewRPr();
         rpr.addNewStrike().setVal(STOnOff1.ON);
@@ -214,6 +240,23 @@ class TestXWPFRun {
     }
 
     @Test
+    void testSetGetFontSizeComplex() {
+        CTRPr rpr = ctRun.addNewRPr();
+        rpr.addNewSzCs().setVal(BigInteger.valueOf(14));
+
+        XWPFRun run = new XWPFRun(ctRun, irb);
+
+        assertEquals(7.0, run.getComplexScriptFontSizeAsDouble(), 0.01);
+
+        run.setComplexScriptFontSize(24);
+        assertEquals("48", rpr.getSzCsArray(0).getVal().toString());
+
+        run.setComplexScriptFontSize(24.5f);
+        assertEquals("49", rpr.getSzCsArray(0).getVal().toString());
+        assertEquals(24.5, run.getComplexScriptFontSizeAsDouble(), 0.01);
+    }
+
+    @Test
     void testSetGetTextForegroundBackground() {
         CTRPr rpr = ctRun.addNewRPr();
         rpr.addNewPosition().setVal(new BigInteger("4000"));
@@ -561,9 +604,9 @@ class TestXWPFRun {
     void testSetFontFamily_52288() throws IOException {
         try (XWPFDocument doc = openSampleDocument("52288.docx")) {
             doc.getParagraphs().stream()
-                .flatMap(p -> p.getRuns().stream())
-                .filter(p -> p != null && p.getText(0) != null)
-                .forEach(r -> assertDoesNotThrow(() -> r.setFontFamily("Times 
New Roman")));
+                    .flatMap(p -> p.getRuns().stream())
+                    .filter(p -> p != null && p.getText(0) != null)
+                    .forEach(r -> assertDoesNotThrow(() -> 
r.setFontFamily("Times New Roman")));
         }
     }
 
@@ -573,7 +616,7 @@ class TestXWPFRun {
         try (XWPFDocument document = new XWPFDocument()) {
 
             document.createParagraph().createRun().addPicture(
-                new ByteArrayInputStream(image), Document.PICTURE_TYPE_JPEG, 
"test.jpg", Units.toEMU(300), Units.toEMU(100));
+                    new ByteArrayInputStream(image), 
Document.PICTURE_TYPE_JPEG, "test.jpg", Units.toEMU(300), Units.toEMU(100));
 
             try (XWPFDocument docBack = writeOutAndReadBack(document)) {
                 List<XWPFPicture> pictures = 
docBack.getParagraphArray(0).getRuns().get(0).getEmbeddedPictures();



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to