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]

Reply via email to