Browse Source

more progress with xlsf: support for gradient and texture fills, backgrounds, improved drawing of preset shapes and many more updates ...

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1198658 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_8_BETA5
Yegor Kozlov 12 years ago
parent
commit
de14b40a97
59 changed files with 2331 additions and 985 deletions
  1. 4
    0
      build.xml
  2. 68
    0
      src/examples/src/org/apache/poi/xslf/usermodel/tutorial/Step1.java
  3. 80
    0
      src/examples/src/org/apache/poi/xslf/usermodel/tutorial/Step2.java
  4. 1
    1
      src/ooxml/java/org/apache/poi/xslf/extractor/XSLFPowerPointExtractor.java
  5. 1
    5
      src/ooxml/java/org/apache/poi/xslf/model/geom/ArcToCommand.java
  6. 7
    5
      src/ooxml/java/org/apache/poi/xslf/model/geom/Context.java
  7. 21
    1
      src/ooxml/java/org/apache/poi/xslf/model/geom/CustomGeometry.java
  8. 0
    7
      src/ooxml/java/org/apache/poi/xslf/model/geom/IAdjustableShape.java
  9. 5
    0
      src/ooxml/java/org/apache/poi/xslf/model/geom/LineToCommand.java
  10. 5
    0
      src/ooxml/java/org/apache/poi/xslf/model/geom/MoveToCommand.java
  11. 45
    0
      src/ooxml/java/org/apache/poi/xslf/model/geom/Outline.java
  12. 31
    1
      src/ooxml/java/org/apache/poi/xslf/model/geom/Path.java
  13. 1
    2
      src/ooxml/java/org/apache/poi/xslf/usermodel/Placeholder.java
  14. 557
    5
      src/ooxml/java/org/apache/poi/xslf/usermodel/RenderableShape.java
  15. 99
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/SlideLayout.java
  16. 4
    1
      src/ooxml/java/org/apache/poi/xslf/usermodel/TextAlign.java
  17. 33
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/TextCap.java
  18. 23
    9
      src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java
  19. 1
    3
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java
  20. 36
    21
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java
  21. 65
    14
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java
  22. 31
    35
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java
  23. 2
    1
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java
  24. 0
    6
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java
  25. 1
    1
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java
  26. 36
    30
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java
  27. 10
    9
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRendener.java
  28. 5
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotes.java
  29. 6
    3
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotesMaster.java
  30. 5
    26
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java
  31. 33
    1
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRenderingHint.java
  32. 32
    16
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java
  33. 56
    7
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java
  34. 112
    45
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java
  35. 194
    427
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java
  36. 48
    25
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java
  37. 56
    44
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java
  38. 44
    6
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java
  39. 5
    5
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java
  40. 0
    19
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java
  41. 51
    14
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java
  42. 51
    4
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
  43. 90
    62
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java
  44. 36
    4
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTheme.java
  45. 23
    9
      src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
  46. 1
    1
      src/ooxml/testcases/org/apache/poi/xslf/geom/TestFormulaParser.java
  47. 1
    5
      src/ooxml/testcases/org/apache/poi/xslf/geom/TestPresetGeometries.java
  48. 1
    1
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java
  49. 30
    30
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java
  50. 8
    8
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFColor.java
  51. 5
    8
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java
  52. 2
    2
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShow.java
  53. 48
    48
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java
  54. 127
    8
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTheme.java
  55. 0
    0
      src/resources/ooxml/org/apache/poi/xslf/usermodel/empty.pptx
  56. 0
    0
      src/resources/ooxml/org/apache/poi/xslf/usermodel/presetShapeDefinitions.xml
  57. BIN
      test-data/slideshow/pptx2svg.pptx
  58. 94
    0
      test-data/slideshow/pptx2svg.svg
  59. BIN
      test-data/slideshow/themes.pptx

+ 4
- 0
build.xml View File



<!-- OOXML support: --> <!-- OOXML support: -->
<property name="ooxml.src" location="src/ooxml/java"/> <property name="ooxml.src" location="src/ooxml/java"/>
<property name="ooxml.resource1.dir" value="src/resources/ooxml"/>
<property name="ooxml.src.test" location="src/ooxml/testcases"/> <property name="ooxml.src.test" location="src/ooxml/testcases"/>
<property name="ooxml.reports.test" location="build/ooxml-test-results"/> <property name="ooxml.reports.test" location="build/ooxml-test-results"/>
<property name="ooxml.output.dir" location="build/ooxml-classes"/> <property name="ooxml.output.dir" location="build/ooxml-classes"/>
<pathelement path="${main.output.test.dir}"/> <pathelement path="${main.output.test.dir}"/>
</classpath> </classpath>
</javac> </javac>
<copy todir="${ooxml.output.dir}">
<fileset dir="${ooxml.resource1.dir}"/>
</copy>
</target> </target>


<target name="compile-excelant" depends="compile-main,compile-ooxml"> <target name="compile-excelant" depends="compile-main,compile-ooxml">

+ 68
- 0
src/examples/src/org/apache/poi/xslf/usermodel/tutorial/Step1.java View File

/*
* ====================================================================
* 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.xslf.usermodel.tutorial;

import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFShape;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
import org.apache.poi.xslf.usermodel.XSLFTextRun;
import org.apache.poi.xslf.usermodel.XSLFTextShape;

import java.io.FileInputStream;

/**
* Reading a .pptx presentation and printing basic shape properties
*
* @author Yegor Kozlov
*/
public class Step1 {

public static void main(String[] args) throws Exception {
if(args.length == 0) {
System.out.println("Input file is required");
return;
}

XMLSlideShow ppt = new XMLSlideShow(new FileInputStream(args[0]));

for(XSLFSlide slide : ppt.getSlides()){
System.out.println("Title: " + slide.getTitle());

for(XSLFShape shape : slide.getShapes()){
if(shape instanceof XSLFTextShape) {
XSLFTextShape tsh = (XSLFTextShape)shape;
for(XSLFTextParagraph p : tsh){
System.out.println("Paragraph level: " + p.getLevel());
for(XSLFTextRun r : p){
System.out.println(r.getText());
System.out.println(" bold: " + r.isBold());
System.out.println(" italic: " + r.isItalic());
System.out.println(" underline: " + r.isUnderline());
System.out.println(" font.family: " + r.getFontFamily());
System.out.println(" font.size: " + r.getFontSize());
System.out.println(" font.color: " + r.getFontColor());
}
}
}
}
}
}
}

+ 80
- 0
src/examples/src/org/apache/poi/xslf/usermodel/tutorial/Step2.java View File

/*
* ====================================================================
* 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.xslf.usermodel.tutorial;

import org.apache.poi.xslf.usermodel.SlideLayout;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
import org.apache.poi.xslf.usermodel.XSLFSlideMaster;
import org.apache.poi.xslf.usermodel.XSLFTextShape;

import java.io.FileOutputStream;

/**
* Create slides from pre-defined slide layouts
*
* @author Yegor Kozlov
*/
public class Step2 {
public static void main(String[] args) throws Exception{
XMLSlideShow ppt = new XMLSlideShow();


// first see what slide layouts are available by default
System.out.println("Available slide layouts:");
for(XSLFSlideMaster master : ppt.getSlideMasters()){
for(XSLFSlideLayout layout : master.getSlideLayouts()){
System.out.println(layout.getType());
}
}

// blank slide
XSLFSlide blankSlide = ppt.createSlide();

XSLFSlideMaster defaultMaster = ppt.getSlideMasters()[0];

// title slide
XSLFSlideLayout titleLayout = defaultMaster.getLayout(SlideLayout.TITLE);
XSLFSlide slide1 = ppt.createSlide(titleLayout);
XSLFTextShape title1 = slide1.getPlaceholder(0);
title1.setText("First Title");

// title and content
XSLFSlideLayout titleBodyLayout = defaultMaster.getLayout(SlideLayout.TITLE_AND_CONTENT);
XSLFSlide slide2 = ppt.createSlide(titleBodyLayout);

XSLFTextShape title2 = slide2.getPlaceholder(0);
title2.setText("Second Title");

XSLFTextShape body2 = slide2.getPlaceholder(1);
body2.clearText(); // unset any existing text
body2.addNewTextParagraph().addNewTextRun().setText("First paragraph");
body2.addNewTextParagraph().addNewTextRun().setText("Second paragraph");
body2.addNewTextParagraph().addNewTextRun().setText("Third paragraph");



FileOutputStream out = new FileOutputStream("step2.pptx");
ppt.write(out);
out.close();

}
}

+ 1
- 1
src/ooxml/java/org/apache/poi/xslf/extractor/XSLFPowerPointExtractor.java View File

XSLFNotes notes = slide.getNotes(); XSLFNotes notes = slide.getNotes();
XSLFComments comments = slide.getComments(); XSLFComments comments = slide.getComments();
XSLFSlideLayout layout = slide.getSlideLayout(); XSLFSlideLayout layout = slide.getSlideLayout();
XSLFSlideMaster master = slide.getMasterSheet();
XSLFSlideMaster master = layout.getSlideMaster();


// TODO Do the slide's name // TODO Do the slide's name
// (Stored in docProps/app.xml) // (Stored in docProps/app.xml)

+ 1
- 5
src/ooxml/java/org/apache/poi/xslf/model/geom/ArcToCommand.java View File

double x0 = pt.getX() - rx - rx * Math.cos(Math.toRadians(start)); double x0 = pt.getX() - rx - rx * Math.cos(Math.toRadians(start));
double y0 = pt.getY() - ry - ry * Math.sin(Math.toRadians(start)); double y0 = pt.getY() - ry - ry * Math.sin(Math.toRadians(start));


if(start == 180 && extent == 180) {
x0 -= rx*2; //YK: TODO revisit the code and get rid of this hack
}

Arc2D arc = new Arc2D.Double( Arc2D arc = new Arc2D.Double(
x0, x0,
y0, y0,
2 * rx, 2 * ry, 2 * rx, 2 * ry,
-start, -extent, // negate angles because DrawingML rotates counter-clockwise
-start, -extent,
Arc2D.OPEN); Arc2D.OPEN);
path.append(arc, true); path.append(arc, true);
} }

+ 7
- 5
src/ooxml/java/org/apache/poi/xslf/model/geom/Context.java View File

* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
public class Context { public class Context {
Map<String, Double> _ctx = new HashMap<String, Double>();
IAdjustableShape _props;

public Context(CustomGeometry geom, IAdjustableShape props){
final Map<String, Double> _ctx = new HashMap<String, Double>();
final IAdjustableShape _props;
final Rectangle2D _anchor;
public Context(CustomGeometry geom, Rectangle2D anchor, IAdjustableShape props){
_props = props; _props = props;
_anchor = anchor;
for(Guide gd : geom.adjusts) evaluate(gd); for(Guide gd : geom.adjusts) evaluate(gd);
for(Guide gd : geom.guides) evaluate(gd); for(Guide gd : geom.guides) evaluate(gd);
} }


public Rectangle2D getShapeAnchor(){ public Rectangle2D getShapeAnchor(){
return _props.getAnchor();
return _anchor;
} }


public Guide getAdjustValue(String name){ public Guide getAdjustValue(String name){

+ 21
- 1
src/ooxml/java/org/apache/poi/xslf/model/geom/CustomGeometry.java View File

import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.awt.geom.Rectangle2D;


/** /**
* Definition of a custom geometric shape * Definition of a custom geometric shape
List<Guide> adjusts = new ArrayList<Guide>(); List<Guide> adjusts = new ArrayList<Guide>();
List<Guide> guides = new ArrayList<Guide>(); List<Guide> guides = new ArrayList<Guide>();
List<Path> paths = new ArrayList<Path>(); List<Path> paths = new ArrayList<Path>();
Path textBounds;


public CustomGeometry(CTCustomGeometry2D geom){
public CustomGeometry(CTCustomGeometry2D geom) {
CTGeomGuideList avLst = geom.getAvLst(); CTGeomGuideList avLst = geom.getAvLst();
if(avLst != null) for(CTGeomGuide gd : avLst.getGdList()){ if(avLst != null) for(CTGeomGuide gd : avLst.getGdList()){
adjusts.add(new AdjustValue(gd)); adjusts.add(new AdjustValue(gd));
if(pathLst != null) for(CTPath2D spPath : pathLst.getPathList()){ if(pathLst != null) for(CTPath2D spPath : pathLst.getPathList()){
paths.add(new Path(spPath)); paths.add(new Path(spPath));
} }

if(geom.isSetRect()) {
CTGeomRect rect = geom.getRect();
textBounds = new Path();
textBounds.addCommand(
new MoveToCommand(rect.getL().toString(), rect.getT().toString()));
textBounds.addCommand(
new LineToCommand(rect.getR().toString(), rect.getT().toString()));
textBounds.addCommand(
new LineToCommand(rect.getR().toString(), rect.getB().toString()));
textBounds.addCommand(
new LineToCommand(rect.getL().toString(), rect.getB().toString()));
textBounds.addCommand(
new ClosePathCommand());
}
} }




return paths.iterator(); return paths.iterator();
} }


public Path getTextBounds(){
return textBounds;
}
} }

+ 0
- 7
src/ooxml/java/org/apache/poi/xslf/model/geom/IAdjustableShape.java View File



package org.apache.poi.xslf.model.geom; package org.apache.poi.xslf.model.geom;


import java.awt.geom.Rectangle2D;


/** /**
* A bridge to the consumer application. * A bridge to the consumer application.
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
public interface IAdjustableShape { public interface IAdjustableShape {
/**
*
* @return bounds of the shape
*/
Rectangle2D getAnchor();

/** /**
* *
* @param name name of a adjust value, e.g. adj1 * @param name name of a adjust value, e.g. adj1

+ 5
- 0
src/ooxml/java/org/apache/poi/xslf/model/geom/LineToCommand.java View File

arg2 = pt.getY().toString(); arg2 = pt.getY().toString();
} }


LineToCommand(String s1, String s2){
arg1 = s1;
arg2 = s2;
}

public void execute(GeneralPath path, Context ctx){ public void execute(GeneralPath path, Context ctx){
double x = ctx.getValue(arg1); double x = ctx.getValue(arg1);
double y = ctx.getValue(arg2); double y = ctx.getValue(arg2);

+ 5
- 0
src/ooxml/java/org/apache/poi/xslf/model/geom/MoveToCommand.java View File

arg2 = pt.getY().toString(); arg2 = pt.getY().toString();
} }


MoveToCommand(String s1, String s2){
arg1 = s1;
arg2 = s2;
}

public void execute(GeneralPath path, Context ctx){ public void execute(GeneralPath path, Context ctx){
double x = ctx.getValue(arg1); double x = ctx.getValue(arg1);
double y = ctx.getValue(arg2); double y = ctx.getValue(arg2);

+ 45
- 0
src/ooxml/java/org/apache/poi/xslf/model/geom/Outline.java View File

/*
* ====================================================================
* 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.xslf.model.geom;

import java.awt.Shape;

/**
* Date: 11/6/11
*
* @author Yegor Kozlov
*/
public class Outline {
private Shape shape;
private Path path;

public Outline(Shape shape, Path path){
this.shape = shape;
this.path = path;
}

public Path getPath(){
return path;
}

public Shape getOutline(){
return shape;
}
}

+ 31
- 1
src/ooxml/java/org/apache/poi/xslf/model/geom/Path.java View File

public class Path { public class Path {
private final List<PathCommand> commands; private final List<PathCommand> commands;
boolean _fill, _stroke; boolean _fill, _stroke;
long _w, _h;

public Path(){
this(true, true);
}

public Path(boolean fill, boolean stroke){
commands = new ArrayList<PathCommand>();
_w = -1;
_h = -1;
_fill = fill;
_stroke = stroke;
}


public Path(CTPath2D spPath){ public Path(CTPath2D spPath){
_fill = spPath.getFill() != STPathFillMode.NONE; _fill = spPath.getFill() != STPathFillMode.NONE;
_stroke = spPath.getStroke(); _stroke = spPath.getStroke();

_w = spPath.isSetW() ? spPath.getW() : -1;
_h = spPath.isSetH() ? spPath.getH() : -1;
commands = new ArrayList<PathCommand>(); commands = new ArrayList<PathCommand>();
for(XmlObject ch : spPath.selectPath("*")){ for(XmlObject ch : spPath.selectPath("*")){
if(ch instanceof CTPath2DMoveTo){ if(ch instanceof CTPath2DMoveTo){
} }
} }


public void addCommand(PathCommand cmd){
commands.add(cmd);
}

/**
* Convert the internal represenation to java.awt.GeneralPath
*/
public GeneralPath getPath(Context ctx) { public GeneralPath getPath(Context ctx) {
GeneralPath path = new GeneralPath(); GeneralPath path = new GeneralPath();
for(PathCommand cmd : commands) for(PathCommand cmd : commands)
public boolean isFilled(){ public boolean isFilled(){
return _fill; return _fill;
} }
public long getW(){
return _w;
}

public long getH(){
return _h;
}
} }

+ 1
- 2
src/ooxml/java/org/apache/poi/xslf/usermodel/Placeholder.java View File

SLIDE_NUMBER, SLIDE_NUMBER,
FOOTER, FOOTER,
HEADER, HEADER,
OBJECT,
CONTENT,
CHART, CHART,
TABLE, TABLE,
CLIP_ART, CLIP_ART,
MEDIA, MEDIA,
SLIDE_IMAGE, SLIDE_IMAGE,
PICTURE PICTURE
} }

+ 557
- 5
src/ooxml/java/org/apache/poi/xslf/usermodel/RenderableShape.java View File

/*
* ====================================================================
* 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.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Internal;
import org.apache.poi.util.Units;
import org.apache.poi.xslf.model.PropertyFetcher;
import org.apache.poi.xslf.model.geom.Context;
import org.apache.poi.xslf.model.geom.CustomGeometry;
import org.apache.poi.xslf.model.geom.Guide;
import org.apache.poi.xslf.model.geom.IAdjustableShape;
import org.apache.poi.xslf.model.geom.Outline;
import org.apache.poi.xslf.model.geom.Path;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientStop;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNoFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPathShadeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference;
import org.openxmlformats.schemas.drawingml.x2006.main.STPathShadeType;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.TexturePaint;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
/** /**
* Created by IntelliJ IDEA.
* User: yegor
* Date: Oct 27, 2011
* Time: 4:50:08 PM
* To change this template use File | Settings | File Templates.
* Encapsulates logic to translate DrawingML objects to Java2D
*/ */
@Internal
class RenderableShape { class RenderableShape {
public final static Color NO_PAINT = new Color(0xFF, 0xFF, 0xFF, 0);
private XSLFSimpleShape _shape;
public RenderableShape(XSLFSimpleShape shape){
_shape = shape;
}
/**
* Convert shape fill into java.awt.Paint. The result is either Color or
* TexturePaint or GradientPaint or null
*
* @param graphics the target graphics
* @param obj the xml to read. Must contain elements from the EG_ColorChoice group:
* <code>
* a:scrgbClr RGB Color Model - Percentage Variant
* a:srgbClr RGB Color Model - Hex Variant
* a:hslClr Hue, Saturation, Luminance Color Model
* a:sysClr System Color
* a:schemeClr Scheme Color
* a:prstClr Preset Color
* </code>
*
* @param phClr context color
* @param parentPart the parent package part. Any external references (images, etc.) are resolved relative to it.
*
* @return the applied Paint or null if none was applied
*/
public Paint selectPaint(Graphics2D graphics, XmlObject obj, CTSchemeColor phClr, PackagePart parentPart) {
XSLFTheme theme = _shape.getSheet().getTheme();
Rectangle2D anchor = _shape.getAnchor();
Paint paint = null;
if (obj instanceof CTNoFillProperties) {
paint = NO_PAINT;
}
else if (obj instanceof CTSolidColorFillProperties) {
CTSolidColorFillProperties solidFill = (CTSolidColorFillProperties) obj;
XSLFColor c = new XSLFColor(solidFill, theme, phClr);
paint = c.getColor();
}
else if (obj instanceof CTBlipFillProperties) {
CTBlipFillProperties blipFill = (CTBlipFillProperties)obj;
paint = createTexturePaint(blipFill, graphics, parentPart);
}
else if (obj instanceof CTGradientFillProperties) {
CTGradientFillProperties gradFill = (CTGradientFillProperties) obj;
if (gradFill.isSetLin()) {
paint = createLinearGradientPaint(gradFill, anchor, theme, phClr);
} else if (gradFill.isSetPath()){
CTPathShadeProperties ps = gradFill.getPath();
if(ps.getPath() == STPathShadeType.CIRCLE){
paint = createRadialGradientPaint(gradFill, anchor, theme, phClr);
}
}
}
return paint;
}
private Paint createTexturePaint(CTBlipFillProperties blipFill, Graphics2D graphics,
PackagePart parentPart){
Paint paint = null;
CTBlip blip = blipFill.getBlip();
String blipId = blip.getEmbed();
PackageRelationship rel = parentPart.getRelationship(blipId);
if (rel != null) {
XSLFImageRendener renderer = null;
if (graphics != null)
renderer = (XSLFImageRendener) graphics.getRenderingHint(XSLFRenderingHint.IMAGE_RENDERER);
if (renderer == null) renderer = new XSLFImageRendener();
try {
BufferedImage img = renderer.readImage(parentPart.getRelatedPart(rel));
if (blip.sizeOfAlphaModFixArray() > 0) {
float alpha = blip.getAlphaModFixArray(0).getAmt() / 100000.f;
AlphaComposite ac = AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, alpha);
if (graphics != null) graphics.setComposite(ac);
}
if(img != null) {
paint = new TexturePaint(
img, new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight()));
}
}
catch (Exception e) {
e.printStackTrace();
}
}
return paint;
}
private static Paint createLinearGradientPaint(
CTGradientFillProperties gradFill, Rectangle2D anchor,
XSLFTheme theme, CTSchemeColor phClr) {
double angle = gradFill.getLin().getAng() / 60000;
CTGradientStop[] gs = gradFill.getGsLst().getGsArray();
Arrays.sort(gs, new Comparator<CTGradientStop>() {
public int compare(CTGradientStop o1, CTGradientStop o2) {
Integer pos1 = o1.getPos();
Integer pos2 = o2.getPos();
return pos1.compareTo(pos2);
}
});
Color[] colors = new Color[gs.length];
float[] fractions = new float[gs.length];
AffineTransform at = AffineTransform.getRotateInstance(
Math.toRadians(angle),
anchor.getX() + anchor.getWidth() / 2,
anchor.getY() + anchor.getHeight() / 2);
double diagonal = Math.sqrt(anchor.getHeight() * anchor.getHeight() + anchor.getWidth() * anchor.getWidth());
Point2D p1 = new Point2D.Double(anchor.getX() + anchor.getWidth() / 2 - diagonal / 2,
anchor.getY() + anchor.getHeight() / 2);
p1 = at.transform(p1, null);
Point2D p2 = new Point2D.Double(anchor.getX() + anchor.getWidth(), anchor.getY() + anchor.getHeight() / 2);
p2 = at.transform(p2, null);
snapToAnchor(p1, anchor);
snapToAnchor(p2, anchor);
for (int i = 0; i < gs.length; i++) {
CTGradientStop stop = gs[i];
colors[i] = new XSLFColor(stop, theme, phClr).getColor();
fractions[i] = stop.getPos() / 100000.f;
}
// Trick to return GradientPaint on JDK 1.5 and LinearGradientPaint on JDK 1.6+
Paint paint;
try {
Class clz = Class.forName("java.awt.LinearGradientPaint");
Constructor c =
clz.getConstructor(Point2D.class, Point2D.class, float[].class, Color[].class);
paint = (Paint) c.newInstance(p1, p2, fractions, colors);
} catch (ClassNotFoundException e) {
paint = new GradientPaint(p1, colors[0], p2, colors[colors.length - 1]);
} catch (Exception e) {
throw new RuntimeException(e);
}
return paint;
}
private static Paint createRadialGradientPaint(
CTGradientFillProperties gradFill, Rectangle2D anchor,
XSLFTheme theme, CTSchemeColor phClr) {
CTGradientStop[] gs = gradFill.getGsLst().getGsArray();
Point2D pCenter = new Point2D.Double(anchor.getX() + anchor.getWidth()/2,
anchor.getY() + anchor.getHeight()/2);
float radius = (float)Math.max(anchor.getWidth(), anchor.getHeight());
Arrays.sort(gs, new Comparator<CTGradientStop>() {
public int compare(CTGradientStop o1, CTGradientStop o2) {
Integer pos1 = o1.getPos();
Integer pos2 = o2.getPos();
return pos1.compareTo(pos2);
}
});
Color[] colors = new Color[gs.length];
float[] fractions = new float[gs.length];
for (int i = 0; i < gs.length; i++) {
CTGradientStop stop = gs[i];
colors[i] = new XSLFColor(stop, theme, phClr).getColor();
fractions[i] = stop.getPos() / 100000.f;
}
// Trick to return GradientPaint on JDK 1.5 and RadialGradientPaint on JDK 1.6+
Paint paint;
try {
Class clz = Class.forName("java.awt.RadialGradientPaint");
Constructor c =
clz.getConstructor(Point2D.class, float.class,
float[].class, Color[].class);
paint = (Paint) c.newInstance(pCenter, radius, fractions, colors);
} catch (ClassNotFoundException e) {
// the result on JDK 1.5 is incorrect, but it is better than nothing
paint = new GradientPaint(
new Point2D.Double(anchor.getX(), anchor.getY()),
colors[0], pCenter, colors[colors.length - 1]);
} catch (Exception e) {
throw new RuntimeException(e);
}
return paint;
}
private static void snapToAnchor(Point2D p, Rectangle2D anchor) {
if (p.getX() < anchor.getX()) {
p.setLocation(anchor.getX(), p.getY());
} else if (p.getX() > (anchor.getX() + anchor.getWidth())) {
p.setLocation(anchor.getX() + anchor.getWidth(), p.getY());
}
if (p.getY() < anchor.getY()) {
p.setLocation(p.getX(), anchor.getY());
} else if (p.getY() > (anchor.getY() + anchor.getHeight())) {
p.setLocation(p.getX(), anchor.getY() + anchor.getHeight());
}
}
@SuppressWarnings("deprecation") // getXYZArray() array accessors are deprecated
Paint getPaint(Graphics2D graphics, XmlObject spPr, CTSchemeColor phClr) {
Paint paint = null;
for (XmlObject obj : spPr.selectPath("*")) {
paint = selectPaint(graphics, obj, phClr, _shape.getSheet().getPackagePart());
if(paint != null) break;
}
return paint == NO_PAINT ? null : paint;
}
/**
* fetch shape fill as a java.awt.Paint
*
* @return either Color or GradientPaint or TexturePaint or null
*/
Paint getFillPaint(final Graphics2D graphics) {
PropertyFetcher<Paint> fetcher = new PropertyFetcher<Paint>() {
public boolean fetch(XSLFSimpleShape shape) {
CTShapeProperties spPr = shape.getSpPr();
if (spPr.isSetNoFill()) {
setValue(RenderableShape.NO_PAINT); // use it as 'nofill' value
return true;
}
Paint paint = getPaint(graphics, spPr, null);
if (paint != null) {
setValue(paint);
return true;
}
return false;
}
};
_shape.fetchShapeProperty(fetcher);
Paint paint = fetcher.getValue();
if (paint == null) {
// fill color was not found, check if it is defined in the theme
CTShapeStyle style = _shape.getSpStyle();
if (style != null) {
// get a reference to a fill style within the style matrix.
CTStyleMatrixReference fillRef = style.getFillRef();
// The idx attribute refers to the index of a fill style or
// background fill style within the presentation's style matrix, defined by the fmtScheme element.
// value of 0 or 1000 indicates no background,
// values 1-999 refer to the index of a fill style within the fillStyleLst element
// values 1001 and above refer to the index of a background fill style within the bgFillStyleLst element.
int idx = (int)fillRef.getIdx();
CTSchemeColor phClr = fillRef.getSchemeClr();
XSLFSheet sheet = _shape.getSheet();
XSLFTheme theme = sheet.getTheme();
XmlObject fillProps = null;
if(idx >= 1 && idx <= 999){
fillProps = theme.getXmlObject().
getThemeElements().getFmtScheme().getFillStyleLst().selectPath("*")[idx - 1];
} else if (idx >= 1001 ){
fillProps = theme.getXmlObject().
getThemeElements().getFmtScheme().getBgFillStyleLst().selectPath("*")[idx - 1001];
}
if(fillProps != null) {
paint = selectPaint(graphics, fillProps, phClr, sheet.getPackagePart());
}
}
}
return paint == RenderableShape.NO_PAINT ? null : paint;
}
public Paint getLinePaint(final Graphics2D graphics) {
PropertyFetcher<Paint> fetcher = new PropertyFetcher<Paint>() {
public boolean fetch(XSLFSimpleShape shape) {
CTLineProperties spPr = shape.getSpPr().getLn();
if (spPr != null) {
if (spPr.isSetNoFill()) {
setValue(NO_PAINT); // use it as 'nofill' value
return true;
}
Paint paint = getPaint(graphics, spPr, null);
if (paint != null) {
setValue(paint);
return true;
}
}
return false;
}
};
_shape.fetchShapeProperty(fetcher);
Paint paint = fetcher.getValue();
if (paint == null) {
// line color was not found, check if it is defined in the theme
CTShapeStyle style = _shape.getSpStyle();
if (style != null) {
// get a reference to a line style within the style matrix.
CTStyleMatrixReference lnRef = style.getLnRef();
int idx = (int)lnRef.getIdx();
CTSchemeColor phClr = lnRef.getSchemeClr();
if(idx > 0){
XSLFTheme theme = _shape.getSheet().getTheme();
XmlObject lnProps = theme.getXmlObject().
getThemeElements().getFmtScheme().getLnStyleLst().selectPath("*")[idx - 1];
paint = getPaint(graphics, lnProps, phClr);
}
}
}
return paint == NO_PAINT ? null : paint;
}
/**
* convert PPT dash into java.awt.BasicStroke
*
* The mapping is derived empirically on PowerPoint 2010
*/
private static float[] getDashPattern(LineDash lineDash, float lineWidth) {
float[] dash = null;
switch (lineDash) {
case SYS_DOT:
dash = new float[]{lineWidth, lineWidth};
break;
case SYS_DASH:
dash = new float[]{2 * lineWidth, 2 * lineWidth};
break;
case DASH:
dash = new float[]{3 * lineWidth, 4 * lineWidth};
break;
case DASH_DOT:
dash = new float[]{4 * lineWidth, 3 * lineWidth, lineWidth,
3 * lineWidth};
break;
case LG_DASH:
dash = new float[]{8 * lineWidth, 3 * lineWidth};
break;
case LG_DASH_DOT:
dash = new float[]{8 * lineWidth, 3 * lineWidth, lineWidth,
3 * lineWidth};
break;
case LG_DASH_DOT_DOT:
dash = new float[]{8 * lineWidth, 3 * lineWidth, lineWidth,
3 * lineWidth, lineWidth, 3 * lineWidth};
break;
}
return dash;
}
public Stroke applyStroke(Graphics2D graphics) {
float lineWidth = (float) _shape.getLineWidth();
LineDash lineDash = _shape.getLineDash();
float[] dash = null;
float dash_phase = 0;
if (lineDash != null) {
dash = getDashPattern(lineDash, lineWidth);
}
int cap = BasicStroke.CAP_BUTT;
LineCap lineCap = _shape.getLineCap();
if (lineCap != null) {
switch (lineCap) {
case ROUND:
cap = BasicStroke.CAP_ROUND;
break;
case SQUARE:
cap = BasicStroke.CAP_SQUARE;
break;
default:
cap = BasicStroke.CAP_BUTT;
break;
}
}
int meter = BasicStroke.JOIN_ROUND;
Stroke stroke = new BasicStroke(lineWidth, cap, meter, Math.max(1, lineWidth), dash,
dash_phase);
graphics.setStroke(stroke);
return stroke;
}
public void render(Graphics2D graphics){
Collection<Outline> elems = computeOutlines();
// shadow
XSLFShadow shadow = _shape.getShadow();
// first fill
Paint fill = getFillPaint(graphics);
if(fill != null) for(Outline o : elems){
if(o.getPath().isFilled()){
if(shadow != null) shadow.fill(graphics, o.getOutline());
graphics.setPaint(fill);
graphics.fill(o.getOutline());
}
}
// then draw any content within this shape (text, image, etc.)
_shape.drawContent(graphics);
// then stroke the shape outline
Paint line = getLinePaint(graphics);
if(line != null) for(Outline o : elems){
if(o.getPath().isStroked()){
applyStroke(graphics); // the stroke applies both to the shadow and the shape
if(shadow != null) shadow.draw(graphics, o.getOutline());
graphics.setPaint(line);
graphics.draw(o.getOutline());
}
}
}
private Collection<Outline> computeOutlines() {
CustomGeometry geom = _shape.getGeometry();
Collection<Outline> lst = new ArrayList<Outline>();
Rectangle2D anchor = _shape.getAnchor();
for (Path p : geom) {
double w = p.getW() == -1 ? anchor.getWidth() * Units.EMU_PER_POINT : p.getW();
double h = p.getH() == -1 ? anchor.getHeight() * Units.EMU_PER_POINT : p.getH();
// the guides in the shape definitions are all defined relative to each other,
// so we build the path starting from (0,0).
final Rectangle2D pathAnchor = new Rectangle2D.Double(
0,
0,
w,
h
);
Context ctx = new Context(geom, pathAnchor, new IAdjustableShape() {
public Guide getAdjustValue(String name) {
CTPresetGeometry2D prst = _shape.getSpPr().getPrstGeom();
if (prst.isSetAvLst()) {
for (CTGeomGuide g : prst.getAvLst().getGdList()) {
if (g.getName().equals(name)) {
return new Guide(g);
}
}
}
return null;
}
}) ;
Shape gp = p.getPath(ctx);
// translate the result to the canvas coordinates in points
AffineTransform at = new AffineTransform();
at.translate(anchor.getX(), anchor.getY());
double scaleX, scaleY;
if (p.getW() != -1) {
scaleX = anchor.getWidth() / p.getW();
} else {
scaleX = 1.0 / Units.EMU_PER_POINT;
}
if (p.getH() != -1) {
scaleY = anchor.getHeight() / p.getH();
} else {
scaleY = 1.0 / Units.EMU_PER_POINT;
}
at.scale(scaleX, scaleY);
Shape canvasShape = at.createTransformedShape(gp);
lst.add(new Outline(canvasShape, p));
}
// add any shape-specific stuff here (line decorations, etc.)
lst.addAll(_shape.getCustomOutlines());
return lst;
}
} }

+ 99
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/SlideLayout.java View File

/*
* ====================================================================
* 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.xslf.usermodel;

/**
* Date: 11/5/11
*
* @author Yegor Kozlov
*/
public enum SlideLayout {
/**
* Title layout with centered title and subtitle placeholders
*/
TITLE,
/**
* Title and text
*/
TEXT,

TWO_COL_TX,
TBL,
TEXT_AND_CHART,

/**
* Title, chart on left and text on right
*/
CHART_AND_TEXT,

DGM,

/**
* Title and chart
*/
CHART,

TX_AND_CLIP_ART,
/**
* Title, clipart on left, text on right
*/
CLIP_ART_AND_TEXT,

/**
* Title only
*/
TITLE_ONLY,

/**
* Blank
*/
BLANK,

TX_AND_OBJ,
OBJ_AND_TX,
OBJ_ONLY,
/**
* title and content
*/
TITLE_AND_CONTENT,
TX_AND_MEDIA,
MEDIA_AND_TX,
OBJ_OVER_TX,
TX_OVER_OBJ,
TX_AND_TWO_OBJ,
TWO_OBJ_AND_TX,
TWO_OBJ_OVER_TX,
FOUR_OBJ,
VERT_TX,
CLIP_ART_AND_VERT_TX,
VERT_TITLE_AND_TX,
VERT_TITLE_AND_TX_OVER_CHART,
TWO_OBJ,
OBJ_AND_TWO_OBJ,
TWO_OBJ_AND_OBJ,
CUST,
/**
* Section Header
*/
SECTION_HEADER,
TWO_TX_TWO_OBJ,
OBJ_TX,
PIC_TX,
}

+ 4
- 1
src/ooxml/java/org/apache/poi/xslf/usermodel/TextAlign.java View File

* is smart in the sense that it will not justify sentences * is smart in the sense that it will not justify sentences
* which are short * which are short
*/ */
JUSTIFY
JUSTIFY,
JUSTIFY_LOW,
DIST,
THAI_DIST
} }

+ 33
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/TextCap.java View File

/*
* ====================================================================
* 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.xslf.usermodel;
/**
* Created by IntelliJ IDEA.
* User: yegor
* Date: 11/3/11
* Time: 5:07 PM
* To change this template use File | Settings | File Templates.
*/
public enum TextCap {
NONE,
SMALL,
ALL
}

+ 23
- 9
src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java View File

import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideSize; import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideSize;
import org.openxmlformats.schemas.presentationml.x2006.main.PresentationDocument; import org.openxmlformats.schemas.presentationml.x2006.main.PresentationDocument;


import java.awt.*;
import java.awt.Dimension;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
return Collections.unmodifiableList(_pictures); return Collections.unmodifiableList(_pictures);
} }


public XSLFSlide createSlide() {
/**
* Create a slide and initialize it from the specified layout.
*
* @param layout
* @return created slide
*/
public XSLFSlide createSlide(XSLFSlideLayout layout) {
int slideNumber = 256, cnt = 1; int slideNumber = 256, cnt = 1;
CTSlideIdList slideList; CTSlideIdList slideList;
if (!_presentation.isSetSldIdLst()) slideList = _presentation.addNewSldIdLst(); if (!_presentation.isSetSldIdLst()) slideList = _presentation.addNewSldIdLst();
slideId.setId(slideNumber); slideId.setId(slideNumber);
slideId.setId2(slide.getPackageRelationship().getId()); slideId.setId2(slide.getPackageRelationship().getId());


String masterId = _presentation.getSldMasterIdLst().getSldMasterIdArray(0).getId2();
XSLFSlideMaster master = _masters.get(masterId);

XSLFSlideLayout layout = master.getLayout("blank");
if(layout == null) throw new IllegalArgumentException("Blank layout was not found");

layout.copyLayout(slide);
slide.addRelation(layout.getPackageRelationship().getId(), layout); slide.addRelation(layout.getPackageRelationship().getId(), layout);


PackagePartName ppName = layout.getPackagePart().getPartName(); PackagePartName ppName = layout.getPackagePart().getPartName();
_slides.add(slide); _slides.add(slide);
return slide; return slide;
} }

/**
* Create a blank slide.
*/
public XSLFSlide createSlide() {
String masterId = _presentation.getSldMasterIdLst().getSldMasterIdArray(0).getId2();
XSLFSlideMaster master = _masters.get(masterId);

XSLFSlideLayout layout = master.getLayout(SlideLayout.BLANK);
if(layout == null) throw new IllegalArgumentException("Blank layout was not found");

return createSlide(layout);
}

/** /**
* Return the Notes Master, if there is one. * Return the Notes Master, if there is one.
* (May not be present if no notes exist) * (May not be present if no notes exist)

+ 1
- 3
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java View File

import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual;
import java.util.regex.Pattern;
/** /**
* Represents a preset geometric shape.
* Represents a shape with a preset geometry.
* *
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
@Beta @Beta
public class XSLFAutoShape extends XSLFTextShape { public class XSLFAutoShape extends XSLFTextShape {
private static final Pattern adjPtrn = Pattern.compile("val\\s+(\\d+)");
/*package*/ XSLFAutoShape(CTShape shape, XSLFSheet sheet) { /*package*/ XSLFAutoShape(CTShape shape, XSLFSheet sheet) {
super(shape, sheet); super(shape, sheet);

+ 36
- 21
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java View File

package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference;
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBackgroundFillStyleList;
import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBackgroundFillStyleList;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;
import javax.xml.namespace.QName;
import java.awt.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
/** /**
public void draw(Graphics2D graphics) { public void draw(Graphics2D graphics) {
Rectangle2D anchor = getAnchor(); Rectangle2D anchor = getAnchor();
XmlObject spPr = null;
Paint fill = getPaint(graphics);
if(fill != null) {
graphics.setPaint(fill);
graphics.fill(anchor);
}
}
/**
* @return the Paint object to fill
*/
Paint getPaint(Graphics2D graphics){
RenderableShape rShape = new RenderableShape(this);
Paint fill = null;
CTBackground bg = (CTBackground)getXmlObject(); CTBackground bg = (CTBackground)getXmlObject();
if(bg.isSetBgPr()){ if(bg.isSetBgPr()){
spPr = bg.getBgPr();
XmlObject spPr = bg.getBgPr();
fill = rShape.getPaint(graphics, spPr, null);
} else if (bg.isSetBgRef()){ } else if (bg.isSetBgRef()){
CTStyleMatrixReference bgRef= bg.getBgRef(); CTStyleMatrixReference bgRef= bg.getBgRef();
int idx = (int)bgRef.getIdx() - 1000;
CTSchemeColor phClr = bgRef.getSchemeClr();
int idx = (int)bgRef.getIdx() - 1001;
XSLFTheme theme = getSheet().getTheme(); XSLFTheme theme = getSheet().getTheme();
CTBackgroundFillStyleList bgStyles = CTBackgroundFillStyleList bgStyles =
theme.getXmlObject().getThemeElements().getFmtScheme().getBgFillStyleLst(); theme.getXmlObject().getThemeElements().getFmtScheme().getBgFillStyleLst();
// TODO pass this to getPaint
XmlObject bgStyle = bgStyles.selectPath("*")[idx]; XmlObject bgStyle = bgStyles.selectPath("*")[idx];
fill = rShape.selectPaint(graphics, bgStyle, phClr, theme.getPackagePart());
} }
if(spPr == null){
return;
}
return fill;
}
Paint fill = getPaint(graphics, spPr);
if(fill != null) {
graphics.setPaint(fill);
graphics.fill(anchor);
@Override
public Color getFillColor(){
Paint p = getPaint(null);
if(p instanceof Color){
return (Color)p;
} }
return null;
} }
} }

+ 65
- 14
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java View File

import org.openxmlformats.schemas.drawingml.x2006.main.CTSystemColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTSystemColor;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import java.awt.*;
import java.awt.Color;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
@Beta @Beta
@Internal
public class XSLFColor { public class XSLFColor {
private XmlObject _xmlObject; private XmlObject _xmlObject;
private Color _color; private Color _color;
private CTSchemeColor _phClr;
XSLFColor(XmlObject obj, XSLFTheme theme) {
public XSLFColor(XmlObject obj, XSLFTheme theme, CTSchemeColor phClr) {
_xmlObject = obj; _xmlObject = obj;
_phClr = phClr;
_color = toColor(obj, theme); _color = toColor(obj, theme);
} }
return result; return result;
} }
static Color toColor(XmlObject obj, XSLFTheme theme) {
Color toColor(XmlObject obj, XSLFTheme theme) {
Color color = null; Color color = null;
for (XmlObject ch : obj.selectPath("*")) { for (XmlObject ch : obj.selectPath("*")) {
if (ch instanceof CTHslColor) { if (ch instanceof CTHslColor) {
int h = hsl.getHue2(); int h = hsl.getHue2();
int s = hsl.getSat2(); int s = hsl.getSat2();
int l = hsl.getLum2(); int l = hsl.getLum2();
// is it correct ?
// This conversion is not correct and differs from PowerPoint.
// TODO: Revisit and improve.
color = Color.getHSBColor(h / 60000f, s / 100000f, l / 100000f); color = Color.getHSBColor(h / 60000f, s / 100000f, l / 100000f);
} else if (ch instanceof CTPresetColor) { } else if (ch instanceof CTPresetColor) {
CTPresetColor prst = (CTPresetColor)ch; CTPresetColor prst = (CTPresetColor)ch;
} else if (ch instanceof CTSchemeColor) { } else if (ch instanceof CTSchemeColor) {
CTSchemeColor schemeColor = (CTSchemeColor)ch; CTSchemeColor schemeColor = (CTSchemeColor)ch;
String colorRef = schemeColor.getVal().toString(); String colorRef = schemeColor.getVal().toString();
if(_phClr != null) {
// context color overrides the theme
colorRef = _phClr.getVal().toString();
}
// find referenced CTColor in the theme and convert it to java.awt.Color via a recursive call // find referenced CTColor in the theme and convert it to java.awt.Color via a recursive call
CTColor ctColor = theme.getCTColor(colorRef); CTColor ctColor = theme.getCTColor(colorRef);
if(ctColor != null) color = toColor(ctColor, null); if(ctColor != null) color = toColor(ctColor, null);
else {
color = Color.black;
}
} else if (ch instanceof CTScRgbColor) { } else if (ch instanceof CTScRgbColor) {
// same as CTSRgbColor but with values expressed in percents // same as CTSRgbColor but with values expressed in percents
CTScRgbColor scrgb = (CTScRgbColor)ch; CTScRgbColor scrgb = (CTScRgbColor)ch;
return color; return color;
} }
/**
* Read a perecentage value from the supplied xml bean.
* Example:
* <a:tint val="45000"/>
*
* the returned value is 45
*
* @return the percentage value in the range [0 .. 100]
*/
private int getPercentageValue(String elem){ private int getPercentageValue(String elem){
XmlObject[] obj = _xmlObject.selectPath(
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' $this//a:" + elem);
String query = "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' $this//a:" + elem;
XmlObject[] obj;
// first ask the context color and if not found, ask the actual color bean
if(_phClr != null){
obj = _phClr.selectPath(query);
if(obj.length == 1){
Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val");
if(attr != null) {
return Integer.parseInt(attr.getNodeValue()) / 1000;
}
}
}
obj = _xmlObject.selectPath(query);
if(obj.length == 1){ if(obj.length == 1){
Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val"); Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val");
if(attr != null) { if(attr != null) {
return Integer.parseInt(attr.getNodeValue()) / 1000; return Integer.parseInt(attr.getNodeValue()) / 1000;
} }
} }
return -1; return -1;
} }
private int getAngleValue(String elem){ private int getAngleValue(String elem){
XmlObject[] obj = _xmlObject.selectPath(
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' $this//a:" + elem);
String color = "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' $this//a:" + elem;
XmlObject[] obj;
// first ask the context color and if not found, ask the actual color bean
if(_phClr != null){
obj = _xmlObject.selectPath( color );
if(obj.length == 1){
Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val");
if(attr != null) {
return Integer.parseInt(attr.getNodeValue()) / 60000;
}
}
}
obj = _xmlObject.selectPath( color );
if(obj.length == 1){ if(obj.length == 1){
Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val"); Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val");
if(attr != null) { if(attr != null) {
* A 10% shade is 10% of the input color combined with 90% black. * A 10% shade is 10% of the input color combined with 90% black.
* *
* @return the value of the shade specified as a * @return the value of the shade specified as a
* percentage with 0% indicating minimal blue and 100% indicating maximum
* percentage with 0% indicating minimal shade and 100% indicating maximum
* or -1 if the value is not set * or -1 if the value is not set
*/ */
int getShade(){ int getShade(){
* A 10% tint is 10% of the input color combined with 90% white. * A 10% tint is 10% of the input color combined with 90% white.
* *
* @return the value of the tint specified as a * @return the value of the tint specified as a
* percentage with 0% indicating minimal blue and 100% indicating maximum
* percentage with 0% indicating minimal tint and 100% indicating maximum
* or -1 if the value is not set * or -1 if the value is not set
*/ */
int getTint(){ int getTint(){
return color; return color;
} }
/**
* This algorithm returns result different from PowerPoint.
* TODO: revisit and improve
*/
private static Color shade(Color c, int shade) { private static Color shade(Color c, int shade) {
return new Color( return new Color(
(int)(c.getRed() * shade * 0.01), (int)(c.getRed() * shade * 0.01),
c.getAlpha()); c.getAlpha());
} }
/**
* This algorithm returns result different from PowerPoint.
* TODO: revisit and improve
*/
private static Color tint(Color c, int tint) { private static Color tint(Color c, int tint) {
int r = c.getRed(); int r = c.getRed();
int g = c.getGreen(); int g = c.getGreen();
/** /**
* Preset colors defined in DrawingML * Preset colors defined in DrawingML
*/ */
static Map<String, Color> presetColors;
static final Map<String, Color> presetColors;
static { static {
presetColors = new HashMap<String, Color>(); presetColors = new HashMap<String, Color>();

+ 31
- 35
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java View File

package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.xslf.model.geom.Outline;
import org.apache.poi.xslf.model.geom.Path;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;
import org.openxmlformats.schemas.presentationml.x2006.main.CTConnectorNonVisual; import org.openxmlformats.schemas.presentationml.x2006.main.CTConnectorNonVisual;
import java.awt.*;
import java.awt.Shape;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D; import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath; import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/** /**
* Specifies a connection shape. * Specifies a connection shape.
return len == null ? LineEndLength.MEDIUM : LineEndLength.values()[len.intValue() - 1]; return len == null ? LineEndLength.MEDIUM : LineEndLength.values()[len.intValue() - 1];
} }
@Override
public void draw(Graphics2D graphics) {
java.awt.Shape outline = getOutline();
// shadow
XSLFShadow shadow = getShadow();
//border
Paint line = getLinePaint(graphics);
if (line != null) {
if (shadow != null) shadow.draw(graphics);
graphics.setPaint(line);
applyStroke(graphics);
graphics.draw(outline);
Shape tailDecoration = getTailDecoration();
if (tailDecoration != null) {
graphics.draw(tailDecoration);
}
Shape headDecoration = getHeadDecoration();
if (headDecoration != null) {
graphics.draw(headDecoration);
}
}
}
Shape getTailDecoration() {
Outline getTailDecoration() {
LineEndLength tailLength = getLineTailLength(); LineEndLength tailLength = getLineTailLength();
LineEndWidth tailWidth = getLineTailWidth(); LineEndWidth tailWidth = getLineTailWidth();
AffineTransform at = new AffineTransform(); AffineTransform at = new AffineTransform();
Shape shape = null; Shape shape = null;
Path p = null;
Rectangle2D bounds; Rectangle2D bounds;
double scaleY = Math.pow(2, tailWidth.ordinal()); double scaleY = Math.pow(2, tailWidth.ordinal());
double scaleX = Math.pow(2, tailLength.ordinal()); double scaleX = Math.pow(2, tailLength.ordinal());
switch (getLineHeadDecoration()) {
switch (getLineTailDecoration()) {
case OVAL: case OVAL:
p = new Path();
shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY); shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
bounds = shape.getBounds2D(); bounds = shape.getBounds2D();
at.translate(x2 - bounds.getWidth() / 2, y2 - bounds.getHeight() / 2); at.translate(x2 - bounds.getWidth() / 2, y2 - bounds.getHeight() / 2);
at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2); at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2);
break; break;
case ARROW: case ARROW:
p = new Path();
GeneralPath arrow = new GeneralPath(); GeneralPath arrow = new GeneralPath();
arrow.moveTo((float) (-lineWidth * 3), (float) (-lineWidth * 2)); arrow.moveTo((float) (-lineWidth * 3), (float) (-lineWidth * 2));
arrow.lineTo(0, 0); arrow.lineTo(0, 0);
at.rotate(alpha); at.rotate(alpha);
break; break;
case TRIANGLE: case TRIANGLE:
p = new Path();
scaleY = tailWidth.ordinal() + 1; scaleY = tailWidth.ordinal() + 1;
scaleX = tailLength.ordinal() + 1; scaleX = tailLength.ordinal() + 1;
GeneralPath triangle = new GeneralPath(); GeneralPath triangle = new GeneralPath();
if (shape != null) { if (shape != null) {
shape = at.createTransformedShape(shape); shape = at.createTransformedShape(shape);
} }
return shape;
return shape == null ? null : new Outline(shape, p);
} }
Shape getHeadDecoration() {
Outline getHeadDecoration() {
LineEndLength headLength = getLineHeadLength(); LineEndLength headLength = getLineHeadLength();
LineEndWidth headWidth = getLineHeadWidth(); LineEndWidth headWidth = getLineHeadWidth();
AffineTransform at = new AffineTransform(); AffineTransform at = new AffineTransform();
Shape shape = null; Shape shape = null;
Path p = null;
Rectangle2D bounds; Rectangle2D bounds;
double scaleY = 1; double scaleY = 1;
double scaleX = 1; double scaleX = 1;
switch (getLineHeadDecoration()) { switch (getLineHeadDecoration()) {
case OVAL: case OVAL:
p = new Path();
shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY); shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
bounds = shape.getBounds2D(); bounds = shape.getBounds2D();
at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2); at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2);
break; break;
case STEALTH: case STEALTH:
case ARROW: case ARROW:
p = new Path();
GeneralPath arrow = new GeneralPath(); GeneralPath arrow = new GeneralPath();
arrow.moveTo((float) (lineWidth * 3 * scaleX), (float) (-lineWidth * scaleY * 2)); arrow.moveTo((float) (lineWidth * 3 * scaleX), (float) (-lineWidth * scaleY * 2));
arrow.lineTo(0, 0); arrow.lineTo(0, 0);
at.rotate(alpha); at.rotate(alpha);
break; break;
case TRIANGLE: case TRIANGLE:
p = new Path();
scaleY = headWidth.ordinal() + 1; scaleY = headWidth.ordinal() + 1;
scaleX = headLength.ordinal() + 1; scaleX = headLength.ordinal() + 1;
GeneralPath triangle = new GeneralPath(); GeneralPath triangle = new GeneralPath();
if (shape != null) { if (shape != null) {
shape = at.createTransformedShape(shape); shape = at.createTransformedShape(shape);
} }
return shape;
return shape == null ? null : new Outline(shape, p);
}
@Override
List<Outline> getCustomOutlines(){
List<Outline> lst = new ArrayList<Outline>();
Outline head = getHeadDecoration();
if(head != null) lst.add(head);
Outline tail = getTailDecoration();
if(tail != null) lst.add(tail);
return lst;
} }
} }

+ 2
- 1
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java View File

import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import java.awt.*;
import java.awt.Color;
import java.awt.Rectangle;
/** /**

+ 0
- 6
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java View File

geom.addNewPathLst(); geom.addNewPathLst();
return ct; return ct;
} }
@Override
protected java.awt.Shape getOutline(){
return getPath();
}
} }

+ 1
- 1
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java View File

import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
/** /**

+ 36
- 30
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java View File

import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual; import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.util.List; import java.util.List;
_spPr = shape.getGrpSpPr(); _spPr = shape.getGrpSpPr();
} }
@Override
public CTGroupShape getXmlObject(){ public CTGroupShape getXmlObject(){
return _shape; return _shape;
} }
@Override
public Rectangle2D getAnchor(){ public Rectangle2D getAnchor(){
CTGroupTransform2D xfrm = _spPr.getXfrm(); CTGroupTransform2D xfrm = _spPr.getXfrm();
CTPoint2D off = xfrm.getOff(); CTPoint2D off = xfrm.getOff();
Units.toPoints(cx), Units.toPoints(cy)); Units.toPoints(cx), Units.toPoints(cy));
} }
@Override
public void setAnchor(Rectangle2D anchor){ public void setAnchor(Rectangle2D anchor){
CTGroupTransform2D xfrm = _spPr.isSetXfrm() ? _spPr.getXfrm() : _spPr.addNewXfrm(); CTGroupTransform2D xfrm = _spPr.isSetXfrm() ? _spPr.getXfrm() : _spPr.addNewXfrm();
CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff(); CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
ext.setCy(cy); ext.setCy(cy);
} }
/**
*
* @return the coordinates of the child extents rectangle
* used for calculations of grouping, scaling, and rotation
* behavior of shapes placed within a group.
*/
public Rectangle2D getInteriorAnchor(){ public Rectangle2D getInteriorAnchor(){
CTGroupTransform2D xfrm = _spPr.getXfrm(); CTGroupTransform2D xfrm = _spPr.getXfrm();
CTPoint2D off = xfrm.getChOff(); CTPoint2D off = xfrm.getChOff();
Units.toPoints(cx), Units.toPoints(cy)); Units.toPoints(cx), Units.toPoints(cy));
} }
/**
*
* @param anchor the coordinates of the child extents rectangle
* used for calculations of grouping, scaling, and rotation
* behavior of shapes placed within a group.
*/
public void setInteriorAnchor(Rectangle2D anchor){ public void setInteriorAnchor(Rectangle2D anchor){
CTGroupTransform2D xfrm = _spPr.isSetXfrm() ? _spPr.getXfrm() : _spPr.addNewXfrm(); CTGroupTransform2D xfrm = _spPr.isSetXfrm() ? _spPr.getXfrm() : _spPr.addNewXfrm();
CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff(); CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff();
ext.setCy(cy); ext.setCy(cy);
} }
/**
*
* @return child shapes contained witin this group
*/
public XSLFShape[] getShapes(){ public XSLFShape[] getShapes(){
return _shapes.toArray(new XSLFShape[_shapes.size()]); return _shapes.toArray(new XSLFShape[_shapes.size()]);
} }
/**
* Remove the specified shape from this group
*/
public boolean removeShape(XSLFShape xShape) { public boolean removeShape(XSLFShape xShape) {
XmlObject obj = xShape.getXmlObject(); XmlObject obj = xShape.getXmlObject();
if(obj instanceof CTShape){ if(obj instanceof CTShape){
return _shapes.remove(xShape); return _shapes.remove(xShape);
} }
@Override
public String getShapeName(){ public String getShapeName(){
return _shape.getNvGrpSpPr().getCNvPr().getName(); return _shape.getNvGrpSpPr().getCNvPr().getName();
} }
@Override
public int getShapeId(){ public int getShapeId(){
return (int)_shape.getNvGrpSpPr().getCNvPr().getId(); return (int)_shape.getNvGrpSpPr().getCNvPr().getId();
} }
return sh; return sh;
} }
@Override
public void setFlipHorizontal(boolean flip){ public void setFlipHorizontal(boolean flip){
_spPr.getXfrm().setFlipH(flip); _spPr.getXfrm().setFlipH(flip);
} }
@Override
public void setFlipVertical(boolean flip){ public void setFlipVertical(boolean flip){
_spPr.getXfrm().setFlipV(flip); _spPr.getXfrm().setFlipV(flip);
} }
/**
* Whether the shape is horizontally flipped
*
* @return whether the shape is horizontally flipped
*/
@Override
public boolean getFlipHorizontal(){ public boolean getFlipHorizontal(){
return _spPr.getXfrm().getFlipH(); return _spPr.getXfrm().getFlipH();
} }
@Override
public boolean getFlipVertical(){ public boolean getFlipVertical(){
return _spPr.getXfrm().getFlipV(); return _spPr.getXfrm().getFlipV();
} }
/**
* Rotate this shape.
* <p>
* Positive angles are clockwise (i.e., towards the positive y axis);
* negative angles are counter-clockwise (i.e., towards the negative y axis).
* </p>
*
* @param theta the rotation angle in degrees.
*/
@Override
public void setRotation(double theta){ public void setRotation(double theta){
_spPr.getXfrm().setRot((int)(theta*60000)); _spPr.getXfrm().setRot((int)(theta*60000));
} }
/**
* Rotation angle in degrees
* <p>
* Positive angles are clockwise (i.e., towards the positive y axis);
* negative angles are counter-clockwise (i.e., towards the negative y axis).
* </p>
*
* @return rotation angle in degrees
*/
@Override
public double getRotation(){ public double getRotation(){
return (double)_spPr.getXfrm().getRot()/60000; return (double)_spPr.getXfrm().getRot()/60000;
} }
@Override
public void draw(Graphics2D graphics){ public void draw(Graphics2D graphics){
// the coordinate system of this group of shape // the coordinate system of this group of shape
for (XSLFShape shape : getShapes()) { for (XSLFShape shape : getShapes()) {
// remember the initial transform and restore it after we are done with the drawing // remember the initial transform and restore it after we are done with the drawing
AffineTransform at0 = graphics.getTransform();
AffineTransform at = graphics.getTransform();
graphics.setRenderingHint(XSLFRenderingHint.GSAVE, true); graphics.setRenderingHint(XSLFRenderingHint.GSAVE, true);
// apply rotation and flipping
shape.applyTransform(graphics);
shape.applyTransform(graphics);
shape.draw(graphics); shape.draw(graphics);
// restore the coordinate system // restore the coordinate system
graphics.setTransform(at0);
graphics.setTransform(at);
graphics.setRenderingHint(XSLFRenderingHint.GRESTORE, true); graphics.setRenderingHint(XSLFRenderingHint.GRESTORE, true);
} }
} }

+ 10
- 9
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRendener.java View File

package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
public boolean drawImage(Graphics2D graphics, XSLFPictureData data, public boolean drawImage(Graphics2D graphics, XSLFPictureData data,
Rectangle2D anchor) { Rectangle2D anchor) {
try { try {
BufferedImage img = readImage(new ByteArrayInputStream(data.getData()));
if (img != null){
graphics.drawImage(img, (int) anchor.getX(), (int) anchor.getY(),
(int) anchor.getWidth(), (int) anchor.getHeight(), null);
}
BufferedImage img = ImageIO.read(data.getPackagePart().getInputStream());
graphics.drawImage(img,
(int) anchor.getX(), (int) anchor.getY(),
(int) anchor.getWidth(), (int) anchor.getHeight(), null);
return true; return true;
} catch (Exception e) { } catch (Exception e) {
return false; return false;
} }
/** /**
* create a buffered image from input stream
* Create a buffered image from the supplied package part.
* This method is called to create texture paints.
* *
* @return a <code>BufferedImage</code> containing the decoded * @return a <code>BufferedImage</code> containing the decoded
* contents of the input, or <code>null</code>. * contents of the input, or <code>null</code>.
*/ */
public BufferedImage readImage(InputStream is) throws IOException {
return ImageIO.read(is);
public BufferedImage readImage(PackagePart packagePart) throws IOException {
return ImageIO.read(packagePart.getInputStream());
} }
} }

+ 5
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotes.java View File

protected String getRootElementName(){ protected String getRootElementName(){
return "notes"; return "notes";
} }

@Override
public XSLFSheet getMasterSheet() {
return null;
}
} }

+ 6
- 3
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotesMaster.java View File

import org.openxmlformats.schemas.presentationml.x2006.main.NotesMasterDocument; import org.openxmlformats.schemas.presentationml.x2006.main.NotesMasterDocument;


import java.io.IOException; import java.io.IOException;
import java.util.Map;


/** /**
* Notes master object associated with this layout. * Notes master object associated with this layout.
@Beta @Beta
public class XSLFNotesMaster extends XSLFSheet { public class XSLFNotesMaster extends XSLFSheet {
private CTNotesMaster _slide; private CTNotesMaster _slide;
private Map<String, XSLFSlideLayout> _layouts;
private XSLFTheme _theme;


XSLFNotesMaster() { XSLFNotesMaster() {
super(); super();
protected String getRootElementName(){ protected String getRootElementName(){
return "notesMaster"; return "notesMaster";
} }

@Override
public XSLFSheet getMasterSheet() {
return null;
}

} }

+ 5
- 26
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java View File

import org.openxmlformats.schemas.presentationml.x2006.main.CTPictureNonVisual; import org.openxmlformats.schemas.presentationml.x2006.main.CTPictureNonVisual;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
/** /**
* Represents a picture shape
*
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
@Beta @Beta
} }
@Override @Override
public void draw(Graphics2D graphics){
java.awt.Shape outline = getOutline();
// shadow
XSLFShadow shadow = getShadow();
Paint fill = getFill(graphics);
Paint line = getLinePaint(graphics);
if(shadow != null) {
shadow.draw(graphics);
}
if(fill != null) {
graphics.setPaint(fill);
graphics.fill(outline);
}
public void drawContent(Graphics2D graphics) {
XSLFPictureData data = getPictureData(); XSLFPictureData data = getPictureData();
if(data == null) return; if(data == null) return;
XSLFImageRendener renderer = (XSLFImageRendener)graphics.getRenderingHint(XSLFRenderingHint.IMAGE_RENDERER); XSLFImageRendener renderer = (XSLFImageRendener)graphics.getRenderingHint(XSLFRenderingHint.IMAGE_RENDERER);
if(renderer == null) renderer = new XSLFImageRendener(); if(renderer == null) renderer = new XSLFImageRendener();
renderer.drawImage(graphics, data, getAnchor()); renderer.drawImage(graphics, data, getAnchor());
if (line != null){
graphics.setPaint(line);
applyStroke(graphics);
graphics.draw(outline);
}
} }
} }

+ 33
- 1
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRenderingHint.java View File

package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import java.awt.*;
import java.awt.RenderingHints;
/** /**
* *
public static final XSLFRenderingHint GSAVE = new XSLFRenderingHint(1); public static final XSLFRenderingHint GSAVE = new XSLFRenderingHint(1);
public static final XSLFRenderingHint GRESTORE = new XSLFRenderingHint(2); public static final XSLFRenderingHint GRESTORE = new XSLFRenderingHint(2);
/**
* Use a custom image rendener
*
* @see XSLFImageRendener
*/
public static final XSLFRenderingHint IMAGE_RENDERER = new XSLFRenderingHint(3); public static final XSLFRenderingHint IMAGE_RENDERER = new XSLFRenderingHint(3);
/**
* how to render text:
*
* {@link #TEXT_MODE_CHARACTERS} (default) means to draw via
* {@link java.awt.Graphics2D#drawString(java.text.AttributedCharacterIterator, float, float)}.
* This mode draws text as characters. Use it if the target graphics writes the actual
* character codes instead of glyph outlines (PDFGraphics2D, SVGGraphics2D, etc.)
*
* {@link #TEXT_MODE_GLYPHS} means to render via
* {@link java.awt.font.TextLayout#draw(java.awt.Graphics2D, float, float)}.
* This mode draws glyphs as shapes and provides some advanced capabilities such as
* justification and font substitution. Use it if the target graphics is an image.
*
*/
public static final XSLFRenderingHint TEXT_RENDERING_MODE = new XSLFRenderingHint(4);
/**
* draw text via {@link java.awt.Graphics2D#drawString(java.text.AttributedCharacterIterator, float, float)}
*/
public static final int TEXT_MODE_CHARACTERS = 1;
/**
* draw text via {@link java.awt.font.TextLayout#draw(java.awt.Graphics2D, float, float)}
*/
public static final int TEXT_MODE_GLYPHS = 2;
} }

+ 32
- 16
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java View File

import org.apache.poi.util.Units; import org.apache.poi.util.Units;
import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect; import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import java.awt.*;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
/** /**
_parent = parentShape; _parent = parentShape;
} }
@Override
public void draw(Graphics2D graphics) {
Shape outline = _parent.getOutline();
Paint parentFillColor = _parent.getFill(graphics);
Paint parentLineColor = _parent.getLinePaint(graphics);
public void fill(Graphics2D graphics, Shape outline) {
double angle = getAngle(); double angle = getAngle();
double dist = getDistance(); double dist = getDistance();
double dx = dist * Math.cos( Math.toRadians(angle));
double dy = dist * Math.sin( Math.toRadians(angle));
double dx = dist * Math.cos(Math.toRadians(angle));
double dy = dist * Math.sin(Math.toRadians(angle));
graphics.translate(dx, dy); graphics.translate(dx, dy);
Color fillColor = getFillColor(); Color fillColor = getFillColor();
if (fillColor != null) { if (fillColor != null) {
graphics.setColor(fillColor); graphics.setColor(fillColor);
graphics.fill(outline);
} }
if(parentFillColor != null) {
graphics.fill(outline);
}
if(parentLineColor != null) {
_parent.applyStroke(graphics);
graphics.draw(outline);
}
graphics.translate(-dx, -dy);
}
public void draw(Graphics2D graphics, Shape outline) {
double angle = getAngle();
double dist = getDistance();
double dx = dist * Math.cos(Math.toRadians(angle));
double dy = dist * Math.sin(Math.toRadians(angle));
graphics.translate(dx, dy);
Color fillColor = getFillColor();
if (fillColor != null) {
graphics.setColor(fillColor);
graphics.draw(outline);
}
graphics.translate(-dx, -dy); graphics.translate(-dx, -dy);
} }
@Override @Override
public Rectangle2D getAnchor(){ public Rectangle2D getAnchor(){
return _parent.getAnchor(); return _parent.getAnchor();
public Color getFillColor() { public Color getFillColor() {
XSLFTheme theme = getSheet().getTheme(); XSLFTheme theme = getSheet().getTheme();
CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject();
return ct == null ? null : new XSLFColor(ct, theme).getColor();
if(ct == null) {
return null;
} else {
CTSchemeColor phClr = ct.getSchemeClr();
return new XSLFColor(ct, theme, phClr).getColor();
}
} }
} }

+ 56
- 7
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java View File

import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlObject;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
/** /**
* Base super-class class for all shapes in PresentationML
*
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
@Beta @Beta
public abstract class XSLFShape { public abstract class XSLFShape {
/**
*
* @return the position of this shape within the drawing canvas.
* The coordinates are expressed in points
*/
public abstract Rectangle2D getAnchor(); public abstract Rectangle2D getAnchor();
/**
*
* @param anchor the position of this shape within the drawing canvas.
* The coordinates are expressed in points
*/
public abstract void setAnchor(Rectangle2D anchor); public abstract void setAnchor(Rectangle2D anchor);
/**
*
* @return the xml bean holding this shape's data
*/
public abstract XmlObject getXmlObject(); public abstract XmlObject getXmlObject();
/**
*
* @return human-readable name of this shape, e.g. "Rectange 3"
*/
public abstract String getShapeName(); public abstract String getShapeName();
/**
* Returns a unique identifier for this shape within the current document.
* This ID may be used to assist in uniquely identifying this object so that it can
* be referred to by other parts of the document.
* <p>
* If multiple objects within the same document share the same id attribute value,
* then the document shall be considered non-conformant.
* </p>
*
* @return unique id of this shape
*/
public abstract int getShapeId(); public abstract int getShapeId();
/** /**
*/ */
public abstract double getRotation(); public abstract double getRotation();
/**
* @param flip whether the shape is horizontally flipped
*/
public abstract void setFlipHorizontal(boolean flip); public abstract void setFlipHorizontal(boolean flip);
/**
* Whether the shape is vertically flipped
*
* @param flip whether the shape is vertically flipped
*/
public abstract void setFlipVertical(boolean flip); public abstract void setFlipVertical(boolean flip);
/** /**
*/ */
public abstract boolean getFlipHorizontal(); public abstract boolean getFlipHorizontal();
/**
* Whether the shape is vertically flipped
*
* @return whether the shape is vertically flipped
*/
public abstract boolean getFlipVertical(); public abstract boolean getFlipVertical();
/**
* Draw this shape into the supplied canvas
*
* @param graphics the graphics to draw into
*/
public abstract void draw(Graphics2D graphics); public abstract void draw(Graphics2D graphics);
protected java.awt.Shape getOutline(){
return getAnchor();
}
/**
* Apply 2-D transforms before drawing this shape. This includes rotation and flipping.
*
* @param graphics the graphics whos transform matrix will be modified
*/
protected void applyTransform(Graphics2D graphics){ protected void applyTransform(Graphics2D graphics){
Rectangle2D anchor = getAnchor(); Rectangle2D anchor = getAnchor();
graphics.translate(-anchor.getX(), -anchor.getY()); graphics.translate(-anchor.getX(), -anchor.getY());
} }
} }
} }

+ 112
- 45
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java View File

import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode; import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions; import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
import org.openxmlformats.schemas.presentationml.x2006.main.CTCommonSlideData; import org.openxmlformats.schemas.presentationml.x2006.main.CTCommonSlideData;
import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;


import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Pattern; import java.util.regex.Pattern;


@Beta @Beta
public abstract class XSLFSheet extends POIXMLDocumentPart {
public abstract class XSLFSheet extends POIXMLDocumentPart implements Iterable<XSLFShape> {
private XSLFCommonSlideData _commonSlideData; private XSLFCommonSlideData _commonSlideData;
private XSLFDrawing _drawing; private XSLFDrawing _drawing;
private List<XSLFShape> _shapes; private List<XSLFShape> _shapes;
private CTGroupShape _spTree; private CTGroupShape _spTree;

private List<XSLFTextShape>_placeholders;
private Map<Integer, XSLFSimpleShape> _placeholderByIdMap; private Map<Integer, XSLFSimpleShape> _placeholderByIdMap;
private Map<Integer, XSLFSimpleShape> _placeholderByTypeMap; private Map<Integer, XSLFSimpleShape> _placeholderByTypeMap;


super(part, rel); super(part, rel);
} }


/**
*
* @return the XMLSlideShow this sheet belongs to
*/
public XMLSlideShow getSlideShow() { public XMLSlideShow getSlideShow() {
POIXMLDocumentPart p = getParent(); POIXMLDocumentPart p = getParent();
while(p != null) { while(p != null) {
} }
p = p.getParent(); p = p.getParent();
} }
return null;
throw new IllegalStateException("SlideShow was not found");
} }


protected List<XSLFShape> buildShapes(CTGroupShape spTree){ protected List<XSLFShape> buildShapes(CTGroupShape spTree){
return shapes; return shapes;
} }


/**
* @return top-level Xml bean representing this sheet
*/
public abstract XmlObject getXmlObject(); public abstract XmlObject getXmlObject();


@Internal
public XSLFCommonSlideData getCommonSlideData() { public XSLFCommonSlideData getCommonSlideData() {
return _commonSlideData; return _commonSlideData;
} }

protected void setCommonSlideData(CTCommonSlideData data) { protected void setCommonSlideData(CTCommonSlideData data) {
if(data == null) { if(data == null) {
_commonSlideData = null; _commonSlideData = null;
return sh; return sh;
} }


/**
* Returns an array containing all of the shapes in this sheet
*
* @return an array of all shapes in this sheet
*/
public XSLFShape[] getShapes(){ public XSLFShape[] getShapes(){
return getShapeList().toArray(new XSLFShape[_shapes.size()]); return getShapeList().toArray(new XSLFShape[_shapes.size()]);
} }


/**
* Returns an iterator over the shapes in this sheet
*
* @return an iterator over the shapes in this sheet
*/
public Iterator<XSLFShape> iterator(){
return getShapeList().iterator();
}

/**
* Removes the specified shape from this sheet, if it is present
* (optional operation). If this sheet does not contain the element,
* it is unchanged.
*
* @param xShape shape to be removed from this sheet, if present
* @return <tt>true</tt> if this sheet contained the specified element
* @throws IllegalArgumentException if the type of the specified shape
* is incompatible with this sheet (optional)
*/
public boolean removeShape(XSLFShape xShape) { public boolean removeShape(XSLFShape xShape) {
XmlObject obj = xShape.getXmlObject(); XmlObject obj = xShape.getXmlObject();
CTGroupShape spTree = getSpTree(); CTGroupShape spTree = getSpTree();
return getShapeList().remove(xShape); return getShapeList().remove(xShape);
} }


public XSLFBackground getBackground(){
return null;
}

protected abstract String getRootElementName(); protected abstract String getRootElementName();


protected CTGroupShape getSpTree(){ protected CTGroupShape getSpTree(){
getXmlObject().set(src.getXmlObject()); getXmlObject().set(src.getXmlObject());
} }


public XSLFTheme getTheme(){
return null;
}

public XSLFSlideMaster getSlideMaster(){
/**
* @return theme (shared styles) associated with this theme.
* By default returns <code>null</code> which means that this sheet is theme-less.
* Sheets that support the notion of themes (slides, masters, layouts, etc.) should override this
* method and return the corresposnding package part.
*/
XSLFTheme getTheme(){
return null; return null;
} }


public XSLFSlideLayout getSlideLayout(){
return null;
}
/**
*
* @return master of this sheet.
*/
public abstract XSLFSheet getMasterSheet();


protected CTTextListStyle getTextProperties(Placeholder textType) {
return null;
}
protected XSLFTextShape getTextShapeByType(Placeholder type){ protected XSLFTextShape getTextShapeByType(Placeholder type){
for(XSLFShape shape : this.getShapes()){ for(XSLFShape shape : this.getShapes()){
if(shape instanceof XSLFTextShape) { if(shape instanceof XSLFTextShape) {
return shape; return shape;
} }


XSLFSimpleShape getPlaceholderById(int id) {
if(_placeholderByIdMap == null) {
void initPlaceholders() {
if(_placeholders == null) {
_placeholders = new ArrayList<XSLFTextShape>();
_placeholderByIdMap = new HashMap<Integer, XSLFSimpleShape>(); _placeholderByIdMap = new HashMap<Integer, XSLFSimpleShape>();
_placeholderByTypeMap = new HashMap<Integer, XSLFSimpleShape>();

for(XSLFShape sh : getShapes()){ for(XSLFShape sh : getShapes()){
if(sh instanceof XSLFSimpleShape){
XSLFSimpleShape sShape = (XSLFSimpleShape)sh;
if(sh instanceof XSLFTextShape){
XSLFTextShape sShape = (XSLFTextShape)sh;
CTPlaceholder ph = sShape.getCTPlaceholder(); CTPlaceholder ph = sShape.getCTPlaceholder();
if(ph != null && ph.isSetIdx()){
int idx = (int)ph.getIdx();
_placeholderByIdMap.put(idx, sShape);
if(ph != null) {
_placeholders.add(sShape);
if(ph.isSetIdx()) {
int idx = (int)ph.getIdx();
_placeholderByIdMap.put(idx, sShape);
}
if(ph.isSetType()){
_placeholderByTypeMap.put(ph.getType().intValue(), sShape);
}
} }
} }
} }
} }
}

XSLFSimpleShape getPlaceholderById(int id) {
initPlaceholders();
return _placeholderByIdMap.get(id); return _placeholderByIdMap.get(id);
} }


XSLFSimpleShape getPlaceholderByType(int ordinal) { XSLFSimpleShape getPlaceholderByType(int ordinal) {
if(_placeholderByTypeMap == null) {
_placeholderByTypeMap = new HashMap<Integer, XSLFSimpleShape>();
for(XSLFShape sh : getShapes()){
if(sh instanceof XSLFSimpleShape){
XSLFSimpleShape sShape = (XSLFSimpleShape)sh;
CTPlaceholder ph = sShape.getCTPlaceholder();
if(ph != null && ph.isSetType()){
_placeholderByTypeMap.put(ph.getType().intValue(), sShape);
}
}
}
}
initPlaceholders();
return _placeholderByTypeMap.get(ordinal); return _placeholderByTypeMap.get(ordinal);
} }


/**
*
* @param idx 0-based index of a placeholder in the sheet
* @return placeholder
*/
public XSLFTextShape getPlaceholder(int idx) {
initPlaceholders();
return _placeholders.get(idx);
}

/**
*
* @return all placeholder shapes in this sheet
*/
public XSLFTextShape[] getPlaceholders() {
initPlaceholders();
return _placeholders.toArray(new XSLFTextShape[_placeholders.size()]);
}

/** /**
* Checks if this <code>sheet</code> displays the specified shape. * Checks if this <code>sheet</code> displays the specified shape.
* *
* Subclasses can override it and skip certain shapes from drawings.
* Subclasses can override it and skip certain shapes from drawings,
* for instance, slide masters and layouts don't display placeholders
*/ */
protected boolean canDraw(XSLFShape shape){ protected boolean canDraw(XSLFShape shape){
return true; return true;
} }


/**
*
* @return whether shapes on the master sheet should be shown. By default master graphics is turned off.
* Sheets that support the notion of master (slide, slideLayout) should override it and
* check this setting in the sheet XML
*/
public boolean getFollowMasterGraphics(){
return false;
}

/** /**
* Render this sheet into the supplied graphics object * Render this sheet into the supplied graphics object
* *
* @param graphics * @param graphics
*/ */
public void draw(Graphics2D graphics){ public void draw(Graphics2D graphics){
XSLFBackground bg = getBackground();
if(bg != null) bg.draw(graphics);
XSLFSheet master = getMasterSheet();
if(getFollowMasterGraphics() && master != null) master.draw(graphics);


for(XSLFShape shape : getShapeList()) { for(XSLFShape shape : getShapeList()) {
if(!canDraw(shape)) continue; if(!canDraw(shape)) continue;


// remember the initial transform and restore it after we are done with drawing // remember the initial transform and restore it after we are done with drawing
AffineTransform at0 = graphics.getTransform();
AffineTransform at = graphics.getTransform();


// concrete implementations can make sense of this hint,
// for example PSGraphics2D or PDFGraphics2D would call gsave() / grestore
graphics.setRenderingHint(XSLFRenderingHint.GSAVE, true); graphics.setRenderingHint(XSLFRenderingHint.GSAVE, true);


// apply rotation and flipping // apply rotation and flipping
shape.applyTransform(graphics); shape.applyTransform(graphics);
// draw stuff
shape.draw(graphics); shape.draw(graphics);


// restore the coordinate system // restore the coordinate system
graphics.setTransform(at0);
graphics.setTransform(at);

graphics.setRenderingHint(XSLFRenderingHint.GRESTORE, true); graphics.setRenderingHint(XSLFRenderingHint.GRESTORE, true);


} }

+ 194
- 427
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java View File

package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
import org.apache.poi.xslf.model.PropertyFetcher; import org.apache.poi.xslf.model.PropertyFetcher;
import org.apache.poi.xslf.model.geom.CustomGeometry; import org.apache.poi.xslf.model.geom.CustomGeometry;
import org.apache.poi.xslf.model.geom.Guide; import org.apache.poi.xslf.model.geom.Guide;
import org.apache.poi.xslf.model.geom.IAdjustableShape; import org.apache.poi.xslf.model.geom.IAdjustableShape;
import org.apache.poi.xslf.model.geom.Outline;
import org.apache.poi.xslf.model.geom.Path; import org.apache.poi.xslf.model.geom.Path;
import org.apache.poi.xslf.model.geom.PresetGeometries; import org.apache.poi.xslf.model.geom.PresetGeometries;
import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.*;
import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetLineDashProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath; import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.Paint;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.TexturePaint;
import java.awt.AlphaComposite;
import java.awt.GradientPaint;
import java.awt.BasicStroke;
import java.awt.Stroke;
import java.util.Arrays;
import java.util.Comparator;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/** /**
* Represents a single (non-group) shape in a .pptx slide show
*
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
@Beta @Beta
public abstract class XSLFSimpleShape extends XSLFShape { public abstract class XSLFSimpleShape extends XSLFShape {
private final XmlObject _shape; private final XmlObject _shape;
private final XSLFSheet _sheet; private final XSLFSheet _sheet;
private CTShapeProperties _spPr; private CTShapeProperties _spPr;
_sheet = sheet; _sheet = sheet;
} }
@Override
public XmlObject getXmlObject() { public XmlObject getXmlObject() {
return _shape; return _shape;
} }
/**
*
* @return the sheet this shape belongs to
*/
public XSLFSheet getSheet() { public XSLFSheet getSheet() {
return _sheet; return _sheet;
} }
return stEnum == null ? 0 : stEnum.intValue(); return stEnum == null ? 0 : stEnum.intValue();
} }
@Override
public String getShapeName() { public String getShapeName() {
return getNvPr().getName(); return getNvPr().getName();
} }
@Override
public int getShapeId() { public int getShapeId() {
return (int) getNvPr().getId(); return (int) getNvPr().getId();
} }
return _spStyle; return _spStyle;
} }
protected CTPlaceholder getCTPlaceholder(){
if(_ph == null){
protected CTPlaceholder getCTPlaceholder() {
if (_ph == null) {
XmlObject[] obj = _shape.selectPath( XmlObject[] obj = _shape.selectPath(
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:nvPr/p:ph"); "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:nvPr/p:ph");
if(obj.length == 1){
_ph = (CTPlaceholder)obj[0];
if (obj.length == 1) {
_ph = (CTPlaceholder) obj[0];
} }
} }
return _ph; return _ph;
} }
private CTTransform2D getXfrm(){
PropertyFetcher<CTTransform2D> fetcher = new PropertyFetcher<CTTransform2D>(){
public boolean fetch(XSLFSimpleShape shape){
private CTTransform2D getXfrm() {
PropertyFetcher<CTTransform2D> fetcher = new PropertyFetcher<CTTransform2D>() {
public boolean fetch(XSLFSimpleShape shape) {
CTShapeProperties pr = shape.getSpPr(); CTShapeProperties pr = shape.getSpPr();
if(pr.isSetXfrm()){
if (pr.isSetXfrm()) {
setValue(pr.getXfrm()); setValue(pr.getXfrm());
return true; return true;
} }
return fetcher.getValue(); return fetcher.getValue();
} }
@Override
public Rectangle2D getAnchor() { public Rectangle2D getAnchor() {
CTTransform2D xfrm = getXfrm(); CTTransform2D xfrm = getXfrm();
CTPoint2D off = xfrm.getOff(); CTPoint2D off = xfrm.getOff();
long x = off.getX(); long x = off.getX();
long y = off.getY(); long y = off.getY();
Units.toPoints(cx), Units.toPoints(cy)); Units.toPoints(cx), Units.toPoints(cy));
} }
@Override
public void setAnchor(Rectangle2D anchor) { public void setAnchor(Rectangle2D anchor) {
CTShapeProperties spPr = getSpPr(); CTShapeProperties spPr = getSpPr();
CTTransform2D xfrm = spPr.isSetXfrm() ? spPr.getXfrm() : spPr.addNewXfrm(); CTTransform2D xfrm = spPr.isSetXfrm() ? spPr.getXfrm() : spPr.addNewXfrm();
ext.setCy(cy); ext.setCy(cy);
} }
/**
* Rotate this shape.
* <p>
* Positive angles are clockwise (i.e., towards the positive y axis);
* negative angles are counter-clockwise (i.e., towards the negative y
* axis).
* </p>
*
* @param theta the rotation angle in degrees.
*/
@Override
public void setRotation(double theta) { public void setRotation(double theta) {
CTShapeProperties spPr = getSpPr(); CTShapeProperties spPr = getSpPr();
CTTransform2D xfrm = spPr.isSetXfrm() ? spPr.getXfrm() : spPr.addNewXfrm(); CTTransform2D xfrm = spPr.isSetXfrm() ? spPr.getXfrm() : spPr.addNewXfrm();
xfrm.setRot((int) (theta * 60000)); xfrm.setRot((int) (theta * 60000));
} }
/**
* Rotation angle in degrees
* <p>
* Positive angles are clockwise (i.e., towards the positive y axis);
* negative angles are counter-clockwise (i.e., towards the negative y
* axis).
* </p>
*
* @return rotation angle in degrees
*/
@Override
public double getRotation() { public double getRotation() {
CTTransform2D xfrm = getXfrm(); CTTransform2D xfrm = getXfrm();
return (double) xfrm.getRot() / 60000; return (double) xfrm.getRot() / 60000;
} }
@Override
public void setFlipHorizontal(boolean flip) { public void setFlipHorizontal(boolean flip) {
CTShapeProperties spPr = getSpPr(); CTShapeProperties spPr = getSpPr();
CTTransform2D xfrm = spPr.isSetXfrm() ? spPr.getXfrm() : spPr.addNewXfrm(); CTTransform2D xfrm = spPr.isSetXfrm() ? spPr.getXfrm() : spPr.addNewXfrm();
xfrm.setFlipH(flip); xfrm.setFlipH(flip);
} }
@Override
public void setFlipVertical(boolean flip) { public void setFlipVertical(boolean flip) {
CTShapeProperties spPr = getSpPr(); CTShapeProperties spPr = getSpPr();
CTTransform2D xfrm = spPr.isSetXfrm() ? spPr.getXfrm() : spPr.addNewXfrm(); CTTransform2D xfrm = spPr.isSetXfrm() ? spPr.getXfrm() : spPr.addNewXfrm();
xfrm.setFlipV(flip); xfrm.setFlipV(flip);
} }
/**
* Whether the shape is horizontally flipped
*
* @return whether the shape is horizontally flipped
*/
@Override
public boolean getFlipHorizontal() { public boolean getFlipHorizontal() {
return getXfrm().getFlipH(); return getXfrm().getFlipH();
} }
@Override
public boolean getFlipVertical() { public boolean getFlipVertical() {
return getXfrm().getFlipV(); return getXfrm().getFlipV();
} }
/** /**
* Get line properties defined in the theme (if any)
* Get default line properties defined in the theme (if any).
* Used internally to resolve shape properties.
* *
* @return line propeties from the theme of null * @return line propeties from the theme of null
*/ */
return ln; return ln;
} }
/**
* @param color the color to paint the shape outline.
* A <code>null</code> value turns off the shape outline.
*/
public void setLineColor(Color color) { public void setLineColor(Color color) {
CTShapeProperties spPr = getSpPr(); CTShapeProperties spPr = getSpPr();
if (color == null) { if (color == null) {
} }
} }
/**
*
* @return the color of the shape outline or <code>null</code>
* if outline is turned off
*/
public Color getLineColor() { public Color getLineColor() {
Paint paint = getLinePaint(null);
if(paint instanceof Color){
return (Color)paint;
RenderableShape rShape = new RenderableShape(this);
Paint paint = rShape.getLinePaint(null);
if (paint instanceof Color) {
return (Color) paint;
} }
return null; return null;
} }
public Paint getLinePaint(final Graphics2D graphics) {
final XSLFTheme theme = _sheet.getTheme();
final Color nofill = new Color(0,0,0,0);
PropertyFetcher<Paint> fetcher = new PropertyFetcher<Paint>(){
public boolean fetch(XSLFSimpleShape shape){
CTLineProperties spPr = shape.getSpPr().getLn();
if (spPr != null) {
if (spPr.isSetNoFill()) {
setValue(nofill); // use it as 'nofill' value
return true;
}
Paint paint = getPaint(graphics, spPr);
if (paint != null) {
setValue( paint );
return true;
}
}
return false;
}
};
fetchShapeProperty(fetcher);
Paint color = fetcher.getValue();
if(color == null){
// line color was not found, check if it is defined in the theme
CTShapeStyle style = getSpStyle();
if (style != null) {
color = new XSLFColor(style.getLnRef(), theme).getColor();
}
}
return color == nofill ? null : color;
}
/**
*
* @param width line width in points. <code>0</code> means no line
*/
public void setLineWidth(double width) { public void setLineWidth(double width) {
CTShapeProperties spPr = getSpPr(); CTShapeProperties spPr = getSpPr();
if (width == 0.) { if (width == 0.) {
} }
} }
/**
*
* @return line width in points. <code>0</code> means no line.
*/
public double getLineWidth() { public double getLineWidth() {
PropertyFetcher<Double> fetcher = new PropertyFetcher<Double>(){
public boolean fetch(XSLFSimpleShape shape){
PropertyFetcher<Double> fetcher = new PropertyFetcher<Double>() {
public boolean fetch(XSLFSimpleShape shape) {
CTShapeProperties spPr = shape.getSpPr(); CTShapeProperties spPr = shape.getSpPr();
CTLineProperties ln = spPr.getLn(); CTLineProperties ln = spPr.getLn();
if (ln != null) { if (ln != null) {
} }
if (ln.isSetW()) { if (ln.isSetW()) {
setValue( Units.toPoints(ln.getW()) );
setValue(Units.toPoints(ln.getW()));
return true; return true;
} }
} }
fetchShapeProperty(fetcher); fetchShapeProperty(fetcher);
double lineWidth = 0; double lineWidth = 0;
if(fetcher.getValue() == null) {
if (fetcher.getValue() == null) {
CTLineProperties defaultLn = getDefaultLineProperties(); CTLineProperties defaultLn = getDefaultLineProperties();
if (defaultLn != null) { if (defaultLn != null) {
if (defaultLn.isSetW()) lineWidth = Units.toPoints(defaultLn.getW()); if (defaultLn.isSetW()) lineWidth = Units.toPoints(defaultLn.getW());
return lineWidth; return lineWidth;
} }
/**
*
* @param dash a preset line dashing scheme to stroke thr shape outline
*/
public void setLineDash(LineDash dash) { public void setLineDash(LineDash dash) {
CTShapeProperties spPr = getSpPr(); CTShapeProperties spPr = getSpPr();
if (dash == null) { if (dash == null) {
} }
} }
/**
* @return a preset line dashing scheme to stroke thr shape outline
*/
public LineDash getLineDash() { public LineDash getLineDash() {
PropertyFetcher<LineDash> fetcher = new PropertyFetcher<LineDash>(){
public boolean fetch(XSLFSimpleShape shape){
PropertyFetcher<LineDash> fetcher = new PropertyFetcher<LineDash>() {
public boolean fetch(XSLFSimpleShape shape) {
CTShapeProperties spPr = shape.getSpPr(); CTShapeProperties spPr = shape.getSpPr();
CTLineProperties ln = spPr.getLn(); CTLineProperties ln = spPr.getLn();
if (ln != null) { if (ln != null) {
CTPresetLineDashProperties ctDash = ln.getPrstDash(); CTPresetLineDashProperties ctDash = ln.getPrstDash();
if (ctDash != null) { if (ctDash != null) {
setValue( LineDash.values()[ctDash.getVal().intValue() - 1] );
setValue(LineDash.values()[ctDash.getVal().intValue() - 1]);
return true; return true;
} }
} }
fetchShapeProperty(fetcher); fetchShapeProperty(fetcher);
LineDash dash = fetcher.getValue(); LineDash dash = fetcher.getValue();
if(dash == null){
if (dash == null) {
CTLineProperties defaultLn = getDefaultLineProperties(); CTLineProperties defaultLn = getDefaultLineProperties();
if (defaultLn != null) { if (defaultLn != null) {
CTPresetLineDashProperties ctDash = defaultLn.getPrstDash(); CTPresetLineDashProperties ctDash = defaultLn.getPrstDash();
return dash; return dash;
} }
/**
*
* @param cap the line end cap style
*/
public void setLineCap(LineCap cap) { public void setLineCap(LineCap cap) {
CTShapeProperties spPr = getSpPr(); CTShapeProperties spPr = getSpPr();
if (cap == null) { if (cap == null) {
} }
} }
/**
*
* @return the line end cap style
*/
public LineCap getLineCap() { public LineCap getLineCap() {
PropertyFetcher<LineCap> fetcher = new PropertyFetcher<LineCap>(){
public boolean fetch(XSLFSimpleShape shape){
PropertyFetcher<LineCap> fetcher = new PropertyFetcher<LineCap>() {
public boolean fetch(XSLFSimpleShape shape) {
CTShapeProperties spPr = shape.getSpPr(); CTShapeProperties spPr = shape.getSpPr();
CTLineProperties ln = spPr.getLn(); CTLineProperties ln = spPr.getLn();
if (ln != null) { if (ln != null) {
STLineCap.Enum stCap = ln.getCap(); STLineCap.Enum stCap = ln.getCap();
if (stCap != null) { if (stCap != null) {
setValue( LineCap.values()[stCap.intValue() - 1] );
setValue(LineCap.values()[stCap.intValue() - 1]);
return true; return true;
} }
} }
fetchShapeProperty(fetcher); fetchShapeProperty(fetcher);
LineCap cap = fetcher.getValue(); LineCap cap = fetcher.getValue();
if(cap == null){
if (cap == null) {
CTLineProperties defaultLn = getDefaultLineProperties(); CTLineProperties defaultLn = getDefaultLineProperties();
if (defaultLn != null) { if (defaultLn != null) {
STLineCap.Enum stCap = defaultLn.getCap(); STLineCap.Enum stCap = defaultLn.getCap();
if (color == null) { if (color == null) {
if (spPr.isSetSolidFill()) spPr.unsetSolidFill(); if (spPr.isSetSolidFill()) spPr.unsetSolidFill();
if(!spPr.isSetNoFill()) spPr.addNewNoFill();
if (!spPr.isSetNoFill()) spPr.addNewNoFill();
} else { } else {
if(spPr.isSetNoFill()) spPr.unsetNoFill();
if (spPr.isSetNoFill()) spPr.unsetNoFill();
CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr
.getSolidFill() : spPr.addNewSolidFill(); .getSolidFill() : spPr.addNewSolidFill();
} }
/** /**
* @return solid fill color of null if not set
* @return solid fill color of null if not set or fill color
* is not solid (pattern or gradient)
*/ */
public Color getFillColor() { public Color getFillColor() {
Paint paint = getFill(null);
if(paint instanceof Color){
return (Color)paint;
RenderableShape rShape = new RenderableShape(this);
Paint paint = rShape.getFillPaint(null);
if (paint instanceof Color) {
return (Color) paint;
} }
return null; return null;
} }
/** /**
* fetch shape fill as a java.awt.Paint
*
* @return either Color or GradientPaint or TexturePaint or null
* @return shadow of this shape or null if shadow is disabled
*/ */
Paint getFill(final Graphics2D graphics) {
final XSLFTheme theme = _sheet.getTheme();
final Color nofill = new Color(0xFF,0xFF,0xFF, 0);
PropertyFetcher<Paint> fetcher = new PropertyFetcher<Paint>(){
public boolean fetch(XSLFSimpleShape shape){
CTShapeProperties spPr = shape.getSpPr();
if (spPr.isSetNoFill()) {
setValue(nofill); // use it as 'nofill' value
return true;
}
Paint paint = getPaint(graphics, spPr);
if (paint != null) {
setValue( paint );
return true;
}
return false;
}
};
fetchShapeProperty(fetcher);
Paint paint = fetcher.getValue();
if(paint == null){
// fill color was not found, check if it is defined in the theme
CTShapeStyle style = getSpStyle();
if (style != null) {
paint = new XSLFColor(style.getFillRef(), theme).getColor();
}
}
return paint == nofill ? null : paint;
}
public XSLFShadow getShadow(){
PropertyFetcher<CTOuterShadowEffect> fetcher = new PropertyFetcher<CTOuterShadowEffect>(){
public boolean fetch(XSLFSimpleShape shape){
public XSLFShadow getShadow() {
PropertyFetcher<CTOuterShadowEffect> fetcher = new PropertyFetcher<CTOuterShadowEffect>() {
public boolean fetch(XSLFSimpleShape shape) {
CTShapeProperties spPr = shape.getSpPr(); CTShapeProperties spPr = shape.getSpPr();
if (spPr.isSetEffectLst()) { if (spPr.isSetEffectLst()) {
CTOuterShadowEffect obj = spPr.getEffectLst().getOuterShdw(); CTOuterShadowEffect obj = spPr.getEffectLst().getOuterShdw();
fetchShapeProperty(fetcher); fetchShapeProperty(fetcher);
CTOuterShadowEffect obj = fetcher.getValue(); CTOuterShadowEffect obj = fetcher.getValue();
if(obj == null){
if (obj == null) {
// fill color was not found, check if it is defined in the theme // fill color was not found, check if it is defined in the theme
CTShapeStyle style = getSpStyle(); CTShapeStyle style = getSpStyle();
if (style != null) { if (style != null) {
// 1-based index of a shadow style within the style matrix // 1-based index of a shadow style within the style matrix
int idx = (int) style.getEffectRef().getIdx(); int idx = (int) style.getEffectRef().getIdx();
CTStyleMatrix styleMatrix = _sheet.getTheme().getXmlObject().getThemeElements().getFmtScheme();
CTEffectStyleItem ef = styleMatrix.getEffectStyleLst().getEffectStyleArray(idx - 1);
obj = ef.getEffectLst().getOuterShdw();
if(idx != 0) {
CTStyleMatrix styleMatrix = _sheet.getTheme().getXmlObject().getThemeElements().getFmtScheme();
CTEffectStyleItem ef = styleMatrix.getEffectStyleLst().getEffectStyleArray(idx - 1);
obj = ef.getEffectLst().getOuterShdw();
}
} }
} }
return obj == null ? null : new XSLFShadow(obj, this); return obj == null ? null : new XSLFShadow(obj, this);
} }
@Override
public void draw(Graphics2D graphics) { public void draw(Graphics2D graphics) {
}
@SuppressWarnings("deprecation") // getXYZArray() array accessors are deprecated
protected Paint getPaint(Graphics2D graphics, XmlObject spPr) {
XSLFTheme theme = getSheet().getTheme();
Rectangle2D anchor = getAnchor();
Paint paint = null;
for(XmlObject obj : spPr.selectPath("*")){
if(obj instanceof CTNoFillProperties){
paint = null;
break;
}
if(obj instanceof CTSolidColorFillProperties){
CTSolidColorFillProperties solidFill = (CTSolidColorFillProperties)obj;
XSLFColor c = new XSLFColor(solidFill, theme);
paint = c.getColor();
}
if(obj instanceof CTBlipFillProperties){
CTBlipFillProperties blipFill = (CTBlipFillProperties)obj;
CTBlip blip = blipFill.getBlip();
String blipId = blip.getEmbed();
PackagePart p = getSheet().getPackagePart();
PackageRelationship rel = p.getRelationship(blipId);
if (rel != null) {
XSLFImageRendener renderer = null;
if(graphics != null) renderer = (XSLFImageRendener)graphics.getRenderingHint(XSLFRenderingHint.IMAGE_RENDERER);
if(renderer == null) renderer = new XSLFImageRendener();
try {
BufferedImage img = renderer.readImage(p.getRelatedPart(rel).getInputStream());
if(blip.sizeOfAlphaModFixArray() > 0){
float alpha = blip.getAlphaModFixArray(0).getAmt()/100000.f;
AlphaComposite ac = AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, alpha);
if(graphics != null) graphics.setComposite(ac);
}
paint = new TexturePaint(
img, new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight()));
}
catch (Exception e) {
return null;
}
}
}
if(obj instanceof CTGradientFillProperties){
CTGradientFillProperties gradFill = (CTGradientFillProperties)obj;
double angle;
if(gradFill.isSetLin()) {
angle = gradFill.getLin().getAng() / 60000;
} else {
// XSLF only supports linear gradient fills. Other types are filled as liner with angle=90 degrees
angle = 90;
}
CTGradientStop[] gs = gradFill.getGsLst().getGsArray();
Arrays.sort(gs, new Comparator<CTGradientStop>(){
public int compare(CTGradientStop o1, CTGradientStop o2){
Integer pos1 = o1.getPos();
Integer pos2 = o2.getPos();
return pos1.compareTo(pos2);
}
});
Color[] colors = new Color[gs.length];
float[] fractions = new float[gs.length];
AffineTransform at = AffineTransform.getRotateInstance(
Math.toRadians(angle),
anchor.getX() + anchor.getWidth()/2,
anchor.getY() + anchor.getHeight()/2);
double diagonal = Math.sqrt(anchor.getHeight()*anchor.getHeight() + anchor.getWidth()*anchor.getWidth());
Point2D p1 = new Point2D.Double(anchor.getX() + anchor.getWidth()/2 - diagonal/2,
anchor.getY() + anchor.getHeight()/2);
p1 = at.transform(p1, null);
Point2D p2 = new Point2D.Double(anchor.getX() + anchor.getWidth(), anchor.getY() + anchor.getHeight()/2);
p2 = at.transform(p2, null);
norm(p1, anchor);
norm(p2, anchor);
for(int i = 0; i < gs.length; i++){
CTGradientStop stop = gs[i];
colors[i] = new XSLFColor(stop, theme).getColor();
fractions[i] = stop.getPos() / 100000.f;
}
paint = createGradientPaint(p1, p2, fractions, colors);
}
}
return paint;
}
/**
* Trick to return GradientPaint on JDK 1.5 and LinearGradientPaint on JDK 1.6+
*/
private Paint createGradientPaint(Point2D p1, Point2D p2, float[] fractions, Color[] colors){
Paint paint;
try {
Class clz = Class.forName("java.awt.LinearGradientPaint");
Constructor c =
clz.getConstructor(Point2D.class, Point2D.class, float[].class, Color[].class);
paint = (Paint)c.newInstance(p1, p2, fractions, colors);
} catch (ClassNotFoundException e){
paint = new GradientPaint(p1, colors[0], p2, colors[colors.length - 1]);
} catch (Exception e){
throw new RuntimeException(e);
}
return paint;
}
void norm(Point2D p, Rectangle2D anchor){
if(p.getX() < anchor.getX()){
p.setLocation(anchor.getX(), p.getY());
} else if(p.getX() > (anchor.getX() + anchor.getWidth())){
p.setLocation(anchor.getX() + anchor.getWidth(), p.getY());
}
if(p.getY() < anchor.getY()){
p.setLocation(p.getX(), anchor.getY());
} else if (p.getY() > (anchor.getY() + anchor.getHeight())){
p.setLocation(p.getX(), anchor.getY() + anchor.getHeight());
}
}
protected float[] getDashPattern(LineDash lineDash, float lineWidth) {
float[] dash = null;
switch (lineDash) {
case SYS_DOT:
dash = new float[]{lineWidth, lineWidth};
break;
case SYS_DASH:
dash = new float[]{2 * lineWidth, 2 * lineWidth};
break;
case DASH:
dash = new float[]{3 * lineWidth, 4 * lineWidth};
break;
case DASH_DOT:
dash = new float[]{4 * lineWidth, 3 * lineWidth, lineWidth,
3 * lineWidth};
break;
case LG_DASH:
dash = new float[]{8 * lineWidth, 3 * lineWidth};
break;
case LG_DASH_DOT:
dash = new float[]{8 * lineWidth, 3 * lineWidth, lineWidth,
3 * lineWidth};
break;
case LG_DASH_DOT_DOT:
dash = new float[]{8 * lineWidth, 3 * lineWidth, lineWidth,
3 * lineWidth, lineWidth, 3 * lineWidth};
break;
}
return dash;
RenderableShape rShape = new RenderableShape(this);
rShape.render(graphics);
} }
protected void applyStroke(Graphics2D graphics) {
float lineWidth = (float) getLineWidth();
LineDash lineDash = getLineDash();
float[] dash = null;
float dash_phase = 0;
if (lineDash != null) {
dash = getDashPattern(lineDash, lineWidth);
}
int cap = BasicStroke.CAP_BUTT;
LineCap lineCap = getLineCap();
if (lineCap != null) {
switch (lineCap) {
case ROUND:
cap = BasicStroke.CAP_ROUND;
break;
case SQUARE:
cap = BasicStroke.CAP_SQUARE;
break;
default:
cap = BasicStroke.CAP_BUTT;
break;
}
}
int meter = BasicStroke.JOIN_ROUND;
Stroke stroke = new BasicStroke(lineWidth, cap, meter, Math.max(1, lineWidth), dash,
dash_phase);
graphics.setStroke(stroke);
}
/** /**
* Walk up the inheritance tree and fetch properties.
*
* slide <-- slideLayout <-- slideMaster
* Walk up the inheritance tree and fetch shape properties.
* *
* The following order of inheritance is assumed:
* <p>
* slide <-- slideLayout <-- slideMaster <-- default styles in the slideMaster
* </p>
* *
* @param visitor the object that collects the desired property
* @param visitor the object that collects the desired property
* @return true if the property was fetched * @return true if the property was fetched
*/ */
boolean fetchShapeProperty(PropertyFetcher visitor){
boolean fetchShapeProperty(PropertyFetcher visitor) {
boolean ok = visitor.fetch(this); boolean ok = visitor.fetch(this);
XSLFSimpleShape masterShape; XSLFSimpleShape masterShape;
if(!ok){
// first try to fetch from the slide layout
XSLFSlideLayout layout = getSheet().getSlideLayout();
if(layout != null) {
XSLFSheet layout = getSheet().getMasterSheet();
if (layout != null) {
if (!ok) {
// first try to fetch from the slide layout
CTPlaceholder ph = getCTPlaceholder(); CTPlaceholder ph = getCTPlaceholder();
if (ph != null) { if (ph != null) {
masterShape = layout.getPlaceholder(ph); masterShape = layout.getPlaceholder(ph);
} }
} }
} }
}
// try slide master
if (!ok) {
int textType;
CTPlaceholder ph = getCTPlaceholder();
if(ph == null || !ph.isSetType()) textType = STPlaceholderType.INT_BODY;
else {
switch(ph.getType().intValue()){
case STPlaceholderType.INT_TITLE:
case STPlaceholderType.INT_CTR_TITLE:
textType = STPlaceholderType.INT_TITLE;
break;
case STPlaceholderType.INT_FTR:
case STPlaceholderType.INT_SLD_NUM:
case STPlaceholderType.INT_DT:
textType = ph.getType().intValue();
break;
default:
textType = STPlaceholderType.INT_BODY;
break;
// try slide master
if (!ok) {
int textType;
CTPlaceholder ph = getCTPlaceholder();
if (ph == null || !ph.isSetType()) textType = STPlaceholderType.INT_BODY;
else {
switch (ph.getType().intValue()) {
case STPlaceholderType.INT_TITLE:
case STPlaceholderType.INT_CTR_TITLE:
textType = STPlaceholderType.INT_TITLE;
break;
case STPlaceholderType.INT_FTR:
case STPlaceholderType.INT_SLD_NUM:
case STPlaceholderType.INT_DT:
textType = ph.getType().intValue();
break;
default:
textType = STPlaceholderType.INT_BODY;
break;
}
} }
}
XSLFSlideMaster master = getSheet().getSlideMaster();
if(master != null) {
masterShape = master.getPlaceholderByType(textType);
if (masterShape != null) {
ok = visitor.fetch(masterShape);
XSLFSheet master = layout.getMasterSheet();
if (master != null) {
masterShape = master.getPlaceholderByType(textType);
if (masterShape != null) {
ok = visitor.fetch(masterShape);
}
} }
} }
} }
return ok; return ok;
} }
@Override
protected java.awt.Shape getOutline(){
PresetGeometries dict = PresetGeometries.getInstance();
/**
*
* @return definition of the shape geometry
*/
CustomGeometry getGeometry(){
CTShapeProperties spPr = getSpPr(); CTShapeProperties spPr = getSpPr();
String name;
if(spPr.isSetPrstGeom()) {
name = spPr.getPrstGeom().getPrst().toString();
CustomGeometry geom;
PresetGeometries dict = PresetGeometries.getInstance();
if(spPr.isSetPrstGeom()){
String name = spPr.getPrstGeom().getPrst().toString();
geom = dict.get(name);
if(geom == null) {
throw new IllegalStateException("Unknown shape geometry: " + name);
}
} else if (spPr.isSetCustGeom()){
geom = new CustomGeometry(spPr.getCustGeom());
} else { } else {
name = "rect";
geom = dict.get("rect");
} }
CustomGeometry geom = dict.get(name);
Rectangle2D anchor = getAnchor();
if(geom != null) {
// the guides in the shape definitions are all defined relative to each other,
// so we build the path starting from (0,0).
final Rectangle2D anchorEmu = new Rectangle2D.Double(
0,
0,
Units.toEMU(anchor.getWidth()),
Units.toEMU(anchor.getHeight())
);
GeneralPath path = new GeneralPath();
Context ctx = new Context(geom, new IAdjustableShape() {
public Rectangle2D getAnchor() {
return anchorEmu;
}
return geom;
}
public Guide getAdjustValue(String name) {
CTPresetGeometry2D prst = getSpPr().getPrstGeom();
if(prst.isSetAvLst()) {
for(CTGeomGuide g : prst.getAvLst().getGdList()){
if(g.getName().equals(name)) {
return new Guide(g);
}
}
}
return null;
}
});
for(Path p : geom){
path.append( p.getPath(ctx) , false);
}
/**
* @return any shape-specific geometry that is not included in presetShapeDefinitions.xml
* (line decorations, etc)
*/
List<Outline> getCustomOutlines(){
return Collections.emptyList();
}
// translate the result to the canvas coordinates in points
AffineTransform at = new AffineTransform();
at.scale(
1.0/Units.EMU_PER_POINT, 1.0/Units.EMU_PER_POINT);
at.translate(Units.toEMU(anchor.getX()), Units.toEMU(anchor.getY()));
return at.createTransformedShape(path);
} else {
return anchor;
}
}
/**
* draw any content within this shape (image, text, etc.).
*
* @param graphics the graphics to draw into
*/
public void drawContent(Graphics2D graphics){
}
} }

+ 48
- 25
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java View File

import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide; import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;
import org.openxmlformats.schemas.presentationml.x2006.main.SldDocument; import org.openxmlformats.schemas.presentationml.x2006.main.SldDocument;


import java.awt.*;
import java.awt.Graphics2D;
import java.io.IOException; import java.io.IOException;


@Beta @Beta
return "sld"; return "sld";
} }


public XSLFSlideMaster getMasterSheet(){
return getSlideLayout().getSlideMaster();
@Override
public XSLFSlideLayout getMasterSheet(){
return getSlideLayout();
} }


@Override
public XSLFSlideLayout getSlideLayout(){ public XSLFSlideLayout getSlideLayout(){
if(_layout == null){ if(_layout == null){
for (POIXMLDocumentPart p : getRelations()) { for (POIXMLDocumentPart p : getRelations()) {
return _layout; return _layout;
} }


@Override
public XSLFSlideMaster getSlideMaster(){ public XSLFSlideMaster getSlideMaster(){
return getSlideLayout().getSlideMaster(); return getSlideLayout().getSlideMaster();
} }
} }
if(_notes == null) { if(_notes == null) {
// This slide lacks notes // This slide lacks notes
// Not al have them, sorry...
// Not all have them, sorry...
return null; return null;
} }
return _notes; return _notes;
} }


public void setFollowMasterBackground(boolean value){
_slide.setShowMasterSp(value);
}

public boolean getFollowMasterBackground(){
return !_slide.isSetShowMasterSp() || _slide.getShowMasterSp();
}

/** /**
* *
* @return title of this slide or empty string if title is not set * @return title of this slide or empty string if title is not set
return txt == null ? "" : txt.getText(); return txt == null ? "" : txt.getText();
} }
@Override
public XSLFTheme getTheme(){ public XSLFTheme getTheme(){
return getSlideLayout().getSlideMaster().getTheme(); return getSlideLayout().getSlideMaster().getTheme();
} }


@Override
public void draw(Graphics2D graphics){

if (getFollowMasterBackground()){
XSLFSlideLayout layout = getSlideLayout();
layout.draw(graphics);
}
/**
*
* @return the information about background appearance of this slide
*/
public XSLFBackground getBackground() {


super.draw(graphics);
}


@Override
public XSLFBackground getBackground(){
if(_slide.getCSld().isSetBg()) { if(_slide.getCSld().isSetBg()) {
return new XSLFBackground(_slide.getCSld().getBg(), this); return new XSLFBackground(_slide.getCSld().getBg(), this);
} }

XSLFSlideLayout layout = getMasterSheet();
if(layout.getXmlObject().getCSld().isSetBg()) {
return new XSLFBackground(layout.getXmlObject().getCSld().getBg(), this);
}

XSLFSlideMaster master = layout.getMasterSheet();
if(master.getXmlObject().getCSld().isSetBg()) {
return new XSLFBackground(master.getXmlObject().getCSld().getBg(), this);
}
return null; return null;
} }


/**
*
* @return whether shapes on the master slide should be shown or not.
*/
public boolean getFollowMasterGraphics(){
return !_slide.isSetShowMasterSp() || _slide.getShowMasterSp();
}

/**
*
* @param value whether shapes on the master slide should be shown or not.
*/
public void setFollowMasterGraphics(boolean value){
_slide.setShowMasterSp(value);
}


@Override
public void draw(Graphics2D graphics){

XSLFBackground bg = getBackground();
if(bg != null) bg.draw(graphics);

super.draw(graphics);
}


} }

+ 56
- 44
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java View File

import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideLayout; import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideLayout;
import org.openxmlformats.schemas.presentationml.x2006.main.SldLayoutDocument; import org.openxmlformats.schemas.presentationml.x2006.main.SldLayoutDocument;
public XSLFSlideLayout(PackagePart part, PackageRelationship rel) throws IOException, XmlException { public XSLFSlideLayout(PackagePart part, PackageRelationship rel) throws IOException, XmlException {
super(part, rel); super(part, rel);
SldLayoutDocument doc = SldLayoutDocument doc =
SldLayoutDocument.Factory.parse(getPackagePart().getInputStream());
SldLayoutDocument.Factory.parse(getPackagePart().getInputStream());
_layout = doc.getSldLayout(); _layout = doc.getSldLayout();
setCommonSlideData(_layout.getCSld()); setCommonSlideData(_layout.getCSld());
} }




public String getName(){
public String getName() {
return _layout.getCSld().getName(); return _layout.getCSld().getName();
} }


} }


@Override @Override
protected String getRootElementName(){
protected String getRootElementName() {
return "sldLayout"; return "sldLayout";
} }


/** /**
* Slide master object associated with this layout. * Slide master object associated with this layout.
* <p>
* Within a slide master slide are contained all elements
* that describe the objects and their corresponding formatting
* for within a presentation slide.
* </p>
* <p>
* Within a slide master slide are two main elements.
* The cSld element specifies the common slide elements such as shapes and
* their attached text bodies. Then the txStyles element specifies the
* formatting for the text within each of these shapes. The other properties
* within a slide master slide specify other properties for within a presentation slide
* such as color information, headers and footers, as well as timing and
* transition information for all corresponding presentation slides.
* </p>
* *
* @return slide master. Never null. * @return slide master. Never null.
* @throws IllegalStateException if slide master was not found * @throws IllegalStateException if slide master was not found
*/ */
@Override
public XSLFSlideMaster getSlideMaster(){
if(_master == null){
public XSLFSlideMaster getSlideMaster() {
if (_master == null) {
for (POIXMLDocumentPart p : getRelations()) { for (POIXMLDocumentPart p : getRelations()) {
if (p instanceof XSLFSlideMaster){
_master = (XSLFSlideMaster)p;
}
}
if (p instanceof XSLFSlideMaster) {
_master = (XSLFSlideMaster) p;
}
}
} }
if(_master == null) {
if (_master == null) {
throw new IllegalStateException("SlideMaster was not found for " + this.toString()); throw new IllegalStateException("SlideMaster was not found for " + this.toString());
} }
return _master; return _master;
} }


public XSLFTheme getTheme(){
return getSlideMaster().getTheme();
}
@Override
public XSLFSlideMaster getMasterSheet() {
return getSlideMaster();
}

@Override
public XSLFTheme getTheme() {
return getSlideMaster().getTheme();
}




@Override @Override
protected CTTextListStyle getTextProperties(Placeholder textType) {
XSLFTextShape lp = getTextShapeByType(textType);
CTTextListStyle props = lp.getTextBody(false).getLstStyle();
return props;
public boolean getFollowMasterGraphics() {
return !_layout.isSetShowMasterSp() || _layout.getShowMasterSp();
} }


/** /**
* Render this sheet into the supplied graphics object * Render this sheet into the supplied graphics object
*
*/ */
@Override @Override
protected boolean canDraw(XSLFShape shape){
if(shape instanceof XSLFSimpleShape){
XSLFSimpleShape txt = (XSLFSimpleShape)shape;
protected boolean canDraw(XSLFShape shape) {
if (shape instanceof XSLFSimpleShape) {
XSLFSimpleShape txt = (XSLFSimpleShape) shape;
CTPlaceholder ph = txt.getCTPlaceholder(); CTPlaceholder ph = txt.getCTPlaceholder();
if(ph != null) {
if (ph != null) {
return false; return false;
} }
} }
return true; return true;
} }


@Override
public XSLFBackground getBackground(){
if(_layout.getCSld().isSetBg()) {
return new XSLFBackground(_layout.getCSld().getBg(), this);
/**
* Copy placeholders from this layout to the destination slide
*
* @param slide destination slide
*/
public void copyLayout(XSLFSlide slide) {
for (XSLFShape sh : getShapes()) {
if (sh instanceof XSLFTextShape) {
XSLFTextShape tsh = (XSLFTextShape) sh;
Placeholder ph = tsh.getTextType();
if (ph == null) continue;

switch (ph) {
// these are special and not copied by default
case DATETIME:
case SLIDE_NUMBER:
case FOOTER:
break;
default:
slide.getSpTree().addNewSp().set(tsh.getXmlObject().copy());
}
}
} }
return getSlideMaster().getBackground();
}

/**
*
* @return type of this layout
*/
public SlideLayout getType(){
int ordinal = _layout.getType().intValue() - 1;
return SlideLayout.values()[ordinal];
} }
} }

+ 44
- 6
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java View File

import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMaster; import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMaster;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMasterTextStyles; import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMasterTextStyles;
import org.openxmlformats.schemas.presentationml.x2006.main.SldMasterDocument; import org.openxmlformats.schemas.presentationml.x2006.main.SldMasterDocument;
return "sldMaster"; return "sldMaster";
} }


public XSLFSlideLayout getLayout(String name){
@Override
public XSLFSheet getMasterSheet() {
return null;
}

private Map<String, XSLFSlideLayout> getLayouts(){
if(_layouts == null){ if(_layouts == null){
_layouts = new HashMap<String, XSLFSlideLayout>(); _layouts = new HashMap<String, XSLFSlideLayout>();
for (POIXMLDocumentPart p : getRelations()) { for (POIXMLDocumentPart p : getRelations()) {
} }
} }
} }
return _layouts.get(name);
return _layouts;
} }


/**
*
* @return all slide layouts referencing this master
*/
public XSLFSlideLayout[] getSlideLayouts() {
return getLayouts().values().toArray(new XSLFSlideLayout[_layouts.size()]);
}

public XSLFSlideLayout getLayout(SlideLayout type){
for(XSLFSlideLayout layout : getLayouts().values()){
if(layout.getType() == type) {
return layout;
}
}
return null;
}

@Override
public XSLFTheme getTheme(){ public XSLFTheme getTheme(){
if(_theme == null){ if(_theme == null){
for (POIXMLDocumentPart p : getRelations()) { for (POIXMLDocumentPart p : getRelations()) {
if (p instanceof XSLFTheme){ if (p instanceof XSLFTheme){
_theme = (XSLFTheme)p; _theme = (XSLFTheme)p;
CTColorMapping cmap = _slide.getClrMap();
if(cmap != null){
_theme.initColorMap(cmap);
}
break; break;
} }
} }
return props; return props;
} }


/**
* Render this sheet into the supplied graphics object
*
*/
@Override @Override
public XSLFBackground getBackground(){
if(_slide.getCSld().isSetBg()) {
return new XSLFBackground(_slide.getCSld().getBg(), this);
protected boolean canDraw(XSLFShape shape){
if(shape instanceof XSLFSimpleShape){
XSLFSimpleShape txt = (XSLFSimpleShape)shape;
CTPlaceholder ph = txt.getCTPlaceholder();
if(ph != null) {
return false;
}
} }
return null;
return true;
} }

} }

+ 5
- 5
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java View File

import org.openxmlformats.schemas.drawingml.x2006.main.STPenAlignment; import org.openxmlformats.schemas.drawingml.x2006.main.STPenAlignment;
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
import java.awt.*;
import java.awt.Color;
/** /**
* Represents a cell of a table in a .pptx presentation * Represents a cell of a table in a .pptx presentation
} }
@Override @Override
public void setMarginLeft(double margin){
public void setLeftInset(double margin){
CTTableCellProperties pr = getXmlObject().getTcPr(); CTTableCellProperties pr = getXmlObject().getTcPr();
if(pr == null) pr = getXmlObject().addNewTcPr(); if(pr == null) pr = getXmlObject().addNewTcPr();
} }
@Override @Override
public void setMarginRight(double margin){
public void setRightInset(double margin){
CTTableCellProperties pr = getXmlObject().getTcPr(); CTTableCellProperties pr = getXmlObject().getTcPr();
if(pr == null) pr = getXmlObject().addNewTcPr(); if(pr == null) pr = getXmlObject().addNewTcPr();
} }
@Override @Override
public void setMarginTop(double margin){
public void setTopInset(double margin){
CTTableCellProperties pr = getXmlObject().getTcPr(); CTTableCellProperties pr = getXmlObject().getTcPr();
if(pr == null) pr = getXmlObject().addNewTcPr(); if(pr == null) pr = getXmlObject().addNewTcPr();
} }
@Override @Override
public void setMarginBottom(double margin){
public void setBottomInset(double margin){
CTTableCellProperties pr = getXmlObject().getTcPr(); CTTableCellProperties pr = getXmlObject().getTcPr();
if(pr == null) pr = getXmlObject().addNewTcPr(); if(pr == null) pr = getXmlObject().addNewTcPr();

+ 0
- 19
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java View File

return ct; return ct;
} }
/**
* Specifies that the corresponding shape should be represented by the generating application
* as a placeholder. When a shape is considered a placeholder by the generating application
* it can have special properties to alert the user that they may enter content into the shape.
* Different types of placeholders are allowed and can be specified by using the placeholder
* type attribute for this element
*
* @param placeholder
*/
public void setPlaceholder(Placeholder placeholder){
CTShape sh = (CTShape)getXmlObject();
CTApplicationNonVisualDrawingProps nv = sh.getNvSpPr().getNvPr();
if(placeholder == null) {
if(nv.isSetPh()) nv.unsetPh();
} else {
nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ordinal() + 1));
}
}
} }

+ 51
- 14
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java View File

import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
import java.awt.*;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.font.LineBreakMeasurer; import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute; import java.awt.font.TextAttribute;
import java.awt.font.TextLayout; import java.awt.font.TextLayout;
return out.toString(); return out.toString();
} }
private String getVisibleText(){
StringBuilder out = new StringBuilder();
for (XSLFTextRun r : _runs) {
String txt = r.getText();
switch (r.getTextCap()){
case ALL:
txt = txt.toUpperCase();
break;
case SMALL:
txt = txt.toLowerCase();
break;
}
out.append(txt);
}
return out.toString();
}
@Internal @Internal
public CTTextParagraph getXmlObject(){ public CTTextParagraph getXmlObject(){
return _p; return _p;
return _shape; return _shape;
} }
public List<XSLFTextRun> getTextRuns(){ public List<XSLFTextRun> getTextRuns(){
return _runs; return _runs;
} }
ParagraphPropertyFetcher<Color> fetcher = new ParagraphPropertyFetcher<Color>(getLevel()){ ParagraphPropertyFetcher<Color> fetcher = new ParagraphPropertyFetcher<Color>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){ public boolean fetch(CTTextParagraphProperties props){
if(props.isSetBuClr()){ if(props.isSetBuClr()){
XSLFColor c = new XSLFColor(props.getBuClr(), theme);
XSLFColor c = new XSLFColor(props.getBuClr(), theme, null);
setValue(c.getColor()); setValue(c.getColor());
return true; return true;
} }
return "[" + getClass() + "]" + getText(); return "[" + getClass() + "]" + getText();
} }
public List<TextFragment> getTextLines(){
List<TextFragment> getTextLines(){
return _lines; return _lines;
} }
public double draw(Graphics2D graphics, double x, double y){ public double draw(Graphics2D graphics, double x, double y){
double marginLeft = _shape.getMarginLeft();
double marginRight = _shape.getMarginRight();
double marginLeft = _shape.getLeftInset();
double marginRight = _shape.getRightInset();
Rectangle2D anchor = _shape.getAnchor(); Rectangle2D anchor = _shape.getAnchor();
double penY = y; double penY = y;
double textOffset = getLeftMargin(); double textOffset = getLeftMargin();
boolean firstLine = true;
for(TextFragment line : _lines){ for(TextFragment line : _lines){
double penX = x; double penX = x;
switch (getTextAlign()) { switch (getTextAlign()) {
break; break;
} }
if(_bullet != null){
if(_bullet != null && firstLine){
_bullet.draw(graphics, penX + getIndent(), penY); _bullet.draw(graphics, penX + getIndent(), penY);
} }
line.draw(graphics, penX, penY); line.draw(graphics, penX, penY);
// positive value means absolute spacing in points // positive value means absolute spacing in points
penY += -spacing; penY += -spacing;
} }
firstLine = false;
} }
return penY - y; return penY - y;
} }
void draw(Graphics2D graphics, double x, double y){ void draw(Graphics2D graphics, double x, double y){
double yBaseline = y + _layout.getAscent(); double yBaseline = y + _layout.getAscent();
graphics.drawString(_str.getIterator(), (float)x, (float)yBaseline );
Integer textMode = (Integer)graphics.getRenderingHint(XSLFRenderingHint.TEXT_RENDERING_MODE);
if(textMode != null && textMode == XSLFRenderingHint.TEXT_MODE_GLYPHS){
_layout.draw(graphics, (float)x, (float)yBaseline);
} else {
graphics.drawString(_str.getIterator(), (float)x, (float)yBaseline );
}
} }
public float getHeight(){ public float getHeight(){
} }
public AttributedString getAttributedString(){
String text = getText();
AttributedString getAttributedString(Graphics2D graphics){
String text = getVisibleText();
AttributedString string = new AttributedString(text); AttributedString string = new AttributedString(text);
int endIndex = startIndex + length; int endIndex = startIndex + length;
string.addAttribute(TextAttribute.FOREGROUND, run.getFontColor(), startIndex, endIndex); string.addAttribute(TextAttribute.FOREGROUND, run.getFontColor(), startIndex, endIndex);
// user can pass an object to convert fonts via a rendering hint
string.addAttribute(TextAttribute.FAMILY, run.getFontFamily(), startIndex, endIndex); string.addAttribute(TextAttribute.FAMILY, run.getFontFamily(), startIndex, endIndex);
string.addAttribute(TextAttribute.SIZE, (float)run.getFontSize(), startIndex, endIndex); string.addAttribute(TextAttribute.SIZE, (float)run.getFontSize(), startIndex, endIndex);
if(run.isBold()) { if(run.isBold()) {
string.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, startIndex, endIndex); string.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, startIndex, endIndex);
string.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, startIndex, endIndex); string.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, startIndex, endIndex);
} }
startIndex = endIndex; startIndex = endIndex;
} }
void breakText(Graphics2D graphics){ void breakText(Graphics2D graphics){
_lines = new ArrayList<TextFragment>(); _lines = new ArrayList<TextFragment>();
AttributedString at = getAttributedString();
AttributedString at = getAttributedString(graphics);
AttributedCharacterIterator it = at.getIterator(); AttributedCharacterIterator it = at.getIterator();
if(it.getBeginIndex() == it.getEndIndex()) { if(it.getBeginIndex() == it.getEndIndex()) {
return; return;
int endIndex = measurer.getPosition(); int endIndex = measurer.getPosition();
if(getTextAlign() == TextAlign.JUSTIFY) {
TextAlign hAlign = getTextAlign();
if(hAlign == TextAlign.JUSTIFY || hAlign == TextAlign.JUSTIFY_LOW) {
layout = layout.getJustifiedLayout((float)wrappingWidth); layout = layout.getJustifiedLayout((float)wrappingWidth);
} }
width = _shape.getSheet().getSlideShow().getPageSize().getWidth(); width = _shape.getSheet().getSlideShow().getPageSize().getWidth();
} else { } else {
width = _shape.getAnchor().getWidth() - width = _shape.getAnchor().getWidth() -
_shape.getMarginLeft() - _shape.getMarginRight() - getLeftMargin();
_shape.getLeftInset() - _shape.getRightInset() - getLeftMargin();
} }
return width; return width;
} }
} }
int level = getLevel(); int level = getLevel();
XmlObject[] o = _shape.getSheet().getSlideMaster().getXmlObject().selectPath(
XSLFSheet masterSheet = _shape.getSheet();
while (masterSheet.getMasterSheet() != null){
masterSheet = masterSheet.getMasterSheet();
}
XmlObject[] o = masterSheet.getXmlObject().selectPath(
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " +
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " + "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " +
".//p:txStyles/p:" + defaultStyleSelector +"/a:lvl" +(level+1)+ "pPr"); ".//p:txStyles/p:" + defaultStyleSelector +"/a:lvl" +(level+1)+ "pPr");

+ 51
- 4
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java View File

import org.apache.poi.xslf.model.CharacterPropertyFetcher; import org.apache.poi.xslf.model.CharacterPropertyFetcher;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;
import java.awt.*;
import java.awt.Color;
/** /**
* Represents a run of text within the containing text body. The run element is the * Represents a run of text within the containing text body. The run element is the
public Color getFontColor(){ public Color getFontColor(){
final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); final XSLFTheme theme = _p.getParentShape().getSheet().getTheme();
CTShapeStyle style = _p.getParentShape().getSpStyle();
final CTSchemeColor shapeStyle = style == null ? null : style.getFontRef().getSchemeClr();
CharacterPropertyFetcher<Color> fetcher = new CharacterPropertyFetcher<Color>(_p.getLevel()){ CharacterPropertyFetcher<Color> fetcher = new CharacterPropertyFetcher<Color>(_p.getLevel()){
public boolean fetch(CTTextCharacterProperties props){ public boolean fetch(CTTextCharacterProperties props){
CTSolidColorFillProperties solidFill = props.getSolidFill(); CTSolidColorFillProperties solidFill = props.getSolidFill();
if(solidFill != null){
Color c = new XSLFColor(solidFill, theme).getColor();
if(solidFill != null) {
Color c = new XSLFColor(solidFill, theme, shapeStyle).getColor();
setValue(c); setValue(c);
return true; return true;
} }
* @return font size in points or -1 if font size is not set. * @return font size in points or -1 if font size is not set.
*/ */
public double getFontSize(){ public double getFontSize(){
double scale = 1;
CTTextNormalAutofit afit = getParentParagraph().getParentShape().getTextBodyPr().getNormAutofit();
if(afit != null) scale = (double)afit.getFontScale() / 100000;
CharacterPropertyFetcher<Double> fetcher = new CharacterPropertyFetcher<Double>(_p.getLevel()){ CharacterPropertyFetcher<Double> fetcher = new CharacterPropertyFetcher<Double>(_p.getLevel()){
public boolean fetch(CTTextCharacterProperties props){ public boolean fetch(CTTextCharacterProperties props){
if(props.isSetSz()){ if(props.isSetSz()){
} }
}; };
fetchCharacterProperty(fetcher); fetchCharacterProperty(fetcher);
return fetcher.getValue() == null ? -1 : fetcher.getValue();
return fetcher.getValue() == null ? -1 : fetcher.getValue()*scale;
}
/**
*
* @return the spacing between characters within a text run,
* If this attribute is omitted than a value of 0 or no adjustment is assumed.
*/
public double getCharacterSpacing(){
CharacterPropertyFetcher<Double> fetcher = new CharacterPropertyFetcher<Double>(_p.getLevel()){
public boolean fetch(CTTextCharacterProperties props){
if(props.isSetSpc()){
setValue(props.getSpc()*0.01);
return true;
}
return false;
}
};
fetchCharacterProperty(fetcher);
return fetcher.getValue() == null ? 0 : fetcher.getValue();
} }
/** /**
return fetcher.getValue() == null ? false : fetcher.getValue(); return fetcher.getValue() == null ? false : fetcher.getValue();
} }
/**
* @return whether a run of text will be formatted as a superscript text. Default is false.
*/
public TextCap getTextCap() {
CharacterPropertyFetcher<TextCap> fetcher = new CharacterPropertyFetcher<TextCap>(_p.getLevel()){
public boolean fetch(CTTextCharacterProperties props){
if(props.isSetCap()){
int idx = props.getCap().intValue() - 1;
setValue(TextCap.values()[idx]);
return true;
}
return false;
}
};
fetchCharacterProperty(fetcher);
return fetcher.getValue() == null ? TextCap.NONE : fetcher.getValue();
}
/** /**
* Specifies whether this run of text will be formatted as bold text * Specifies whether this run of text will be formatted as bold text
* *

+ 90
- 62
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java View File

import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;


import java.awt.*;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;


/** /**
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
@Beta @Beta
public abstract class XSLFTextShape extends XSLFSimpleShape {
public abstract class XSLFTextShape extends XSLFSimpleShape implements Iterable<XSLFTextParagraph>{
private final List<XSLFTextParagraph> _paragraphs; private final List<XSLFTextParagraph> _paragraphs;


/*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) { /*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) {
} }
} }


// textual properties
public Iterator<XSLFTextParagraph> iterator(){
return _paragraphs.iterator();
}

/**
*
* @return text contained within this shape or empty string
*/
public String getText() { public String getText() {
StringBuilder out = new StringBuilder(); StringBuilder out = new StringBuilder();
for (XSLFTextParagraph p : _paragraphs) { for (XSLFTextParagraph p : _paragraphs) {
return out.toString(); return out.toString();
} }


/**
* unset text from this shape
*/
public void clearText(){
_paragraphs.clear();
CTTextBody txBody = getTextBody(true);
txBody.setPArray(null); // remove any existing paragraphs
}

public void setText(String text){
clearText();

addNewTextParagraph().addNewTextRun().setText(text);
}

/**
*
* @return text paragraphs in this shape
*/
public List<XSLFTextParagraph> getTextParagraphs() { public List<XSLFTextParagraph> getTextParagraphs() {
return _paragraphs; return _paragraphs;
} }


/**
* add a new paragraph run to this shape
*
* @return created paragraph run
*/
public XSLFTextParagraph addNewTextParagraph() { public XSLFTextParagraph addNewTextParagraph() {
CTTextBody txBody = getTextBody(true); CTTextBody txBody = getTextBody(true);
CTTextParagraph p = txBody.addNewP(); CTTextParagraph p = txBody.addNewP();


/** /**
* Sets the type of vertical alignment for the text. * Sets the type of vertical alignment for the text.
* One of the <code>Anchor*</code> constants defined in this class.
* *
* @param anchor - the type of alignment. Default is {@link org.apache.poi.xslf.usermodel.VerticalAlignment#TOP}
* @param anchor - the type of alignment.
* A <code>null</code> values unsets this property.
*/ */
public void setVerticalAlignment(VerticalAlignment anchor){ public void setVerticalAlignment(VerticalAlignment anchor){
CTTextBodyProperties bodyPr = getTextBodyPr(); CTTextBodyProperties bodyPr = getTextBodyPr();
/** /**
* Returns the type of vertical alignment for the text. * Returns the type of vertical alignment for the text.
* *
* @return the type of alignment
* @return the type of vertical alignment
*/ */
public VerticalAlignment getVerticalAlignment(){ public VerticalAlignment getVerticalAlignment(){
PropertyFetcher<VerticalAlignment> fetcher = new TextBodyPropertyFetcher<VerticalAlignment>(){ PropertyFetcher<VerticalAlignment> fetcher = new TextBodyPropertyFetcher<VerticalAlignment>(){
} }
return TextDirection.HORIZONTAL; return TextDirection.HORIZONTAL;
} }


/** /**
* Returns the distance (in points) between the bottom of the text frame * Returns the distance (in points) between the bottom of the text frame
* and the bottom of the inscribed rectangle of the shape that contains the text. * and the bottom of the inscribed rectangle of the shape that contains the text.
* *
* @return the bottom margin or -1 if not set
* @return the bottom inset in points
*/ */
public double getMarginBottom(){
public double getBottomInset(){
PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){ PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){
public boolean fetch(CTTextBodyProperties props){ public boolean fetch(CTTextBodyProperties props){
if(props.isSetBIns()){ if(props.isSetBIns()){
* and the left edge of the inscribed rectangle of the shape that contains * and the left edge of the inscribed rectangle of the shape that contains
* the text. * the text.
* *
* @return the left margin
* @return the left inset in points
*/ */
public double getMarginLeft(){
public double getLeftInset(){
PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){ PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){
public boolean fetch(CTTextBodyProperties props){ public boolean fetch(CTTextBodyProperties props){
if(props.isSetLIns()){ if(props.isSetLIns()){
* text frame and the right edge of the inscribed rectangle of the shape * text frame and the right edge of the inscribed rectangle of the shape
* that contains the text. * that contains the text.
* *
* @return the right margin
* @return the right inset in points
*/ */
public double getMarginRight(){
public double getRightInset(){
PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){ PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){
public boolean fetch(CTTextBodyProperties props){ public boolean fetch(CTTextBodyProperties props){
if(props.isSetRIns()){ if(props.isSetRIns()){
* Returns the distance (in points) between the top of the text frame * Returns the distance (in points) between the top of the text frame
* and the top of the inscribed rectangle of the shape that contains the text. * and the top of the inscribed rectangle of the shape that contains the text.
* *
* @return the top margin
* @return the top inset in points
*/ */
public double getMarginTop(){
public double getTopInset(){
PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){ PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){
public boolean fetch(CTTextBodyProperties props){ public boolean fetch(CTTextBodyProperties props){
if(props.isSetTIns()){ if(props.isSetTIns()){


/** /**
* Sets the botom margin. * Sets the botom margin.
* @see #getMarginBottom()
* @see #getBottomInset()
* *
* @param margin the bottom margin * @param margin the bottom margin
*/ */
public void setMarginBottom(double margin){
public void setBottomInset(double margin){
CTTextBodyProperties bodyPr = getTextBodyPr(); CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) { if (bodyPr != null) {
if(margin == -1) bodyPr.unsetBIns(); if(margin == -1) bodyPr.unsetBIns();


/** /**
* Sets the left margin. * Sets the left margin.
* @see #getMarginLeft()
* @see #getLeftInset()
* *
* @param margin the left margin * @param margin the left margin
*/ */
public void setMarginLeft(double margin){
public void setLeftInset(double margin){
CTTextBodyProperties bodyPr = getTextBodyPr(); CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) { if (bodyPr != null) {
if(margin == -1) bodyPr.unsetLIns(); if(margin == -1) bodyPr.unsetLIns();


/** /**
* Sets the right margin. * Sets the right margin.
* @see #getMarginRight()
* @see #getRightInset()
* *
* @param margin the right margin * @param margin the right margin
*/ */
public void setMarginRight(double margin){
public void setRightInset(double margin){
CTTextBodyProperties bodyPr = getTextBodyPr(); CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) { if (bodyPr != null) {
if(margin == -1) bodyPr.unsetRIns(); if(margin == -1) bodyPr.unsetRIns();


/** /**
* Sets the top margin. * Sets the top margin.
* @see #getMarginTop()
* @see #getTopInset()
* *
* @param margin the top margin * @param margin the top margin
*/ */
public void setMarginTop(double margin){
public void setTopInset(double margin){
CTTextBodyProperties bodyPr = getTextBodyPr(); CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) { if (bodyPr != null) {
if(margin == -1) bodyPr.unsetTIns(); if(margin == -1) bodyPr.unsetTIns();




/** /**
* Returns the value indicating word wrap.
* One of the <code>Wrap*</code> constants defined in this class.
*
* @return the value indicating word wrap
* @return whether to wrap words within the bounding rectangle
*/ */
public boolean getWordWrap(){ public boolean getWordWrap(){
PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>(){ PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>(){
} }


/** /**
* Specifies how the text should be wrapped
* *
* @param wrap the value indicating how the text should be wrapped
* @param wrap whether to wrap words within the bounding rectangle
*/ */
public void setWordWrap(boolean wrap){ public void setWordWrap(boolean wrap){
CTTextBodyProperties bodyPr = getTextBodyPr(); CTTextBodyProperties bodyPr = getTextBodyPr();
} }
} }


@Override
public void draw(Graphics2D graphics){
java.awt.Shape outline = getOutline();

// shadow
XSLFShadow shadow = getShadow();

Paint fill = getFill(graphics);
Paint line = getLinePaint(graphics);
if(shadow != null) {
shadow.draw(graphics);
}

if(fill != null) {
graphics.setPaint(fill);
graphics.fill(outline);
}


if (line != null){
graphics.setPaint(line);
applyStroke(graphics);
graphics.draw(outline);
/**
* Specifies that the corresponding shape should be represented by the generating application
* as a placeholder. When a shape is considered a placeholder by the generating application
* it can have special properties to alert the user that they may enter content into the shape.
* Different types of placeholders are allowed and can be specified by using the placeholder
* type attribute for this element
*
* @param placeholder
*/
public void setPlaceholder(Placeholder placeholder){
CTShape sh = (CTShape)getXmlObject();
CTApplicationNonVisualDrawingProps nv = sh.getNvSpPr().getNvPr();
if(placeholder == null) {
if(nv.isSetPh()) nv.unsetPh();
} else {
nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ordinal() + 1));
} }

// text
if(getText().length() > 0) drawText(graphics);
}
}


/** /**
* Compute the cumulative height occupied by the text * Compute the cumulative height occupied by the text
return drawParagraphs(img.createGraphics(), 0, 0); return drawParagraphs(img.createGraphics(), 0, 0);
} }


void breakText(Graphics2D graphics){
/**
* break the contained text into lines
*/
private void breakText(Graphics2D graphics){
for(XSLFTextParagraph p : _paragraphs) p.breakText(graphics); for(XSLFTextParagraph p : _paragraphs) p.breakText(graphics);
} }


public void drawText(Graphics2D graphics) {
@Override
public void drawContent(Graphics2D graphics) {
breakText(graphics); breakText(graphics);


Rectangle2D anchor = getAnchor(); Rectangle2D anchor = getAnchor();
double x = anchor.getX() + getMarginLeft();
double x = anchor.getX() + getLeftInset();
double y = anchor.getY(); double y = anchor.getY();


// first dry-run to calculate the total height of the text // first dry-run to calculate the total height of the text


switch (getVerticalAlignment()){ switch (getVerticalAlignment()){
case TOP: case TOP:
y += getMarginTop();
y += getTopInset();
break; break;
case BOTTOM: case BOTTOM:
y += anchor.getHeight() - textHeight - getMarginBottom();
y += anchor.getHeight() - textHeight - getBottomInset();
break; break;
default: default:
case MIDDLE: case MIDDLE:
double delta = anchor.getHeight() - textHeight - double delta = anchor.getHeight() - textHeight -
getMarginTop() - getMarginBottom();
y += getMarginTop() + delta/2;
getTopInset() - getBottomInset();
y += getTopInset() + delta/2;
break; break;
} }


drawParagraphs(graphics, x, y); drawParagraphs(graphics, x, y);

} }




double y0 = y; double y0 = y;
for(int i = 0; i < _paragraphs.size(); i++){ for(int i = 0; i < _paragraphs.size(); i++){
XSLFTextParagraph p = _paragraphs.get(i); XSLFTextParagraph p = _paragraphs.get(i);
java.util.List<XSLFTextParagraph.TextFragment> lines = p.getTextLines();
List<XSLFTextParagraph.TextFragment> lines = p.getTextLines();


if(i > 0 && lines.size() > 0) { if(i > 0 && lines.size() > 0) {
// the amount of vertical white space before the paragraph // the amount of vertical white space before the paragraph

+ 36
- 4
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTheme.java View File

import org.apache.xmlbeans.XmlOptions; import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBaseStyles; import org.openxmlformats.schemas.drawingml.x2006.main.CTBaseStyles;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorScheme; import org.openxmlformats.schemas.drawingml.x2006.main.CTColorScheme;
import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeStyleSheet; import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeStyleSheet;
import org.openxmlformats.schemas.drawingml.x2006.main.ThemeDocument; import org.openxmlformats.schemas.drawingml.x2006.main.ThemeDocument;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;


/**
* A shared style sheet in a .pptx slide show
*
* @author Yegor Kozlov
*/
@Beta @Beta
public class XSLFTheme extends POIXMLDocumentPart { public class XSLFTheme extends POIXMLDocumentPart {
private CTOfficeStyleSheet _theme; private CTOfficeStyleSheet _theme;
String name = c.getDomNode().getLocalName(); String name = c.getDomNode().getLocalName();
_schemeColors.put(name, c); _schemeColors.put(name, c);
} }
}


_schemeColors.put("bg1", _schemeColors.get("lt1"));
_schemeColors.put("bg2", _schemeColors.get("lt2"));
_schemeColors.put("tx1", _schemeColors.get("dk1"));
_schemeColors.put("tx2", _schemeColors.get("dk2"));
/**
* re-map colors
*
* @param cmap color map defined in the master slide referencing this theme
*/
void initColorMap(CTColorMapping cmap) {
_schemeColors.put("bg1", _schemeColors.get(cmap.getBg1().toString()));
_schemeColors.put("bg2", _schemeColors.get(cmap.getBg2().toString()));
_schemeColors.put("tx1", _schemeColors.get(cmap.getTx1().toString()));
_schemeColors.put("tx2", _schemeColors.get(cmap.getTx2().toString()));
} }


/**
*
* @return name of this theme, e.g. "Office Theme"
*/
public String getName(){ public String getName(){
return _theme.getName(); return _theme.getName();
} }


/**
* Set name of this theme
*
* @param name name of this theme
*/
public void setName(String name){ public void setName(String name){
_theme.setName(name); _theme.setName(name);
} }
out.close(); out.close();
} }


/**
* @return typeface of the major font to use in a document.
* Typically the major font is used for heading areas of a document.
*
*/
public String getMajorFont(){ public String getMajorFont(){
return _theme.getThemeElements().getFontScheme().getMajorFont().getLatin().getTypeface(); return _theme.getThemeElements().getFontScheme().getMajorFont().getLatin().getTypeface();
} }


/**
* @return typeface of the minor font to use in a document.
* Typically the monor font is used for normal text or paragraph areas.
*
*/
public String getMinorFont(){ public String getMinorFont(){
return _theme.getThemeElements().getFontScheme().getMinorFont().getLatin().getTypeface(); return _theme.getThemeElements().getFontScheme().getMinorFont().getLatin().getTypeface();
} }

+ 23
- 9
src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java View File

import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
/** /**
* Date: 10/11/11
* An utulity to convert slides of a .pptx slide show to a PNG image
* *
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
public class PPTX2PNG { public class PPTX2PNG {
static void usage(){
System.out.println("Usage: PPTX2PNG [options] <pptx file>");
System.out.println("Options:");
System.out.println(" -scale <float> scale factor");
System.out.println(" -slide <integer> 1-based index of a slide to render");
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
if (args.length == 0) { if (args.length == 0) {
System.out.println("Usage: PPTX2PNG [options] <pptx file>");
usage();
return; return;
} }
} }
} }
if(file == null){
usage();
return;
}
System.out.println("Processing " + file); System.out.println("Processing " + file);
XMLSlideShow ppt = new XMLSlideShow(OPCPackage.open(file)); XMLSlideShow ppt = new XMLSlideShow(OPCPackage.open(file));
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = img.createGraphics(); Graphics2D graphics = img.createGraphics();
// default rendering options
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
graphics.setPaint(Color.white);
graphics.fill(new Rectangle2D.Float(0, 0, width, height));
graphics.setColor(Color.white);
graphics.clearRect(0, 0, width, height);
graphics.scale((double) width / pgsize.width, (double) height / pgsize.height);
graphics.scale(scale, scale);
// draw stuff
slide[i].draw(graphics); slide[i].draw(graphics);
String fname = file.replaceAll("\\.pptx", "-" + (i + 1) + ".png");
// save the result
int sep = file.lastIndexOf(".");
String fname = file.substring(0, sep == -1 ? file.length() : sep) + "-" + (i + 1) +".png";
FileOutputStream out = new FileOutputStream(fname); FileOutputStream out = new FileOutputStream(fname);
ImageIO.write(img, "png", out); ImageIO.write(img, "png", out);
out.close(); out.close();

+ 1
- 1
src/ooxml/testcases/org/apache/poi/xslf/geom/TestFormulaParser.java View File

}; };


CustomGeometry geom = new CustomGeometry(CTCustomGeometry2D.Factory.newInstance()); CustomGeometry geom = new CustomGeometry(CTCustomGeometry2D.Factory.newInstance());
Context ctx = new Context(geom, null);
Context ctx = new Context(geom, null, null);
for(Formula fmla : ops) { for(Formula fmla : ops) {
ctx.evaluate(fmla); ctx.evaluate(fmla);
} }

+ 1
- 5
src/ooxml/testcases/org/apache/poi/xslf/geom/TestPresetGeometries.java View File



for(String name : shapes.keySet()) { for(String name : shapes.keySet()) {
CustomGeometry geom = shapes.get(name); CustomGeometry geom = shapes.get(name);
Context ctx = new Context(geom, new IAdjustableShape() {
public Rectangle2D getAnchor() {
return new Rectangle2D.Double(0, 0, 100, 100);
}

Context ctx = new Context(geom, new Rectangle2D.Double(0, 0, 100, 100), new IAdjustableShape() {
public Guide getAdjustValue(String name) { public Guide getAdjustValue(String name) {
return null; return null;
} }

+ 1
- 1
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java View File

public class TestPPTX2PNG extends TestCase { public class TestPPTX2PNG extends TestCase {
public void testRender(){ public void testRender(){
String[] testFiles = {"layouts.pptx", "sample.pptx", "shapes.pptx", String[] testFiles = {"layouts.pptx", "sample.pptx", "shapes.pptx",
"45541_Header.pptx", "backgrounds.pptx"};
"themes.pptx", "backgrounds.pptx"};
for(String sampleFile : testFiles){ for(String sampleFile : testFiles){
XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument(sampleFile); XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument(sampleFile);
Dimension pg = pptx.getPageSize(); Dimension pg = pptx.getPageSize();

+ 30
- 30
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java View File

shape.addNewTextParagraph().addNewTextRun().setText("POI"); shape.addNewTextParagraph().addNewTextRun().setText("POI");
// default margins from slide master // default margins from slide master
assertEquals(3.6, shape.getMarginBottom());
assertEquals(3.6, shape.getMarginTop());
assertEquals(7.2, shape.getMarginLeft());
assertEquals(7.2, shape.getMarginRight());
shape.setMarginBottom(1.0);
assertEquals(1.0, shape.getMarginBottom());
shape.setMarginTop(2.0);
assertEquals(2.0, shape.getMarginTop());
shape.setMarginLeft(3.0);
assertEquals(3.0, shape.getMarginLeft());
shape.setMarginRight(4.0);
assertEquals(4.0, shape.getMarginRight());
shape.setMarginBottom(0.0);
assertEquals(0.0, shape.getMarginBottom());
shape.setMarginTop(0.0);
assertEquals(0.0, shape.getMarginTop());
shape.setMarginLeft(0.0);
assertEquals(0.0, shape.getMarginLeft());
shape.setMarginRight(0.0);
assertEquals(0.0, shape.getMarginRight());
assertEquals(3.6, shape.getBottomInset());
assertEquals(3.6, shape.getTopInset());
assertEquals(7.2, shape.getLeftInset());
assertEquals(7.2, shape.getRightInset());
shape.setBottomInset(1.0);
assertEquals(1.0, shape.getBottomInset());
shape.setTopInset(2.0);
assertEquals(2.0, shape.getTopInset());
shape.setLeftInset(3.0);
assertEquals(3.0, shape.getLeftInset());
shape.setRightInset(4.0);
assertEquals(4.0, shape.getRightInset());
shape.setBottomInset(0.0);
assertEquals(0.0, shape.getBottomInset());
shape.setTopInset(0.0);
assertEquals(0.0, shape.getTopInset());
shape.setLeftInset(0.0);
assertEquals(0.0, shape.getLeftInset());
shape.setRightInset(0.0);
assertEquals(0.0, shape.getRightInset());
// unset to defauls // unset to defauls
shape.setMarginBottom(-1);
assertEquals(3.6, shape.getMarginBottom());
shape.setMarginTop(-1);
assertEquals(3.6, shape.getMarginTop());
shape.setMarginLeft(-1);
assertEquals(7.2, shape.getMarginLeft());
shape.setMarginRight(-1);
assertEquals(7.2, shape.getMarginRight());
shape.setBottomInset(-1);
assertEquals(3.6, shape.getBottomInset());
shape.setTopInset(-1);
assertEquals(3.6, shape.getTopInset());
shape.setLeftInset(-1);
assertEquals(7.2, shape.getLeftInset());
shape.setRightInset(-1);
assertEquals(7.2, shape.getRightInset());
// shape // shape
assertTrue(shape.getWordWrap()); assertTrue(shape.getWordWrap());

+ 8
- 8
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFColor.java View File

CTSRgbColor c = xml.addNewSrgbClr(); CTSRgbColor c = xml.addNewSrgbClr();
c.setVal(new byte[]{(byte)0xFF, 0, 0}); c.setVal(new byte[]{(byte)0xFF, 0, 0});
XSLFColor color = new XSLFColor(xml, null);
XSLFColor color = new XSLFColor(xml, null, null);
assertEquals(-1, color.getAlpha()); assertEquals(-1, color.getAlpha());
c.addNewAlpha().setVal(50000); c.addNewAlpha().setVal(50000);
c.setSat2(100000); c.setSat2(100000);
c.setLum2(50000); c.setLum2(50000);
XSLFColor color = new XSLFColor(xml, null);
XSLFColor color = new XSLFColor(xml, null, null);
assertEquals(new Color(128, 00, 00), color.getColor()); assertEquals(new Color(128, 00, 00), color.getColor());
} }
CTColor xml = CTColor.Factory.newInstance(); CTColor xml = CTColor.Factory.newInstance();
xml.addNewSrgbClr().setVal(new byte[]{ (byte)0xFF, (byte)0xFF, 0}); xml.addNewSrgbClr().setVal(new byte[]{ (byte)0xFF, (byte)0xFF, 0});
XSLFColor color = new XSLFColor(xml, null);
XSLFColor color = new XSLFColor(xml, null, null);
assertEquals(new Color(0xFF, 0xFF, 0), color.getColor()); assertEquals(new Color(0xFF, 0xFF, 0), color.getColor());
} }
CTColor xml = CTColor.Factory.newInstance(); CTColor xml = CTColor.Factory.newInstance();
xml.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_2); xml.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_2);
XSLFColor color = new XSLFColor(xml, theme);
XSLFColor color = new XSLFColor(xml, theme, null);
// accent2 is theme1.xml is <a:srgbClr val="C0504D"/> // accent2 is theme1.xml is <a:srgbClr val="C0504D"/>
assertEquals(Color.decode("0xC0504D"), color.getColor()); assertEquals(Color.decode("0xC0504D"), color.getColor());
xml = CTColor.Factory.newInstance(); xml = CTColor.Factory.newInstance();
xml.addNewSchemeClr().setVal(STSchemeColorVal.LT_1); xml.addNewSchemeClr().setVal(STSchemeColorVal.LT_1);
color = new XSLFColor(xml, theme);
color = new XSLFColor(xml, theme, null);
// <a:sysClr val="window" lastClr="FFFFFF"/> // <a:sysClr val="window" lastClr="FFFFFF"/>
assertEquals(Color.decode("0xFFFFFF"), color.getColor()); assertEquals(Color.decode("0xFFFFFF"), color.getColor());
xml = CTColor.Factory.newInstance(); xml = CTColor.Factory.newInstance();
xml.addNewSchemeClr().setVal(STSchemeColorVal.DK_1); xml.addNewSchemeClr().setVal(STSchemeColorVal.DK_1);
color = new XSLFColor(xml, theme);
color = new XSLFColor(xml, theme, null);
// <a:sysClr val="windowText" lastClr="000000"/> // <a:sysClr val="windowText" lastClr="000000"/>
assertEquals(Color.decode("0x000000"), color.getColor()); assertEquals(Color.decode("0x000000"), color.getColor());
} }
public void testPresetColor() { public void testPresetColor() {
CTColor xml = CTColor.Factory.newInstance(); CTColor xml = CTColor.Factory.newInstance();
xml.addNewPrstClr().setVal(STPresetColorVal.AQUAMARINE); xml.addNewPrstClr().setVal(STPresetColorVal.AQUAMARINE);
XSLFColor color = new XSLFColor(xml, null);
XSLFColor color = new XSLFColor(xml, null, null);
assertEquals(new Color(127, 255, 212), color.getColor()); assertEquals(new Color(127, 255, 212), color.getColor());
STPresetColorVal.Enum val = STPresetColorVal.Enum.forString(colorName); STPresetColorVal.Enum val = STPresetColorVal.Enum.forString(colorName);
assertNotNull(colorName, val); assertNotNull(colorName, val);
xml.addNewPrstClr().setVal(val); xml.addNewPrstClr().setVal(val);
color = new XSLFColor(xml, null);
color = new XSLFColor(xml, null, null);
assertEquals(XSLFColor.presetColors.get(colorName), color.getColor()); assertEquals(XSLFColor.presetColors.get(colorName), color.getColor());
} }
} }

+ 5
- 8
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java View File

import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.xslf.XSLFTestDataSamples; import org.apache.poi.xslf.XSLFTestDataSamples;
import org.apache.poi.POIXMLDocumentPart;
import java.util.List;
/** /**
* @author Yegor Kozlov * @author Yegor Kozlov
assertEquals(0, ppt.getSlides().length); assertEquals(0, ppt.getSlides().length);
XSLFSlide slide = ppt.createSlide(); XSLFSlide slide = ppt.createSlide();
assertTrue(slide.getFollowMasterBackground());
slide.setFollowMasterBackground(false);
assertFalse(slide.getFollowMasterBackground());
slide.setFollowMasterBackground(true);
assertTrue(slide.getFollowMasterBackground());
assertTrue(slide.getFollowMasterGraphics());
slide.setFollowMasterGraphics(false);
assertFalse(slide.getFollowMasterGraphics());
slide.setFollowMasterGraphics(true);
assertTrue(slide.getFollowMasterGraphics());
} }
} }

+ 2
- 2
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShow.java View File

List<POIXMLDocumentPart> rels = slide1.getRelations(); List<POIXMLDocumentPart> rels = slide1.getRelations();
assertEquals(1, rels.size()); assertEquals(1, rels.size());
assertEquals(slide1.getMasterSheet().getLayout("blank"), rels.get(0));
assertEquals(slide1.getSlideMaster().getLayout(SlideLayout.BLANK), rels.get(0));
XSLFSlide slide2 = ppt.createSlide(); XSLFSlide slide2 = ppt.createSlide();
assertEquals(2, ppt.getSlides().length); assertEquals(2, ppt.getSlides().length);
assertEquals(1, masters.length); assertEquals(1, masters.length);
XSLFSlide slide = ppt.createSlide(); XSLFSlide slide = ppt.createSlide();
assertSame(masters[0], slide.getMasterSheet());
assertSame(masters[0], slide.getSlideMaster());
} }
public void testSlideLayout(){ public void testSlideLayout(){

+ 48
- 48
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java View File

!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&
!bodyPr1.isSetAnchor() !bodyPr1.isSetAnchor()
); );
assertEquals(7.2, shape1.getMarginLeft()); // 0.1"
assertEquals(7.2, shape1.getMarginRight()); // 0.1"
assertEquals(3.6, shape1.getMarginTop()); // 0.05"
assertEquals(3.6, shape1.getMarginBottom()); // 0.05"
assertEquals(7.2, shape1.getLeftInset()); // 0.1"
assertEquals(7.2, shape1.getRightInset()); // 0.1"
assertEquals(3.6, shape1.getTopInset()); // 0.05"
assertEquals(3.6, shape1.getBottomInset()); // 0.05"
assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());
// now check text properties // now check text properties
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&
!bodyPr2.isSetAnchor() !bodyPr2.isSetAnchor()
); );
assertEquals(7.2, shape2.getMarginLeft()); // 0.1"
assertEquals(7.2, shape2.getMarginRight()); // 0.1"
assertEquals(3.6, shape2.getMarginTop()); // 0.05"
assertEquals(3.6, shape2.getMarginBottom()); // 0.05"
assertEquals(7.2, shape2.getLeftInset()); // 0.1"
assertEquals(7.2, shape2.getRightInset()); // 0.1"
assertEquals(3.6, shape2.getTopInset()); // 0.05"
assertEquals(3.6, shape2.getBottomInset()); // 0.05"
assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment());
assertEquals("subtitle", shape2.getText()); assertEquals("subtitle", shape2.getText());
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&
!bodyPr1.isSetAnchor() !bodyPr1.isSetAnchor()
); );
assertEquals(7.2, shape1.getMarginLeft()); // 0.1"
assertEquals(7.2, shape1.getMarginRight()); // 0.1"
assertEquals(3.6, shape1.getMarginTop()); // 0.05"
assertEquals(3.6, shape1.getMarginBottom()); // 0.05"
assertEquals(7.2, shape1.getLeftInset()); // 0.1"
assertEquals(7.2, shape1.getRightInset()); // 0.1"
assertEquals(3.6, shape1.getTopInset()); // 0.05"
assertEquals(3.6, shape1.getBottomInset()); // 0.05"
assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());
// now check text properties // now check text properties
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&
!bodyPr2.isSetAnchor() !bodyPr2.isSetAnchor()
); );
assertEquals(7.2, shape2.getMarginLeft()); // 0.1"
assertEquals(7.2, shape2.getMarginRight()); // 0.1"
assertEquals(3.6, shape2.getMarginTop()); // 0.05"
assertEquals(3.6, shape2.getMarginBottom()); // 0.05"
assertEquals(7.2, shape2.getLeftInset()); // 0.1"
assertEquals(7.2, shape2.getRightInset()); // 0.1"
assertEquals(3.6, shape2.getTopInset()); // 0.05"
assertEquals(3.6, shape2.getBottomInset()); // 0.05"
assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment());
XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&
!bodyPr1.isSetAnchor() !bodyPr1.isSetAnchor()
); );
assertEquals(7.2, shape1.getMarginLeft()); // 0.1"
assertEquals(7.2, shape1.getMarginRight()); // 0.1"
assertEquals(3.6, shape1.getMarginTop()); // 0.05"
assertEquals(3.6, shape1.getMarginBottom()); // 0.05"
assertEquals(7.2, shape1.getLeftInset()); // 0.1"
assertEquals(7.2, shape1.getRightInset()); // 0.1"
assertEquals(3.6, shape1.getTopInset()); // 0.05"
assertEquals(3.6, shape1.getBottomInset()); // 0.05"
assertEquals(VerticalAlignment.TOP, shape1.getVerticalAlignment()); assertEquals(VerticalAlignment.TOP, shape1.getVerticalAlignment());
// now check text properties // now check text properties
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&
!bodyPr2.isSetAnchor() !bodyPr2.isSetAnchor()
); );
assertEquals(7.2, shape2.getMarginLeft()); // 0.1"
assertEquals(7.2, shape2.getMarginRight()); // 0.1"
assertEquals(3.6, shape2.getMarginTop()); // 0.05"
assertEquals(3.6, shape2.getMarginBottom()); // 0.05"
assertEquals(7.2, shape2.getLeftInset()); // 0.1"
assertEquals(7.2, shape2.getRightInset()); // 0.1"
assertEquals(3.6, shape2.getTopInset()); // 0.05"
assertEquals(3.6, shape2.getBottomInset()); // 0.05"
assertEquals(VerticalAlignment.BOTTOM, shape2.getVerticalAlignment()); assertEquals(VerticalAlignment.BOTTOM, shape2.getVerticalAlignment());
assertEquals("Section Header", shape2.getText()); assertEquals("Section Header", shape2.getText());
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&
!bodyPr1.isSetAnchor() !bodyPr1.isSetAnchor()
); );
assertEquals(7.2, shape1.getMarginLeft()); // 0.1"
assertEquals(7.2, shape1.getMarginRight()); // 0.1"
assertEquals(3.6, shape1.getMarginTop()); // 0.05"
assertEquals(3.6, shape1.getMarginBottom()); // 0.05"
assertEquals(7.2, shape1.getLeftInset()); // 0.1"
assertEquals(7.2, shape1.getRightInset()); // 0.1"
assertEquals(3.6, shape1.getTopInset()); // 0.05"
assertEquals(3.6, shape1.getBottomInset()); // 0.05"
assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());
// now check text properties // now check text properties
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&
!bodyPr2.isSetAnchor() !bodyPr2.isSetAnchor()
); );
assertEquals(7.2, shape2.getMarginLeft()); // 0.1"
assertEquals(7.2, shape2.getMarginRight()); // 0.1"
assertEquals(3.6, shape2.getMarginTop()); // 0.05"
assertEquals(3.6, shape2.getMarginBottom()); // 0.05"
assertEquals(7.2, shape2.getLeftInset()); // 0.1"
assertEquals(7.2, shape2.getRightInset()); // 0.1"
assertEquals(3.6, shape2.getTopInset()); // 0.05"
assertEquals(3.6, shape2.getBottomInset()); // 0.05"
assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment());
XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&
!bodyPr1.isSetAnchor() !bodyPr1.isSetAnchor()
); );
assertEquals(7.2, shape1.getMarginLeft()); // 0.1"
assertEquals(7.2, shape1.getMarginRight()); // 0.1"
assertEquals(3.6, shape1.getMarginTop()); // 0.05"
assertEquals(3.6, shape1.getMarginBottom()); // 0.05"
assertEquals(7.2, shape1.getLeftInset()); // 0.1"
assertEquals(7.2, shape1.getRightInset()); // 0.1"
assertEquals(3.6, shape1.getTopInset()); // 0.05"
assertEquals(3.6, shape1.getBottomInset()); // 0.05"
assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());
// now check text properties // now check text properties
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&
!bodyPr2.isSetAnchor() !bodyPr2.isSetAnchor()
); );
assertEquals(7.2, shape2.getMarginLeft()); // 0.1"
assertEquals(7.2, shape2.getMarginRight()); // 0.1"
assertEquals(3.6, shape2.getMarginTop()); // 0.05"
assertEquals(3.6, shape2.getMarginBottom()); // 0.05"
assertEquals(7.2, shape2.getLeftInset()); // 0.1"
assertEquals(7.2, shape2.getRightInset()); // 0.1"
assertEquals(3.6, shape2.getTopInset()); // 0.05"
assertEquals(3.6, shape2.getBottomInset()); // 0.05"
assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment());
XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&
!bodyPr1.isSetAnchor() !bodyPr1.isSetAnchor()
); );
assertEquals(7.2, shape1.getMarginLeft()); // 0.1"
assertEquals(7.2, shape1.getMarginRight()); // 0.1"
assertEquals(3.6, shape1.getMarginTop()); // 0.05"
assertEquals(3.6, shape1.getMarginBottom()); // 0.05"
assertEquals(7.2, shape1.getLeftInset()); // 0.1"
assertEquals(7.2, shape1.getRightInset()); // 0.1"
assertEquals(3.6, shape1.getTopInset()); // 0.05"
assertEquals(3.6, shape1.getBottomInset()); // 0.05"
assertEquals(VerticalAlignment.BOTTOM, shape1.getVerticalAlignment()); assertEquals(VerticalAlignment.BOTTOM, shape1.getVerticalAlignment());
// now check text properties // now check text properties
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&
!bodyPr2.isSetAnchor() !bodyPr2.isSetAnchor()
); );
assertEquals(7.2, shape2.getMarginLeft()); // 0.1"
assertEquals(7.2, shape2.getMarginRight()); // 0.1"
assertEquals(3.6, shape2.getMarginTop()); // 0.05"
assertEquals(3.6, shape2.getMarginBottom()); // 0.05"
assertEquals(7.2, shape2.getLeftInset()); // 0.1"
assertEquals(7.2, shape2.getRightInset()); // 0.1"
assertEquals(3.6, shape2.getTopInset()); // 0.05"
assertEquals(3.6, shape2.getBottomInset()); // 0.05"
assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment());
XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);

+ 127
- 8
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTheme.java View File

import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.xslf.XSLFTestDataSamples; import org.apache.poi.xslf.XSLFTestDataSamples;
import java.awt.Color;
import java.awt.TexturePaint;
/** /**
* test common properties for sheets (slides, masters, layouts, etc.)
* test reading properties from a multi-theme and multi-master document
* *
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
public class TestXSLFTheme extends TestCase { public class TestXSLFTheme extends TestCase {
public void testRead(){ public void testRead(){
XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide();
XSLFTheme theme = slide.getSlideLayout().getSlideMaster().getTheme();
assertNotNull(theme);
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("themes.pptx");
XSLFSlide[] slides = ppt.getSlides();
slide1(slides[0]);
slide2(slides[1]);
slide3(slides[2]);
slide4(slides[3]);
slide5(slides[4]);
slide6(slides[5]);
slide7(slides[6]);
slide8(slides[7]);
slide9(slides[8]);
slide10(slides[9]);
}
private XSLFShape getShape(XSLFSheet sheet, String name){
for(XSLFShape sh : sheet.getShapes()){
if(sh.getShapeName().equals(name)) return sh;
}
throw new IllegalArgumentException("Shape not found: " + name);
}
void slide1(XSLFSlide slide){
assertEquals(Color.white, slide.getBackground().getFillColor());
XSLFTheme theme = slide.getTheme();
assertEquals("Office Theme", theme.getName()); assertEquals("Office Theme", theme.getName());
//XSLFColor accent1 = theme.getColor("accent1");
//assertNotNull(accent1);
XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Rectangle 3");
RenderableShape rsh1 = new RenderableShape(sh1);
XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(Color.white, run1.getFontColor());
assertEquals(new Color(79, 129, 189), sh1.getFillColor());
assertTrue(rsh1.getFillPaint(null) instanceof Color) ; // solid fill
}
void slide2(XSLFSlide slide){
// Background 2, darker 10%
// YK: PPT shows slightly different color: new Color(221, 217, 195)
assertEquals(new Color(214, 212, 203), slide.getBackground().getFillColor());
}
void slide3(XSLFSlide slide){
assertNull(slide.getBackground().getFillColor());
assertTrue(slide.getBackground().getPaint(null).getClass().getName().indexOf("Gradient") > 0);
}
void slide4(XSLFSlide slide){
assertNull(slide.getBackground().getFillColor());
assertTrue(slide.getBackground().getPaint(null).getClass().getName().indexOf("Gradient") > 0);
XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Rectangle 4");
RenderableShape rsh1 = new RenderableShape(sh1);
XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(Color.white, run1.getFontColor());
assertEquals(new Color(148, 198, 0), sh1.getFillColor());
assertTrue(rsh1.getFillPaint(null) instanceof Color) ; // solid fill
XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 3");
XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(new Color(148, 198, 0), run2.getFontColor());
assertNull(sh2.getFillColor()); // no fill
assertTrue(slide.getSlideLayout().getFollowMasterGraphics());
}
void slide5(XSLFSlide slide){
assertTrue(slide.getBackground().getPaint(null) instanceof TexturePaint);
XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 1");
XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(new Color(148, 198, 0), run2.getFontColor());
assertNull(sh2.getFillColor()); // no fill
// font size is 40pt and scale factor is 90%
assertEquals(36.0, run2.getFontSize());
assertTrue(slide.getSlideLayout().getFollowMasterGraphics());
}
void slide6(XSLFSlide slide){
XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Subtitle 3");
XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(new Color(66, 66, 66), run1.getFontColor());
assertNull(sh1.getFillColor()); // no fill
XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 2");
XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(new Color(148, 198, 0), run2.getFontColor());
assertNull(sh2.getFillColor()); // no fill
assertFalse(slide.getSlideLayout().getFollowMasterGraphics());
}
void slide7(XSLFSlide slide){
//YK: PPT reports a slightly different color: r=189,g=239,b=87
assertEquals(new Color(182, 218, 108), slide.getBackground().getFillColor());
assertFalse(slide.getFollowMasterGraphics());
}
void slide8(XSLFSlide slide){
assertTrue(slide.getBackground().getPaint(null) instanceof TexturePaint);
}
void slide9(XSLFSlide slide){
assertTrue(slide.getBackground().getPaint(null) instanceof TexturePaint);
}
void slide10(XSLFSlide slide){
assertTrue(slide.getBackground().getPaint(null).getClass().getName().indexOf("Gradient") > 0);
XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Title 3");
XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(Color.white, run1.getFontColor());
assertNull(sh1.getFillColor()); // no fill
XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Subtitle 4");
XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(Color.white, run2.getFontColor());
assertNull(sh2.getFillColor()); // no fill
} }
} }

src/resources/scratchpad/org/apache/poi/xslf/usermodel/empty.pptx → src/resources/ooxml/org/apache/poi/xslf/usermodel/empty.pptx View File


src/resources/scratchpad/org/apache/poi/xslf/usermodel/presetShapeDefinitions.xml → src/resources/ooxml/org/apache/poi/xslf/usermodel/presetShapeDefinitions.xml View File


BIN
test-data/slideshow/pptx2svg.pptx View File


+ 94
- 0
test-data/slideshow/pptx2svg.svg
File diff suppressed because it is too large
View File


BIN
test-data/slideshow/themes.pptx View File


Loading…
Cancel
Save