summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPJ Fanning <fanningpj@apache.org>2023-10-14 14:31:52 +0000
committerPJ Fanning <fanningpj@apache.org>2023-10-14 14:31:52 +0000
commitbc870ab76497d3f968a32282104fb170bea7a77f (patch)
treea659b24c1609883c64a8dfb8ecc2f1fa07ae8b37
parent407bb3744cb541aac682e622101fe5881e1c2eec (diff)
downloadpoi-bc870ab76497d3f968a32282104fb170bea7a77f.tar.gz
poi-bc870ab76497d3f968a32282104fb170bea7a77f.zip
[bug-67735] Add Complex scripts support in XWPFRun. Thanks to Mohammed Alhaddar. This closes #536
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1912963 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java173
-rw-r--r--poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java51
2 files changed, 206 insertions, 18 deletions
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java
index a8a1af4ca9..e86ca85720 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java
@@ -252,7 +252,7 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun {
* 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 ISDTContents, IRunElement, CharacterRun {
}
/**
- * 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 ISDTContents, IRunElement, CharacterRun {
* 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 ISDTContents, IRunElement, CharacterRun {
}
/**
+ * 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 ISDTContents, IRunElement, CharacterRun {
* 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 ISDTContents, IRunElement, CharacterRun {
}
/**
- * 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 ISDTContents, IRunElement, CharacterRun {
* 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 ISDTContents, IRunElement, CharacterRun {
}
/**
+ * 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 ISDTContents, IRunElement, CharacterRun {
}
/**
- * 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 ISDTContents, IRunElement, CharacterRun {
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 ISDTContents, IRunElement, CharacterRun {
}
/**
- * 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 ISDTContents, IRunElement, CharacterRun {
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 ISDTContents, IRunElement, CharacterRun {
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);
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java b/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java
index dcdfa4c3b9..eee37446e1 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java
@@ -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();