From c6960a5c086cd7c6f7885c2f423b8fc2831cd3f2 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Tue, 28 Nov 2006 15:55:27 +0000 Subject: [PATCH] Update from Yegor in bug 41046 - support background shapes and fills git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@480104 13f79535-47bb-0310-9956-ffa450edef68 --- .../content/xdocs/hslf/how-to-shapes.xml | 42 ++++ .../org/apache/poi/hslf/model/Background.java | 37 +++ .../src/org/apache/poi/hslf/model/Fill.java | 228 ++++++++++++++++++ .../src/org/apache/poi/hslf/model/Shape.java | 22 ++ .../src/org/apache/poi/hslf/model/Slide.java | 54 +++++ .../apache/poi/hslf/model/SlideMaster.java | 32 +++ .../org/apache/poi/hslf/data/backgrounds.ppt | Bin 0 -> 27136 bytes .../apache/poi/hslf/model/TestBackground.java | 182 ++++++++++++++ 8 files changed, 597 insertions(+) create mode 100644 src/scratchpad/src/org/apache/poi/hslf/model/Background.java create mode 100644 src/scratchpad/src/org/apache/poi/hslf/model/Fill.java create mode 100644 src/scratchpad/testcases/org/apache/poi/hslf/data/backgrounds.ppt create mode 100644 src/scratchpad/testcases/org/apache/poi/hslf/model/TestBackground.java diff --git a/src/documentation/content/xdocs/hslf/how-to-shapes.xml b/src/documentation/content/xdocs/hslf/how-to-shapes.xml index 8c90d2b8f0..cdd1605749 100644 --- a/src/documentation/content/xdocs/hslf/how-to-shapes.xml +++ b/src/documentation/content/xdocs/hslf/how-to-shapes.xml @@ -19,6 +19,7 @@
  • Drawing a shape on a slide
  • How to work with pictures
  • How to set slide title
  • +
  • How to work with slide/shape background
  • Features @@ -252,6 +253,47 @@ myDocument.Shapes.AddTitle.TextFrame.TextRange.Text = "Hello, World!"
    + +
    How to modify background of a slide master + + SlideShow ppt = new SlideShow(); + SlideMaster master = ppt.getSlidesMasters()[0]; + + Fill fill = master.getBackground().getFill(); + int idx = ppt.addPicture(new File("background.png"), Picture.PNG); + fill.setFillType(Fill.FILL_PICTURE); + fill.setPictureData(idx); + +
    +
    How to modify background of a slide + + SlideShow ppt = new SlideShow(); + Slide slide = ppt.createSlide(); + + //This slide has its own background. + //Without this line it will use master's background. + slide.setFollowMasterBackground(false); + Fill fill = slide.getBackground().getFill(); + int idx = ppt.addPicture(new File("background.png"), Picture.PNG); + fill.setFillType(Fill.FILL_PATTERN); + fill.setPictureData(idx); + +
    +
    How to modify background of a shape + + SlideShow ppt = new SlideShow(); + Slide slide = ppt.createSlide(); + + Shape shape = new AutoShape(ShapeTypes.Rectangle); + shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200)); + Fill fill = shape.getFill(); + fill.setFillType(Fill.FILL_SHADE); + fill.setBackgroundColor(Color.red); + fill.setForegroundColor(Color.green); + + slide.addShape(shape); + +
    diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Background.java b/src/scratchpad/src/org/apache/poi/hslf/model/Background.java new file mode 100644 index 0000000000..87faedfbe3 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Background.java @@ -0,0 +1,37 @@ + +/* ==================================================================== + Copyright 2002-2004 Apache Software Foundation + + Licensed 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.hslf.model; + +import org.apache.poi.ddf.EscherContainerRecord; + +/** + * Background shape + * + * @author Yegor Kozlov + */ +public class Background extends Shape { + + protected Background(EscherContainerRecord escherRecord, Shape parent){ + super(escherRecord, parent); + } + + protected EscherContainerRecord createSpContainer(boolean isChild){ + return null; + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Fill.java b/src/scratchpad/src/org/apache/poi/hslf/model/Fill.java new file mode 100644 index 0000000000..fbe5e98ef6 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Fill.java @@ -0,0 +1,228 @@ + +/* ==================================================================== + Copyright 2002-2004 Apache Software Foundation + + Licensed 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.hslf.model; + +import org.apache.poi.ddf.*; +import org.apache.poi.hslf.record.*; +import org.apache.poi.hslf.usermodel.PictureData; +import org.apache.poi.hslf.usermodel.SlideShow; + +import java.awt.*; +import java.util.*; + +/** + * Represents functionality provided by the 'Fill Effects' dialog in PowerPoint. + * + * @author Yegor Kozlov + */ +public class Fill { + /** + * Fill with a solid color + */ + public static final int FILL_SOLID = 0; + + /** + * Fill with a pattern (bitmap) + */ + public static final int FILL_PATTERN = 1; + + /** + * A texture (pattern with its own color map) + */ + public static final int FILL_TEXTURE = 2; + + /** + * Center a picture in the shape + */ + public static final int FILL_PICTURE = 3; + + /** + * Shade from start to end points + */ + public static final int FILL_SHADE = 4; + + /** + * Shade from bounding rectangle to end point + */ + public static final int FILL_SHADE_CENTER = 5; + + /** + * Shade from shape outline to end point + */ + public static final int FILL_SHADE_SHAPE = 6; + + /** + * Similar to FILL_SHADE, but the fill angle + * is additionally scaled by the aspect ratio of + * the shape. If shape is square, it is the same as FILL_SHADE + */ + public static final int FILL_SHADE_SCALE = 7; + + /** + * shade to title + */ + public static final int FILL_SHADE_TITLE = 8; + + /** + * Use the background fill color/pattern + */ + public static final int FILL_BACKGROUND = 9; + + + + /** + * The shape this background applies to + */ + protected Shape shape; + + /** + * Construct a Fill object for a shape. + * Fill information will be read from shape's escher properties. + * + * @param shape the shape this background applies to + */ + public Fill(Shape shape){ + this.shape = shape; + } + + /** + * Returns fill type. + * Must be one of the FILL_* constants defined in this class. + * + * @return type of fill + */ + public int getFillType(){ + EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID); + EscherSimpleProperty prop = (EscherSimpleProperty)Shape.getEscherProperty(opt, EscherProperties.FILL__FILLTYPE); + return prop == null ? FILL_SOLID : prop.getPropertyValue(); + } + + /** + * Sets fill type. + * Must be one of the FILL_* constants defined in this class. + * + * @param type type of the fill + */ + public void setFillType(int type){ + EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID); + Shape.setEscherProperty(opt, EscherProperties.FILL__FILLTYPE, type); + } + + /** + * Foreground color + */ + public Color getForegroundColor(){ + EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID); + EscherSimpleProperty p1 = (EscherSimpleProperty)Shape.getEscherProperty(opt, EscherProperties.FILL__FILLCOLOR); + EscherSimpleProperty p2 = (EscherSimpleProperty)Shape.getEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST); + + int p2val = p2 == null ? 0 : p2.getPropertyValue(); + + Color clr = null; + if (p1 != null && (p2val & 0x10) != 0){ + int rgb = p1.getPropertyValue(); + clr = shape.getColor(rgb); + } + return clr; + } + + /** + * Foreground color + */ + public void setForegroundColor(Color color){ + EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID); + if (color == null) { + Shape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, -1); + } + else { + int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB(); + Shape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, rgb); + } + } + + /** + * Background color + */ + public Color getBackgroundColor(){ + EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID); + EscherSimpleProperty p1 = (EscherSimpleProperty)Shape.getEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR); + EscherSimpleProperty p2 = (EscherSimpleProperty)Shape.getEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST); + + int p2val = p2 == null ? 0 : p2.getPropertyValue(); + + Color clr = null; + if (p1 != null && (p2val & 0x10) != 0){ + int rgb = p1.getPropertyValue(); + clr = shape.getColor(rgb); + } + return clr; + } + + /** + * Background color + */ + public void setBackgroundColor(Color color){ + EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID); + if (color == null) { + Shape.setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, -1); + } + else { + int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB(); + Shape.setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, rgb); + } + } + + /** + * PictureData object used in a texture, pattern of picture fill. + */ + public PictureData getPictureData(){ + EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID); + EscherSimpleProperty p = (EscherSimpleProperty)Shape.getEscherProperty(opt, EscherProperties.FILL__PATTERNTEXTURE); + if (p == null) return null; + + SlideShow ppt = shape.getSheet().getSlideShow(); + PictureData[] pict = ppt.getPictureData(); + Document doc = ppt.getDocumentRecord(); + + EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer(); + EscherContainerRecord bstore = (EscherContainerRecord)Shape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER); + + java.util.List lst = bstore.getChildRecords(); + int idx = p.getPropertyValue(); + EscherBSERecord bse = (EscherBSERecord)lst.get(idx); + for ( int i = 0; i < pict.length; i++ ) { + if (pict[i].getOffset() == bse.getOffset()){ + return pict[i]; + } + } + throw new RuntimeException("Picture data not found: \n" + + " bse: " + bse + " at " + bse.getOffset() ); + + } + + /** + * Assign picture used to fill the underlying shape. + * + * @param idx 0-based index of the picture added to this ppt by SlideShow.addPicture method. + */ + public void setPictureData(int idx){ + EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID); + Shape.setEscherProperty(opt, (short)(EscherProperties.FILL__PATTERNTEXTURE + 0x4000), idx); + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java b/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java index fe8788b97c..a4d5276345 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java @@ -17,7 +17,10 @@ package org.apache.poi.hslf.model; import org.apache.poi.ddf.*; import org.apache.poi.hslf.model.ShapeTypes; +import org.apache.poi.hslf.record.ColorSchemeAtom; + import java.util.Iterator; +import java.awt.*; /** *

    @@ -282,4 +285,23 @@ public abstract class Shape { _sheet = sheet; } + protected Color getColor(int rgb){ + if (rgb >= 0x8000000) { + int idx = rgb - 0x8000000; + ColorSchemeAtom ca = getSheet().getColorScheme(); + if(idx >= 0 && idx <= 7) rgb = ca.getColor(idx); + } + Color tmp = new Color(rgb, true); + return new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed()); + } + + /** + * Fill properties of this shape + * + * @return fill properties of this shape + */ + public Fill getFill(){ + return new Fill(this); + } + } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java index eab57d8a02..b88aed9f4c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java @@ -20,12 +20,17 @@ package org.apache.poi.hslf.model; import java.util.Vector; +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; import org.apache.poi.hslf.record.PPDrawing; import org.apache.poi.hslf.record.SlideAtom; import org.apache.poi.hslf.record.TextHeaderAtom; import org.apache.poi.hslf.record.ColorSchemeAtom; import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherRecord; /** * This class represents a slide in a PowerPoint Document. It allows @@ -33,6 +38,7 @@ import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet; * the text side of things though * * @author Nick Burch + * @author Yegor Kozlov */ public class Slide extends Sheet @@ -45,6 +51,7 @@ public class Slide extends Sheet private TextRun[] _runs; private TextRun[] _otherRuns; // Any from the PPDrawing, shouldn't really be any though private Notes _notes; // usermodel needs to set this + private Background _background; /** * Constructs a Slide from the Slide record, and the SlideAtomsSet @@ -245,4 +252,51 @@ public class Slide extends Sheet return _slide.getColorScheme(); } + /** + * Returns the background shape for this sheet. + * + * @return the background shape for this sheet. + */ + public Background getBackground(){ + if (_background == null){ + PPDrawing ppdrawing = getPPDrawing(); + + EscherContainerRecord dg = (EscherContainerRecord)ppdrawing.getEscherRecords()[0]; + EscherContainerRecord spContainer = null; + List ch = dg.getChildRecords(); + + for (Iterator it = ch.iterator(); it.hasNext();) { + EscherRecord rec = (EscherRecord)it.next(); + if (rec.getRecordId() == EscherContainerRecord.SP_CONTAINER){ + spContainer = (EscherContainerRecord)rec; + break; + } + } + _background = new Background(spContainer, null); + _background.setSheet(this); + } + return _background; + } + + /** + * Sets whether this slide follows master background + * + * @param flag true if the slide follows master, + * false otherwise + */ + public void setFollowMasterBackground(boolean flag){ + SlideAtom sa = _slide.getSlideAtom(); + sa.setFollowMasterBackground(flag); + } + + /** + * Whether this slide follows master sheet background + * + * @return true if the slide follows master background, + * false otherwise + */ + public boolean getFollowMasterBackground(){ + SlideAtom sa = _slide.getSlideAtom(); + return sa.getFollowMasterBackground(); + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/SlideMaster.java b/src/scratchpad/src/org/apache/poi/hslf/model/SlideMaster.java index e09396a1b2..af2f97ef28 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/SlideMaster.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/SlideMaster.java @@ -19,6 +19,11 @@ package org.apache.poi.hslf.model; import org.apache.poi.hslf.record.*; import org.apache.poi.hslf.usermodel.SlideShow; import org.apache.poi.hslf.record.StyleTextPropAtom.*; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherRecord; + +import java.util.List; +import java.util.Iterator; /** * SlideMaster determines the graphics, layout, and formatting for all the slides in a given presentation. @@ -32,6 +37,7 @@ public class SlideMaster extends MasterSheet { private int _sheetNo; private MainMaster _master; private TextRun[] _runs; + private Background _background; /** * all TxMasterStyleAtoms available in this master @@ -143,4 +149,30 @@ public class SlideMaster extends MasterSheet { return _master.getColorScheme(); } + /** + * Returns the background shape for this sheet. + * + * @return the background shape for this sheet. + */ + public Background getBackground(){ + if (_background == null){ + PPDrawing ppdrawing = getPPDrawing(); + + EscherContainerRecord dg = (EscherContainerRecord)ppdrawing.getEscherRecords()[0]; + EscherContainerRecord spContainer = null; + List ch = dg.getChildRecords(); + + for (Iterator it = ch.iterator(); it.hasNext();) { + EscherRecord rec = (EscherRecord)it.next(); + if (rec.getRecordId() == EscherContainerRecord.SP_CONTAINER){ + spContainer = (EscherContainerRecord)rec; + break; + } + } + _background = new Background(spContainer, null); + _background.setSheet(this); + } + return _background; + } + } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/backgrounds.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/backgrounds.ppt new file mode 100644 index 0000000000000000000000000000000000000000..591efafef22360564d65a6607af87019a999d3bd GIT binary patch literal 27136 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

    lvw}w3v6hzW9EzAZ`v?ku5tCY46iw0o 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 object. + * + * @author Yegor Kozlov + */ +public class TestBackground extends TestCase { + + /** + * Default background for slide, shape and slide master. + */ + public void testDefaults() throws Exception { + SlideShow ppt = new SlideShow(); + + assertEquals(Fill.FILL_SOLID, ppt.getSlidesMasters()[0].getBackground().getFill().getFillType()); + + Slide slide = ppt.createSlide(); + assertTrue(slide.getFollowMasterBackground()); + assertEquals(Fill.FILL_SOLID, slide.getBackground().getFill().getFillType()); + + Shape shape = new AutoShape(ShapeTypes.Rectangle); + assertEquals(Fill.FILL_SOLID, shape.getFill().getFillType()); + } + + /** + * Read fill information from an reference ppt file + */ + public void testReadBackground() throws Exception { + SlideShow ppt = new SlideShow(new HSLFSlideShow(System.getProperty("HSLF.testdata.path") + "/backgrounds.ppt")); + Fill fill; + Shape shape; + + Slide[] slide = ppt.getSlides(); + + fill = slide[0].getBackground().getFill(); + assertEquals(Fill.FILL_PICTURE, fill.getFillType()); + shape = slide[0].getShapes()[0]; + assertEquals(Fill.FILL_SOLID, shape.getFill().getFillType()); + + fill = slide[1].getBackground().getFill(); + assertEquals(Fill.FILL_PATTERN, fill.getFillType()); + shape = slide[1].getShapes()[0]; + assertEquals(Fill.FILL_BACKGROUND, shape.getFill().getFillType()); + + fill = slide[2].getBackground().getFill(); + assertEquals(Fill.FILL_TEXTURE, fill.getFillType()); + shape = slide[2].getShapes()[0]; + assertEquals(Fill.FILL_PICTURE, shape.getFill().getFillType()); + + fill = slide[3].getBackground().getFill(); + assertEquals(Fill.FILL_SHADE_CENTER, fill.getFillType()); + shape = slide[3].getShapes()[0]; + assertEquals(Fill.FILL_SHADE, shape.getFill().getFillType()); + } + + /** + * Create a ppt with various fill effects + */ + public void testBackgroundPicture() throws Exception { + SlideShow ppt = new SlideShow(); + Slide slide; + Fill fill; + Shape shape; + int idx; + + //slide 1 + slide = ppt.createSlide(); + slide.setFollowMasterBackground(false); + fill = slide.getBackground().getFill(); + idx = ppt.addPicture(new File(System.getProperty("HSLF.testdata.path") + "/tomcat.png"), Picture.PNG); + fill.setFillType(Fill.FILL_PICTURE); + fill.setPictureData(idx); + + shape = new AutoShape(ShapeTypes.Rectangle); + shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200)); + fill = shape.getFill(); + fill.setFillType(Fill.FILL_SOLID); + slide.addShape(shape); + + //slide 2 + slide = ppt.createSlide(); + slide.setFollowMasterBackground(false); + fill = slide.getBackground().getFill(); + idx = ppt.addPicture(new File(System.getProperty("HSLF.testdata.path") + "/tomcat.png"), Picture.PNG); + fill.setFillType(Fill.FILL_PATTERN); + fill.setPictureData(idx); + fill.setBackgroundColor(Color.green); + fill.setForegroundColor(Color.red); + + shape = new AutoShape(ShapeTypes.Rectangle); + shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200)); + fill = shape.getFill(); + fill.setFillType(Fill.FILL_BACKGROUND); + slide.addShape(shape); + + //slide 3 + slide = ppt.createSlide(); + slide.setFollowMasterBackground(false); + fill = slide.getBackground().getFill(); + idx = ppt.addPicture(new File(System.getProperty("HSLF.testdata.path") + "/tomcat.png"), Picture.PNG); + fill.setFillType(Fill.FILL_TEXTURE); + fill.setPictureData(idx); + + shape = new AutoShape(ShapeTypes.Rectangle); + shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200)); + fill = shape.getFill(); + fill.setFillType(Fill.FILL_PICTURE); + idx = ppt.addPicture(new File(System.getProperty("HSLF.testdata.path") + "/clock.jpg"), Picture.JPEG); + fill.setPictureData(idx); + slide.addShape(shape); + + // slide 4 + slide = ppt.createSlide(); + slide.setFollowMasterBackground(false); + fill = slide.getBackground().getFill(); + fill.setFillType(Fill.FILL_SHADE_CENTER); + fill.setBackgroundColor(Color.white); + fill.setForegroundColor(Color.darkGray); + + shape = new AutoShape(ShapeTypes.Rectangle); + shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200)); + fill = shape.getFill(); + fill.setFillType(Fill.FILL_SHADE); + fill.setBackgroundColor(Color.red); + fill.setForegroundColor(Color.green); + slide.addShape(shape); + + //serialize and read again + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ppt.write(out); + out.close(); + + ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()))); + Slide[] slides = ppt.getSlides(); + + fill = slides[0].getBackground().getFill(); + assertEquals(Fill.FILL_PICTURE, fill.getFillType()); + shape = slides[0].getShapes()[0]; + assertEquals(Fill.FILL_SOLID, shape.getFill().getFillType()); + + fill = slides[1].getBackground().getFill(); + assertEquals(Fill.FILL_PATTERN, fill.getFillType()); + shape = slides[1].getShapes()[0]; + assertEquals(Fill.FILL_BACKGROUND, shape.getFill().getFillType()); + + fill = slides[2].getBackground().getFill(); + assertEquals(Fill.FILL_TEXTURE, fill.getFillType()); + shape = slides[2].getShapes()[0]; + assertEquals(Fill.FILL_PICTURE, shape.getFill().getFillType()); + + fill = slides[3].getBackground().getFill(); + assertEquals(Fill.FILL_SHADE_CENTER, fill.getFillType()); + shape = slides[3].getShapes()[0]; + assertEquals(Fill.FILL_SHADE, shape.getFill().getFillType()); + + } + +} -- 2.39.5