From dfbab3ff6af87898de6101ea827db7e75cecca61 Mon Sep 17 00:00:00 2001 From: Andreas Beeker Date: Sat, 16 Oct 2021 00:00:50 +0000 Subject: [PATCH] #64036 - Replace reflection calls in factories for Java 9+ use ServiceLoader for HSLF Metro Shapes git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1894298 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/xslf/usermodel/XSLFMetroShape.java | 19 +- poi-ooxml/src/main/java9/module-info.class | Bin 3733 -> 3840 bytes poi-ooxml/src/main/java9/module-info.java | 1 + ...apache.poi.sl.usermodel.MetroShapeProvider | 18 + .../poi/xslf/usermodel/TestXSLFTextShape.java | 633 +++++++++--------- poi-ooxml/src/test/java9/module-info.class | Bin 5120 -> 5227 bytes poi-ooxml/src/test/java9/module-info.java | 1 + .../apache/poi/hslf/model/HSLFMetroShape.java | 44 +- .../poi/hslf/usermodel/HSLFTextRun.java | 20 +- .../poi/hslf/usermodel/HSLFTextShape.java | 21 +- .../src/main/java9/module-info.class | Bin 2642 -> 2695 bytes .../src/main/java9/module-info.java | 2 + .../src/test/java9/module-info.class | Bin 3289 -> 3342 bytes .../src/test/java9/module-info.java | 2 + .../poi/sl/usermodel/MetroShapeProvider.java | 31 + poi/src/test/java9/module-info.class | Bin 4145 -> 4198 bytes poi/src/test/java9/module-info.java | 2 + 17 files changed, 444 insertions(+), 350 deletions(-) create mode 100644 poi-ooxml/src/main/resources/META-INF/services/org.apache.poi.sl.usermodel.MetroShapeProvider create mode 100644 poi/src/main/java/org/apache/poi/sl/usermodel/MetroShapeProvider.java diff --git a/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFMetroShape.java b/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFMetroShape.java index 69931a2e91..5912d05745 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFMetroShape.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFMetroShape.java @@ -28,7 +28,7 @@ import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePartName; import org.apache.poi.openxml4j.opc.PackagingURIHelper; -import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.sl.usermodel.MetroShapeProvider; import org.apache.poi.util.Internal; import org.apache.xmlbeans.XmlException; import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; @@ -39,18 +39,21 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; * This is the helper class for HSLFMetroShape to dive into OOXML classes */ @Internal -public class XSLFMetroShape { - /* - * parses the metro bytes to a XSLF shape - */ - public static Shape parseShape(byte[] metroBytes) - throws InvalidFormatException, IOException, XmlException { - PackagePartName shapePN = PackagingURIHelper.createPartName("/drs/shapexml.xml"); +public class XSLFMetroShape implements MetroShapeProvider { + /** parses the metro bytes to a XSLF shape */ + @Override + public XSLFShape parseShape(byte[] metroBytes) throws IOException { try (OPCPackage pkg = OPCPackage.open(new UnsynchronizedByteArrayInputStream(metroBytes))) { + PackagePartName shapePN = PackagingURIHelper.createPartName("/drs/shapexml.xml"); PackagePart shapePart = pkg.getPart(shapePN); + if (shapePart == null) { + return null; + } CTGroupShape gs = CTGroupShape.Factory.parse(shapePart.getInputStream(), DEFAULT_XML_OPTIONS); XSLFGroupShape xgs = new XSLFGroupShape(gs, null); return xgs.getShapes().get(0); + } catch (InvalidFormatException | XmlException e) { + throw new IOException("can't parse metro shape", e); } } } diff --git a/poi-ooxml/src/main/java9/module-info.class b/poi-ooxml/src/main/java9/module-info.class index f4db29c6148bb418b977c028df8257512d4751e3..d79f2de6431f38013e21697e5598c837378448fc 100644 GIT binary patch literal 3840 zcma)w2Q%;aoIJ?zQ!KHp7desA8qH*aQghyOiz2mm(0KOHcE!4yXrHJf)?ZbdNY zEQy-0^FGVw3}&Xflp(FIF_<(!Y6&_R$ig=j&C~QMS3F@ULNpv(g2@afM`ER{1vtp0 z?p|es(j&oC2D393XeGgP22!dW$0&2n4J4S!U~#G=aiIk0(a}&bo58Y_LKluB+(6NV zZF4=e@VQq4nZf)*k->Ed<}z4R*z0&c575Va26GAomXKf}gK1+v9WAVGlwdJ~sU=VI z1HRP?OFWcdX}fz{n5N~L3jX#EVRm{H%ulxjC!ir^ttpUT#aN5MgW*tk60E`uk|yAK z&9}l)Wyp-Ccp`%t)Q-7Rbbr(fadKWi7OZ70tCA33?e! zZ@!O&N-eaoN>0Y;;lm#x;mF=6ZBHWPLug1M)aK#rP{`Zwwu8a-a zW5{qVgC#hi8gFnFcc0oA@hU1N*4K12lA%0~q!w@=j}C6jV8lh18>QJ@DHy>p+niJx zEX~d%mgwB0JuU-oq}*I1O===GgH=VtBoY-jMKqiYE(7JLq^ikNrVGMHC1I2M8o_4s^g%P_@`+f0VWIK9!#W!M)V;%Qqt#AUc4Z$~|< z!Rs>IlwXs$H&q-5@+%)}qPmvhmZBvy+Lr7#2Fr6{rzL8L{$#kLDEDnT9k(tD@5&2> z$6ZWg?@(L9?}=}ow!9=l;psBmmoKN*P^eHX7dN`AVWbZ*=+1;uEL9!6H>w)mU49_L zLku<^omtIoGkheU*_OXJ`H#g{ZaTh35L9G%B5xaYq&NLj1*<}mI>#HPwez1DXQ-6q zxqK4ITOv`b-1aCNFECh>$wo$srNG@Fy7OgtiNV4mb=h*YXt%zSuT2`Qc`Cg&&eVg@ z=bD4Jw+wIO_eVS*D(<(6dhLp8_}YjJ?-UK+?4=_`hWEyiB$<)ngQ6I4lx7ScjWdO~ z06vL7oYDn=2Ye+^>FYr?0t;jOjKS(m7PBI?qUk)ujDL||pPUwJqi*RO)nEO;`;a?c z2OMOuF5^BqUes-4x6rQU2TKQh%V1MRpE;D&T|4^+2X-X3eRPkFcEBM9>ocZ7(7HX; zy}}6H!W1|j-=`60 z5NA=pM4UsMM_fQ$L|lSgM(R#jj?bO2lDL|<2DaeuI^uewg4_Vz^t_R{iFgX}RO0Ex zGl^#t&mo>m+(z6^>?dAG93bu_UQ8?zFD33JUPiovcone=uE7}sXhfaJi6+q^4ig=s zAYMldh&AE}ag=yH@kZi);?2ZciMJE)B;HNDmv}$%LE^*2M~ROUpCmp_e3tk;@kQdx z#8-*06W=7hO?;R5KJi21$HY&GpA)|%GKgk`e?cH8!q@op4Sa|E9)3jr48J0Ohd+^j F{Rfo>U&{ah literal 3733 zcma) zMa5qKC_lcu8w+Y-XaEHL10(S}AEpU&(y#n_M z+%NEez=Hx02|O(Dh`^%)j|n_3@Px#Z5>H7yE%A)Rvl7oqJTLKr#ETLyNxUraio~lD zuSvWv@rJ~k5^qVoE%A=TyAtn7yf5*A#D@|eNqj8viNvQ8pGkZ!@rA^f5?@JtE%A-S zw-Vn;9Fq86;s=QzB@RpcB=K_&zvS?14!`B_dk%l(@MjKxDe!-CXk%bOmM^QuYW#VN7nRjZyG z=$2QhC@Xa6xmUxSjvBVIG|cZPs@8lJkn5Qpq>iUy@^GB08J5>;n3S)XexSBEVO~*X zq~le*Qps^kI(_z1aZTbBB!k1Rwh9J9uSQ8>X`rmS?}S5oe<_;8R34;s=$1cJ3n_eh z(t+uQb<=k|oixZ&!`x`n1+VT}LzWqY71{#dYdE&@lLfWQ2ApQH8Jtx7P?u~9M7AKijk%SH`->H%6tk`u>HhpF5v~%3<6lZcGXq0r0 zHEh=?l@xguEwN8|QoeH_O3}1U4JSD1h@$6)Jh;GCy6=Vb@9VLmKJ2Z>*07NL7_p5(b#F8WYej<+<(n2+96??W zlux~=XosRg7-gTxM)|f&ZN3*}ZDYBmYTQ&Ef=3Fe;43;gXvqz#)X0$r{kZgulJcr5 z^oKMoJBC5otWh~0%Wb4Zxg1%~>`rcZlcR2KOCzt8d!VBznreImrmd1AFl)iXhOHVJ zvMG;6sr}CGXRHuc<>>vi+qPrrs70jZM#%j)I<;*|7Bv{PTUN`fDVGw}+uxSY=+JIk ze@n}&(E*Vyj}a#%HXN7Q(KV@tyN~9krDs&>_$`}s=KIw4>yOW-?zUNFGdMD%IK$E1 zlwMFX2#OurfJW0jIx6ohZzwvnM;bL7I&yu~UTTvYWmT#1!dG>e;)tJUTFMQgJ5j^D zPO1gRHKP{G78=jzNC!tWmmu_&S*2?(zWcIiGU5zoYrh#(iiYi*gPqcth`8~OAWvm* z^o+?qnQ_Ok@rJuS9Id}4aZWXdbFsa zs?zs>HJPZbL%`TNeEjcj-RT=L%9(S+*u87}{+&BohJAc{&@Qjd*abnVR`z-RK*93{ zM#5w}vAsx*{rP;~uu&^SS2jc?6(V1u?0=Yd^6(mrI|$@( z5|+^Wc;*D=M3zrtPG(MFPGwGGPAATQAm$*MGnuoPv$2^z=P>6o=Mm>)0Y5KfE@Ccb zE@7U`T*_R=T+UpFJoTL+{@g@+|Rs%c_s5I=GDw=nAb9|V`_+Iq)|11s^oflGEpE}u!#yqV(EVs CaXFd* diff --git a/poi-ooxml/src/main/java9/module-info.java b/poi-ooxml/src/main/java9/module-info.java index b11e2a9ebe..51533acbd6 100644 --- a/poi-ooxml/src/main/java9/module-info.java +++ b/poi-ooxml/src/main/java9/module-info.java @@ -34,6 +34,7 @@ module org.apache.poi.ooxml { provides org.apache.poi.ss.usermodel.WorkbookProvider with org.apache.poi.xssf.usermodel.XSSFWorkbookFactory; provides org.apache.poi.sl.usermodel.SlideShowProvider with org.apache.poi.xslf.usermodel.XSLFSlideShowFactory; provides org.apache.poi.sl.draw.ImageRenderer with org.apache.poi.xslf.draw.SVGImageRenderer; + provides org.apache.poi.sl.usermodel.MetroShapeProvider with org.apache.poi.xslf.usermodel.XSLFMetroShape; exports org.apache.poi.xwpf.extractor; exports org.apache.poi.xwpf.usermodel; diff --git a/poi-ooxml/src/main/resources/META-INF/services/org.apache.poi.sl.usermodel.MetroShapeProvider b/poi-ooxml/src/main/resources/META-INF/services/org.apache.poi.sl.usermodel.MetroShapeProvider new file mode 100644 index 0000000000..ba99414720 --- /dev/null +++ b/poi-ooxml/src/main/resources/META-INF/services/org.apache.poi.sl.usermodel.MetroShapeProvider @@ -0,0 +1,18 @@ +# ==================================================================== +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ==================================================================== + +org.apache.poi.xslf.usermodel.XSLFMetroShape \ No newline at end of file diff --git a/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java b/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java index 372e0216f4..397db98d12 100644 --- a/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java +++ b/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java @@ -17,7 +17,10 @@ package org.apache.poi.xslf.usermodel; import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor; +import static org.apache.poi.sl.usermodel.TextRun.FieldType.DATE_TIME; +import static org.apache.poi.sl.usermodel.TextRun.FieldType.SLIDE_NUMBER; import static org.apache.poi.xslf.usermodel.TestXSLFSimpleShape.getSpPr; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -27,17 +30,23 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeFalse; import java.awt.Color; -import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import org.apache.poi.POIDataSamples; +import org.apache.poi.sl.usermodel.MasterSheet; import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.Shape; import org.apache.poi.sl.usermodel.SlideShow; import org.apache.poi.sl.usermodel.SlideShowFactory; +import org.apache.poi.sl.usermodel.TextParagraph; import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; +import org.apache.poi.sl.usermodel.TextRun; +import org.apache.poi.sl.usermodel.TextRun.FieldType; +import org.apache.poi.sl.usermodel.TextShape; import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.xddf.usermodel.text.XDDFBodyProperties; import org.apache.poi.xddf.usermodel.text.XDDFTextBody; @@ -66,19 +75,19 @@ class TestXSLFTextShape { @Test void testLayouts() throws IOException { - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("layouts.pptx"); + try (XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("layouts.pptx")) { - List slide = ppt.getSlides(); + List slide = ppt.getSlides(); - verifySlide1(slide.get(0)); - verifySlide2(slide.get(1)); - verifySlide3(slide.get(2)); - verifySlide4(slide.get(3)); - verifySlide7(slide.get(6)); - verifySlide8(slide.get(7)); - verifySlide10(slide.get(9)); + verifySlide1(slide.get(0)); + verifySlide2(slide.get(1)); + verifySlide3(slide.get(2)); + verifySlide4(slide.get(3)); + verifySlide7(slide.get(6)); + verifySlide8(slide.get(7)); + verifySlide10(slide.get(9)); - ppt.close(); + } } void verifySlide1(XSLFSlide slide){ @@ -90,7 +99,7 @@ class TestXSLFTextShape { XDDFTextBody tb1 = shape1.getTextBody(); XDDFBodyProperties tbp1 = tb1.getBodyProperties(); CTPlaceholder ph1 = shape1.getPlaceholderDetails().getCTPlaceholder(false); - assertEquals(STPlaceholderType.CTR_TITLE, ph1.getType()); + assertSame(STPlaceholderType.CTR_TITLE, ph1.getType()); // anchor is not defined in the shape assertNull(getSpPr(shape1).getXfrm()); @@ -129,7 +138,7 @@ class TestXSLFTextShape { XDDFTextBody tb2 = shape2.getTextBody(); XDDFBodyProperties tbp2 = tb2.getBodyProperties(); CTPlaceholder ph2 = shape2.getPlaceholderDetails().getCTPlaceholder(false); - assertEquals(STPlaceholderType.SUB_TITLE, ph2.getType()); + assertSame(STPlaceholderType.SUB_TITLE, ph2.getType()); // anchor is not defined in the shape assertNull(getSpPr(shape2).getXfrm()); @@ -171,7 +180,7 @@ class TestXSLFTextShape { XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); CTPlaceholder ph1 = shape1.getPlaceholderDetails().getCTPlaceholder(false); - assertEquals(STPlaceholderType.TITLE, ph1.getType()); + assertSame(STPlaceholderType.TITLE, ph1.getType()); // anchor is not defined in the shape assertNull(getSpPr(shape1).getXfrm()); @@ -284,7 +293,7 @@ class TestXSLFTextShape { XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); CTPlaceholder ph1 = shape1.getPlaceholderDetails().getCTPlaceholder(false); - assertEquals(STPlaceholderType.TITLE, ph1.getType()); + assertSame(STPlaceholderType.TITLE, ph1.getType()); // anchor is not defined in the shape assertNull(getSpPr(shape1).getXfrm()); @@ -318,7 +327,7 @@ class TestXSLFTextShape { XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); CTPlaceholder ph2 = shape2.getPlaceholderDetails().getCTPlaceholder(false); - assertEquals(STPlaceholderType.BODY, ph2.getType()); + assertSame(STPlaceholderType.BODY, ph2.getType()); // anchor is not defined in the shape assertNull(getSpPr(shape2).getXfrm()); @@ -355,7 +364,7 @@ class TestXSLFTextShape { XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); CTPlaceholder ph1 = shape1.getPlaceholderDetails().getCTPlaceholder(false); - assertEquals(STPlaceholderType.TITLE, ph1.getType()); + assertSame(STPlaceholderType.TITLE, ph1.getType()); // anchor is not defined in the shape assertNull(getSpPr(shape1).getXfrm()); @@ -470,7 +479,7 @@ class TestXSLFTextShape { XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); CTPlaceholder ph1 = shape1.getPlaceholderDetails().getCTPlaceholder(false); - assertEquals(STPlaceholderType.TITLE, ph1.getType()); + assertSame(STPlaceholderType.TITLE, ph1.getType()); // anchor is not defined in the shape assertNull(getSpPr(shape1).getXfrm()); @@ -538,7 +547,7 @@ class TestXSLFTextShape { XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); CTPlaceholder ph1 = shape1.getPlaceholderDetails().getCTPlaceholder(false); - assertEquals(STPlaceholderType.TITLE, ph1.getType()); + assertSame(STPlaceholderType.TITLE, ph1.getType()); // anchor is not defined in the shape assertNull(getSpPr(shape1).getXfrm()); @@ -664,301 +673,313 @@ class TestXSLFTextShape { @Test void testTitleStyles() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - - XSLFSlideMaster master = ppt.getSlideMasters().get(0); - XSLFTheme theme = master.getTheme(); - XSLFSlideLayout layout = master.getLayout(SlideLayout.TITLE); - XSLFSlide slide = ppt.createSlide(layout) ; - assertSame(layout, slide.getSlideLayout()); - assertSame(master, slide.getSlideMaster()); - - XSLFTextShape titleShape = slide.getPlaceholder(0); - titleShape.setText("Apache POI"); - XSLFTextParagraph paragraph = titleShape.getTextParagraphs().get(0); - XSLFTextRun textRun = paragraph.getTextRuns().get(0); - - // level 1 : default title style on the master slide - // /p:sldMaster/p:txStyles/p:titleStyle/a:lvl1pPr - CTTextParagraphProperties lv1PPr = master.getXmlObject().getTxStyles().getTitleStyle().getLvl1PPr(); - CTTextCharacterProperties lv1CPr = lv1PPr.getDefRPr(); - assertEquals(4400, lv1CPr.getSz()); - assertEquals(44.0, textRun.getFontSize(), 0); - assertEquals("+mj-lt", lv1CPr.getLatin().getTypeface()); - assertEquals("Calibri", theme.getMajorFont()); - assertEquals("Calibri", textRun.getFontFamily()); - lv1CPr.setSz(3200); - assertEquals(32.0, textRun.getFontSize(), 0); - lv1CPr.getLatin().setTypeface("Arial"); - assertEquals("Arial", textRun.getFontFamily()); - assertEquals(STTextAlignType.CTR, lv1PPr.getAlgn()); - assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); - lv1PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, paragraph.getTextAlign()); - - // level 2: title placeholder on the master slide - // /p:sldMaster/p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="title"] - XSLFTextShape tx2 = master.getPlaceholder(0); - CTTextParagraphProperties lv2PPr = tx2.getTextBody(true).getLstStyle().addNewLvl1PPr(); - CTTextCharacterProperties lv2CPr = lv2PPr.addNewDefRPr(); - lv2CPr.setSz(3300); - assertEquals(33.0, textRun.getFontSize(), 0); - lv2CPr.addNewLatin().setTypeface("Times"); - assertEquals("Times", textRun.getFontFamily()); - lv2PPr.setAlgn(STTextAlignType.R); - assertEquals(TextAlign.RIGHT, paragraph.getTextAlign()); - - - // level 3: title placeholder on the slide layout - // /p:sldLayout /p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="ctrTitle"] - XSLFTextShape tx3 = layout.getPlaceholder(0); - CTTextParagraphProperties lv3PPr = tx3.getTextBody(true).getLstStyle().addNewLvl1PPr(); - CTTextCharacterProperties lv3CPr = lv3PPr.addNewDefRPr(); - lv3CPr.setSz(3400); - assertEquals(34.0, textRun.getFontSize(), 0); - lv3CPr.addNewLatin().setTypeface("Courier New"); - assertEquals("Courier New", textRun.getFontFamily()); - lv3PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); - - // level 4: default text properties in the shape itself - // ./p:sp/p:txBody/a:lstStyle/a:lvl1pPr - CTTextParagraphProperties lv4PPr = titleShape.getTextBody(true).getLstStyle().addNewLvl1PPr(); - CTTextCharacterProperties lv4CPr = lv4PPr.addNewDefRPr(); - lv4CPr.setSz(3500); - assertEquals(35.0, textRun.getFontSize(), 0); - lv4CPr.addNewLatin().setTypeface("Arial"); - assertEquals("Arial", textRun.getFontFamily()); - lv4PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, paragraph.getTextAlign()); - - // level 5: text properties are defined in the text run - CTTextParagraphProperties lv5PPr = paragraph.getXmlObject().addNewPPr(); - CTTextCharacterProperties lv5CPr = textRun.getRPr(false); - lv5CPr.setSz(3600); - assertEquals(36.0, textRun.getFontSize(), 0); - lv5CPr.addNewLatin().setTypeface("Calibri"); - assertEquals("Calibri", textRun.getFontFamily()); - lv5PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); - - ppt.close(); + try (XMLSlideShow ppt = new XMLSlideShow()) { + + XSLFSlideMaster master = ppt.getSlideMasters().get(0); + XSLFTheme theme = master.getTheme(); + XSLFSlideLayout layout = master.getLayout(SlideLayout.TITLE); + XSLFSlide slide = ppt.createSlide(layout); + assertSame(layout, slide.getSlideLayout()); + assertSame(master, slide.getSlideMaster()); + + XSLFTextShape titleShape = slide.getPlaceholder(0); + titleShape.setText("Apache POI"); + XSLFTextParagraph paragraph = titleShape.getTextParagraphs().get(0); + XSLFTextRun textRun = paragraph.getTextRuns().get(0); + + // level 1 : default title style on the master slide + // /p:sldMaster/p:txStyles/p:titleStyle/a:lvl1pPr + CTTextParagraphProperties lv1PPr = master.getXmlObject().getTxStyles().getTitleStyle().getLvl1PPr(); + CTTextCharacterProperties lv1CPr = lv1PPr.getDefRPr(); + assertEquals(4400, lv1CPr.getSz()); + assertEquals(44.0, textRun.getFontSize(), 0); + assertEquals("+mj-lt", lv1CPr.getLatin().getTypeface()); + assertEquals("Calibri", theme.getMajorFont()); + assertEquals("Calibri", textRun.getFontFamily()); + lv1CPr.setSz(3200); + assertEquals(32.0, textRun.getFontSize(), 0); + lv1CPr.getLatin().setTypeface("Arial"); + assertEquals("Arial", textRun.getFontFamily()); + assertSame(STTextAlignType.CTR, lv1PPr.getAlgn()); + assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); + lv1PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, paragraph.getTextAlign()); + + // level 2: title placeholder on the master slide + // /p:sldMaster/p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="title"] + XSLFTextShape tx2 = master.getPlaceholder(0); + CTTextParagraphProperties lv2PPr = tx2.getTextBody(true).getLstStyle().addNewLvl1PPr(); + CTTextCharacterProperties lv2CPr = lv2PPr.addNewDefRPr(); + lv2CPr.setSz(3300); + assertEquals(33.0, textRun.getFontSize(), 0); + lv2CPr.addNewLatin().setTypeface("Times"); + assertEquals("Times", textRun.getFontFamily()); + lv2PPr.setAlgn(STTextAlignType.R); + assertEquals(TextAlign.RIGHT, paragraph.getTextAlign()); + + + // level 3: title placeholder on the slide layout + // /p:sldLayout /p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="ctrTitle"] + XSLFTextShape tx3 = layout.getPlaceholder(0); + CTTextParagraphProperties lv3PPr = tx3.getTextBody(true).getLstStyle().addNewLvl1PPr(); + CTTextCharacterProperties lv3CPr = lv3PPr.addNewDefRPr(); + lv3CPr.setSz(3400); + assertEquals(34.0, textRun.getFontSize(), 0); + lv3CPr.addNewLatin().setTypeface("Courier New"); + assertEquals("Courier New", textRun.getFontFamily()); + lv3PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); + + // level 4: default text properties in the shape itself + // ./p:sp/p:txBody/a:lstStyle/a:lvl1pPr + CTTextParagraphProperties lv4PPr = titleShape.getTextBody(true).getLstStyle().addNewLvl1PPr(); + CTTextCharacterProperties lv4CPr = lv4PPr.addNewDefRPr(); + lv4CPr.setSz(3500); + assertEquals(35.0, textRun.getFontSize(), 0); + lv4CPr.addNewLatin().setTypeface("Arial"); + assertEquals("Arial", textRun.getFontFamily()); + lv4PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, paragraph.getTextAlign()); + + // level 5: text properties are defined in the text run + CTTextParagraphProperties lv5PPr = paragraph.getXmlObject().addNewPPr(); + CTTextCharacterProperties lv5CPr = textRun.getRPr(false); + lv5CPr.setSz(3600); + assertEquals(36.0, textRun.getFontSize(), 0); + lv5CPr.addNewLatin().setTypeface("Calibri"); + assertEquals("Calibri", textRun.getFontFamily()); + lv5PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); + } } @Test void testBodyStyles() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - - XSLFSlideMaster master = ppt.getSlideMasters().get(0); - XSLFTheme theme = master.getTheme(); - XSLFSlideLayout layout = master.getLayout(SlideLayout.TITLE_AND_CONTENT); - XSLFSlide slide = ppt.createSlide(layout) ; - assertSame(layout, slide.getSlideLayout()); - assertSame(master, slide.getSlideMaster()); - - XSLFTextShape tx1 = slide.getPlaceholder(1); - tx1.clearText(); - - XSLFTextParagraph p1 = tx1.addNewTextParagraph(); - assertEquals(0, p1.getIndentLevel()); - XSLFTextRun r1 = p1.addNewTextRun(); - r1.setText("Apache POI"); - - XSLFTextParagraph p2 = tx1.addNewTextParagraph(); - p2.setIndentLevel(1); - assertEquals(1, p2.getIndentLevel()); - XSLFTextRun r2 = p2.addNewTextRun(); - r2.setText("HSLF"); - - XSLFTextParagraph p3 = tx1.addNewTextParagraph(); - p3.setIndentLevel(2); - assertEquals(2, p3.getIndentLevel()); - XSLFTextRun r3 = p3.addNewTextRun(); - r3.setText("XSLF"); - - // level 1 : default title style on the master slide - // /p:sldMaster/p:txStyles/p:bodyStyle/a:lvl1pPr - CTTextParagraphProperties lv1PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl1PPr(); - CTTextCharacterProperties lv1CPr = lv1PPr.getDefRPr(); - CTTextParagraphProperties lv2PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl2PPr(); - CTTextCharacterProperties lv2CPr = lv2PPr.getDefRPr(); - CTTextParagraphProperties lv3PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl3PPr(); - CTTextCharacterProperties lv3CPr = lv3PPr.getDefRPr(); - // lv1 - assertEquals(3200, lv1CPr.getSz()); - assertEquals(32.0, r1.getFontSize(), 0); - assertEquals("+mn-lt", lv1CPr.getLatin().getTypeface()); - assertEquals("Calibri", theme.getMinorFont()); - assertEquals("Calibri", r1.getFontFamily()); - lv1CPr.setSz(3300); - assertEquals(33.0, r1.getFontSize(), 0); - lv1CPr.getLatin().setTypeface("Arial"); - assertEquals("Arial", r1.getFontFamily()); - assertEquals(STTextAlignType.L, lv1PPr.getAlgn()); - assertEquals(TextAlign.LEFT, p1.getTextAlign()); - lv1PPr.setAlgn(STTextAlignType.R); - assertEquals(TextAlign.RIGHT, p1.getTextAlign()); - //lv2 - assertEquals(2800, lv2CPr.getSz()); - assertEquals(28.0, r2.getFontSize(), 0); - lv2CPr.setSz(3300); - assertEquals(33.0, r2.getFontSize(), 0); - lv2CPr.getLatin().setTypeface("Times"); - assertEquals("Times", r2.getFontFamily()); - assertEquals(STTextAlignType.L, lv2PPr.getAlgn()); - assertEquals(TextAlign.LEFT, p2.getTextAlign()); - lv2PPr.setAlgn(STTextAlignType.R); - assertEquals(TextAlign.RIGHT, p2.getTextAlign()); - //lv3 - assertEquals(2400, lv3CPr.getSz()); - assertEquals(24.0, r3.getFontSize(), 0); - lv3CPr.setSz(2500); - assertEquals(25.0, r3.getFontSize(), 0); - lv3CPr.getLatin().setTypeface("Courier New"); - assertEquals("Courier New", r3.getFontFamily()); - assertEquals(STTextAlignType.L, lv3PPr.getAlgn()); - assertEquals(TextAlign.LEFT, p3.getTextAlign()); - lv3PPr.setAlgn(STTextAlignType.R); - assertEquals(TextAlign.RIGHT, p3.getTextAlign()); - - - // level 2: body placeholder on the master slide - // /p:sldMaster/p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="body"] - XSLFTextShape tx2 = master.getPlaceholder(1); - assertEquals(Placeholder.BODY, tx2.getTextType()); - - lv1PPr = tx2.getTextBody(true).getLstStyle().addNewLvl1PPr(); - lv1CPr = lv1PPr.addNewDefRPr(); - lv2PPr = tx2.getTextBody(true).getLstStyle().addNewLvl2PPr(); - lv2CPr = lv2PPr.addNewDefRPr(); - lv3PPr = tx2.getTextBody(true).getLstStyle().addNewLvl3PPr(); - lv3CPr = lv3PPr.addNewDefRPr(); - - lv1CPr.setSz(3300); - assertEquals(33.0, r1.getFontSize(), 0); - lv1CPr.addNewLatin().setTypeface("Times"); - assertEquals("Times", r1.getFontFamily()); - lv1PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, p1.getTextAlign()); - - lv2CPr.setSz(3300); - assertEquals(33.0, r2.getFontSize(), 0); - lv2CPr.addNewLatin().setTypeface("Times"); - assertEquals("Times", r2.getFontFamily()); - lv2PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, p2.getTextAlign()); - - lv3CPr.setSz(3300); - assertEquals(33.0, r3.getFontSize(), 0); - lv3CPr.addNewLatin().setTypeface("Times"); - assertEquals("Times", r3.getFontFamily()); - lv3PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, p3.getTextAlign()); - - // level 3: body placeholder on the slide layout - // /p:sldLayout /p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="ctrTitle"] - XSLFTextShape tx3 = layout.getPlaceholder(1); - assertEquals(Placeholder.BODY, tx2.getTextType()); - lv1PPr = tx3.getTextBody(true).getLstStyle().addNewLvl1PPr(); - lv1CPr = lv1PPr.addNewDefRPr(); - lv2PPr = tx3.getTextBody(true).getLstStyle().addNewLvl2PPr(); - lv2CPr = lv2PPr.addNewDefRPr(); - lv3PPr = tx3.getTextBody(true).getLstStyle().addNewLvl3PPr(); - lv3CPr = lv3PPr.addNewDefRPr(); - - lv1CPr.setSz(3400); - assertEquals(34.0, r1.getFontSize(), 0); - lv1CPr.addNewLatin().setTypeface("Courier New"); - assertEquals("Courier New", r1.getFontFamily()); - lv1PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, p1.getTextAlign()); - - lv2CPr.setSz(3400); - assertEquals(34.0, r2.getFontSize(), 0); - lv2CPr.addNewLatin().setTypeface("Courier New"); - assertEquals("Courier New", r2.getFontFamily()); - lv2PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, p2.getTextAlign()); - - lv3CPr.setSz(3400); - assertEquals(34.0, r3.getFontSize(), 0); - lv3CPr.addNewLatin().setTypeface("Courier New"); - assertEquals("Courier New", r3.getFontFamily()); - lv3PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, p3.getTextAlign()); - - // level 4: default text properties in the shape itself - // ./p:sp/p:txBody/a:lstStyle/a:lvl1pPr - lv1PPr = tx1.getTextBody(true).getLstStyle().addNewLvl1PPr(); - lv1CPr = lv1PPr.addNewDefRPr(); - lv2PPr = tx1.getTextBody(true).getLstStyle().addNewLvl2PPr(); - lv2CPr = lv2PPr.addNewDefRPr(); - lv3PPr = tx1.getTextBody(true).getLstStyle().addNewLvl3PPr(); - lv3CPr = lv3PPr.addNewDefRPr(); - - lv1CPr.setSz(3500); - assertEquals(35.0, r1.getFontSize(), 0); - lv1CPr.addNewLatin().setTypeface("Arial"); - assertEquals("Arial", r1.getFontFamily()); - lv1PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, p1.getTextAlign()); - - lv2CPr.setSz(3500); - assertEquals(35.0, r2.getFontSize(), 0); - lv2CPr.addNewLatin().setTypeface("Arial"); - assertEquals("Arial", r2.getFontFamily()); - lv2PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, p2.getTextAlign()); - - lv3CPr.setSz(3500); - assertEquals(35.0, r3.getFontSize(), 0); - lv3CPr.addNewLatin().setTypeface("Arial"); - assertEquals("Arial", r3.getFontFamily()); - lv3PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, p3.getTextAlign()); - - // level 5: text properties are defined in the text run - lv1PPr = p1.getXmlObject().isSetPPr() ? p1.getXmlObject().getPPr() : p1.getXmlObject().addNewPPr(); - lv1CPr = r1.getRPr(false); - lv2PPr = p2.getXmlObject().isSetPPr() ? p2.getXmlObject().getPPr() : p2.getXmlObject().addNewPPr(); - lv2CPr = r2.getRPr(false); - lv3PPr = p3.getXmlObject().isSetPPr() ? p3.getXmlObject().getPPr() : p3.getXmlObject().addNewPPr(); - lv3CPr = r3.getRPr(false); - - lv1CPr.setSz(3600); - assertEquals(36.0, r1.getFontSize(), 0); - lv1CPr.addNewLatin().setTypeface("Calibri"); - assertEquals("Calibri", r1.getFontFamily()); - lv1PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, p1.getTextAlign()); - - lv2CPr.setSz(3600); - assertEquals(36.0, r2.getFontSize(), 0); - lv2CPr.addNewLatin().setTypeface("Calibri"); - assertEquals("Calibri", r2.getFontFamily()); - lv2PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, p2.getTextAlign()); - - lv3CPr.setSz(3600); - assertEquals(36.0, r3.getFontSize(), 0); - lv3CPr.addNewLatin().setTypeface("Calibri"); - assertEquals("Calibri", r3.getFontFamily()); - lv3PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, p3.getTextAlign()); - - ppt.close(); + try (XMLSlideShow ppt = new XMLSlideShow()) { + + XSLFSlideMaster master = ppt.getSlideMasters().get(0); + XSLFTheme theme = master.getTheme(); + XSLFSlideLayout layout = master.getLayout(SlideLayout.TITLE_AND_CONTENT); + XSLFSlide slide = ppt.createSlide(layout); + assertSame(layout, slide.getSlideLayout()); + assertSame(master, slide.getSlideMaster()); + + XSLFTextShape tx1 = slide.getPlaceholder(1); + tx1.clearText(); + + XSLFTextParagraph p1 = tx1.addNewTextParagraph(); + assertEquals(0, p1.getIndentLevel()); + XSLFTextRun r1 = p1.addNewTextRun(); + r1.setText("Apache POI"); + + XSLFTextParagraph p2 = tx1.addNewTextParagraph(); + p2.setIndentLevel(1); + assertEquals(1, p2.getIndentLevel()); + XSLFTextRun r2 = p2.addNewTextRun(); + r2.setText("HSLF"); + + XSLFTextParagraph p3 = tx1.addNewTextParagraph(); + p3.setIndentLevel(2); + assertEquals(2, p3.getIndentLevel()); + XSLFTextRun r3 = p3.addNewTextRun(); + r3.setText("XSLF"); + + // level 1 : default title style on the master slide + // /p:sldMaster/p:txStyles/p:bodyStyle/a:lvl1pPr + CTTextParagraphProperties lv1PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl1PPr(); + CTTextCharacterProperties lv1CPr = lv1PPr.getDefRPr(); + CTTextParagraphProperties lv2PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl2PPr(); + CTTextCharacterProperties lv2CPr = lv2PPr.getDefRPr(); + CTTextParagraphProperties lv3PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl3PPr(); + CTTextCharacterProperties lv3CPr = lv3PPr.getDefRPr(); + // lv1 + assertEquals(3200, lv1CPr.getSz()); + assertEquals(32.0, r1.getFontSize(), 0); + assertEquals("+mn-lt", lv1CPr.getLatin().getTypeface()); + assertEquals("Calibri", theme.getMinorFont()); + assertEquals("Calibri", r1.getFontFamily()); + lv1CPr.setSz(3300); + assertEquals(33.0, r1.getFontSize(), 0); + lv1CPr.getLatin().setTypeface("Arial"); + assertEquals("Arial", r1.getFontFamily()); + assertSame(STTextAlignType.L, lv1PPr.getAlgn()); + assertEquals(TextAlign.LEFT, p1.getTextAlign()); + lv1PPr.setAlgn(STTextAlignType.R); + assertEquals(TextAlign.RIGHT, p1.getTextAlign()); + //lv2 + assertEquals(2800, lv2CPr.getSz()); + assertEquals(28.0, r2.getFontSize(), 0); + lv2CPr.setSz(3300); + assertEquals(33.0, r2.getFontSize(), 0); + lv2CPr.getLatin().setTypeface("Times"); + assertEquals("Times", r2.getFontFamily()); + assertSame(STTextAlignType.L, lv2PPr.getAlgn()); + assertEquals(TextAlign.LEFT, p2.getTextAlign()); + lv2PPr.setAlgn(STTextAlignType.R); + assertEquals(TextAlign.RIGHT, p2.getTextAlign()); + //lv3 + assertEquals(2400, lv3CPr.getSz()); + assertEquals(24.0, r3.getFontSize(), 0); + lv3CPr.setSz(2500); + assertEquals(25.0, r3.getFontSize(), 0); + lv3CPr.getLatin().setTypeface("Courier New"); + assertEquals("Courier New", r3.getFontFamily()); + assertSame(STTextAlignType.L, lv3PPr.getAlgn()); + assertEquals(TextAlign.LEFT, p3.getTextAlign()); + lv3PPr.setAlgn(STTextAlignType.R); + assertEquals(TextAlign.RIGHT, p3.getTextAlign()); + + + // level 2: body placeholder on the master slide + // /p:sldMaster/p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="body"] + XSLFTextShape tx2 = master.getPlaceholder(1); + assertEquals(Placeholder.BODY, tx2.getTextType()); + + lv1PPr = tx2.getTextBody(true).getLstStyle().addNewLvl1PPr(); + lv1CPr = lv1PPr.addNewDefRPr(); + lv2PPr = tx2.getTextBody(true).getLstStyle().addNewLvl2PPr(); + lv2CPr = lv2PPr.addNewDefRPr(); + lv3PPr = tx2.getTextBody(true).getLstStyle().addNewLvl3PPr(); + lv3CPr = lv3PPr.addNewDefRPr(); + + lv1CPr.setSz(3300); + assertEquals(33.0, r1.getFontSize(), 0); + lv1CPr.addNewLatin().setTypeface("Times"); + assertEquals("Times", r1.getFontFamily()); + lv1PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, p1.getTextAlign()); + + lv2CPr.setSz(3300); + assertEquals(33.0, r2.getFontSize(), 0); + lv2CPr.addNewLatin().setTypeface("Times"); + assertEquals("Times", r2.getFontFamily()); + lv2PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, p2.getTextAlign()); + + lv3CPr.setSz(3300); + assertEquals(33.0, r3.getFontSize(), 0); + lv3CPr.addNewLatin().setTypeface("Times"); + assertEquals("Times", r3.getFontFamily()); + lv3PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, p3.getTextAlign()); + + // level 3: body placeholder on the slide layout + // /p:sldLayout /p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="ctrTitle"] + XSLFTextShape tx3 = layout.getPlaceholder(1); + assertEquals(Placeholder.BODY, tx2.getTextType()); + lv1PPr = tx3.getTextBody(true).getLstStyle().addNewLvl1PPr(); + lv1CPr = lv1PPr.addNewDefRPr(); + lv2PPr = tx3.getTextBody(true).getLstStyle().addNewLvl2PPr(); + lv2CPr = lv2PPr.addNewDefRPr(); + lv3PPr = tx3.getTextBody(true).getLstStyle().addNewLvl3PPr(); + lv3CPr = lv3PPr.addNewDefRPr(); + + lv1CPr.setSz(3400); + assertEquals(34.0, r1.getFontSize(), 0); + lv1CPr.addNewLatin().setTypeface("Courier New"); + assertEquals("Courier New", r1.getFontFamily()); + lv1PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, p1.getTextAlign()); + + lv2CPr.setSz(3400); + assertEquals(34.0, r2.getFontSize(), 0); + lv2CPr.addNewLatin().setTypeface("Courier New"); + assertEquals("Courier New", r2.getFontFamily()); + lv2PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, p2.getTextAlign()); + + lv3CPr.setSz(3400); + assertEquals(34.0, r3.getFontSize(), 0); + lv3CPr.addNewLatin().setTypeface("Courier New"); + assertEquals("Courier New", r3.getFontFamily()); + lv3PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, p3.getTextAlign()); + + // level 4: default text properties in the shape itself + // ./p:sp/p:txBody/a:lstStyle/a:lvl1pPr + lv1PPr = tx1.getTextBody(true).getLstStyle().addNewLvl1PPr(); + lv1CPr = lv1PPr.addNewDefRPr(); + lv2PPr = tx1.getTextBody(true).getLstStyle().addNewLvl2PPr(); + lv2CPr = lv2PPr.addNewDefRPr(); + lv3PPr = tx1.getTextBody(true).getLstStyle().addNewLvl3PPr(); + lv3CPr = lv3PPr.addNewDefRPr(); + + lv1CPr.setSz(3500); + assertEquals(35.0, r1.getFontSize(), 0); + lv1CPr.addNewLatin().setTypeface("Arial"); + assertEquals("Arial", r1.getFontFamily()); + lv1PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, p1.getTextAlign()); + + lv2CPr.setSz(3500); + assertEquals(35.0, r2.getFontSize(), 0); + lv2CPr.addNewLatin().setTypeface("Arial"); + assertEquals("Arial", r2.getFontFamily()); + lv2PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, p2.getTextAlign()); + + lv3CPr.setSz(3500); + assertEquals(35.0, r3.getFontSize(), 0); + lv3CPr.addNewLatin().setTypeface("Arial"); + assertEquals("Arial", r3.getFontFamily()); + lv3PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, p3.getTextAlign()); + + // level 5: text properties are defined in the text run + lv1PPr = p1.getXmlObject().isSetPPr() ? p1.getXmlObject().getPPr() : p1.getXmlObject().addNewPPr(); + lv1CPr = r1.getRPr(false); + lv2PPr = p2.getXmlObject().isSetPPr() ? p2.getXmlObject().getPPr() : p2.getXmlObject().addNewPPr(); + lv2CPr = r2.getRPr(false); + lv3PPr = p3.getXmlObject().isSetPPr() ? p3.getXmlObject().getPPr() : p3.getXmlObject().addNewPPr(); + lv3CPr = r3.getRPr(false); + + lv1CPr.setSz(3600); + assertEquals(36.0, r1.getFontSize(), 0); + lv1CPr.addNewLatin().setTypeface("Calibri"); + assertEquals("Calibri", r1.getFontFamily()); + lv1PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, p1.getTextAlign()); + + lv2CPr.setSz(3600); + assertEquals(36.0, r2.getFontSize(), 0); + lv2CPr.addNewLatin().setTypeface("Calibri"); + assertEquals("Calibri", r2.getFontFamily()); + lv2PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, p2.getTextAlign()); + + lv3CPr.setSz(3600); + assertEquals(36.0, r3.getFontSize(), 0); + lv3CPr.addNewLatin().setTypeface("Calibri"); + assertEquals("Calibri", r3.getFontFamily()); + lv3PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, p3.getTextAlign()); + } } @Test void metroBlob() throws IOException, ReflectiveOperationException { assumeFalse(xslfOnly); - File f = POIDataSamples.getSlideShowInstance().getFile("bug52297.ppt"); - SlideShow ppt = SlideShowFactory.create(f); - Shape sh = ppt.getSlides().get(1).getShapes().get(3); - XSLFAutoShape xsh = (XSLFAutoShape)sh.getClass().getMethod("getMetroShape").invoke(sh); - String textExp = " ___ ___ ___ ________ __ _______ ___ ___________ __________ __ _____ ___ ___ ___ _______ ____ ______ ___________ _____________ ___ _______ ______ ____ ______ __ ___________ __________ ___ _________ _____ ________ __________ ___ _______ __________ "; - String textAct = xsh.getText(); - ppt.close(); - assertEquals(textExp, textAct); + POIDataSamples samples = POIDataSamples.getSlideShowInstance(); + String textAct; + try (InputStream is = samples.openResourceAsStream("bug52297.ppt"); + SlideShow ppt = SlideShowFactory.create(is)) { + // check metro shapes on master sheet + MasterSheet master = ppt.getSlideMasters().get(0); + FieldType[] tl = master.getShapes().stream(). + filter(f -> f instanceof TextShape).map(f -> (TextShape)f). + flatMap(f -> ((List>) f.getTextParagraphs()).stream()). + flatMap(f -> f.getTextRuns().stream()). + map(TextRun::getFieldType). + filter(Objects::nonNull). + toArray(FieldType[]::new); + assertArrayEquals(new FieldType[]{DATE_TIME, SLIDE_NUMBER, SLIDE_NUMBER}, tl); + + // check metro shapes on slides + Shape sh = ppt.getSlides().get(1).getShapes().get(3); + XSLFAutoShape xsh = (XSLFAutoShape) sh.getClass().getMethod("getMetroShape").invoke(sh); + String textExp = " ___ ___ ___ ________ __ _______ ___ ___________ __________ __ _____ ___ ___ ___ _______ ____ ______ ___________ _____________ ___ _______ ______ ____ ______ __ ___________ __________ ___ _________ _____ ________ __________ ___ _______ __________ "; + textAct = xsh.getText(); + assertEquals(textExp, textAct); + } } } \ No newline at end of file diff --git a/poi-ooxml/src/test/java9/module-info.class b/poi-ooxml/src/test/java9/module-info.class index 2cd55eb942abe5e2d34493e2f899c32212601558..75444a4c92c5a626ecc49f8c0d56ef5eae49908e 100644 GIT binary patch literal 5227 zcmd5823L1w;UO%FB`>)zFEe?$G0A%~gQzP~ zrDIo=js+DgSU?x-iVb`3z4!8$KhHV2FE202u>8sH@ArK#_nv$2Dc>#g(Esk+1_0~e zzZ0-bz%D)I^+UNPh&oEZik9jpuAB)%DPWIMmo@7Q90AKWv9$pc0!)?omJ>T}S6Z>=R5Qb)0b zmEwv$2QBs#a7f9*RlS~yQp;6gDBUc;-_r(|0`_e*@}z6P-U4pMxHEHuLL1{^J5KQd^me&jB? zPMU>Si$o0qPbLN&D`2mB_gt`G!11~ouJUBp>8DnjISW$)cAB;@90M%WLfgrLIm?NH zo&hHc*iC=WXI4K8u+nJ0GH+`qf#*vDrcqCM3(boTJ|4pwHbl5YlwqvvQ6ajKLVr^6 z=_y?4DaEH;z}!Er`1A+(d2-=bFu6W5;FQ7#t{4XWjG`rVlOV=1GXnO`*Gs!jB0VdS zDa#xee{_qng?glQ&m1S$dIRaLd${l;1w!%_v8Q(Y^6=mH1Jlr3iv=Wu!|HR78 zt>Ls&o&o3U`p@>GAhTxsae$uVmJP7Z>#X%u=ND;dkDFjFogQWfcl;`J&+?V>QCYdC zCb$9)LPza<^V_&H?S=WcV`IS*$34cyo=a_tqt* zDw*6=Pa>~YnAlwz#+;2?1RPVzM#U7RAfuGt118)iVE-oTb`UwVTkoiAlV{VX(%YAC zJi2US$6P!sxRbkJwhNQ4S%O0UBh^D zp?<3K;S%?SOkCxa#g@R1@3BDLBA@LRtlnFnpC#G`T@Rfpc_(g*U_)MCB zUkNy_GJUbQecJF5wOPO8C*U^%)>Z5)cdEVlj15~hZ7jyl@H1?20)8jpgvwB?b&+TL zT$RkVm6{tZ_J{hNREcj(t2HwmS1j}=0c)xYg{6gBA^uI$>ZTmT5;7+0g)ZWl@e0i3P@EtCb3HV1{n!Ezrw$3@dV*aoC0}Lk~xw8o$ zbgD&fuu%~IsVBH0h|$Qc00RH~&i^fg9q`98*b#OD*zsXl&dtZeL!~@_!#1(Kb<7&pk7>|IHk&j|LhVeMW6JQPhwizcG*D|hSd;;SW z8K2DfRK}ASpU!wH<7teiGj3pfHsdD7GZ@cgY%xBU@m$997@v>+y#QXw_+muB);6=p z*kSB4&N7CK5o64lFlLMc#s$U;7%yaeIpbEwix@9vyp-{B##b|5#dr5j(@jk|nAqvtme;aen|6|G=D|&!pk#H2f7QXcV*nn`{1eY56UHQ%oJPR*o4vLhuDlM0DR ths2~rV$vcpsgaoUNKA?(20XQXiNAggzeW5#{1Nfb@K?mY!#@%K{eR?s)+_)3 literal 5120 zcmd5GqNO0@~*pV%e@NFolc2TtvK;HN~BmZ6I@C^43;Da@+AL^^nLGvJF~m9vu|hj4*mD$TLA3De=2yq zgJY|4FA2e!jZMKC`BX$@3zVG0eebS_GgTg@vm6;iLyF0U8;Ry;)RCtoY zlNFw#@KlATDLkDz%(^pk?u^1S6rQQ@EQK2tZc=!*!gCa!>)_})ms}K{r|^7*7bv_? z;YA8BR(OfROBG(G@N$J$D7;ePRSK_Gc#Xnq6<(+CdWAPAyiwsz3U5|;i^5xJyq)eY z9`9`mZ`XK-#yd6MrSWc!_h`IV<9!FKFDVaht{$HNK>ANaM>IU(xug#@95yuJH|xZ)$u?$_cXq*@dJe)YWzs!#~MG;_^HOvG=8q}3yoiD{7U238o$x_t;X*(ey{NdjX!Gq zN#oBI{H21wR`9n9{$9a9D)?sw|El2M4%QWR$AONMrt5e8pk>@{9J+D5+-W;l%iHGG z{FJuy_>v2`IZ%a0>QOU(lsec_XdRB`rZjlRC-a#Fa}akrag@42+-{p73+a2#!O2rS z>LzfoVbG)FXRRF$)>pfJlA6oItZK6Hp6$5V45Ow?JhwoevKZSq_*pmUVitF4d16gX z&`ZK>#a(Eo6zN83q=mUbveM0B2d5PxOZ_P8`AHbN3&hz)!O_B{PZp zVcjGSPMEYUhRZguL0mU2zn8jc<}c6EL8|##xaj&(*l}>2{jrp}y)2|{S)Vu5lCa*S zomrRv)NYtXOXY#JI>4b2JV$t2%=jHz@n#CbZN_nvc0G^B!RZu^mrw1{LGYHBx($!= zo%jJwyo$Y-nuHFgp^aueP4u_6iLvX=v9Zr6_s#8r>B=daGC4aGCO>c507JV+g6Dx8 zxVOvCYnr%YvSh`}QKtg9}$L;IWi^h7D zGdPMU&oEzB#RV;=X=BPUpw{9Uoyfb``-W=&=%ALT=AjRJmd5N}%e1?)@C&DeI2wn; zGEvHxq=QqZxz@tS=Ob1Yn#8kO;ow-(EHQqEZp*yJmDA+q87ymmIc+z*dg3olOQSW( z!C%E*$lzqe)Za!tb=o{4eoGXCr7GJFNXdM*=yvJ0Lq7_rN^UKA z7K6@A%IhlE#k5VuLM-JIKCsv=o#>bjI-XUUHMN%FxhZF0=)+6(sS1^oIOfo6)1M3H zt~L!1K^~szbA`F+NNx>!kl9Ob)yNA{oJh-Hb-CoqO6Ar;VkS#WduoXxZ4VVeuc*=j z#4m-}v z1BMFCrKNtfiNj2K*T%_WEshsQ)08iR(t-|DtMh|S!zs3vr)U?ZsJ7{KU2Vlnqd8_v z{!*kyK^>^>ogelZPEyV^9R;py-ky%%G*_F59;5smElX`!0KMupSC07}1RVOyIRCc> zYv^MQ?tr6!qYmL{X}$!<90V%3Bev4-wSvbAt`qxu!3~1P32r3Zgw2E%951K@wcrWZ zO?;x@NrER6o`O^5`!vBVf~O0fA$X?XR>89b&lWsK@La+31kV?|K=4Ariv%wgyhQL) z!EJ)BpeMLpaE9WW#SXzaLQv~Y;X4W5S#X!&T?FqccsIej3*JNUo`RPN?iRe4;N^n% z7QBz(6@v4ER|?)&aF5{q1n)1nS8$);0|c)U+%Nb*!K($Uf)5gWu;4X<*9smGe2Cyf z1s^8(aKT3iK2q>eg4YT9f;B=10qT~G<%Z>^<(B2p@`B|>%WcaY%aP^Sa@X>sEhm;! z%bDe#<;%dCT0>e5@c$YkD~WT*T4H83F|(eSSy9ZaDP~p`GwX_(mBq~3VrF$Q@3zbe zy(9>x`L|#>`q{X0`a0S;BJ_e5^ HeBA#4Mx%ea diff --git a/poi-ooxml/src/test/java9/module-info.java b/poi-ooxml/src/test/java9/module-info.java index 3bb546f87f..a6a78d6e4e 100644 --- a/poi-ooxml/src/test/java9/module-info.java +++ b/poi-ooxml/src/test/java9/module-info.java @@ -32,6 +32,7 @@ module org.apache.poi.ooxml { provides org.apache.poi.ss.usermodel.WorkbookProvider with org.apache.poi.xssf.usermodel.XSSFWorkbookFactory; provides org.apache.poi.sl.usermodel.SlideShowProvider with org.apache.poi.xslf.usermodel.XSLFSlideShowFactory; provides org.apache.poi.sl.draw.ImageRenderer with org.apache.poi.xslf.draw.SVGImageRenderer; + provides org.apache.poi.sl.usermodel.MetroShapeProvider with org.apache.poi.xslf.usermodel.XSLFMetroShape; exports org.apache.poi.xwpf.extractor; exports org.apache.poi.xwpf.usermodel; diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/HSLFMetroShape.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/HSLFMetroShape.java index 54495aab2a..cc64c4c82f 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/HSLFMetroShape.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/HSLFMetroShape.java @@ -17,7 +17,8 @@ package org.apache.poi.hslf.model; -import java.lang.reflect.Method; +import java.io.IOException; +import java.util.ServiceLoader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -26,7 +27,10 @@ import org.apache.poi.ddf.EscherComplexProperty; import org.apache.poi.ddf.EscherPropertyTypes; import org.apache.poi.ddf.EscherTertiaryOptRecord; import org.apache.poi.hslf.usermodel.HSLFShape; +import org.apache.poi.sl.usermodel.MetroShapeProvider; import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.sl.usermodel.TextParagraph; +import org.apache.poi.sl.usermodel.TextRun; import org.apache.poi.util.Internal; /** @@ -34,7 +38,10 @@ import org.apache.poi.util.Internal; * containing an ooxml representation of the shape */ @Internal -public class HSLFMetroShape> { +public class HSLFMetroShape< + S extends Shape, + P extends TextParagraph +> { private static final Logger LOGGER = LogManager.getLogger(HSLFMetroShape.class); private final HSLFShape shape; @@ -42,9 +49,9 @@ public class HSLFMetroShape> { public HSLFMetroShape(HSLFShape shape) { this.shape = shape; } - + /** - * @return the bytes of the metro blob, which are bytes of an OPCPackage, i.e. a zip stream + * @return the bytes of the metro blob, which are bytes of an OPCPackage, i.e. a zip stream */ public byte[] getMetroBytes() { EscherComplexProperty ep = getMetroProp(); @@ -57,33 +64,36 @@ public class HSLFMetroShape> { public boolean hasMetroBlob() { return getMetroProp() != null; } - + private EscherComplexProperty getMetroProp() { AbstractEscherOptRecord opt = shape.getEscherChild(EscherTertiaryOptRecord.RECORD_ID); return (opt == null) ? null : (EscherComplexProperty)opt.lookup(EscherPropertyTypes.GROUPSHAPE__METROBLOB.propNumber); } - + /** * @return the metro blob shape or null if either there's no metro blob or the ooxml classes * aren't in the classpath */ @SuppressWarnings("unchecked") - public T getShape() { + public Shape getShape() { byte[] metroBytes = getMetroBytes(); if (metroBytes == null) { return null; } - - // org.apache.poi.xslf.usermodel.XSLFMetroShape - ClassLoader cl = getClass().getClassLoader(); - try { - Class ms = cl.loadClass("org.apache.poi.xslf.usermodel.XSLFMetroShape"); - Method m = ms.getMethod("parseShape", byte[].class); - return (T)m.invoke(null, new Object[]{metroBytes}); - } catch (Exception e) { - LOGGER.atError().withThrowable(e).log("can't process metro blob, check if all dependencies for POI OOXML are in the classpath."); - return null; + + ClassLoader cl = HSLFMetroShape.class.getClassLoader(); + IOException lastError = null; + for (MetroShapeProvider msp : ServiceLoader.load(MetroShapeProvider.class, cl)) { + try { + return (Shape) msp.parseShape(metroBytes); + } catch (IOException ex) { + lastError = ex; + break; + } } + + LOGGER.atError().withThrowable(lastError).log("can't process metro blob, check if all dependencies for POI OOXML are in the classpath."); + return null; } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextRun.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextRun.java index f69ee6e432..a30281eeeb 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextRun.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextRun.java @@ -19,6 +19,7 @@ package org.apache.poi.hslf.usermodel; import java.awt.Color; import java.util.List; +import java.util.stream.Stream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -35,6 +36,7 @@ import org.apache.poi.sl.usermodel.MasterSheet; import org.apache.poi.sl.usermodel.PaintStyle; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.apache.poi.sl.usermodel.Placeholder; +import org.apache.poi.sl.usermodel.Shape; import org.apache.poi.sl.usermodel.TextParagraph; import org.apache.poi.sl.usermodel.TextRun; import org.apache.poi.sl.usermodel.TextShape; @@ -506,16 +508,14 @@ public final class HSLFTextRun implements TextRun { } } - if (ts.getSheet() instanceof MasterSheet) { - TextShape> ms = ts.getMetroShape(); - if (ms == null || ms.getTextParagraphs().isEmpty()) { - return null; - } - List trList = ms.getTextParagraphs().get(0).getTextRuns(); - if (trList.isEmpty()) { - return null; - } - return trList.get(0).getFieldType(); + Shape ms = (ts.getSheet() instanceof MasterSheet) ? ts.getMetroShape() : null; + if (ms instanceof TextShape) { + return Stream.of((TextShape)ms). + flatMap(tsh -> ((List>)tsh.getTextParagraphs()).stream()). + flatMap(tph -> tph.getTextRuns().stream()). + findFirst(). + map(TextRun::getFieldType). + orElse(null); } return null; diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextShape.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextShape.java index 9a60a2e8ae..8efa7cadb1 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextShape.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextShape.java @@ -51,6 +51,7 @@ import org.apache.poi.sl.draw.DrawFactory; import org.apache.poi.sl.draw.DrawTextShape; import org.apache.poi.sl.usermodel.Insets2D; import org.apache.poi.sl.usermodel.Placeholder; +import org.apache.poi.sl.usermodel.Shape; import org.apache.poi.sl.usermodel.ShapeContainer; import org.apache.poi.sl.usermodel.TextParagraph; import org.apache.poi.sl.usermodel.TextRun; @@ -153,7 +154,7 @@ implements TextShape { /** * Create a TextBox object and initialize it from the supplied Record container. * - * @param escherRecord EscherSpContainer container which holds information about this shape + * @param escherRecord {@code EscherSpContainer} container which holds information about this shape * @param parent the parent of the shape */ protected HSLFTextShape(EscherContainerRecord escherRecord, ShapeContainer parent){ @@ -192,7 +193,7 @@ implements TextShape { /** * When a textbox is added to a sheet we need to tell upper-level - * PPDrawing about it. + * {@code PPDrawing} about it. * * @param sh the sheet we are adding to */ @@ -403,7 +404,7 @@ implements TextShape { /** * Sets the type of alignment for the text. - * One of the Anchor* constants defined in this class. + * One of the {@code Anchor*} constants defined in this class. * * @param isCentered horizontal centered? * @param vAlign vertical alignment @@ -572,7 +573,7 @@ implements TextShape { * Returns the value indicating word wrap. * * @return the value indicating word wrap. - * Must be one of the Wrap* constants defined in this class. + * Must be one of the {@code Wrap*} constants defined in this class. * * @see MSOWRAPMODE */ @@ -586,7 +587,7 @@ implements TextShape { * Specifies how the text should be wrapped * * @param wrap the value indicating how the text should be wrapped. - * Must be one of the Wrap* constants defined in this class. + * Must be one of the {@code Wrap*} constants defined in this class. */ public void setWordWrapEx(int wrap){ setEscherProperty(EscherPropertyTypes.TEXT__WRAPTEXT, wrap); @@ -841,7 +842,7 @@ implements TextShape { /** * Returns the array of all hyperlinks in this text run * - * @return the array of all hyperlinks in this text run or null + * @return the array of all hyperlinks in this text run or {@code null} * if not found. */ public List getHyperlinks() { @@ -904,8 +905,10 @@ implements TextShape { * * @return null, if there's no alternative representation, otherwise the text shape */ - public TextShape> getMetroShape() { - HSLFMetroShape>> mbs = new HSLFMetroShape<>(this); - return mbs.getShape(); + public < + S extends Shape, + P extends TextParagraph + > Shape getMetroShape() { + return new HSLFMetroShape(this).getShape(); } } \ No newline at end of file diff --git a/poi-scratchpad/src/main/java9/module-info.class b/poi-scratchpad/src/main/java9/module-info.class index 72189ac318dd5fdfbb0c5ec62efaff1fb5a610cb..1c076d2f61d18824bc169cce38b053e0018182af 100644 GIT binary patch literal 2695 zcmZ{m`Fh(#6vfX3h-unFsZ_eRp%f^ENR6Aa7Rr{8LPAT;zRS|YQX*OENOls|urH6q zA3OjL#mAj1N4Dj$zt2C*K6mciId?SjzyJOH4}fdIrWil$b+<@&4eQ&^Xnl)@^^s7n z?`qk&v5sgl&s1XLnqhHT_0w)&DyrSavr|Gw*8lvJkX|ko-2gJS@nX5zC(0PeFBu%v zb+GJ4sf`-~=j-kaBZ}Qjl0~l?EZj~uTqXTf1vXwcnL&D>ylorHre%;ivWzz;Lnmx;eY}n{!$Z(^7Iwj4B&z~C_rPH+ID6{dU!3nJnoS;MYQr(G4 zb_=RDQ)x!qJJNf`pE6aih-lx^$vbg0<@wkR(lInVPpILM$!opa^qIG1N~}e%@CLg% znG!N$H$87A&J~)QIx@8TuHl5!F`1|6{v-!-LlQ{=W!qi4w9yl|Q1^5^CX0KNYun(a zjw|o5UBimBT6MmGZv>p$M0q?6aMxv_(pKnY^0rF*Q6NhGZMoU19>!IQ6@D7+Ht?gsLM_8sm93a6YlZ3daMGUznzbRJ-j&tb-PP9G zN;R;W>Q{k_wQ)3+_S3zYcpZ61cF6>7!|#(eg!=U3*j2i!#s6uD-|v;XN>^j?dw`%n zJ>_c#_t3=*?!|rdb04$(a|8G90dqKrdHQ~s-g9`62t35Jn8%36v4|7=?G*D2^Bi-Y zd4YM6`8e|u^D^^kro+6#Y%-Ua&oG~3zQDZBe3|(Q^EKuh%oXM;^DX8Y^Bv}G<{jpH z%nz6!F+X8`#{7c$6|>C@m>bNHxyg)~U1r8q%!1ix?l86MUz6M4(&zWsBmRV6$ob#! F$Ny2_{}liL literal 2642 zcmai$d3)PL5XN7nP|*uYHKlhON`X>{6uT*Bxk*SNrKRS+WqD&Okt|h`?SwPjd?xoNgEv+HXlb_{%XEi(T&TjJeKY#uO;2Qq0@ur1?jii?aY9)-6g`;uO>P2cH z?5-#7hTr!s?7t~P4ptr9uwd6}?xI^;bnupgw;ilGxar^>2e&x1?$(yv8sRqKUBVqg zgYX{VeZmKX4+$R;J|=uZ_>}M&;d8!*IuQEr-qZXRTQ5p+_&W#ND}!)^LGn{=!c$FUX;OF&EIn?;gZI1(gr zoOE+H_KVI{3&$ts>`Gx`;iO?aNLnhGmZGHH4!doaKbJNvI6TW6uGHh~UME)T7ETyO zy_V`*IA>DSR+0HZkz_M;zbLY>*(O1@Uxl#fS;`OcK{X(cZ*<;S@pn^q@QbJjGQ z%j^~^Mlh0~^hpwsJavREl)keW*2(P1figQl$3N}gu1p$;ttNw=>u zUg->dqRz^$==r@|W!#l28unu)^+>CDr00s}>9)FHTJ=yawo_#?X%Me_nF^AOyS-X8 zi>=Hbn2KU)V$tQI#`Sthr0NF$)27LP9-Yy;S{c98V3O8HCe4>!7;E0$pcxiyL*>lm z(I|1Hi?p(9P`S#E7AIC!>CvIS*Q3T4OxRf20sVqz6!O)guc@iF(9)>l%QH2v;N_)R zl5%r~x&e$CdPT^MS6y5_)!3CYl*gt$D2iYBqh74$1W}FEvO>E|s()-7ydCR+Z@a-(=hb?_;T%Q@N z50H0jZMohU|6v->Uy+-9+rmO=dLHeq#A`&HqtQtQd+F+>cWo_z~cX4hCg$dnm$;eNh}~L=_9)te5q8y0 zxzeub8T*1=F3~X?Ik$Glvs3nNQ#?f ziC=AH+M+XtxodTv`>bJZ4&-y6Q*>-_ZUoaT(Y!{B&KqV%LQiuKC^~Mc!OL&5qFlsQ zbi$OOH#{9@K3iwe1w}_qIbNgHT;+J#u)g(}*EeHW9|!XFJ(wHV=LmvnoP-u#GAs^J zFKVvognPH>ks&EP>%TlCrIqT0p9~#X^mzUhY-^(kKWR`9eMs2xd1pPX=;WX}-HdEA z)-2I81_{^0Whc>Il+-MmH;KXVTH>x-v|w5WM|+m>-1d}?4o(#4vPFvqo8l_l^n$@A z4&*jn-(I+ZV5ho8Hw+RYrI7F?MU#U9b;8a~uj*&4&?|-}(x7PKHG_Nzw&i=n&?MqL zO}=H==y^(aqrWqxOpng*8H_@iYT(BfRSilYS}0LdbZ$_IPT0w~+c=40-rhd;%<_<_ zTA9!Lwqfcu?R!A@MBR4gr6C(0n6$=j!m1ry9uf_W-4%}=xNCcMF149~kVmiJ!3zfzB&cM!8zbZO2Fpj5!*Ur_@ zt?L`Q$s$08-?z)qz{xDR3w$+@|ED3py^ov)zUs^0B2xTME&q(r4!#(n+h`}zjs@B! zKkug9TSQ~DmnQjsKYz#Q4o0Fo`CB53@h&IGB?-RUV za7xe-oEE$&I4k&&;KPEC3O*+Igy2(xR|Mw-pB20+_`Kkf;5ES)1uKFt3%)A&y5O6F zZwtOF=n8s*TCgtY3$6-=f|1}&!Bns%xGuOU_<`U@jEZj2Ck202@D~No5>_}upo xFgydpH86Yw!#Oa#1H(Nq`~$aLgOj+2mtaL-@$>Ty^LO+E<4^PpJN6s>@jqwTYRUir literal 3289 zcmai0`Fqq<6g?@zuqrYa*`XpLqD^R_ii(O0wP+Ef?t7X^XVT70LMGFKEAIQQ|BOHQ z2lz+%dC#4t(@94AeLW|6_r1J(&$%y|zyJC3F96f{qlD)jY@LtWX%Nmt_0Yl2MqFvv z!-=T57`sdUitk|4B^xT^av4_~lqM(LQ|{!cGF~X-Y8mroyr`3=+{rWUWEn3x*f{N; z<>kv|ydrp2@S5Ot!5e}%1#b!77Q7>PSKtd41c9I;2nCCRs-Px_1WSTtL0!-gGzGCB z5nL0bf|ei?v;`}IRl#+^4Z(YY_XQsaJ`{W;_*igL@QL74!DoWc1z!lh6nrK4TJTL7 z-wM7Hd@uN+gda=zsf3?P_@#tjOZcsX-yLil5W>N}IIX&V;s>?RP2$LH1*x9}wZyMD z*g~1y1;3^8?HZb=a~*8A36-$5oW+TQ9YNe^#Lbr5@Uz-!2YUzB)Z=P3YF1t4GfNJ3 zGqluhMwwy~WnrpG=o4+p`tih1{YFdk=8{GnEJs=FpsaUZCvQ)4@oJ55(ZQaAQLhrN zI5<=k39o0VA7pVlBJO8d8ZERltv|P4rCPL~j&}AtFuWfltt<_#mRvTB4rFt%XtkEv zRH0Og!$slndJraAr20G9Uo;`8wVTTt%$2g56qTZ*ol@w@I;k0HC26BTHHLz?xe}(D z>4^A1ojD!2zTFB_?a{E_>CW8N-B?Z|uCuW+NPit2(YlQEA6g(1<6V))hgImuylcTil&K84 zGt;VfH_mktBRzqJtE@3NkX5cnJMpz1EquU$j5!DRfQ5RbFB-nI*0lvg-HK0)jCq-+ zm!xr`%^9%)3U_E{kv3jFxz@VI&YhuFqsT)Y9pRxx{LJt6Vtzke`JZZ9d`->V`-U6n zt5eUCR+=*-)M&>^PcI!D9ae4qgrwds(u=Ae^mXJYjgR;Yq{$4DUCbFmw$)!&8QnhEs;84bK=( z8$Mw8py64=hYTM!e8lja;iHC+89r`!-tY;-Clwt$g{QlGq02K}o(3x%!%m&U`Z`zC zmaC{Pnfj8cFqs;YsWO>5lc_YBT9c_ZnR=6{IGLK0sXCdulgGPE?Rih#$-QiQ+0z4# z(*-hpAkzsly&%&KGW{Ua5i&g?_f(-fyr(~8Iz*;NWV%GAPh>hprdMRTMW$b5I!2~v tWV%MCZ)7@0rgvnzN2Y(|o@?j3_w8{hGt2e*p<(Lk<7{ diff --git a/poi-scratchpad/src/test/java9/module-info.java b/poi-scratchpad/src/test/java9/module-info.java index aa1e3d76c8..0d6ba80e5b 100644 --- a/poi-scratchpad/src/test/java9/module-info.java +++ b/poi-scratchpad/src/test/java9/module-info.java @@ -21,6 +21,8 @@ module org.apache.poi.scratchpad { requires commons.math3; requires org.apache.logging.log4j; + uses org.apache.poi.sl.usermodel.MetroShapeProvider; + provides org.apache.poi.extractor.ExtractorProvider with org.apache.poi.extractor.ole2.OLE2ScratchpadExtractorFactory; provides org.apache.poi.sl.usermodel.SlideShowProvider with org.apache.poi.hslf.usermodel.HSLFSlideShowFactory; provides org.apache.poi.sl.draw.ImageRenderer with org.apache.poi.hwmf.draw.HwmfImageRenderer, org.apache.poi.hemf.draw.HemfImageRenderer; diff --git a/poi/src/main/java/org/apache/poi/sl/usermodel/MetroShapeProvider.java b/poi/src/main/java/org/apache/poi/sl/usermodel/MetroShapeProvider.java new file mode 100644 index 0000000000..e89a14df56 --- /dev/null +++ b/poi/src/main/java/org/apache/poi/sl/usermodel/MetroShapeProvider.java @@ -0,0 +1,31 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +import java.io.IOException; + +import org.apache.poi.util.Internal; + +/** + * Experimental provider / loader for metro shapes. + * Metro shapes are xslf fragments stored in hslf shapes. + */ +@Internal +public interface MetroShapeProvider { + Shape parseShape(byte[] metroBytes) throws IOException; +} diff --git a/poi/src/test/java9/module-info.class b/poi/src/test/java9/module-info.class index 028b943d0ae7577c19f08d4b20ce352134f4f685..438e778ab515b0d480b1fb79ccaffeeafa4e55c6 100644 GIT binary patch literal 4198 zcmai1X`9qU5UxgGT}4L4TQW)SOm;I#OfoZ!=ZdI!-}i-h zE8aIB`~m(bAFC>vnd~I9?8CnAcDlN|y58#Q=HLI${R04d;9MU}6ELUhSv5!Pu-#El z!0e(|3rsa+J4(R9RF^hp)C~bMN7%XmeF7GHL0L0=!>lOH_iXwtz$^i?$W$vCAx<%~ ze?Z%*?JB@r0qausrdO?cZm5}_<0vz-@$Z2G%ongc*T_<40Tv3F*BVzfqRQ?9EEX`g z=o>+(2JNV*q5{atQ#f9^Y`bL*d0-6P*`=XF{RLQt1KG{Qpa3gcUn~`lN1k7RRRR`_ zS>syG4Qsyd1(C7}um+uQRiu@gkt)?Jt0|zbU+c$z`wFmLz!LI*tmfJgqHjkkz!2F2 zX6(`S(!!e(|0bK@7K~~rVT*wIIDsBVRmX@*xHz6P^-YhXAmNfYsM#*P7ODW%Q;vj7 z1#Fo-XEMHHq>p-Tgv;-UMNQ9VS)&s4*y;3lbvz0TGx7on{Q?SI3sn3NhwT=yCZ|JB zjos73q@f&V-1Qo+gv)cL4{7>+0+w}8j~%+D>JqLLur{w#)s-71k-1vH#-28*2wp2d zJHMT7)vDEIpiD2YBwUxXF>)@o_v;0$$eT9t?x28`dEKoQZpi9dp%vnO-6)p>RW>4p zx*qD`Ok!$cFmDpDzV~XnSuui0!iazkQ(5t;mT+q}FVn7>m~9enJI`D}(~mp}#i_UH z+jTFBjFO`y+|gs3DJhTkn5}K1SCr$c0E2dSHtBg2waCU(b+3R`U6H`kIvTdm=KWdu z5(CpS!;htnN_M(5#5Q~i$9p-&$8Z$47&gO5RV7rjDHG3=Ho^-kKj>A%3_R5A zp1E~N zE+5G?NY#YLvNa87u&ccE6SBx!GcHV5qNlTA3q!mV0=#A=Je#dk zNpH3g|yq-6Xc*PpgQr$l{}lZ&Aq7pPCN z2MRYueY%O4Yr}BHC48E_TjSB6WqoY;od<)2FS1ENm%fhAJ{#X^U&Ylgc?tQB5m7eb zbB~{W628e+zw`~kRlN_s%U-;A8aja(QBmL(D~7KQ2VUK_RL}?C3)t3m2HNLKKiGP; zbnJf=u)WKk;?#OS=|?e{N}e~~8S%4#9o-|+UKJhmq*(D9ogu$w>tL%e9HO&*M7iiZ zx&M21@{ao>hV8buFvQQVW*_`1pufwX_@Zj>VYpZvYVD&v?C)%#T0Y@px@!27JevRz z_`inuXBu39e@uhvFauz^gqi$#E?hVPFdOD@YaZhQ#zl+;#3is4aW*VxT*hVa7)pA7`9k zJi&O9@fpTbjL$Q^$oMkjtBkKRzRCDD~*GmM`j3iuMfPB>PCzK|xw zTN5T-s7=ZclQzVp4smNH(uvxn6ftQni7+$#H1@RDN9V+5+6&rl(3aBX-xf4smF{w^Wx)YP~#H2m(M8YQ$KAAA(0QH|rnDT(ylnKO?3&fNS#FP)jlo7;~ v6U3Ai#FQ7rlo`a78^os*K9lea_!iE>5AYNGg4N(G+Wdws0e@gyz+e9ZM%i|U literal 4145 zcmai1`Fj*a5PgH_iXbRkf)@fR9w<9RgZF``2r7z1#ak!4lg%W%Gvmx`LOk)l@B6;* z`}Xq({{a6eKkL=*Cd2Fy^L=?Q(_P(NU9Y;j^UuG3{S9Cf{;c3G2ZxMAouuw>4O+f~ z!`e}!)ABb2;aF6g@TNQm2ko$?D!eL29aM&fY8z`q8>^^S(Wt_&Vyud$+MQ7w8m00%V!_>lM34$HK}Rqpm=^32%n0rg+$*?G zaKGRI!GnUmf`zBx!?=Imx8YZUkknwd@J}) z@O>3O2!5>KrwV?q;Fk)1t>Cu`ey`vU2a9u2bg(>1nl&%>>f?SbjspHVSj6DgM!i&n zzB*@6kJ{}hOl$S1)$;3EpnnfLII`5D;ny7;+8@#Ovhgz=EE$QtB=xrh*@&O*JF*ou zn?cyDDGyJmrMb{+?0+`=bTW%#2g@cJleJEmcH%fnGQXiKg??5Woyq*sPNOm7;0QW3 z(Fuc0F%B|6(Ov4+%-Mb0)g`Z;I#{Yh+-@jb3j^oKHMrf)bVD-O?sif?(b)Q$OzTQV z&RMu)QJCqHjDCKmMq{k&V!qMelOVQ=xt!{2qY5%m}YE6dGbXYQL z%2`(yXVq4>;ZHd@uB^wO^24mR{p0s*kc(06|Bc*6r`?`O{CbqA!~@%)L%D4pRW@PI zqod3E`V$w`8t25_PS_3NQ!>gWQ+yvZ5) zQ(no%Q81vVlf3TcS#7Kn+STl!n9I4z`bH&HEoT*H`gEFS;~idCCDG35Q{uyH?_BX1 zNU7BAmJYr?@>NBhV~1PU+iTiu=_9UqC63Ht)9n_iEsH@MNK%XouN4~-7{E@28ybK^#zY-bKJeWe~<4>qN$+aYneE`V9f3HUlHzZ)p|6FCg;pI6wO;X z^O2U$IWiti&)FACP5(e{=gHdThw1~pC{8=)@(wQuXWiavj}Wa7Lj^awrGD1$Z6hOF z`@YYPDTbx*iarI~Uc8S(djUuP1?c`Pzykea0S>@IVBvBcXw6G-&|aW|gY9dP;UR{L z4VNe$ilvGbEHgaJ@NmWDs45DMFx-L_%D_s)BMpx-JlgOW!($Cs86Ic2+Hj5GTEpWF zPcS^uaGl{vh9?`IVtA_Idc)HUPdD6PSTl4DHyREZo?&>V;jrN*!?O&}Hay4hT*LDW z&o{il@Iu3j3@cUbB2z2!njTXxep4|r zH6v3sGIb+UIWn~)Q#~^EBU3>#H6&9-a(^e(liyU7OijsDl}ug9RF+I_$yAq2eaTdq zOpVD@nM|F@RGLh!$yA$6y~$LZOwGxgdraN=P36hdo=o-0)St`@ATtNZ%mOm=fXqxF zGZ)Cr1~T)3%#0v2C&z9K&^xMIm F{{h);L3;oI diff --git a/poi/src/test/java9/module-info.java b/poi/src/test/java9/module-info.java index 58ac2220c5..7b9cf162cf 100644 --- a/poi/src/test/java9/module-info.java +++ b/poi/src/test/java9/module-info.java @@ -24,6 +24,8 @@ module org.apache.poi.poi { requires java.logging; requires java.desktop; + uses org.apache.poi.sl.usermodel.MetroShapeProvider; + /* needed for CleanerUtil */ requires jdk.unsupported; -- 2.39.5