This is an automated email from the ASF dual-hosted git repository. centic9 pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/poi.git
commit 1c53108d260f446d6cafc598c85cd061e97d1aca Author: Dominik Stadler <[email protected]> AuthorDate: Sun Apr 12 17:50:24 2026 +0200 Bug 66568: Adjust selecting color from master-slide Co-authored-by: Copilot <[email protected]> --- .../org/apache/poi/xslf/usermodel/XSLFSheet.java | 15 ++++++++--- .../apache/poi/xslf/usermodel/TestXSLFTextRun.java | 30 +++++++++++++++++---- test-data/slideshow/placeholder-layout-color.pptx | Bin 0 -> 346876 bytes 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFSheet.java b/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFSheet.java index 1a4e3de194..4f74f741e4 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFSheet.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFSheet.java @@ -197,7 +197,7 @@ public abstract class XSLFSheet extends POIXMLDocumentPart /** * Returns an array containing all of the shapes in this sheet * - * @return an array of all shapes in this sheet + * @return a list of all shapes in this sheet */ @Override public List<XSLFShape> getShapes(){ @@ -578,7 +578,16 @@ public abstract class XSLFSheet extends POIXMLDocumentPart _placeholderByIdMap.put(ph.getIdx(), sShape); } if(ph.isSetType()){ - _placeholderByTypeMap.put(ph.getType().intValue(), sShape); + int typeInt = ph.getType().intValue(); + // Prefer the canonical (unindexed or idx=0) placeholder as the + // representative for its type. A placeholder with an explicit non-zero + // idx is a secondary variant (e.g. a second title box in a layout) and + // must not displace the canonical entry, otherwise type-based lookups + // will resolve to the wrong shape and inherit incorrect styles. + boolean isCanonical = !ph.isSetIdx() || ph.getIdx() == 0; + if (isCanonical || !_placeholderByTypeMap.containsKey(typeInt)) { + _placeholderByTypeMap.put(typeInt, sShape); + } } } } @@ -676,7 +685,7 @@ public abstract class XSLFSheet extends POIXMLDocumentPart PackagePart part = pkg.createPart(srcPPName, srcPart.getContentType()); try( OutputStream out = part.getOutputStream(); - InputStream is = srcPart.getInputStream(); + InputStream is = srcPart.getInputStream() ) { IOUtils.copy(is, out); } catch (IOException e){ diff --git a/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java b/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java index 944880c121..50c84734db 100644 --- a/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java +++ b/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java @@ -22,6 +22,7 @@ import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -32,17 +33,12 @@ import java.io.IOException; import java.io.InputStream; import org.apache.poi.POIDataSamples; -import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.sl.draw.DrawPaint; import org.apache.poi.sl.draw.DrawTextParagraph; import org.apache.poi.sl.usermodel.PaintStyle; -import org.apache.poi.xslf.model.PropertyFetcher; import org.junit.jupiter.api.Test; import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; -import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; @@ -158,6 +154,30 @@ class TestXSLFTextRun { } } + @Test + void testFontColorFromCorrectLayoutPlaceholder() throws IOException { + // When a layout has two placeholders with the same type but different idx values + // (e.g. type="title" with no idx carrying cyan, and type="title" idx="2" carrying red), + // a slide text run that inherits its color must resolve to the canonical (unindexed) + // placeholder's style — not the secondary indexed one. + try (InputStream is = POIDataSamples.getSlideShowInstance().openResourceAsStream("placeholder-layout-color.pptx"); + XMLSlideShow ppt = new XMLSlideShow(is)) { + XSLFSlide slide = ppt.getSlides().get(0); + XSLFTextShape titleShape = (XSLFTextShape) slide.getShapes().get(0); + XSLFTextRun run = titleShape.getTextParagraphs().get(0).getTextRuns().get(0); + + // The text run has no explicit color; the color comes from the layout's + // lstStyle.lvl1pPr.defRPr for the canonical title placeholder (cyan, 00FFFF). + PaintStyle paintStyle = run.getFontColor(); + assertInstanceOf(PaintStyle.SolidPaint.class, paintStyle, + "Expected a SolidPaint, got: " + paintStyle); + + Color color = ((PaintStyle.SolidPaint) paintStyle).getSolidColor().getColor(); + assertEquals(new Color(0, 255, 255), color, + "Expected cyan from the canonical (unindexed) layout placeholder, got: " + color); + } + } + @Test void testDefaultRunProperties() throws IOException { // bug #63290 diff --git a/test-data/slideshow/placeholder-layout-color.pptx b/test-data/slideshow/placeholder-layout-color.pptx new file mode 100644 index 0000000000..ff1a1eddf0 Binary files /dev/null and b/test-data/slideshow/placeholder-layout-color.pptx differ --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
