Browse Source

initial support for rendering pptx slides into images with a PPTX2PNG command-line utility

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1187328 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_8_BETA5
Yegor Kozlov 12 years ago
parent
commit
2490ebd2ff
39 changed files with 23961 additions and 337 deletions
  1. 1
    0
      src/documentation/content/xdocs/status.xml
  2. 2
    1
      src/ooxml/java/org/apache/poi/util/Units.java
  3. 45
    0
      src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java
  4. 52
    0
      src/ooxml/java/org/apache/poi/xslf/model/ParagraphPropertyFetcher.java
  5. 48
    0
      src/ooxml/java/org/apache/poi/xslf/model/PropertyFetcher.java
  6. 52
    0
      src/ooxml/java/org/apache/poi/xslf/model/TextBodyPropertyFetcher.java
  7. 42
    39
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java
  8. 70
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java
  9. 54
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java
  10. 36
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java
  11. 33
    13
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java
  12. 82
    2
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java
  13. 79
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java
  14. 47
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java
  15. 637
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPresetGeometry.java
  16. 42
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRenderingHint.java
  17. 106
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java
  18. 74
    1
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java
  19. 120
    1
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java
  20. 499
    90
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java
  21. 45
    1
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java
  22. 45
    1
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java
  23. 22
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java
  24. 0
    28
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java
  25. 6
    10
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java
  26. 418
    34
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java
  27. 117
    19
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
  28. 203
    72
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java
  29. 196
    6
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTheme.java
  30. 101
    0
      src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
  31. 0
    1
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXMLSlideShow.java
  32. 16
    15
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java
  33. 105
    0
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java
  34. 3
    3
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java
  35. 609
    0
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java
  36. 39
    0
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTheme.java
  37. 19915
    0
      src/resources/scratchpad/org/apache/poi/xslf/usermodel/presetShapeDefinitions.xml
  38. BIN
      test-data/slideshow/layouts.pptx
  39. BIN
      test-data/slideshow/shapes.pptx

+ 1
- 0
src/documentation/content/xdocs/status.xml View File

@@ -34,6 +34,7 @@

<changes>
<release version="3.8-beta5" date="2011-??-??">
<action dev="poi-developers" type="add">support for converting pptx files into images with a PPTX2PNG tool</action>
<action dev="poi-developers" type="add">52050 - Support for the Excel RATE function</action>
<action dev="poi-developers" type="fix">51566 - HSLF fix for finishing parsing the picture stream on the first non-valid type</action>
<action dev="poi-developers" type="fix">51974 - Avoid HWPF issue when identifying the picture type</action>

+ 2
- 1
src/ooxml/java/org/apache/poi/util/Units.java View File

@@ -13,7 +13,8 @@
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.util;
==================================================================== */
package org.apache.poi.util;
/**
* @author Yegor Kozlov

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

@@ -0,0 +1,45 @@
/*
* ====================================================================
* 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;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
/**
*
* @author Yegor Kozlov
*/
public abstract class CharacterPropertyFetcher<T> extends ParagraphPropertyFetcher<T> {
public CharacterPropertyFetcher(int level) {
super(level);
}
public boolean fetch(CTTextParagraphProperties props) {
if (props.isSetDefRPr()) {
return fetch(props.getDefRPr());
}
return false;
}
public abstract boolean fetch(CTTextCharacterProperties props);
}

+ 52
- 0
src/ooxml/java/org/apache/poi/xslf/model/ParagraphPropertyFetcher.java View File

@@ -0,0 +1,52 @@
/*
* ====================================================================
* 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;
import org.apache.poi.xslf.usermodel.XSLFSimpleShape;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
/**
*
* @author Yegor Kozlov
*/
public abstract class ParagraphPropertyFetcher<T> extends PropertyFetcher<T> {
int _level;
public ParagraphPropertyFetcher(int level) {
_level = level;
}
public boolean fetch(XSLFSimpleShape shape) {
XmlObject[] o = shape.getXmlObject().selectPath(
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " +
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " +
".//p:txBody/a:lstStyle/a:lvl" + (_level + 1) + "pPr"
);
if (o.length == 1) {
CTTextParagraphProperties props = (CTTextParagraphProperties) o[0];
return fetch(props);
}
return false;
}
public abstract boolean fetch(CTTextParagraphProperties props);
}

+ 48
- 0
src/ooxml/java/org/apache/poi/xslf/model/PropertyFetcher.java View File

@@ -0,0 +1,48 @@
/*
* ====================================================================
* 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;
import org.apache.poi.xslf.usermodel.XSLFSimpleShape;
import org.apache.poi.util.Internal;
/**
* Used internally to navigate the PresentationML text style hierarchy and fetch properties
*
* @author Yegor Kozlov
*/
@Internal
public abstract class PropertyFetcher<T> {
private T _value;
/**
*
* @param shape the shape being examined
* @return true if the desired property was fetched
*/
public abstract boolean fetch(XSLFSimpleShape shape) ;
public T getValue(){
return _value;
}
public void setValue(T val){
_value = val;
}
}

+ 52
- 0
src/ooxml/java/org/apache/poi/xslf/model/TextBodyPropertyFetcher.java View File

@@ -0,0 +1,52 @@
/*
* ====================================================================
* 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;
import org.apache.poi.xslf.usermodel.XSLFSimpleShape;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
/**
* Created by IntelliJ IDEA.
* User: yegor
* Date: Oct 21, 2011
* Time: 1:18:52 PM
* To change this template use File | Settings | File Templates.
*/
public abstract class TextBodyPropertyFetcher<T> extends PropertyFetcher<T> {
public boolean fetch(XSLFSimpleShape shape) {
XmlObject[] o = shape.getXmlObject().selectPath(
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " +
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " +
".//p:txBody/a:bodyPr"
);
if (o.length == 1) {
CTTextBodyProperties props = (CTTextBodyProperties) o[0];
return fetch(props);
}
return false;
}
public abstract boolean fetch(CTTextBodyProperties props);
}

+ 42
- 39
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java View File

@@ -21,6 +21,8 @@ package org.apache.poi.xslf.usermodel;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Units;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuideList;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
@@ -39,8 +41,12 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**
* Represents a preset geometric shape.
@@ -49,6 +55,7 @@ import java.util.List;
*/
@Beta
public class XSLFAutoShape extends XSLFTextShape {
private static final Pattern adjPtrn = Pattern.compile("val\\s+(\\d+)");
/*package*/ XSLFAutoShape(CTShape shape, XSLFSheet sheet) {
super(shape, sheet);
@@ -83,44 +90,6 @@ public class XSLFAutoShape extends XSLFTextShape {
return ct;
}
/**
* Specifies a solid color fill. The shape is filled entirely with the specified color.
*
* @param color the solid color fill.
* The value of <code>null</code> unsets the solidFIll attribute from the underlying xml
*/
public void setFillColor(Color color) {
CTShapeProperties spPr = getSpPr();
if (color == null) {
if(spPr.isSetSolidFill()) spPr.unsetSolidFill();
}
else {
CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill();
CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
rgb.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()});
fill.setSrgbClr(rgb);
}
}
/**
*
* @return solid fill color of null if not set
*/
public Color getFillColor(){
CTShapeProperties spPr = getSpPr();
if(!spPr.isSetSolidFill() ) return null;
CTSolidColorFillProperties fill = spPr.getSolidFill();
if(!fill.isSetSrgbClr()) {
// TODO for now return null for all colors except explicit RGB
return null;
}
byte[] val = fill.getSrgbClr().getVal();
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
}
protected CTTextBody getTextBody(boolean create){
CTShape shape = (CTShape) getXmlObject();
CTTextBody txBody = shape.getTxBody();
@@ -132,4 +101,38 @@ public class XSLFAutoShape extends XSLFTextShape {
return txBody;
}
}
int getAdjustValue(String name, int defaultValue){
/*
CTShape shape = (CTShape) getXmlObject();
CTGeomGuideList av = shape.getSpPr().getPrstGeom().getAvLst();
if(av != null){
for(CTGeomGuide gd : av.getGdList()){
if(gd.getName().equals(name)) {
String fmla = gd.getFmla();
Matcher m = adjPtrn.matcher(fmla);
if(m.matches()){
int val = Integer.parseInt(m.group(1));
return 21600*val/100000;
}
}
}
}
*/
return defaultValue;
}
@Override
protected java.awt.Shape getOutline(){
java.awt.Shape outline = XSLFPresetGeometry.getOutline(this);
Rectangle2D anchor = getAnchor();
AffineTransform at = new AffineTransform();
at.translate(anchor.getX(), anchor.getY());
at.scale(
1.0f/21600*anchor.getWidth(),
1.0f/21600*anchor.getHeight()
);
return outline == null ? anchor : at.createTransformedShape(outline);
}
}

+ 70
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java View File

@@ -0,0 +1,70 @@
/* ====================================================================
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;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
/**
* Background shape
*
* @author Yegor Kozlov
*/
public class XSLFBackground extends XSLFSimpleShape {
/* package */XSLFBackground(CTBackground shape, XSLFSheet sheet) {
super(shape, sheet);
}
public void draw(Graphics2D graphics) {
Dimension pg = getSheet().getSlideShow().getPageSize();
Rectangle anchor = new Rectangle(0, 0, pg.width, pg.height);
CTBackgroundProperties pr = ((CTBackground) getXmlObject()).getBgPr();
if (pr == null) return;
XSLFTheme theme = getSheet().getTheme();
if (pr.isSetSolidFill()) {
Color color = theme.getSolidFillColor(pr.getSolidFill());
graphics.setPaint(color);
graphics.fill(anchor);
}
if (pr.isSetBlipFill()) {
String blipId = pr.getBlipFill().getBlip().getEmbed();
PackagePart p = getSheet().getPackagePart();
PackageRelationship rel = p.getRelationship(blipId);
if (rel != null) {
try {
BufferedImage img = ImageIO.read(p.getRelatedPart(rel).getInputStream());
graphics.drawImage(img, (int) anchor.getX(), (int) anchor.getY(),
(int) anchor.getWidth(), (int) anchor.getHeight(), null);
}
catch (Exception e) {
return;
}
}
}
}
}

+ 54
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java View File

@@ -0,0 +1,54 @@
/*
* ====================================================================
* 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;
import java.awt.Color;
import org.apache.poi.util.Internal;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeStyleSheet;
public class XSLFColor {
private final CTColor _ctColor;
XSLFColor(CTColor ctColor){
_ctColor = ctColor;
}
@Internal
public CTColor getXmlObject() {
return _ctColor;
}
public Color getColor(){
return getColor(0xFF);
}
public Color getColor(int alpha){
Color color = Color.black;
if(_ctColor.isSetSrgbClr()){
byte[] val = _ctColor.getSrgbClr().getVal();
color = new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2], alpha);
} else if (_ctColor.isSetSysClr()){
byte[] val = _ctColor.getSysClr().getLastClr();
color = new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2], alpha);
}
return color;
}
}

+ 36
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java View File

@@ -32,6 +32,10 @@ import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;
import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;
import org.openxmlformats.schemas.presentationml.x2006.main.CTConnectorNonVisual;
import java.awt.*;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
/**
*
* Specifies a connection shape.
@@ -192,4 +196,36 @@ public class XSLFConnectorShape extends XSLFSimpleShape {
return len == null ? null : LineEndLength.values()[len.intValue() - 1];
}
@Override
public void draw(Graphics2D graphics){
java.awt.Shape outline = getOutline();
// shadow
XSLFShadow shadow = getShadow();
if(shadow != null) shadow.draw(graphics);
//border
Color lineColor = getLineColor();
if (lineColor != null){
graphics.setColor(lineColor);
applyStroke(graphics);
graphics.draw(outline);
}
}
@Override
protected java.awt.Shape getOutline(){
Rectangle2D anchor = getAnchor();
double x1 = anchor.getX(),
y1 = anchor.getY(),
x2 = anchor.getX() + anchor.getWidth(),
y2 = anchor.getY() + anchor.getHeight();
GeneralPath line = new GeneralPath();
line.moveTo((float)x1, (float)y1);
line.lineTo((float)x2, (float)y2);
return line;
}
}

+ 33
- 13
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java View File

@@ -111,34 +111,45 @@ public class XSLFFreeformShape extends XSLFAutoShape {
return numPoints;
}
/**
* Gets the shape path.
* <p>
* The path is translated in the shape's coordinate system, i.e.
* freeform.getPath().getBounds2D() equals to freeform.getAnchor()
* (small discrepancies are possible due to rounding errors)
* </p>
*
* @return the path
*/
public GeneralPath getPath() {
GeneralPath path = new GeneralPath();
Rectangle2D bounds = getAnchor();
int x0 = Units.toEMU(bounds.getX());
int y0 = Units.toEMU(bounds.getY());
CTCustomGeometry2D geom = getSpPr().getCustGeom();
for(CTPath2D spPath : geom.getPathLst().getPathList()){
double scaleW = bounds.getWidth() / Units.toPoints(spPath.getW());
double scaleH = bounds.getHeight() / Units.toPoints(spPath.getH());
for(XmlObject ch : spPath.selectPath("*")){
if(ch instanceof CTPath2DMoveTo){
CTAdjPoint2D pt = ((CTPath2DMoveTo)ch).getPt();
path.moveTo((float)Units.toPoints((Long)pt.getX() + x0),
(float)Units.toPoints((Long)pt.getY() + y0));
path.moveTo((float)Units.toPoints((Long)pt.getX())*scaleW,
(float)Units.toPoints((Long)pt.getY())*scaleH);
} else if (ch instanceof CTPath2DLineTo){
CTAdjPoint2D pt = ((CTPath2DLineTo)ch).getPt();
path.lineTo((float)Units.toPoints((Long)pt.getX() + x0),
(float)Units.toPoints((Long)pt.getY() + y0));
path.lineTo((float)Units.toPoints((Long)pt.getX()),
(float)Units.toPoints((Long)pt.getY()));
} else if (ch instanceof CTPath2DCubicBezierTo){
CTPath2DCubicBezierTo bez = ((CTPath2DCubicBezierTo)ch);
CTAdjPoint2D pt1 = bez.getPtArray(0);
CTAdjPoint2D pt2 = bez.getPtArray(1);
CTAdjPoint2D pt3 = bez.getPtArray(2);
path.curveTo(
(float)Units.toPoints((Long) pt1.getX() + x0),
(float)Units.toPoints((Long) pt1.getY() + y0),
(float)Units.toPoints((Long) pt2.getX() + x0),
(float)Units.toPoints((Long) pt2.getY() + y0),
(float)Units.toPoints((Long) pt3.getX() + x0),
(float)Units.toPoints((Long) pt3.getY() + y0)
(float)Units.toPoints((Long) pt1.getX())*scaleW,
(float)Units.toPoints((Long) pt1.getY())*scaleH,
(float)Units.toPoints((Long) pt2.getX())*scaleW,
(float)Units.toPoints((Long) pt2.getY())*scaleH,
(float)Units.toPoints((Long) pt3.getX())*scaleW,
(float)Units.toPoints((Long) pt3.getY())*scaleH
);
} else if (ch instanceof CTPath2DClose){
@@ -147,7 +158,11 @@ public class XSLFFreeformShape extends XSLFAutoShape {
}
}
return path;
// the created path starts at (x=0, y=0).
// The returned path should fit in the bounding rectangle
AffineTransform at = new AffineTransform();
at.translate(bounds.getX(), bounds.getY());
return new GeneralPath(at.createTransformedShape(path));
}
/**
* @param shapeId 1-based shapeId
@@ -175,4 +190,9 @@ public class XSLFFreeformShape extends XSLFAutoShape {
return ct;
}
@Override
protected java.awt.Shape getOutline(){
return getPath();
}
}

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

@@ -23,8 +23,16 @@ import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeGroup;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Units;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
/**
@@ -61,11 +69,31 @@ public class XSLFGraphicFrame extends XSLFShape {
}
public Rectangle2D getAnchor(){
throw new RuntimeException("NotImplemented");
CTTransform2D xfrm = _shape.getXfrm();
CTPoint2D off = xfrm.getOff();
long x = off.getX();
long y = off.getY();
CTPositiveSize2D ext = xfrm.getExt();
long cx = ext.getCx();
long cy = ext.getCy();
return new Rectangle2D.Double(
Units.toPoints(x), Units.toPoints(y),
Units.toPoints(cx), Units.toPoints(cy));
}
public void setAnchor(Rectangle2D anchor){
throw new RuntimeException("NotImplemented");
CTTransform2D xfrm = _shape.getXfrm();
CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
long x = Units.toEMU(anchor.getX());
long y = Units.toEMU(anchor.getY());
off.setX(x);
off.setY(y);
CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm
.addNewExt();
long cx = Units.toEMU(anchor.getWidth());
long cy = Units.toEMU(anchor.getHeight());
ext.setCx(cx);
ext.setCy(cy);
}
@@ -78,4 +106,56 @@ public class XSLFGraphicFrame extends XSLFShape {
}
}
/**
* 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.
*/
public void setRotation(double theta){
throw new IllegalArgumentException("Operation not supported");
}
/**
* 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
*/
public double getRotation(){
return 0;
}
public void setFlipHorizontal(boolean flip){
throw new IllegalArgumentException("Operation not supported");
}
public void setFlipVertical(boolean flip){
throw new IllegalArgumentException("Operation not supported");
}
/**
* Whether the shape is horizontally flipped
*
* @return whether the shape is horizontally flipped
*/
public boolean getFlipHorizontal(){
return false;
}
public boolean getFlipVertical(){
return false;
}
public void draw(Graphics2D graphics){
}
}

+ 79
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java View File

@@ -33,11 +33,14 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.List;
import java.util.regex.Pattern;
@@ -217,4 +220,80 @@ public class XSLFGroupShape extends XSLFShape {
return sh;
}
public void setFlipHorizontal(boolean flip){
_spPr.getXfrm().setFlipH(flip);
}
public void setFlipVertical(boolean flip){
_spPr.getXfrm().setFlipV(flip);
}
/**
* Whether the shape is horizontally flipped
*
* @return whether the shape is horizontally flipped
*/
public boolean getFlipHorizontal(){
return _spPr.getXfrm().getFlipH();
}
public boolean getFlipVertical(){
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.
*/
public void setRotation(double theta){
_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
*/
public double getRotation(){
return (double)_spPr.getXfrm().getRot()/60000;
}
public void draw(Graphics2D graphics){
// the coordinate system of this group of shape
Rectangle2D interior = getInteriorAnchor();
// anchor of this group relative to the parent shape
Rectangle2D exterior = getAnchor();
graphics.translate(exterior.getX(), exterior.getY());
double scaleX = exterior.getWidth() / interior.getWidth();
double scaleY = exterior.getHeight() / interior.getHeight();
graphics.scale(scaleX, scaleY);
graphics.translate(-interior.getX(), -interior.getY());
for (XSLFShape shape : getShapes()) {
// remember the initial transform and restore it after we are done with the drawing
AffineTransform at0 = graphics.getTransform();
graphics.setRenderingHint(XSLFRenderingHint.GSAVE, true);
// apply rotation and flipping
shape.applyTransform(graphics);
shape.draw(graphics);
// restore the coordinate system
graphics.setTransform(at0);
graphics.setRenderingHint(XSLFRenderingHint.GRESTORE, true);
}
}
}

+ 47
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java View File

@@ -22,16 +22,24 @@ package org.apache.poi.xslf.usermodel;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.util.Beta;
import org.apache.poi.util.POILogger;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPictureNonVisual;
import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
@@ -104,4 +112,43 @@ public class XSLFPictureShape extends XSLFSimpleShape {
}
return _data;
}
@Override
public void draw(Graphics2D graphics){
java.awt.Shape outline = getOutline();
//fill
Color fillColor = getFillColor();
if (fillColor != null) {
graphics.setColor(fillColor);
applyFill(graphics);
graphics.fill(outline);
}
// text
XSLFPictureData data = getPictureData();
if(data == null) return;
BufferedImage img;
try {
img = ImageIO.read(new ByteArrayInputStream(data.getData()));
}
catch (Exception e){
return;
}
Rectangle2D anchor = getAnchor();
graphics.drawImage(img, (int)anchor.getX(), (int)anchor.getY(),
(int)anchor.getWidth(), (int)anchor.getHeight(), null);
//border overlays the image
Color lineColor = getLineColor();
if (lineColor != null){
graphics.setColor(lineColor);
applyStroke(graphics);
graphics.draw(outline);
}
}
}

+ 637
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPresetGeometry.java View File

@@ -0,0 +1,637 @@
/*
* ====================================================================
* 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;
import java.awt.*;
import java.awt.geom.*;
/**
* TODO: re-write and initialize from presetShapeDefinitions.xml
*
* @author Yegor Kozlov
*/
public class XSLFPresetGeometry {
public static final int LINE = 1;
public static final int LINE_INV = 2;
public static final int TRIANGLE = 3;
public static final int RT_TRIANGLE = 4;
public static final int RECT = 5;
public static final int DIAMOND = 6;
public static final int PARALLELOGRAM = 7;
public static final int TRAPEZOID = 8;
public static final int NON_ISOSCELES_TRAPEZOID = 9;
public static final int PENTAGON = 10;
public static final int HEXAGON = 11;
public static final int HEPTAGON = 12;
public static final int OCTAGON = 13;
public static final int DECAGON = 14;
public static final int DODECAGON = 15;
public static final int STAR_4 = 16;
public static final int STAR_5 = 17;
public static final int STAR_6 = 18;
public static final int STAR_7 = 19;
public static final int STAR_8 = 20;
public static final int STAR_10 = 21;
public static final int STAR_12 = 22;
public static final int STAR_16 = 23;
public static final int STAR_24 = 24;
public static final int STAR_32 = 25;
public static final int ROUND_RECT = 26;
public static final int ROUND_1_RECT = 27;
public static final int ROUND_2_SAME_RECT = 28;
public static final int ROUND_2_DIAG_RECT = 29;
public static final int SNIP_ROUND_RECT = 30;
public static final int SNIP_1_RECT = 31;
public static final int SNIP_2_SAME_RECT = 32;
public static final int SNIP_2_DIAG_RECT = 33;
public static final int PLAQUE = 34;
public static final int ELLIPSE = 35;
public static final int TEARDROP = 36;
public static final int HOME_PLATE = 37;
public static final int CHEVRON = 38;
public static final int PIE_WEDGE = 39;
public static final int PIE = 40;
public static final int BLOCK_ARC = 41;
public static final int DONUT = 42;
public static final int NO_SMOKING = 43;
public static final int RIGHT_ARROW = 44;
public static final int LEFT_ARROW = 45;
public static final int UP_ARROW = 46;
public static final int DOWN_ARROW = 47;
public static final int STRIPED_RIGHT_ARROW = 48;
public static final int NOTCHED_RIGHT_ARROW = 49;
public static final int BENT_UP_ARROW = 50;
public static final int LEFT_RIGHT_ARROW = 51;
public static final int UP_DOWN_ARROW = 52;
public static final int LEFT_UP_ARROW = 53;
public static final int LEFT_RIGHT_UP_ARROW = 54;
public static final int QUAD_ARROW = 55;
public static final int LEFT_ARROW_CALLOUT = 56;
public static final int RIGHT_ARROW_CALLOUT = 57;
public static final int UP_ARROW_CALLOUT = 58;
public static final int DOWN_ARROW_CALLOUT = 59;
public static final int LEFT_RIGHT_ARROW_CALLOUT = 60;
public static final int UP_DOWN_ARROW_CALLOUT = 61;
public static final int QUAD_ARROW_CALLOUT = 62;
public static final int BENT_ARROW = 63;
public static final int UTURN_ARROW = 64;
public static final int CIRCULAR_ARROW = 65;
public static final int LEFT_CIRCULAR_ARROW = 66;
public static final int LEFT_RIGHT_CIRCULAR_ARROW = 67;
public static final int CURVED_RIGHT_ARROW = 68;
public static final int CURVED_LEFT_ARROW = 69;
public static final int CURVED_UP_ARROW = 70;
public static final int CURVED_DOWN_ARROW = 71;
public static final int SWOOSH_ARROW = 72;
public static final int CUBE = 73;
public static final int CAN = 74;
public static final int LIGHTNING_BOLT = 75;
public static final int HEART = 76;
public static final int SUN = 77;
public static final int MOON = 78;
public static final int SMILEY_FACE = 79;
public static final int IRREGULAR_SEAL_1 = 80;
public static final int IRREGULAR_SEAL_2 = 81;
public static final int FOLDED_CORNER = 82;
public static final int BEVEL = 83;
public static final int FRAME = 84;
public static final int HALF_FRAME = 85;
public static final int CORNER = 86;
public static final int DIAG_STRIPE = 87;
public static final int CHORD = 88;
public static final int ARC = 89;
public static final int LEFT_BRACKET = 90;
public static final int RIGHT_BRACKET = 91;
public static final int LEFT_BRACE = 92;
public static final int RIGHT_BRACE = 93;
public static final int BRACKET_PAIR = 94;
public static final int BRACE_PAIR = 95;
public static final int STRAIGHT_CONNECTOR_1 = 96;
public static final int BENT_CONNECTOR_2 = 97;
public static final int BENT_CONNECTOR_3 = 98;
public static final int BENT_CONNECTOR_4 = 99;
public static final int BENT_CONNECTOR_5 = 100;
public static final int CURVED_CONNECTOR_2 = 101;
public static final int CURVED_CONNECTOR_3 = 102;
public static final int CURVED_CONNECTOR_4 = 103;
public static final int CURVED_CONNECTOR_5 = 104;
public static final int CALLOUT_1 = 105;
public static final int CALLOUT_2 = 106;
public static final int CALLOUT_3 = 107;
public static final int ACCENT_CALLOUT_1 = 108;
public static final int ACCENT_CALLOUT_2 = 109;
public static final int ACCENT_CALLOUT_3 = 110;
public static final int BORDER_CALLOUT_1 = 111;
public static final int BORDER_CALLOUT_2 = 112;
public static final int BORDER_CALLOUT_3 = 113;
public static final int ACCENT_BORDER_CALLOUT_1 = 114;
public static final int ACCENT_BORDER_CALLOUT_2 = 115;
public static final int ACCENT_BORDER_CALLOUT_3 = 116;
public static final int WEDGE_RECT_CALLOUT = 117;
public static final int WEDGE_ROUND_RECT_CALLOUT = 118;
public static final int WEDGE_ELLIPSE_CALLOUT = 119;
public static final int CLOUD_CALLOUT = 120;
public static final int CLOUD = 121;
public static final int RIBBON = 122;
public static final int RIBBON_2 = 123;
public static final int ELLIPSE_RIBBON = 124;
public static final int ELLIPSE_RIBBON_2 = 125;
public static final int LEFT_RIGHT_RIBBON = 126;
public static final int VERTICAL_SCROLL = 127;
public static final int HORIZONTAL_SCROLL = 128;
public static final int WAVE = 129;
public static final int DOUBLE_WAVE = 130;
public static final int PLUS = 131;
public static final int FLOW_CHART_PROCESS = 132;
public static final int FLOW_CHART_DECISION = 133;
public static final int FLOW_CHART_INPUT_OUTPUT = 134;
public static final int FLOW_CHART_PREDEFINED_PROCESS = 135;
public static final int FLOW_CHART_INTERNAL_STORAGE = 136;
public static final int FLOW_CHART_DOCUMENT = 137;
public static final int FLOW_CHART_MULTIDOCUMENT = 138;
public static final int FLOW_CHART_TERMINATOR = 139;
public static final int FLOW_CHART_PREPARATION = 140;
public static final int FLOW_CHART_MANUAL_INPUT = 141;
public static final int FLOW_CHART_MANUAL_OPERATION = 142;
public static final int FLOW_CHART_CONNECTOR = 143;
public static final int FLOW_CHART_PUNCHED_CARD = 144;
public static final int FLOW_CHART_PUNCHED_TAPE = 145;
public static final int FLOW_CHART_SUMMING_JUNCTION = 146;
public static final int FLOW_CHART_OR = 147;
public static final int FLOW_CHART_COLLATE = 148;
public static final int FLOW_CHART_SORT = 149;
public static final int FLOW_CHART_EXTRACT = 150;
public static final int FLOW_CHART_MERGE = 151;
public static final int FLOW_CHART_OFFLINE_STORAGE = 152;
public static final int FLOW_CHART_ONLINE_STORAGE = 153;
public static final int FLOW_CHART_MAGNETIC_TAPE = 154;
public static final int FLOW_CHART_MAGNETIC_DISK = 155;
public static final int FLOW_CHART_MAGNETIC_DRUM = 156;
public static final int FLOW_CHART_DISPLAY = 157;
public static final int FLOW_CHART_DELAY = 158;
public static final int FLOW_CHART_ALTERNATE_PROCESS = 159;
public static final int FLOW_CHART_OFFPAGE_CONNECTOR = 160;
public static final int ACTION_BUTTON_BLANK = 161;
public static final int ACTION_BUTTON_HOME = 162;
public static final int ACTION_BUTTON_HELP = 163;
public static final int ACTION_BUTTON_INFORMATION = 164;
public static final int ACTION_BUTTON_FORWARD_NEXT = 165;
public static final int ACTION_BUTTON_BACK_PREVIOUS = 166;
public static final int ACTION_BUTTON_END = 167;
public static final int ACTION_BUTTON_BEGINNING = 168;
public static final int ACTION_BUTTON_RETURN = 169;
public static final int ACTION_BUTTON_DOCUMENT = 170;
public static final int ACTION_BUTTON_SOUND = 171;
public static final int ACTION_BUTTON_MOVIE = 172;
public static final int GEAR_6 = 173;
public static final int GEAR_9 = 174;
public static final int FUNNEL = 175;
public static final int MATH_PLUS = 176;
public static final int MATH_MINUS = 177;
public static final int MATH_MULTIPLY = 178;
public static final int MATH_DIVIDE = 179;
public static final int MATH_EQUAL = 180;
public static final int MATH_NOT_EQUAL = 181;
public static final int CORNER_TABS = 182;
public static final int SQUARE_TABS = 183;
public static final int PLAQUE_TABS = 184;
public static final int CHART_X = 185;
public static final int CHART_STAR = 186;
public static final int CHART_PLUS = 187;
private static interface ShapeOutline {
java.awt.Shape getOutline(XSLFAutoShape shape);
}
static ShapeOutline[] shapes;
static {
shapes = new ShapeOutline[255];
shapes[RECT] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
Rectangle2D path = new Rectangle2D.Float(0, 0, 21600, 21600);
return path;
}
};
shapes[ROUND_RECT] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
int adjval = shape.getAdjustValue("adj1", 5400);
RoundRectangle2D path = new RoundRectangle2D.Float(0, 0, 21600, 21600, adjval, adjval);
return path;
}
};
shapes[ELLIPSE] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
Ellipse2D path = new Ellipse2D.Float(0, 0, 21600, 21600);
return path;
}
};
shapes[DIAMOND] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
GeneralPath path = new GeneralPath();
path.moveTo(10800, 0);
path.lineTo(21600, 10800);
path.lineTo(10800, 21600);
path.lineTo(0, 10800);
path.closePath();
return path;
}
};
//m@0,l,21600r21600
shapes[TRIANGLE] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
int adjval = shape.getAdjustValue("adj1", 5400);
GeneralPath path = new GeneralPath();
path.moveTo(adjval, 0);
path.lineTo(0, 21600);
path.lineTo(21600, 21600);
path.closePath();
return path;
}
};
shapes[RT_TRIANGLE] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
GeneralPath path = new GeneralPath();
path.moveTo(0, 0);
path.lineTo(21600, 21600);
path.lineTo(0, 21600);
path.closePath();
return path;
}
};
shapes[PARALLELOGRAM] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
int adjval = shape.getAdjustValue("adj1", 5400);
GeneralPath path = new GeneralPath();
path.moveTo(adjval, 0);
path.lineTo(21600, 0);
path.lineTo(21600 - adjval, 21600);
path.lineTo(0, 21600);
path.closePath();
return path;
}
};
shapes[TRAPEZOID] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
int adjval = shape.getAdjustValue("adj1", 5400);
GeneralPath path = new GeneralPath();
path.moveTo(0, 0);
path.lineTo(adjval, 21600);
path.lineTo(21600 - adjval, 21600);
path.lineTo(21600, 0);
path.closePath();
return path;
}
};
shapes[HEXAGON] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
int adjval = shape.getAdjustValue("adj1", 5400);
GeneralPath path = new GeneralPath();
path.moveTo(adjval, 0);
path.lineTo(21600 - adjval, 0);
path.lineTo(21600, 10800);
path.lineTo(21600 - adjval, 21600);
path.lineTo(adjval, 21600);
path.lineTo(0, 10800);
path.closePath();
return path;
}
};
shapes[OCTAGON] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
int adjval = shape.getAdjustValue("adj1", 6324);
GeneralPath path = new GeneralPath();
path.moveTo(adjval, 0);
path.lineTo(21600 - adjval, 0);
path.lineTo(21600, adjval);
path.lineTo(21600, 21600-adjval);
path.lineTo(21600-adjval, 21600);
path.lineTo(adjval, 21600);
path.lineTo(0, 21600-adjval);
path.lineTo(0, adjval);
path.closePath();
return path;
}
};
shapes[PLUS] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
int adjval = shape.getAdjustValue("adj1", 5400);
GeneralPath path = new GeneralPath();
path.moveTo(adjval, 0);
path.lineTo(21600 - adjval, 0);
path.lineTo(21600 - adjval, adjval);
path.lineTo(21600, adjval);
path.lineTo(21600, 21600-adjval);
path.lineTo(21600-adjval, 21600-adjval);
path.lineTo(21600-adjval, 21600);
path.lineTo(adjval, 21600);
path.lineTo(adjval, 21600-adjval);
path.lineTo(0, 21600-adjval);
path.lineTo(0, adjval);
path.lineTo(adjval, adjval);
path.closePath();
return path;
}
};
shapes[PENTAGON] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
GeneralPath path = new GeneralPath();
path.moveTo(10800, 0);
path.lineTo(21600, 8259);
path.lineTo(21600 - 4200, 21600);
path.lineTo(4200, 21600);
path.lineTo(0, 8259);
path.closePath();
return path;
}
};
shapes[HOME_PLATE] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
GeneralPath path = new GeneralPath();
int adjval = shape.getAdjustValue("adj1", 16200);
path.moveTo(0, 0);
path.lineTo(adjval, 0 );
path.lineTo(21600, 10800);
path.lineTo(adjval, 21600);
path.lineTo(0, 21600);
path.closePath();
return path;
}
};
shapes[CHEVRON] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
GeneralPath path = new GeneralPath();
int adjval = shape.getAdjustValue("adj1", 16200);
path.moveTo(0, 0);
path.lineTo(adjval, 0 );
path.lineTo(21600, 10800);
path.lineTo(adjval, 21600);
path.lineTo(0, 21600);
path.lineTo(21600 - adjval, 10800);
path.closePath();
return path;
}
};
shapes[CAN] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
int adjval = shape.getAdjustValue("adj1", 5400);
GeneralPath path = new GeneralPath();
path.moveTo(0, 0);
path.lineTo(21600, 0);
path.lineTo(21600, 21600);
path.lineTo(0, 21600);
//path.lineTo(21600, adjval);
path.closePath();
path.moveTo(10800, 0);
//path.append(new Arc2D.Float(10800, 0, 10800, adjval, 0, 90, Arc2D.OPEN), true);
path.moveTo(10800, adjval/2);
path.append(new Arc2D.Float(10800, adjval/2, 10800, adjval, 90, 180, Arc2D.OPEN), true);
//path.append(new Arc2D.Float(0, adjval/2, 10800, adjval, 180, 270, Arc2D.OPEN), true);
//path.append(new Arc2D.Float(0, 0, 10800, adjval, 270, 360, Arc2D.OPEN), true);
return path;
}
};
shapes[DOWN_ARROW] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
//m0@0 l@1@0 @1,0 @2,0 @2@0,21600@0,10800,21600xe
int adjval = shape.getAdjustValue("adj1", 16200);
int adjval2 = shape.getAdjustValue("adj2", 5400);
GeneralPath path = new GeneralPath();
path.moveTo(0, adjval);
path.lineTo(adjval2, adjval);
path.lineTo(adjval2, 0);
path.lineTo(21600-adjval2, 0);
path.lineTo(21600-adjval2, adjval);
path.lineTo(21600, adjval);
path.lineTo(10800, 21600);
path.closePath();
return path;
}
};
shapes[UP_ARROW] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
//m0@0 l@1@0 @1,21600@2,21600@2@0,21600@0,10800,xe
int adjval = shape.getAdjustValue("adj1", 5400);
int adjval2 = shape.getAdjustValue("adj2", 5400);
GeneralPath path = new GeneralPath();
path.moveTo(0, adjval);
path.lineTo(adjval2, adjval);
path.lineTo(adjval2, 21600);
path.lineTo(21600-adjval2, 21600);
path.lineTo(21600-adjval2, adjval);
path.lineTo(21600, adjval);
path.lineTo(10800, 0);
path.closePath();
return path;
}
};
shapes[RIGHT_ARROW] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
//m@0, l@0@1 ,0@1,0@2@0@2@0,21600,21600,10800xe
int adjval = shape.getAdjustValue("adj1", 16200);
int adjval2 = shape.getAdjustValue("adj2", 5400);
GeneralPath path = new GeneralPath();
path.moveTo(adjval, 0);
path.lineTo(adjval, adjval2);
path.lineTo(0, adjval2);
path.lineTo(0, 21600-adjval2);
path.lineTo(adjval, 21600-adjval2);
path.lineTo(adjval, 21600);
path.lineTo(21600, 10800);
path.closePath();
return path;
}
};
shapes[LEFT_ARROW] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
//m@0, l@0@1,21600@1,21600@2@0@2@0,21600,,10800xe
int adjval = shape.getAdjustValue("adj1", 5400);
int adjval2 = shape.getAdjustValue("adj2", 5400);
GeneralPath path = new GeneralPath();
path.moveTo(adjval, 0);
path.lineTo(adjval, adjval2);
path.lineTo(21600, adjval2);
path.lineTo(21600, 21600-adjval2);
path.lineTo(adjval, 21600-adjval2);
path.lineTo(adjval, 21600);
path.lineTo(0, 10800);
path.closePath();
return path;
}
};
shapes[LEFT_BRACE] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
//m21600,qx10800@0l10800@2qy0@11,10800@3l10800@1qy21600,21600e
int adjval = shape.getAdjustValue("adj1", 1800);
int adjval2 = shape.getAdjustValue("adj2", 10800);
GeneralPath path = new GeneralPath();
path.moveTo(21600, 0);
path.append(new Arc2D.Float(10800, 0, 21600, adjval*2, 90, 90, Arc2D.OPEN), false);
path.moveTo(10800, adjval);
path.lineTo(10800, adjval2 - adjval);
path.append(new Arc2D.Float(-10800, adjval2 - 2*adjval, 21600, adjval*2, 270, 90, Arc2D.OPEN), false);
path.moveTo(0, adjval2);
path.append(new Arc2D.Float(-10800, adjval2, 21600, adjval*2, 0, 90, Arc2D.OPEN), false);
path.moveTo(10800, adjval2 + adjval);
path.lineTo(10800, 21600 - adjval);
path.append(new Arc2D.Float(10800, 21600 - 2*adjval, 21600, adjval*2, 180, 90, Arc2D.OPEN), false);
return path;
}
};
shapes[RIGHT_BRACE] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
//m,qx10800@0 l10800@2qy21600@11,10800@3l10800@1qy,21600e
int adjval = shape.getAdjustValue("adj1", 1800);
int adjval2 = shape.getAdjustValue("adj2", 10800);
GeneralPath path = new GeneralPath();
path.moveTo(0, 0);
path.append(new Arc2D.Float(-10800, 0, 21600, adjval*2, 0, 90, Arc2D.OPEN), false);
path.moveTo(10800, adjval);
path.lineTo(10800, adjval2 - adjval);
path.append(new Arc2D.Float(10800, adjval2 - 2*adjval, 21600, adjval*2, 180, 90, Arc2D.OPEN), false);
path.moveTo(21600, adjval2);
path.append(new Arc2D.Float(10800, adjval2, 21600, adjval*2, 90, 90, Arc2D.OPEN), false);
path.moveTo(10800, adjval2 + adjval);
path.lineTo(10800, 21600 - adjval);
path.append(new Arc2D.Float(-10800, 21600 - 2*adjval, 21600, adjval*2, 270, 90, Arc2D.OPEN), false);
return path;
}
};
shapes[LEFT_RIGHT_ARROW] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
//m,10800l@0,21600@0@3@2@3@2,21600,21600,10800@2,0@2@1@0@1@0,xe
int adjval = shape.getAdjustValue("adj1", 4320);
int adjval2 = shape.getAdjustValue("adj2", 5400);
GeneralPath path = new GeneralPath();
path.moveTo(0, 10800);
path.lineTo(adjval, 0);
path.lineTo(adjval, adjval2);
path.lineTo(21600 - adjval, adjval2);
path.lineTo(21600 - adjval, 0);
path.lineTo(21600, 10800);
path.lineTo(21600 - adjval, 21600);
path.lineTo(21600 - adjval, 21600 - adjval2);
path.lineTo(adjval, 21600 - adjval2);
path.lineTo(adjval, 21600);
path.closePath();
return path;
}
};
shapes[UP_DOWN_ARROW] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
//m10800,l21600@0@3@0@3@2,21600@2,10800,21600,0@2@1@2@1@0,0@0xe
int adjval1 = shape.getAdjustValue("adj1", 5400);
int adjval2 = shape.getAdjustValue("adj2", 4320);
GeneralPath path = new GeneralPath();
path.moveTo(10800, 0);
path.lineTo(21600, adjval2);
path.lineTo(21600 - adjval1, adjval2);
path.lineTo(21600 - adjval1, 21600 - adjval2);
path.lineTo(21600, 21600 - adjval2);
path.lineTo(10800, 21600);
path.lineTo(0, 21600 - adjval2);
path.lineTo(adjval1, 21600 - adjval2);
path.lineTo(adjval1, adjval2);
path.lineTo(0, adjval2);
path.closePath();
return path;
}
};
shapes[NOTCHED_RIGHT_ARROW] = new ShapeOutline(){
public java.awt.Shape getOutline(XSLFAutoShape shape){
//m@0,l@0@1,0@1@5,10800,0@2@0@2@0,21600,21600,10800xe
int adjval1 = shape.getAdjustValue("adj1", 16200);
int adjval2 = shape.getAdjustValue("adj2", 5400);
GeneralPath path = new GeneralPath();
path.moveTo(adjval1, 0);
path.lineTo(adjval1, adjval2);
path.lineTo(0, adjval2);
//The notch at the end stays adjusted so that it matches the shape of the arrowhead.
int notch = (21600-2*adjval2)*(21600-adjval1)/21600;
path.lineTo(notch, 10800);
path.lineTo(0, 21600 - adjval2);
path.lineTo(adjval1, 21600 - adjval2);
path.lineTo(adjval1, 21600);
path.lineTo(21600, 10800);
path.closePath();
return path;
}
};
}
static Shape getOutline(XSLFAutoShape shape){
ShapeOutline outline = shapes[shape.getShapeType()];
return outline == null ? null : outline.getOutline(shape);
}
}

+ 42
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRenderingHint.java View File

@@ -0,0 +1,42 @@
/*
* ====================================================================
* 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;
import java.awt.*;
/**
*
* @author Yegor Kozlov
*/
public class XSLFRenderingHint extends RenderingHints.Key {
public XSLFRenderingHint(int i){
super(i);
}
@Override
public boolean isCompatibleValue(Object val) {
return true;
}
public static final XSLFRenderingHint GSAVE = new XSLFRenderingHint(1);
public static final XSLFRenderingHint GRESTORE = new XSLFRenderingHint(2);
public static final XSLFRenderingHint SKIP_PLACEHOLDERS = new XSLFRenderingHint(3);
}

+ 106
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java View File

@@ -0,0 +1,106 @@
/* ====================================================================
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;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Units;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetColor;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
/**
* Represents a shadow of a shape. For now supports only outer shadows.
*
* @author Yegor Kozlov
*/
public class XSLFShadow extends XSLFSimpleShape {
private XSLFSimpleShape _parent;
/* package */XSLFShadow(CTOuterShadowEffect shape, XSLFSimpleShape parentShape) {
super(shape, parentShape.getSheet());
_parent = parentShape;
}
public void draw(Graphics2D graphics) {
Shape outline = _parent.getOutline();
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);
//fill
Color fillColor = getFillColor();
if (fillColor != null) {
graphics.setColor(fillColor);
graphics.fill(outline);
}
graphics.translate(-dx, -dy);
}
@Override
public Rectangle2D getAnchor(){
return _parent.getAnchor();
}
@Override
public void setAnchor(Rectangle2D anchor){
throw new IllegalStateException("You can't set anchor of a shadow");
}
public double getDistance(){
CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject();
return ct.isSetDist() ? Units.toPoints(ct.getDist()) : 0;
}
public double getAngle(){
CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject();
return ct.isSetDir() ? (double)ct.getDir() / 60000 : 0;
}
public double getBlur(){
CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject();
return ct.isSetBlurRad() ? Units.toPoints(ct.getBlurRad()) : 0;
}
@Override
public Color getFillColor() {
XSLFTheme theme = getSheet().getTheme();
CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject();
if(ct.isSetSchemeClr()) {
return theme.getSchemeColor(ct.getSchemeClr());
}
else if (ct.isSetPrstClr()) {
return theme.getPresetColor(ct.getPrstClr());
}
return Color.black;
}
}

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

@@ -19,10 +19,11 @@
package org.apache.poi.xslf.usermodel;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.util.Beta;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
/**
@@ -41,4 +42,76 @@ public abstract class XSLFShape {
public abstract String getShapeName();
public abstract int getShapeId();
/**
* 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.
*/
public abstract void setRotation(double theta);
/**
* 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
*/
public abstract double getRotation();
public abstract void setFlipHorizontal(boolean flip);
public abstract void setFlipVertical(boolean flip);
/**
* Whether the shape is horizontally flipped
*
* @return whether the shape is horizontally flipped
*/
public abstract boolean getFlipHorizontal();
public abstract boolean getFlipVertical();
public abstract void draw(Graphics2D graphics);
protected java.awt.Shape getOutline(){
return getAnchor();
}
protected void applyTransform(Graphics2D graphics){
Rectangle2D anchor = getAnchor();
// rotation
double rotation = getRotation();
if(rotation != 0.) {
// PowerPoint rotates shapes relative to the geometric center
double centerX = anchor.getX() + anchor.getWidth()/2;
double centerY = anchor.getY() + anchor.getHeight()/2;
graphics.translate(centerX, centerY);
graphics.rotate(Math.toRadians(rotation));
graphics.translate(-centerX, -centerY);
}
//flip horizontal
if(getFlipHorizontal()){
graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
graphics.scale(-1, 1);
graphics.translate(-anchor.getX() , -anchor.getY());
}
//flip vertical
if(getFlipVertical()){
graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
graphics.scale(1, -1);
graphics.translate(-anchor.getX(), -anchor.getY());
}
}
}

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

@@ -21,6 +21,7 @@ import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
@@ -30,9 +31,13 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFra
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;

import javax.xml.namespace.QName;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
@@ -47,6 +52,8 @@ public abstract class XSLFSheet extends POIXMLDocumentPart {
private XSLFDrawing _drawing;
private List<XSLFShape> _shapes;
private CTGroupShape _spTree;
private Map<Integer, XSLFSimpleShape> _placeholderByIdMap;
private Map<Integer, XSLFSimpleShape> _placeholderByTypeMap;

public XSLFSheet() {
super();
@@ -187,6 +194,10 @@ public abstract class XSLFSheet extends POIXMLDocumentPart {
return getShapeList().remove(xShape);
}

public XSLFBackground getBackground(){
return null;
}

protected abstract String getRootElementName();

protected CTGroupShape getSpTree(){
@@ -232,4 +243,112 @@ public abstract class XSLFSheet extends POIXMLDocumentPart {
getXmlObject().set(src.getXmlObject());
}

public XSLFTheme getTheme(){
return null;
}

public XSLFSlideMaster getSlideMaster(){
return null;
}

public XSLFSlideLayout getSlideLayout(){
return null;
}

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

XSLFSimpleShape getPlaceholder(CTPlaceholder ph) {
XSLFSimpleShape shape = null;
if(ph.isSetIdx()) shape = getPlaceholderById((int)ph.getIdx());

if (shape == null && ph.isSetType()) {
shape = getPlaceholderByType(ph.getType().intValue());
}
return shape;
}

XSLFSimpleShape getPlaceholderById(int id) {
if(_placeholderByIdMap == null) {
_placeholderByIdMap = new HashMap<Integer, XSLFSimpleShape>();
for(XSLFShape sh : getShapes()){
if(sh instanceof XSLFSimpleShape){
XSLFSimpleShape sShape = (XSLFSimpleShape)sh;
CTPlaceholder ph = sShape.getCTPlaceholder();
if(ph != null && ph.isSetIdx()){
int idx = (int)ph.getIdx();
_placeholderByIdMap.put(idx, sShape);
}
}
}
}
return _placeholderByIdMap.get(id);
}

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);
}
}
}
}
return _placeholderByTypeMap.get(ordinal);
}

/**
* Checks if this <code>sheet</code> displays the specified shape.
*
* Subclasses can override it and skip certain shapes from drawings.
*/
protected boolean canDraw(XSLFShape shape){
return true;
}

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

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

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

graphics.setRenderingHint(XSLFRenderingHint.GSAVE, true);

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

shape.draw(graphics);

// restore the coordinate system
graphics.setTransform(at0);
graphics.setRenderingHint(XSLFRenderingHint.GRESTORE, true);

}
}
}

+ 499
- 90
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java View File

@@ -21,6 +21,7 @@ package org.apache.poi.xslf.usermodel;
import org.apache.poi.xslf.usermodel.LineCap;
import org.apache.poi.xslf.usermodel.LineDash;
import org.apache.poi.xslf.model.PropertyFetcher;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Units;
import org.apache.xmlbeans.XmlObject;
@@ -28,14 +29,22 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
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.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.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.drawingml.x2006.main.CTOuterShadowEffect;
import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
import java.awt.*;
import java.awt.geom.Rectangle2D;
@@ -48,26 +57,31 @@ public abstract class XSLFSimpleShape extends XSLFShape {
private final XmlObject _shape;
private final XSLFSheet _sheet;
private CTShapeProperties _spPr;
private CTShapeStyle _spStyle;
private CTNonVisualDrawingProps _nvPr;
private CTPlaceholder _ph;
/*package*/ XSLFSimpleShape(XmlObject shape, XSLFSheet sheet){
/* package */XSLFSimpleShape(XmlObject shape, XSLFSheet sheet) {
_shape = shape;
_sheet = sheet;
}
public XmlObject getXmlObject(){
public XmlObject getXmlObject() {
return _shape;
}
public XSLFSheet getSheet(){
public XSLFSheet getSheet() {
return _sheet;
}
/**
* TODO match STShapeType with {@link org.apache.poi.sl.usermodel.ShapeTypes}
* TODO match STShapeType with
* {@link org.apache.poi.sl.usermodel.ShapeTypes}
*/
public int getShapeType() {
STShapeType.Enum stEnum = getSpPr().getPrstGeom().getPrst();
return stEnum.intValue();
CTPresetGeometry2D prst = getSpPr().getPrstGeom();
STShapeType.Enum stEnum = prst == null ? null : prst.getPrst();
return stEnum == null ? 0 : stEnum.intValue();
}
public String getShapeName() {
@@ -75,36 +89,75 @@ public abstract class XSLFSimpleShape extends XSLFShape {
}
public int getShapeId() {
return (int)getNvPr().getId();
return (int) getNvPr().getId();
}
protected CTNonVisualDrawingProps getNvPr(){
if(_nvPr == null){
XmlObject[] rs = _shape.selectPath(
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr");
if(rs.length != 0) {
_nvPr = (CTNonVisualDrawingProps)rs[0];
protected CTNonVisualDrawingProps getNvPr() {
if (_nvPr == null) {
XmlObject[] rs = _shape
.selectPath("declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr");
if (rs.length != 0) {
_nvPr = (CTNonVisualDrawingProps) rs[0];
}
}
return _nvPr;
}
protected CTShapeProperties getSpPr(){
if(_spPr == null) {
for(XmlObject obj : _shape.selectPath("*")){
if(obj instanceof CTShapeProperties){
_spPr = (CTShapeProperties)obj;
protected CTShapeProperties getSpPr() {
if (_spPr == null) {
for (XmlObject obj : _shape.selectPath("*")) {
if (obj instanceof CTShapeProperties) {
_spPr = (CTShapeProperties) obj;
}
}
}
if(_spPr == null) {
if (_spPr == null) {
throw new IllegalStateException("CTShapeProperties was not found.");
}
return _spPr;
}
public Rectangle2D getAnchor(){
CTTransform2D xfrm = getSpPr().getXfrm();
protected CTShapeStyle getSpStyle() {
if (_spStyle == null) {
for (XmlObject obj : _shape.selectPath("*")) {
if (obj instanceof CTShapeStyle) {
_spStyle = (CTShapeStyle) obj;
}
}
}
return _spStyle;
}
protected CTPlaceholder getCTPlaceholder(){
if(_ph == null){
XmlObject[] obj = _shape.selectPath(
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:nvPr/p:ph");
if(obj.length == 1){
_ph = (CTPlaceholder)obj[0];
}
}
return _ph;
}
private CTTransform2D getXfrm(){
PropertyFetcher<CTTransform2D> fetcher = new PropertyFetcher<CTTransform2D>(){
public boolean fetch(XSLFSimpleShape shape){
CTShapeProperties pr = shape.getSpPr();
if(pr.isSetXfrm()){
setValue(pr.getXfrm());
return true;
}
return false;
}
};
fetchShapeProperty(fetcher);
return fetcher.getValue();
}
public Rectangle2D getAnchor() {
CTTransform2D xfrm = getXfrm();
CTPoint2D off = xfrm.getOff();
long x = off.getX();
long y = off.getY();
@@ -116,14 +169,16 @@ public abstract class XSLFSimpleShape extends XSLFShape {
Units.toPoints(cx), Units.toPoints(cy));
}
public void setAnchor(Rectangle2D anchor){
CTTransform2D xfrm = getSpPr().isSetXfrm() ? getSpPr().getXfrm() : getSpPr().addNewXfrm();
public void setAnchor(Rectangle2D anchor) {
CTShapeProperties spPr = getSpPr();
CTTransform2D xfrm = spPr.isSetXfrm() ? spPr.getXfrm() : spPr.addNewXfrm();
CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
long x = Units.toEMU(anchor.getX());
long y = Units.toEMU(anchor.getY());
off.setX(x);
off.setY(y);
CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm.addNewExt();
CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm
.addNewExt();
long cx = Units.toEMU(anchor.getWidth());
long cy = Units.toEMU(anchor.getHeight());
ext.setCx(cx);
@@ -134,135 +189,489 @@ public abstract class XSLFSimpleShape extends XSLFShape {
* 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).
* negative angles are counter-clockwise (i.e., towards the negative y
* axis).
* </p>
*
* @param theta the rotation angle in degrees.
*/
public void setRotation(double theta){
CTTransform2D xfrm = getSpPr().getXfrm();
xfrm.setRot((int)(theta*60000));
public void setRotation(double theta) {
CTShapeProperties spPr = getSpPr();
CTTransform2D xfrm = spPr.isSetXfrm() ? spPr.getXfrm() : spPr.addNewXfrm();
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).
* negative angles are counter-clockwise (i.e., towards the negative y
* axis).
* </p>
*
* @return rotation angle in degrees
*/
public double getRotation(){
CTTransform2D xfrm = getSpPr().getXfrm();
return (double)xfrm.getRot()/60000;
public double getRotation() {
CTTransform2D xfrm = getXfrm();
return (double) xfrm.getRot() / 60000;
}
public void setFlipHorizontal(boolean flip){
CTTransform2D xfrm = getSpPr().getXfrm();
public void setFlipHorizontal(boolean flip) {
CTShapeProperties spPr = getSpPr();
CTTransform2D xfrm = spPr.isSetXfrm() ? spPr.getXfrm() : spPr.addNewXfrm();
xfrm.setFlipH(flip);
}
public void setFlipVertical(boolean flip){
CTTransform2D xfrm = getSpPr().getXfrm();
public void setFlipVertical(boolean flip) {
CTShapeProperties spPr = getSpPr();
CTTransform2D xfrm = spPr.isSetXfrm() ? spPr.getXfrm() : spPr.addNewXfrm();
xfrm.setFlipV(flip);
}
/**
* Whether the shape is horizontally flipped
*
* @return whether the shape is horizontally flipped
*/
public boolean getFlipHorizontal(){
return getSpPr().getXfrm().getFlipH();
public boolean getFlipHorizontal() {
return getXfrm().getFlipH();
}
public boolean getFlipVertical(){
return getSpPr().getXfrm().getFlipV();
public boolean getFlipVertical() {
return getXfrm().getFlipV();
}
public void setLineColor(Color color){
CTShapeProperties spPr = getSpPr();
if(color == null) {
if(spPr.isSetLn() && spPr.getLn().isSetSolidFill()) spPr.getLn().unsetSolidFill();
/**
* Get line properties defined in the theme (if any)
*
* @return line propeties from the theme of null
*/
CTLineProperties getDefaultLineProperties() {
CTLineProperties ln = null;
CTShapeStyle style = getSpStyle();
if (style != null) {
// 1-based index of a line style within the style matrix
int idx = (int) style.getLnRef().getIdx();
CTStyleMatrix styleMatrix = _sheet.getTheme().getXmlObject().getThemeElements().getFmtScheme();
ln = styleMatrix.getLnStyleLst().getLnArray(idx - 1);
}
else {
CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();
return ln;
}
public void setLineColor(Color color) {
CTShapeProperties spPr = getSpPr();
if (color == null) {
if (spPr.isSetLn() && spPr.getLn().isSetSolidFill())
spPr.getLn().unsetSolidFill();
} else {
CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr
.addNewLn();
CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
rgb.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});
rgb.setVal(new byte[]{(byte) color.getRed(),
(byte) color.getGreen(), (byte) color.getBlue()});
CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln.getSolidFill() : ln.addNewSolidFill();
CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln
.getSolidFill() : ln.addNewSolidFill();
fill.setSrgbClr(rgb);
}
}
public Color getLineColor(){
CTShapeProperties spPr = getSpPr();
if(!spPr.isSetLn() || !spPr.getLn().isSetSolidFill()) return null;
CTSRgbColor rgb = spPr.getLn().getSolidFill().getSrgbClr();
byte[] val = rgb.getVal();
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
public Color getLineColor() {
final XSLFTheme theme = _sheet.getTheme();
PropertyFetcher<Color> fetcher = new PropertyFetcher<Color>(){
public boolean fetch(XSLFSimpleShape shape){
CTShapeProperties spPr = shape.getSpPr();
CTLineProperties ln = spPr.getLn();
if (ln != null) {
if (ln.isSetNoFill()) {
setValue(null);
return true;
}
CTSolidColorFillProperties solidLine = ln.getSolidFill();
if (solidLine != null) {
setValue( theme.getSolidFillColor(ln.getSolidFill()) );
return true;
}
}
return false;
}
};
fetchShapeProperty(fetcher);
Color 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) {
CTSchemeColor schemeColor = style.getLnRef().getSchemeClr();
if (schemeColor != null) {
color = theme.getSchemeColor(schemeColor);
}
}
}
return color;
}
public void setLineWidth(double width){
public void setLineWidth(double width) {
CTShapeProperties spPr = getSpPr();
if(width == 0.) {
if(spPr.isSetLn()) spPr.getLn().unsetW();
}
else {
CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();
if (width == 0.) {
if (spPr.isSetLn())
spPr.getLn().unsetW();
} else {
CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr
.addNewLn();
ln.setW(Units.toEMU(width));
}
}
public double getLineWidth(){
CTShapeProperties spPr = getSpPr();
CTLineProperties ln = spPr.getLn();
if(ln == null || !ln.isSetW()) return 0;
public double getLineWidth() {
PropertyFetcher<Double> fetcher = new PropertyFetcher<Double>(){
public boolean fetch(XSLFSimpleShape shape){
CTShapeProperties spPr = shape.getSpPr();
CTLineProperties ln = spPr.getLn();
if (ln != null) {
if (ln.isSetNoFill()) {
setValue(0.);
return true;
}
if (ln.isSetW()) {
setValue( Units.toPoints(ln.getW()) );
return true;
}
}
return false;
}
};
fetchShapeProperty(fetcher);
double lineWidth = 0;
if(fetcher.getValue() == null) {
CTLineProperties defaultLn = getDefaultLineProperties();
if (defaultLn != null) {
if (defaultLn.isSetW()) lineWidth = Units.toPoints(defaultLn.getW());
}
} else {
lineWidth = fetcher.getValue();
}
return Units.toPoints(ln.getW());
return lineWidth;
}
public void setLineDash(LineDash dash){
public void setLineDash(LineDash dash) {
CTShapeProperties spPr = getSpPr();
if(dash == null) {
if(spPr.isSetLn()) spPr.getLn().unsetPrstDash();
}
else {
CTPresetLineDashProperties val = CTPresetLineDashProperties.Factory.newInstance();
if (dash == null) {
if (spPr.isSetLn())
spPr.getLn().unsetPrstDash();
} else {
CTPresetLineDashProperties val = CTPresetLineDashProperties.Factory
.newInstance();
val.setVal(STPresetLineDashVal.Enum.forInt(dash.ordinal() + 1));
CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();
CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr
.addNewLn();
ln.setPrstDash(val);
}
}
public LineDash getLineDash(){
public LineDash getLineDash() {
PropertyFetcher<LineDash> fetcher = new PropertyFetcher<LineDash>(){
public boolean fetch(XSLFSimpleShape shape){
CTShapeProperties spPr = shape.getSpPr();
CTLineProperties ln = spPr.getLn();
if (ln != null) {
CTPresetLineDashProperties ctDash = ln.getPrstDash();
if (ctDash != null) {
setValue( LineDash.values()[ctDash.getVal().intValue() - 1] );
return true;
}
}
return false;
}
};
fetchShapeProperty(fetcher);
LineDash dash = fetcher.getValue();
if(dash == null){
CTLineProperties defaultLn = getDefaultLineProperties();
if (defaultLn != null) {
CTPresetLineDashProperties ctDash = defaultLn.getPrstDash();
if (ctDash != null) {
dash = LineDash.values()[ctDash.getVal().intValue() - 1];
}
}
}
return dash;
}
public void setLineCap(LineCap cap) {
CTShapeProperties spPr = getSpPr();
CTLineProperties ln = spPr.getLn();
if(ln == null || !ln.isSetPrstDash()) return null;
if (cap == null) {
if (spPr.isSetLn())
spPr.getLn().unsetCap();
} else {
CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr
.addNewLn();
ln.setCap(STLineCap.Enum.forInt(cap.ordinal() + 1));
}
}
CTPresetLineDashProperties dash = ln.getPrstDash();
return LineDash.values()[dash.getVal().intValue() - 1];
public LineCap getLineCap() {
PropertyFetcher<LineCap> fetcher = new PropertyFetcher<LineCap>(){
public boolean fetch(XSLFSimpleShape shape){
CTShapeProperties spPr = shape.getSpPr();
CTLineProperties ln = spPr.getLn();
if (ln != null) {
STLineCap.Enum stCap = ln.getCap();
if (stCap != null) {
setValue( LineCap.values()[stCap.intValue() - 1] );
return true;
}
}
return false;
}
};
fetchShapeProperty(fetcher);
LineCap cap = fetcher.getValue();
if(cap == null){
CTLineProperties defaultLn = getDefaultLineProperties();
if (defaultLn != null) {
STLineCap.Enum stCap = defaultLn.getCap();
if (stCap != null) {
cap = LineCap.values()[stCap.intValue() - 1];
}
}
}
return cap;
}
public void setLineCap(LineCap cap){
/**
* Specifies a solid color fill. The shape is filled entirely with the
* specified color.
*
* @param color the solid color fill. The value of <code>null</code> unsets
* the solidFIll attribute from the underlying xml
*/
public void setFillColor(Color color) {
CTShapeProperties spPr = getSpPr();
if(cap == null) {
if(spPr.isSetLn()) spPr.getLn().unsetCap();
if (color == null) {
if (spPr.isSetSolidFill()) spPr.unsetSolidFill();
if(!spPr.isSetNoFill()) spPr.addNewNoFill();
} else {
if(spPr.isSetNoFill()) spPr.unsetNoFill();
CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr
.getSolidFill() : spPr.addNewSolidFill();
CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
rgb.setVal(new byte[]{(byte) color.getRed(),
(byte) color.getGreen(), (byte) color.getBlue()});
fill.setSrgbClr(rgb);
}
else {
CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();
ln.setCap(STLineCap.Enum.forInt(cap.ordinal() + 1));
}
/**
* @return solid fill color of null if not set
*/
public Color getFillColor() {
final XSLFTheme theme = _sheet.getTheme();
PropertyFetcher<Color> fetcher = new PropertyFetcher<Color>(){
public boolean fetch(XSLFSimpleShape shape){
CTShapeProperties spPr = shape.getSpPr();
if (spPr.isSetNoFill()) {
setValue(null);
return true;
}
if (spPr.isSetSolidFill()) {
setValue( theme.getSolidFillColor(spPr.getSolidFill()) );
return true;
}
return false;
}
};
fetchShapeProperty(fetcher);
Color color = fetcher.getValue();
if(color == null){
// fill color was not found, check if it is defined in the theme
CTShapeStyle style = getSpStyle();
if (style != null) {
CTSchemeColor schemeColor = style.getFillRef().getSchemeClr();
if (schemeColor != null) {
color = theme.getSchemeColor(schemeColor);
}
}
}
return color;
}
public LineCap getLineCap(){
CTShapeProperties spPr = getSpPr();
CTLineProperties ln = spPr.getLn();
if(ln == null || !ln.isSetCap()) return null;
public XSLFShadow getShadow(){
PropertyFetcher<CTOuterShadowEffect> fetcher = new PropertyFetcher<CTOuterShadowEffect>(){
public boolean fetch(XSLFSimpleShape shape){
CTShapeProperties spPr = shape.getSpPr();
if (spPr.isSetEffectLst()) {
CTOuterShadowEffect obj = spPr.getEffectLst().getOuterShdw();
setValue(obj);
return true;
}
return false;
}
};
fetchShapeProperty(fetcher);
CTOuterShadowEffect obj = fetcher.getValue();
if(obj == null){
// fill color was not found, check if it is defined in the theme
CTShapeStyle style = getSpStyle();
if (style != null) {
// 1-based index of a shadow style within the style matrix
int idx = (int) style.getEffectRef().getIdx();
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);
}
public void draw(Graphics2D graphics) {
}
protected void applyFill(Graphics2D graphics) {
}
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;
}
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, 0.0f, dash,
dash_phase);
graphics.setStroke(stroke);
}
/**
* Walk up the inheritance tree and fetch properties.
*
* slide <-- slideLayout <-- slideMaster
*
*
* @param visitor the object that collects the desired property
* @return true if the property was fetched
*/
boolean fetchShapeProperty(PropertyFetcher visitor){
boolean ok = visitor.fetch(this);
XSLFSimpleShape masterShape;
if(!ok){
// first try to fetch from the slide layout
XSLFSlideLayout layout = getSheet().getSlideLayout();
if(layout != null) {
CTPlaceholder ph = getCTPlaceholder();
if (ph != null) {
masterShape = layout.getPlaceholder(ph);
if (masterShape != null) {
ok = visitor.fetch(masterShape);
}
}
}
}
// 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);
}
}
}
return LineCap.values()[ln.getCap().intValue() - 1];
return ok;
}
}

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

@@ -16,6 +16,7 @@
==================================================================== */
package org.apache.poi.xslf.usermodel;

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

import org.apache.poi.POIXMLDocumentPart;
@@ -23,16 +24,20 @@ import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Beta;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;
import org.openxmlformats.schemas.presentationml.x2006.main.CTCommonSlideData;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;
import org.openxmlformats.schemas.presentationml.x2006.main.SldDocument;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;

@Beta
public final class XSLFSlide extends XSLFSheet {
@@ -112,6 +117,7 @@ public final class XSLFSlide extends XSLFSheet {
return getSlideLayout().getSlideMaster();
}

@Override
public XSLFSlideLayout getSlideLayout(){
if(_layout == null){
for (POIXMLDocumentPart p : getRelations()) {
@@ -125,7 +131,12 @@ public final class XSLFSlide extends XSLFSheet {
}
return _layout;
}

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

public XSLFComments getComments() {
if(_comments == null) {
for (POIXMLDocumentPart p : getRelations()) {
@@ -165,4 +176,37 @@ public final class XSLFSlide extends XSLFSheet {
public boolean getFollowMasterBackground(){
return !_slide.isSetShowMasterSp() || _slide.getShowMasterSp();
}

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

@Override
public void draw(Graphics2D graphics){

if (getFollowMasterBackground()){
XSLFSlideLayout layout = getSlideLayout();
layout.draw(graphics);
}

super.draw(graphics);
}

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

}

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

@@ -22,11 +22,18 @@ import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideLayout;
import org.openxmlformats.schemas.presentationml.x2006.main.SldLayoutDocument;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMaster;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;

import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
import java.awt.*;
import java.awt.geom.AffineTransform;

@Beta
public class XSLFSlideLayout extends XSLFSheet {
@@ -84,6 +91,7 @@ public class XSLFSlideLayout extends XSLFSheet {
* @return slide master. Never null.
* @throws IllegalStateException if slide master was not found
*/
@Override
public XSLFSlideMaster getSlideMaster(){
if(_master == null){
for (POIXMLDocumentPart p : getRelations()) {
@@ -101,4 +109,40 @@ public class XSLFSlideLayout extends XSLFSheet {
public XMLSlideShow getSlideShow() {
return (XMLSlideShow)getParent().getParent();
}
public XSLFTheme getTheme(){
return getSlideMaster().getTheme();
}


@Override
protected CTTextListStyle getTextProperties(Placeholder textType) {
XSLFTextShape lp = getTextShapeByType(textType);
CTTextListStyle props = lp.getTextBody(false).getLstStyle();
return props;
}

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

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

+ 22
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java View File

@@ -24,6 +24,8 @@ import org.apache.poi.util.Beta;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMaster;
import org.openxmlformats.schemas.presentationml.x2006.main.SldMasterDocument;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMasterTextStyles;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;

import java.io.IOException;
import java.util.HashMap;
@@ -101,4 +103,24 @@ import java.util.Map;
}
return _theme;
}

protected CTTextListStyle getTextProperties(Placeholder textType) {
CTTextListStyle props;
CTSlideMasterTextStyles txStyles = getXmlObject().getTxStyles();
switch (textType){
case TITLE:
case CENTERED_TITLE:
case SUBTITLE:
props = txStyles.getTitleStyle();
break;
case BODY:
props = txStyles.getBodyStyle();
break;
default:
props = txStyles.getOtherStyle();
break;
}
return props;
}

}

+ 0
- 28
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java View File

@@ -126,32 +126,4 @@ public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow
gr.setUri(TABLE_URI);
return frame;
}
public Rectangle2D getAnchor(){
CTTransform2D xfrm = getXmlObject().getXfrm();
CTPoint2D off = xfrm.getOff();
long x = off.getX();
long y = off.getY();
CTPositiveSize2D ext = xfrm.getExt();
long cx = ext.getCx();
long cy = ext.getCy();
return new Rectangle2D.Double(
Units.toPoints(x), Units.toPoints(y),
Units.toPoints(cx), Units.toPoints(cy));
}
public void setAnchor(Rectangle2D anchor){
CTTransform2D xfrm = getXmlObject().getXfrm();
CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
long x = Units.toEMU(anchor.getX());
long y = Units.toEMU(anchor.getY());
off.setX(x);
off.setY(y);
CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm.addNewExt();
long cx = Units.toEMU(anchor.getWidth());
long cy = Units.toEMU(anchor.getHeight());
ext.setCx(cx);
ext.setCy(cy);
}
}

+ 6
- 10
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java View File

@@ -21,17 +21,23 @@ package org.apache.poi.xslf.usermodel;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Units;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
import java.awt.geom.Rectangle2D;
/**
* @author Yegor Kozlov
@@ -84,14 +90,4 @@ public class XSLFTextBox extends XSLFAutoShape {
nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ordinal() + 1));
}
}
public Placeholder getPlaceholder(){
CTShape sh = (CTShape)getXmlObject();
CTPlaceholder ph = sh.getNvSpPr().getNvPr().getPh();
if(ph == null) return null;
else {
int val = ph.getType().intValue();
return Placeholder.values()[val - 1];
}
}
}

+ 418
- 34
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java View File

@@ -19,15 +19,28 @@ package org.apache.poi.xslf.usermodel;
import org.apache.poi.util.Beta;
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.ParagraphPropertyFetcher;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.font.TextLayout;
import java.awt.font.TextAttribute;
import java.awt.font.LineBreakMeasurer;
import java.text.AttributedString;
import java.text.AttributedCharacterIterator;
/**
* Represents a paragraph of text within the containing text body.
@@ -41,20 +54,29 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
private final CTTextParagraph _p;
private final List<XSLFTextRun> _runs;
private final XSLFTextShape _shape;
private List<TextFragment> _lines;
private TextFragment _bullet;
XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){
_p = p;
_runs = new ArrayList<XSLFTextRun>();
_shape = shape;
for (CTRegularTextRun r : _p.getRList()) {
_runs.add(new XSLFTextRun(r, this));
}
for (CTTextField f : _p.getFldList()) {
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
r.setT(f.getT());
_runs.add(new XSLFTextRun(r, this));
}
}
public String getText(){
StringBuilder out = new StringBuilder();
for (CTRegularTextRun r : _p.getRList()) {
out.append(r.getT());
for (XSLFTextRun r : _runs) {
out.append(r.getText());
}
return out.toString();
}
@@ -95,10 +117,18 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
* @return ??? alignment that is applied to the paragraph
*/
public TextAlign getTextAlign(){
CTTextParagraphProperties pr = _p.getPPr();
if(pr == null || !pr.isSetAlgn()) return TextAlign.LEFT;
return TextAlign.values()[pr.getAlgn().intValue() - 1];
ParagraphPropertyFetcher<TextAlign> fetcher = new ParagraphPropertyFetcher<TextAlign>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){
if(props.isSetAlgn()){
TextAlign val = TextAlign.values()[props.getAlgn().intValue() - 1];
setValue(val);
return true;
}
return false;
}
};
fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? TextAlign.LEFT : fetcher.getValue();
}
/**
@@ -117,6 +147,74 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
}
}
/**
* @return the font to be used on bullet characters within a given paragraph
*/
public String getBulletFont(){
ParagraphPropertyFetcher<String> fetcher = new ParagraphPropertyFetcher<String>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){
if(props.isSetBuFont()){
setValue(props.getBuFont().getTypeface());
return true;
}
return false;
}
};
fetchParagraphProperty(fetcher);
return fetcher.getValue();
}
/**
* @return the character to be used in place of the standard bullet point
*/
public String getBulletCharacter(){
ParagraphPropertyFetcher<String> fetcher = new ParagraphPropertyFetcher<String>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){
if(props.isSetBuChar()){
setValue(props.getBuChar().getChar());
return true;
}
return false;
}
};
fetchParagraphProperty(fetcher);
return fetcher.getValue();
}
public Color getBulletFontColor(){
final XSLFTheme theme = getParentShape().getSheet().getTheme();
ParagraphPropertyFetcher<Color> fetcher = new ParagraphPropertyFetcher<Color>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){
if(props.isSetBuClr()){
setValue(theme.getColor(props.getBuClr()));
return true;
}
return false;
}
};
fetchParagraphProperty(fetcher);
return fetcher.getValue();
}
public double getBulletFontSize(){
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){
if(props.isSetBuSzPct()){
setValue(props.getBuSzPct().getVal() * 0.001);
return true;
}
if(props.isSetBuSzPts()){
setValue( - props.getBuSzPts().getVal() * 0.01);
return true;
}
return false;
}
};
fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? 100 : fetcher.getValue();
}
/**
* Specifies the indent size that will be applied to the first line of text in the paragraph.
*
@@ -137,10 +235,19 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
* @return the indent applied to the first line of text in the paragraph.
*/
public double getIndent(){
CTTextParagraphProperties pr = _p.getPPr();
if(pr == null || !pr.isSetIndent()) return 0;
return Units.toPoints(pr.getIndent());
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){
if(props.isSetIndent()){
setValue(Units.toPoints(props.getIndent()));
return true;
}
return false;
}
};
fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? 0 : fetcher.getValue();
}
/**
@@ -160,10 +267,18 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
* @return the left margin of the paragraph
*/
public double getLeftMargin(){
CTTextParagraphProperties pr = _p.getPPr();
if(pr == null || !pr.isSetMarL()) return 0;
return Units.toPoints(pr.getMarL());
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){
if(props.isSetMarL()){
double val = Units.toPoints(props.getMarL());
setValue(val);
return true;
}
return false;
}
};
fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? 0 : fetcher.getValue();
}
/**
@@ -206,13 +321,20 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
* @return the vertical line spacing.
*/
public double getLineSpacing(){
CTTextParagraphProperties pr = _p.getPPr();
if(pr == null || !pr.isSetLnSpc()) return 100; // TODO fetch from master
CTTextSpacing spc = pr.getLnSpc();
if(spc.isSetSpcPct()) return spc.getSpcPct().getVal()*0.001;
else if (spc.isSetSpcPts()) return -spc.getSpcPts().getVal()*0.01;
else return 100;
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){
if(props.isSetLnSpc()){
CTTextSpacing spc = props.getLnSpc();
if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 );
else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 );
return true;
}
return false;
}
};
fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? 100 : fetcher.getValue();
}
/**
@@ -253,13 +375,20 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
* @return the vertical white space before the paragraph
*/
public double getSpaceBefore(){
CTTextParagraphProperties pr = _p.getPPr();
if(pr == null || !pr.isSetSpcBef()) return 0; // TODO fetch from master
CTTextSpacing spc = pr.getSpcBef();
if(spc.isSetSpcPct()) return spc.getSpcPct().getVal()*0.001;
else if (spc.isSetSpcPts()) return -spc.getSpcPts().getVal()*0.01;
else return 0;
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){
if(props.isSetSpcBef()){
CTTextSpacing spc = props.getSpcBef();
if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 );
else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 );
return true;
}
return false;
}
};
fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? 0 : fetcher.getValue();
}
/**
@@ -300,13 +429,20 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
* @return the vertical white space after the paragraph
*/
public double getSpaceAfter(){
CTTextParagraphProperties pr = _p.getPPr();
if(pr == null || !pr.isSetSpcAft()) return 0; // TODO fetch from master
CTTextSpacing spc = pr.getSpcAft();
if(spc.isSetSpcPct()) return spc.getSpcPct().getVal()*0.001;
else if (spc.isSetSpcPts()) return -spc.getSpcPts().getVal()*0.01;
else return 0;
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){
if(props.isSetSpcAft()){
CTTextSpacing spc = props.getSpcAft();
if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 );
else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 );
return true;
}
return false;
}
};
fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? 0 : fetcher.getValue();
}
/**
@@ -334,8 +470,256 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
}
/**
* Returns whether this paragraph has bullets
*/
public boolean isBullet() {
ParagraphPropertyFetcher<Boolean> fetcher = new ParagraphPropertyFetcher<Boolean>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){
if(props.isSetBuNone()) {
setValue(false);
return true;
}
if(props.isSetBuFont()){
setValue(true);
return true;
}
return false;
}
};
fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? false : fetcher.getValue();
}
@Override
public String toString(){
return "[" + getClass() + "]" + getText();
}
public List<TextFragment> getTextLines(){
return _lines;
}
public double draw(Graphics2D graphics, double x, double y){
double marginLeft = _shape.getMarginLeft();
double marginRight = _shape.getMarginRight();
Rectangle2D anchor = _shape.getAnchor();
double penY = y;
double textOffset = getLeftMargin();
for(TextFragment line : _lines){
double penX = x;
switch (getTextAlign()) {
case CENTER:
penX += textOffset + (anchor.getWidth() - textOffset - line.getWidth() - marginLeft - marginRight) / 2;
break;
case RIGHT:
penX += (anchor.getWidth() - line.getWidth() - marginLeft - marginRight);
break;
default:
penX = x + textOffset;
break;
}
if(_bullet != null){
_bullet.draw(graphics, penX + getIndent(), penY);
}
line.draw(graphics, penX, penY);
//The vertical line spacing
double spacing = getLineSpacing();
if(spacing > 0) {
// If linespacing >= 0, then linespacing is a percentage of normal line height.
penY += spacing*0.01*line.getHeight();
} else {
// positive value means absolute spacing in points
penY += -spacing;
}
}
return penY - y;
}
static class TextFragment {
private TextLayout _layout;
private AttributedString _str;
TextFragment(TextLayout layout, AttributedString str){
_layout = layout;
_str = str;
}
void draw(Graphics2D graphics, double x, double y){
double yBaseline = y + _layout.getAscent();
graphics.drawString(_str.getIterator(), (float)x, (float)yBaseline );
}
public float getHeight(){
return _layout.getAscent() + _layout.getDescent() + _layout.getLeading();
}
public float getWidth(){
return _layout.getAdvance();
}
}
public AttributedString getAttributedString(){
String text = getText();
AttributedString string = new AttributedString(text);
int startIndex = 0;
for (XSLFTextRun run : _runs){
int length = run.getText().length();
if(length == 0) {
// skip empty runs
continue;
}
int endIndex = startIndex + length;
string.addAttribute(TextAttribute.FOREGROUND, run.getFontColor(), startIndex, endIndex);
string.addAttribute(TextAttribute.FAMILY, run.getFontFamily(), startIndex, endIndex);
string.addAttribute(TextAttribute.SIZE, run.getFontSize(), startIndex, endIndex);
if(run.isBold()) {
string.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, startIndex, endIndex);
}
if(run.isItalic()) {
string.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE, startIndex, endIndex);
}
if(run.isUnderline()) {
string.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON, startIndex, endIndex);
}
if(run.isStrikethrough()) {
string.addAttribute(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON, startIndex, endIndex);
}
startIndex = endIndex;
}
return string;
}
void breakText(Graphics2D graphics){
_lines = new ArrayList<TextFragment>();
AttributedString at = getAttributedString();
AttributedCharacterIterator it = at.getIterator();
if(it.getBeginIndex() == it.getEndIndex()) {
return;
}
LineBreakMeasurer measurer = new LineBreakMeasurer(it, graphics.getFontRenderContext());
for (;;) {
int startIndex = measurer.getPosition();
double wrappingWidth = getWrappingWidth() + 1; // add a pixel to compensate rounding errors
TextLayout layout = measurer.nextLayout((float)wrappingWidth, it.getEndIndex(), true);
if (layout == null) {
// layout can be null if the entire word at the current position
// does not fit within the wrapping width. Try with requireNextWord=false.
layout = measurer.nextLayout((float)wrappingWidth, it.getEndIndex(), false);
}
int endIndex = measurer.getPosition();
if(getTextAlign() == TextAlign.JUSTIFY) {
layout = layout.getJustifiedLayout((float)wrappingWidth);
}
AttributedString str = new AttributedString(it, startIndex, endIndex);
TextFragment line = new TextFragment(layout, str);
_lines.add(line);
if(endIndex == it.getEndIndex()) break;
}
if(isBullet()) {
String buCharacter = getBulletCharacter();
String buFont = getBulletFont();
if(buCharacter != null && buFont != null && _lines.size() > 0) {
AttributedString str = new AttributedString(buCharacter);
TextFragment firstLine = _lines.get(0);
AttributedCharacterIterator bit = firstLine._str.getIterator();
Color buColor = getBulletFontColor();
str.addAttribute(TextAttribute.FOREGROUND, buColor == null ?
bit.getAttribute(TextAttribute.FOREGROUND) : buColor);
str.addAttribute(TextAttribute.FAMILY, buFont);
double fontSize = (Double)bit.getAttribute(TextAttribute.SIZE);
double buSz = getBulletFontSize();
if(buSz > 0) fontSize *= buSz* 0.01;
else fontSize = -buSz;
str.addAttribute(TextAttribute.SIZE, fontSize);
TextLayout layout = new TextLayout(str.getIterator(), graphics.getFontRenderContext());
_bullet = new TextFragment(layout, str);
}
}
}
double getWrappingWidth(){
double width;
if(!_shape.getWordWrap()) {
width = _shape.getSheet().getSlideShow().getPageSize().getWidth();
} else {
width = _shape.getAnchor().getWidth() -
_shape.getMarginLeft() - _shape.getMarginRight() - getLeftMargin();
}
return width;
}
CTTextParagraphProperties getDefaultStyle(){
CTPlaceholder ph = _shape.getCTPlaceholder();
String defaultStyleSelector;
if(ph == null) defaultStyleSelector = "otherStyle";
else {
switch(ph.getType().intValue()){
case STPlaceholderType.INT_TITLE:
case STPlaceholderType.INT_CTR_TITLE:
defaultStyleSelector = "titleStyle";
break;
case STPlaceholderType.INT_FTR:
case STPlaceholderType.INT_SLD_NUM:
case STPlaceholderType.INT_DT:
defaultStyleSelector = "otherStyle";
break;
default:
defaultStyleSelector = "bodyStyle";
break;
}
}
int level = getLevel();
XmlObject[] o = _shape.getSheet().getSlideMaster().getXmlObject().selectPath(
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " +
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " +
".//p:txStyles/p:" + defaultStyleSelector +"/a:lvl" +(level+1)+ "pPr");
if(o.length == 1){
return (CTTextParagraphProperties)o[0];
}
throw new IllegalArgumentException("Failed to fetch default style for " +
defaultStyleSelector + " and level=" + level);
}
private boolean fetchParagraphProperty(ParagraphPropertyFetcher visitor){
boolean ok = false;
if(_p.isSetPPr()) ok = visitor.fetch(_p.getPPr());
if(!ok) {
XSLFTextShape shape = getParentShape();
ok = shape.fetchShapeProperty(visitor);
if(!ok) {
CTTextParagraphProperties defaultProps = getDefaultStyle();
if(defaultProps != null) ok = visitor.fetch(defaultProps);
}
}
return ok;
}
}

+ 117
- 19
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java View File

@@ -17,6 +17,8 @@
package org.apache.poi.xslf.usermodel;
import org.apache.poi.util.Beta;
import org.apache.poi.xslf.model.CharacterPropertyFetcher;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
@@ -24,6 +26,9 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
import java.awt.*;
@@ -66,6 +71,23 @@ public class XSLFTextRun {
clr.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});
}
public Color getFontColor(){
final XSLFTheme theme = _p.getParentShape().getSheet().getTheme();
CharacterPropertyFetcher<Color> fetcher = new CharacterPropertyFetcher<Color>(_p.getLevel()){
public boolean fetch(CTTextCharacterProperties props){
CTSolidColorFillProperties solidFill = props.getSolidFill();
if(solidFill != null){
setValue(theme.getSolidFillColor(solidFill));
return true;
}
return false;
}
};
fetchCharacterProperty(fetcher);
return fetcher.getValue();
}
/**
*
* @param fontSize font size in points.
@@ -84,9 +106,17 @@ public class XSLFTextRun {
* @return font size in points or -1 if font size is not set.
*/
public double getFontSize(){
if(!_r.isSetRPr() || !_r.getRPr().isSetSz()) return -1;
return _r.getRPr().getSz()*0.01;
CharacterPropertyFetcher<Double> fetcher = new CharacterPropertyFetcher<Double>(_p.getLevel()){
public boolean fetch(CTTextCharacterProperties props){
if(props.isSetSz()){
setValue(props.getSz()*0.01);
return true;
}
return false;
}
};
fetchCharacterProperty(fetcher);
return fetcher.getValue() == null ? -1 : fetcher.getValue();
}
/**
@@ -120,12 +150,30 @@ public class XSLFTextRun {
}
/**
* @return font family or null if niot set
* @return font family or null if not set
*/
public String getFontFamily(){
if(!_r.isSetRPr() || !_r.getRPr().isSetLatin()) return null;
final XSLFTheme theme = _p.getParentShape().getSheet().getTheme();
CharacterPropertyFetcher<String> visitor = new CharacterPropertyFetcher<String>(_p.getLevel()){
public boolean fetch(CTTextCharacterProperties props){
CTTextFont font = props.getLatin();
if(font != null){
String typeface = font.getTypeface();
if("+mj-lt".equals(typeface)) {
typeface = theme.getMajorFont();
} else if ("+mn-lt".equals(typeface)){
typeface = theme.getMinorFont();
}
setValue(typeface);
return true;
}
return false;
}
};
fetchCharacterProperty(visitor);
return _r.getRPr().getLatin().getTypeface();
return visitor.getValue();
}
/**
@@ -140,10 +188,18 @@ public class XSLFTextRun {
/**
* @return whether a run of text will be formatted as strikethrough text. Default is false.
*/
public boolean isStrikethrough(){
if(!_r.isSetRPr()) return false;
return _r.getRPr().getStrike() == STTextStrikeType.SNG_STRIKE;
public boolean isStrikethrough() {
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getLevel()){
public boolean fetch(CTTextCharacterProperties props){
if(props.isSetStrike()){
setValue(props.getStrike() != STTextStrikeType.NO_STRIKE);
return true;
}
return false;
}
};
fetchCharacterProperty(fetcher);
return fetcher.getValue() == null ? false : fetcher.getValue();
}
/**
@@ -159,9 +215,17 @@ public class XSLFTextRun {
* @return whether this run of text is formatted as bold text
*/
public boolean isBold(){
if(!_r.isSetRPr()) return false;
return _r.getRPr().getB();
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getLevel()){
public boolean fetch(CTTextCharacterProperties props){
if(props.isSetB()){
setValue(props.getB());
return true;
}
return false;
}
};
fetchCharacterProperty(fetcher);
return fetcher.getValue() == null ? false : fetcher.getValue();
}
/**
@@ -175,9 +239,17 @@ public class XSLFTextRun {
* @return whether this run of text is formatted as italic text
*/
public boolean isItalic(){
if(!_r.isSetRPr()) return false;
return _r.getRPr().getI();
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getLevel()){
public boolean fetch(CTTextCharacterProperties props){
if(props.isSetI()){
setValue(props.getI());
return true;
}
return false;
}
};
fetchCharacterProperty(fetcher);
return fetcher.getValue() == null ? false : fetcher.getValue();
}
/**
@@ -191,9 +263,17 @@ public class XSLFTextRun {
* @return whether this run of text is formatted as underlined text
*/
public boolean isUnderline(){
if(!_r.isSetRPr() || !_r.getRPr().isSetU()) return false;
return _r.getRPr().getU() != STTextUnderlineType.NONE;
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getLevel()){
public boolean fetch(CTTextCharacterProperties props){
if(props.isSetU()){
setValue(props.getU() != STTextUnderlineType.NONE);
return true;
}
return false;
}
};
fetchCharacterProperty(fetcher);
return fetcher.getValue() == null ? false : fetcher.getValue();
}
protected CTTextCharacterProperties getRpR(){
@@ -216,4 +296,22 @@ public class XSLFTextRun {
return new XSLFHyperlink(_r.getRPr().getHlinkClick(), this);
}
private boolean fetchCharacterProperty(CharacterPropertyFetcher fetcher){
boolean ok = false;
if(_r.isSetRPr()) ok = fetcher.fetch(_r.getRPr());
if(!ok) {
XSLFTextShape shape = _p.getParentShape();
ok = shape.fetchShapeProperty(fetcher);
if(!ok) {
CTTextParagraphProperties defaultProps = _p.getDefaultStyle();
if(defaultProps != null) ok = fetcher.fetch(defaultProps);
}
}
return ok;
}
}

+ 203
- 72
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java View File

@@ -21,18 +21,20 @@ package org.apache.poi.xslf.usermodel;

import org.apache.poi.util.Beta;
import org.apache.poi.util.Units;
import org.apache.poi.xslf.model.PropertyFetcher;
import org.apache.poi.xslf.model.TextBodyPropertyFetcher;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;

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

@@ -79,43 +81,6 @@ public abstract class XSLFTextShape extends XSLFSimpleShape {
return paragraph;
}

/**
* Specifies a solid color fill. The shape is filled entirely with the specified color.
*
* @param color the solid color fill.
* The value of <code>null</code> unsets the solidFIll attribute from the underlying xml
*/
public void setFillColor(Color color) {
CTShapeProperties spPr = getSpPr();
if (color == null) {
if(spPr.isSetSolidFill()) spPr.unsetSolidFill();
}
else {
CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill();

CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
rgb.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()});

fill.setSrgbClr(rgb);
}
}

/**
*
* @return solid fill color of null if not set
*/
public Color getFillColor(){
CTShapeProperties spPr = getSpPr();
if(!spPr.isSetSolidFill() ) return null;

CTSolidColorFillProperties fill = spPr.getSolidFill();
if(!fill.isSetSrgbClr()) {
// TODO for now return null for all colors except explicit RGB
return null;
}
byte[] val = fill.getSrgbClr().getVal();
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
}

/**
* Sets the type of vertical alignment for the text.
@@ -140,14 +105,18 @@ public abstract class XSLFTextShape extends XSLFSimpleShape {
* @return the type of alignment
*/
public VerticalAlignment getVerticalAlignment(){
CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) {
STTextAnchoringType.Enum val = bodyPr.getAnchor();
if(val != null){
return VerticalAlignment.values()[val.intValue() - 1];
PropertyFetcher<VerticalAlignment> fetcher = new TextBodyPropertyFetcher<VerticalAlignment>(){
public boolean fetch(CTTextBodyProperties props){
if(props.isSetAnchor()){
int val = props.getAnchor().intValue();
setValue(VerticalAlignment.values()[val - 1]);
return true;
}
return false;
}
}
return VerticalAlignment.TOP;
};
fetchShapeProperty(fetcher);
return fetcher.getValue() == null ? VerticalAlignment.TOP : fetcher.getValue();
}

/**
@@ -185,11 +154,18 @@ public abstract class XSLFTextShape extends XSLFSimpleShape {
* @return the bottom margin or -1 if not set
*/
public double getMarginBottom(){
CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) {
return bodyPr.isSetBIns() ? Units.toPoints(bodyPr.getBIns()) : -1;
}
return -1;
PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){
public boolean fetch(CTTextBodyProperties props){
if(props.isSetBIns()){
double val = Units.toPoints(props.getBIns());
setValue(val);
return true;
}
return false;
}
};
fetchShapeProperty(fetcher);
return fetcher.getValue() == null ? 0 : fetcher.getValue();
}

/**
@@ -200,11 +176,18 @@ public abstract class XSLFTextShape extends XSLFSimpleShape {
* @return the left margin
*/
public double getMarginLeft(){
CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) {
return bodyPr.isSetLIns() ? Units.toPoints(bodyPr.getLIns()) : -1;
}
return -1;
PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){
public boolean fetch(CTTextBodyProperties props){
if(props.isSetLIns()){
double val = Units.toPoints(props.getLIns());
setValue(val);
return true;
}
return false;
}
};
fetchShapeProperty(fetcher);
return fetcher.getValue() == null ? 0 : fetcher.getValue();
}

/**
@@ -215,11 +198,18 @@ public abstract class XSLFTextShape extends XSLFSimpleShape {
* @return the right margin
*/
public double getMarginRight(){
CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) {
return bodyPr.isSetRIns() ? Units.toPoints(bodyPr.getRIns()) : -1;
}
return -1;
PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){
public boolean fetch(CTTextBodyProperties props){
if(props.isSetRIns()){
double val = Units.toPoints(props.getRIns());
setValue(val);
return true;
}
return false;
}
};
fetchShapeProperty(fetcher);
return fetcher.getValue() == null ? 0 : fetcher.getValue();
}

/**
@@ -229,11 +219,18 @@ public abstract class XSLFTextShape extends XSLFSimpleShape {
* @return the top margin
*/
public double getMarginTop(){
CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) {
return bodyPr.isSetTIns() ? Units.toPoints(bodyPr.getTIns()) : -1;
}
return -1;
PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>(){
public boolean fetch(CTTextBodyProperties props){
if(props.isSetTIns()){
double val = Units.toPoints(props.getTIns());
setValue(val);
return true;
}
return false;
}
};
fetchShapeProperty(fetcher);
return fetcher.getValue() == null ? 0 : fetcher.getValue();
}

/**
@@ -300,11 +297,17 @@ public abstract class XSLFTextShape extends XSLFSimpleShape {
* @return the value indicating word wrap
*/
public boolean getWordWrap(){
CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) {
return bodyPr.getWrap() == STTextWrappingType.SQUARE;
}
return false;
PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>(){
public boolean fetch(CTTextBodyProperties props){
if(props.isSetWrap()){
setValue(props.getWrap() == STTextWrappingType.SQUARE);
return true;
}
return false;
}
};
fetchShapeProperty(fetcher);
return fetcher.getValue() == null ? true : fetcher.getValue();
}

/**
@@ -362,4 +365,132 @@ public abstract class XSLFTextShape extends XSLFSimpleShape {


protected abstract CTTextBody getTextBody(boolean create);


public Placeholder getTextType(){
CTPlaceholder ph;
XmlObject[] obj = getXmlObject().selectPath(
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:nvPr/p:ph");
if(obj.length == 1){
ph = (CTPlaceholder)obj[0];
int val = ph.getType().intValue();
return Placeholder.values()[val - 1];
}
else {
return null;
}
}

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

// shadow
XSLFShadow shadow = getShadow();
if(shadow != null) shadow.draw(graphics);

//fill
Color fillColor = getFillColor();
if (fillColor != null) {
graphics.setColor(fillColor);
applyFill(graphics);
graphics.fill(outline);
}
//border
Color lineColor = getLineColor();
if (lineColor != null){
graphics.setColor(lineColor);
applyStroke(graphics);
graphics.draw(outline);
}

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

/**
* Compute the cumulative height occupied by the text
*/
private double getTextHeight(){
// dry-run in a 1x1 image and return the vertical advance
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
return drawParagraphs(img.createGraphics(), 0, 0);
}

void breakText(Graphics2D graphics){
for(XSLFTextParagraph p : _paragraphs) p.breakText(graphics);
}

public void drawText(Graphics2D graphics) {
breakText(graphics);

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

// first dry-run to calculate the total height of the text
double textHeight = getTextHeight();

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

drawParagraphs(graphics, x, y);

}


/**
* pain the paragraphs starting from top left (x,y)
*
* @return the vertical advance, i.e. the cumulative space occupied by the text
*/
private double drawParagraphs(Graphics2D graphics, double x, double y) {
double y0 = y;
for(int i = 0; i < _paragraphs.size(); i++){
XSLFTextParagraph p = _paragraphs.get(i);
java.util.List<XSLFTextParagraph.TextFragment> lines = p.getTextLines();

if(i > 0 && lines.size() > 0) {
// the amount of vertical white space before the paragraph
double spaceBefore = p.getSpaceBefore();
if(spaceBefore > 0) {
// positive value means percentage spacing of the height of the first line, e.g.
// the higher the first line, the bigger the space before the paragraph
y += spaceBefore*0.01*lines.get(0).getHeight();
} else {
// negative value means the absolute spacing in points
y += -spaceBefore;
}
}

y += p.draw(graphics, x, y);

if(i < _paragraphs.size() - 1) {
double spaceAfter = p.getSpaceAfter();
if(spaceAfter > 0) {
// positive value means percentage spacing of the height of the last line, e.g.
// the higher the last line, the bigger the space after the paragraph
y += spaceAfter*0.01*lines.get(lines.size() - 1).getHeight();
} else {
// negative value means the absolute spacing in points
y += -spaceAfter;
}
}
}
return y - y0;
}

}

+ 196
- 6
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTheme.java View File

@@ -22,15 +22,21 @@ import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideLayout;
import org.openxmlformats.schemas.presentationml.x2006.main.SldLayoutDocument;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMaster;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBaseStyles;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorScheme;
import org.openxmlformats.schemas.drawingml.x2006.main.ThemeDocument;
import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeStyleSheet;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetColor;

import javax.xml.namespace.QName;

import java.awt.Color;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
@@ -39,7 +45,8 @@ import java.util.HashMap;
@Beta
public class XSLFTheme extends POIXMLDocumentPart {
private CTOfficeStyleSheet _theme;

private Map<String, XSLFColor> _schemeColors;
XSLFTheme() {
super();
_theme = CTOfficeStyleSheet.Factory.newInstance();
@@ -50,8 +57,24 @@ public class XSLFTheme extends POIXMLDocumentPart {
ThemeDocument doc =
ThemeDocument.Factory.parse(getPackagePart().getInputStream());
_theme = doc.getTheme();
initialize();
}

private void initialize(){
CTBaseStyles elems = _theme.getThemeElements();
CTColorScheme scheme = elems.getClrScheme();
// The color scheme is responsible for defining a list of twelve colors.
_schemeColors = new HashMap<String, XSLFColor>(12);
for(XmlObject o : scheme.selectPath("*")){
CTColor c = (CTColor)o;
String name = c.getDomNode().getLocalName();
_schemeColors.put(name, new XSLFColor(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"));
}

public String getName(){
return _theme.getName();
@@ -62,6 +85,146 @@ public class XSLFTheme extends POIXMLDocumentPart {
}

/**
* Get a color from the theme's color scheme by name
*
* @return a theme color or <code>null</code> if not found
*/
public XSLFColor getColor(String name){
return _schemeColors.get(name);
}
Color getSchemeColor(CTSchemeColor schemeColor){
String colorRef = schemeColor.getVal().toString();
int alpha = 0xFF;
if(schemeColor.sizeOfAlphaArray() > 0){
int aval = schemeColor.getAlphaArray(0).getVal();
alpha = Math.round(255 * aval / 100000f);
}
Color themeColor = _schemeColors.get(colorRef).getColor(alpha);

int lumMod = 100, lumOff = 0;
if (schemeColor.sizeOfLumModArray() > 0) {
lumMod = schemeColor.getLumModArray(0).getVal() / 1000;
}
if (schemeColor.sizeOfLumOffArray() > 0) {
lumOff = schemeColor.getLumOffArray(0).getVal() / 1000;
}
if(schemeColor.sizeOfShadeArray() > 0) {
lumMod = schemeColor.getShadeArray(0).getVal() / 1000;
}
Color color = modulateLuminanace(themeColor, lumMod, lumOff);

if(schemeColor.sizeOfTintArray() > 0) {
float tint = schemeColor.getTintArray(0).getVal() / 100000f;
int red = Math.round(tint * themeColor.getRed() + (1 - tint) * 255);
int green = Math.round(tint * themeColor.getGreen() + (1 - tint) * 255);
int blue = Math.round(tint * themeColor.getBlue() + (1 - tint) * 255);
color = new Color(red, green, blue);
}

return color;
}

/**
* TODO get rid of code duplication. Re-write to use xpath instead of beans
*/
Color getPresetColor(CTPresetColor presetColor){
String colorName = presetColor.getVal().toString();
Color color;
try {
color = (Color)Color.class.getField(colorName).get(null);
} catch (Exception e){
color = Color.black;
}
if(presetColor.sizeOfAlphaArray() > 0){
int aval = presetColor.getAlphaArray(0).getVal();
int alpha = Math.round(255 * aval / 100000f);
color = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
}

int lumMod = 100, lumOff = 0;
if (presetColor.sizeOfLumModArray() > 0) {
lumMod = presetColor.getLumModArray(0).getVal() / 1000;
}
if (presetColor.sizeOfLumOffArray() > 0) {
lumOff = presetColor.getLumOffArray(0).getVal() / 1000;
}
if(presetColor.sizeOfShadeArray() > 0) {
lumMod = presetColor.getShadeArray(0).getVal() / 1000;
}
color = modulateLuminanace(color, lumMod, lumOff);

if(presetColor.sizeOfTintArray() > 0) {
float tint = presetColor.getTintArray(0).getVal() / 100000f;
int red = Math.round(tint * color.getRed() + (1 - tint) * 255);
int green = Math.round(tint * color.getGreen() + (1 - tint) * 255);
int blue = Math.round(tint * color.getBlue() + (1 - tint) * 255);
color = new Color(red, green, blue);
}

return color;
}

public Color brighter(Color color, double tint) {
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();

/* From 2D group:
* 1. black.brighter() should return grey
* 2. applying brighter to blue will always return blue, brighter
* 3. non pure color (non zero rgb) will eventually return white
*/
int i = (int)(1.0/(1.0-tint));
if ( r == 0 && g == 0 && b == 0) {
return new Color(i, i, i);
}
if ( r > 0 && r < i ) r = i;
if ( g > 0 && g < i ) g = i;
if ( b > 0 && b < i ) b = i;

return new Color(Math.min((int)(r/tint), 255),
Math.min((int)(g/tint), 255),
Math.min((int)(b/tint), 255));
}

Color getSrgbColor(CTSRgbColor srgb){
byte[] val = srgb.getVal();
int alpha = 0xFF;
if(srgb.sizeOfAlphaArray() > 0){
int aval = srgb.getAlphaArray(0).getVal();
alpha = Math.round(255 * aval / 100000f);
}
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2], alpha);
}

Color getSolidFillColor(CTSolidColorFillProperties solidFill){
Color color;
if (solidFill.isSetSrgbClr()) {
color = getSrgbColor(solidFill.getSrgbClr());
} else if (solidFill.isSetSchemeClr()) {
color = getSchemeColor(solidFill.getSchemeClr());
} else {
// TODO support other types
color = Color.black;
}
return color;
}

Color getColor(CTColor solidFill){
Color color;
if (solidFill.isSetSrgbClr()) {
color = getSrgbColor(solidFill.getSrgbClr());
} else if (solidFill.isSetSchemeClr()) {
color = getSchemeColor(solidFill.getSchemeClr());
} else {
// TODO support other types
color = Color.black;
}
return color;
}

/**
* While developing only!
*/
@Internal
@@ -84,4 +247,31 @@ public class XSLFTheme extends POIXMLDocumentPart {
out.close();
}

}
public static Color modulateLuminanace(Color c, int lumMod, int lumOff) {
Color color;
if (lumOff > 0) {
color = new Color(
(int) (Math.round((255 - c.getRed()) * (100.0 - lumMod) / 100.0 + c.getRed())),
(int) (Math.round((255 - c.getGreen()) * lumOff / 100.0 + c.getGreen())),
(int) (Math.round((255 - c.getBlue()) * lumOff / 100.0 + c.getBlue())),
c.getAlpha()
);
} else {
color = new Color(
(int) (Math.round(c.getRed() * lumMod / 100.0)),
(int) (Math.round(c.getGreen() * lumMod / 100.0)),
(int) (Math.round(c.getBlue() * lumMod / 100.0)),
c.getAlpha()
);
}
return color;
}

public String getMajorFont(){
return _theme.getThemeElements().getFontScheme().getMajorFont().getLatin().getTypeface();
}

public String getMinorFont(){
return _theme.getThemeElements().getFontScheme().getMinorFont().getLatin().getTypeface();
}
}

+ 101
- 0
src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java View File

@@ -0,0 +1,101 @@
/*
* ====================================================================
* 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.util;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
/**
* Date: 10/11/11
*
* @author Yegor Kozlov
*/
public class PPTX2PNG {
public static void main(String[] args) throws Exception {
if (args.length == 0) {
System.out.println("Usage: PPTX2PNG [options] <pptx file>");
return;
}
int slidenum = -1;
float scale = 1;
String file = null;
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("-")) {
if ("-scale".equals(args[i])) {
scale = Float.parseFloat(args[++i]);
} else if ("-slide".equals(args[i])) {
slidenum = Integer.parseInt(args[++i]);
}
} else {
file = args[i];
}
}
System.out.println("Processing " + file);
XMLSlideShow ppt = new XMLSlideShow(OPCPackage.open(file));
Dimension pgsize = ppt.getPageSize();
int width = (int) (pgsize.width * scale);
int height = (int) (pgsize.height * scale);
XSLFSlide[] slide = ppt.getSlides();
for (int i = 0; i < slide.length; i++) {
if (slidenum != -1 && slidenum != (i + 1)) continue;
String title = slide[i].getTitle();
System.out.println("Rendering slide " + (i + 1) + (title == null ? "" : ": " + title));
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = img.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
graphics.setPaint(Color.white);
graphics.fill(new Rectangle2D.Float(0, 0, width, height));
graphics.scale((double) width / pgsize.width, (double) height / pgsize.height);
slide[i].draw(graphics);
String fname = file.replaceAll("\\.pptx", "-" + (i + 1) + ".png");
FileOutputStream out = new FileOutputStream(fname);
ImageIO.write(img, "png", out);
out.close();
}
System.out.println("Done");
}
}

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

@@ -41,7 +41,6 @@ public class TestXMLSlideShow extends TestCase {
if(part.getContentType().equals(XSLFRelation.MAIN.getContentType())) {
found = true;
}
//System.out.println(part);
}
assertTrue(found);
}

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

@@ -33,11 +33,11 @@ public class TestXSLFAutoShape extends TestCase {
XSLFAutoShape shape = slide.createAutoShape();
shape.addNewTextParagraph().addNewTextRun().setText("POI");
// margins
assertEquals(-1., shape.getMarginBottom());
assertEquals(-1., shape.getMarginTop());
assertEquals(-1., shape.getMarginLeft());
assertEquals(-1., shape.getMarginRight());
// 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());
@@ -57,21 +57,22 @@ public class TestXSLFAutoShape extends TestCase {
shape.setMarginRight(0.0);
assertEquals(0.0, shape.getMarginRight());
// unset to defauls
shape.setMarginBottom(-1);
assertEquals(-1., shape.getMarginBottom());
assertEquals(3.6, shape.getMarginBottom());
shape.setMarginTop(-1);
assertEquals(-1.0, shape.getMarginTop());
assertEquals(3.6, shape.getMarginTop());
shape.setMarginLeft(-1);
assertEquals(-1.0, shape.getMarginLeft());
assertEquals(7.2, shape.getMarginLeft());
shape.setMarginRight(-1);
assertEquals(-1.0, shape.getMarginRight());
assertEquals(7.2, shape.getMarginRight());
// shape
assertFalse(shape.getWordWrap());
shape.setWordWrap(true);
assertTrue(shape.getWordWrap());
shape.setWordWrap(false);
assertFalse(shape.getWordWrap());
shape.setWordWrap(true);
assertTrue(shape.getWordWrap());
// shape
assertEquals(TextAutofit.NORMAL, shape.getTextAutofit());
@@ -209,7 +210,7 @@ public class TestXSLFAutoShape extends TestCase {
assertEquals(1, p.getTextRuns().size());
assertSame(r, p.getTextRuns().get(0));
assertEquals(-1.0, r.getFontSize());
assertEquals(18.0, r.getFontSize()); // default font size for text boxes
assertFalse(r.getXmlObject().getRPr().isSetSz());
r.setFontSize(10.0);
assertTrue(r.getXmlObject().isSetRPr());
@@ -220,9 +221,9 @@ public class TestXSLFAutoShape extends TestCase {
assertFalse(r.getXmlObject().getRPr().isSetSz());
assertFalse(r.getXmlObject().getRPr().isSetLatin());
assertNull(r.getFontFamily());
assertEquals("Calibri", r.getFontFamily()); // comes from the slide master
r.setFontFamily(null);
assertNull(r.getFontFamily());
assertEquals("Calibri", r.getFontFamily()); // comes from the slide master
r.setFontFamily("Arial");
assertEquals("Arial", r.getFontFamily());
assertEquals("Arial", r.getXmlObject().getRPr().getLatin().getTypeface());
@@ -230,7 +231,7 @@ public class TestXSLFAutoShape extends TestCase {
assertEquals("Symbol", r.getFontFamily());
assertEquals("Symbol", r.getXmlObject().getRPr().getLatin().getTypeface());
r.setFontFamily(null);
assertNull(r.getFontFamily());
assertEquals("Calibri", r.getFontFamily()); // comes from the slide master
assertFalse(r.getXmlObject().getRPr().isSetLatin());
assertFalse(r.isStrikethrough());

+ 105
- 0
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java View File

@@ -21,8 +21,10 @@ import junit.framework.TestCase;
import org.apache.poi.util.Units;
import org.apache.poi.xslf.usermodel.LineCap;
import org.apache.poi.xslf.usermodel.LineDash;
import org.apache.poi.xslf.XSLFTestDataSamples;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import java.awt.*;
@@ -129,4 +131,107 @@ public class TestXSLFSimpleShape extends TestCase {
assertFalse(shape.getSpPr().isSetSolidFill());
}
public void testDefaultProperties() {
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");
XSLFSlide slide6 = ppt.getSlides()[5];
XSLFShape[] shapes = slide6.getShapes();
for(int i = 1; i < shapes.length; i++){
XSLFSimpleShape s = (XSLFSimpleShape) shapes[i];
// all shapes have a theme color="accent1"
assertEquals("accent1", s.getSpStyle().getFillRef().getSchemeClr().getVal().toString());
assertEquals(2.0, s.getLineWidth());
assertEquals(LineCap.FLAT, s.getLineCap());
// YK: calculated color is slightly different from PowerPoint
assertEquals(new Color(40, 65, 95), s.getLineColor());
}
XSLFSimpleShape s0 = (XSLFSimpleShape) shapes[0];
// fill is not set
assertNull(s0.getSpPr().getSolidFill());
assertEquals(slide6.getTheme().getColor("accent1").getColor(), s0.getFillColor());
assertEquals(new Color(79, 129, 189), s0.getFillColor());
// lighter 80%
XSLFSimpleShape s1 = (XSLFSimpleShape)shapes[1];
CTSchemeColor ref1 = s1.getSpPr().getSolidFill().getSchemeClr();
assertEquals(1, ref1.sizeOfLumModArray());
assertEquals(1, ref1.sizeOfLumOffArray());
assertEquals(20000, ref1.getLumModArray(0).getVal());
assertEquals(80000, ref1.getLumOffArray(0).getVal());
assertEquals("accent1", ref1.getVal().toString());
assertEquals(new Color(220, 230, 242), s1.getFillColor());
// lighter 60%
XSLFSimpleShape s2 = (XSLFSimpleShape)shapes[2];
CTSchemeColor ref2 = s2.getSpPr().getSolidFill().getSchemeClr();
assertEquals(1, ref2.sizeOfLumModArray());
assertEquals(1, ref2.sizeOfLumOffArray());
assertEquals(40000, ref2.getLumModArray(0).getVal());
assertEquals(60000, ref2.getLumOffArray(0).getVal());
assertEquals("accent1", ref2.getVal().toString());
assertEquals(new Color(185, 205, 229), s2.getFillColor());
// lighter 40%
XSLFSimpleShape s3 = (XSLFSimpleShape)shapes[3];
CTSchemeColor ref3 = s3.getSpPr().getSolidFill().getSchemeClr();
assertEquals(1, ref3.sizeOfLumModArray());
assertEquals(1, ref3.sizeOfLumOffArray());
assertEquals(60000, ref3.getLumModArray(0).getVal());
assertEquals(40000, ref3.getLumOffArray(0).getVal());
assertEquals("accent1", ref3.getVal().toString());
assertEquals(new Color(149, 179, 215), s3.getFillColor());
// darker 25%
XSLFSimpleShape s4 = (XSLFSimpleShape)shapes[4];
CTSchemeColor ref4 = s4.getSpPr().getSolidFill().getSchemeClr();
assertEquals(1, ref4.sizeOfLumModArray());
assertEquals(0, ref4.sizeOfLumOffArray());
assertEquals(75000, ref4.getLumModArray(0).getVal());
assertEquals("accent1", ref3.getVal().toString());
// YK: calculated color is slightly different from PowerPoint
assertEquals(new Color(59, 97, 142), s4.getFillColor());
XSLFSimpleShape s5 = (XSLFSimpleShape)shapes[5];
CTSchemeColor ref5 = s5.getSpPr().getSolidFill().getSchemeClr();
assertEquals(1, ref5.sizeOfLumModArray());
assertEquals(0, ref5.sizeOfLumOffArray());
assertEquals(50000, ref5.getLumModArray(0).getVal());
assertEquals("accent1", ref5.getVal().toString());
// YK: calculated color is slightly different from PowerPoint
assertEquals(new Color(40, 65, 95), s5.getFillColor());
}
public void testAnchor(){
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");
XSLFSlide[] slide = ppt.getSlides();
XSLFSlide slide2 = slide[1];
XSLFSlideLayout layout2 = slide2.getSlideLayout();
XSLFShape[] shapes2 = slide2.getShapes();
XSLFTextShape sh1 = (XSLFTextShape)shapes2[0];
assertEquals(Placeholder.CENTERED_TITLE, sh1.getTextType());
assertEquals("PPTX Title", sh1.getText());
assertNull(sh1.getSpPr().getXfrm()); // xfrm is not set, the query is delegated to the slide layout
assertEquals(sh1.getAnchor(), layout2.getTextShapeByType(Placeholder.CENTERED_TITLE).getAnchor());
XSLFTextShape sh2 = (XSLFTextShape)shapes2[1];
assertEquals("Subtitle\nAnd second line", sh2.getText());
assertEquals(Placeholder.SUBTITLE, sh2.getTextType());
assertNull(sh2.getSpPr().getXfrm()); // xfrm is not set, the query is delegated to the slide layout
assertEquals(sh2.getAnchor(), layout2.getTextShapeByType(Placeholder.SUBTITLE).getAnchor());
XSLFSlide slide5 = slide[4];
XSLFSlideLayout layout5 = slide5.getSlideLayout();
XSLFTextShape shTitle = slide5.getTextShapeByType(Placeholder.TITLE);
assertEquals("Hyperlinks", shTitle.getText());
// xfrm is not set, the query is delegated to the slide layout
assertNull(shTitle.getSpPr().getXfrm());
// xfrm is not set, the query is delegated to the slide master
assertNull(layout5.getTextShapeByType(Placeholder.TITLE).getSpPr().getXfrm());
assertNotNull(layout5.getSlideMaster().getTextShapeByType(Placeholder.TITLE).getSpPr().getXfrm());
assertEquals(shTitle.getAnchor(), layout5.getSlideMaster().getTextShapeByType(Placeholder.TITLE).getAnchor());
}
}

+ 3
- 3
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java View File

@@ -28,10 +28,10 @@ public class TestXSLFTextBox extends TestCase {
XSLFSlide slide = ppt.createSlide();
XSLFTextBox shape = slide.createTextBox();
assertNull(shape.getPlaceholder());
assertNull(shape.getTextType());
shape.setPlaceholder(Placeholder.TITLE);
assertEquals(Placeholder.TITLE, shape.getPlaceholder());
assertEquals(Placeholder.TITLE, shape.getTextType());
shape.setPlaceholder(null);
assertNull(shape.getPlaceholder());
assertNull(shape.getTextType());
}
}

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

@@ -0,0 +1,609 @@
/* ====================================================================
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;
import junit.framework.TestCase;
import org.apache.poi.xslf.XSLFTestDataSamples;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
import java.awt.*;
/**
* @author Yegor Kozlov
*/
public class TestXSLFTextShape extends TestCase {
public void testLayouts(){
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("layouts.pptx");
XSLFSlide[] slide = ppt.getSlides();
verifySlide1(slide[0]);
verifySlide2(slide[1]);
verifySlide3(slide[2]);
verifySlide4(slide[3]);
verifySlide7(slide[6]);
verifySlide8(slide[7]);
verifySlide10(slide[9]);
}
void verifySlide1(XSLFSlide slide){
XSLFSlideLayout layout = slide.getSlideLayout();
XSLFShape[] shapes = slide.getShapes();
assertEquals("Title Slide",layout.getName());
XSLFTextShape shape1 = (XSLFTextShape)shapes[0];
CTPlaceholder ph1 = shape1.getCTPlaceholder();
assertEquals(STPlaceholderType.CTR_TITLE, ph1.getType());
// anchor is not defined in the shape
assertNull(shape1.getSpPr().getXfrm());
XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1);
assertNotNull(masterShape1.getSpPr().getXfrm());
assertEquals(masterShape1.getAnchor(), shape1.getAnchor());
CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr();
// none of the following properties are set in the shapes and fetched from the master shape
assertTrue(
!bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() &&
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&
!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(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());
// now check text properties
assertEquals("Centered Title", shape1.getText());
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals("Calibri", r1.getFontFamily());
assertEquals(44.0, r1.getFontSize());
assertEquals(Color.black, r1.getFontColor());
XSLFTextShape shape2 = (XSLFTextShape)shapes[1];
CTPlaceholder ph2 = shape2.getCTPlaceholder();
assertEquals(STPlaceholderType.SUB_TITLE, ph2.getType());
// anchor is not defined in the shape
assertNull(shape2.getSpPr().getXfrm());
XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2);
assertNotNull(masterShape2.getSpPr().getXfrm());
assertEquals(masterShape2.getAnchor(), shape2.getAnchor());
CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr();
// none of the following properties are set in the shapes and fetched from the master shape
assertTrue(
!bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() &&
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&
!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(VerticalAlignment.TOP, shape2.getVerticalAlignment());
assertEquals("subtitle", shape2.getText());
XSLFTextRun r2 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals("Calibri", r2.getFontFamily());
assertEquals(32.0, r2.getFontSize());
// TODO fix calculation of tint
//assertEquals(new Color(137, 137, 137), r2.getFontColor());
}
void verifySlide2(XSLFSlide slide){
XSLFSlideLayout layout = slide.getSlideLayout();
XSLFShape[] shapes = slide.getShapes();
assertEquals("Title and Content",layout.getName());
XSLFTextShape shape1 = (XSLFTextShape)shapes[0];
CTPlaceholder ph1 = shape1.getCTPlaceholder();
assertEquals(STPlaceholderType.TITLE, ph1.getType());
// anchor is not defined in the shape
assertNull(shape1.getSpPr().getXfrm());
XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1);
// layout does not have anchor info either, it is in the slide master
assertNull(masterShape1.getSpPr().getXfrm());
masterShape1 = (XSLFTextShape)layout.getSlideMaster().getPlaceholder(ph1);
assertNotNull(masterShape1.getSpPr().getXfrm());
assertEquals(masterShape1.getAnchor(), shape1.getAnchor());
CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr();
// none of the following properties are set in the shapes and fetched from the master shape
assertTrue(
!bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() &&
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&
!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(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());
// now check text properties
assertEquals("Title", shape1.getText());
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals("Calibri", r1.getFontFamily());
assertEquals(44.0, r1.getFontSize());
assertEquals(Color.black, r1.getFontColor());
XSLFTextShape shape2 = (XSLFTextShape)shapes[1];
CTPlaceholder ph2 = shape2.getCTPlaceholder();
assertFalse(ph2.isSetType()); // <p:ph idx="1"/>
assertTrue(ph2.isSetIdx());
assertEquals(1, ph2.getIdx());
// anchor is not defined in the shape
assertNull(shape2.getSpPr().getXfrm());
XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2);
// anchor of the body text is missing in the slide layout, llokup in the slide master
assertNull(masterShape2.getSpPr().getXfrm());
masterShape2 = (XSLFTextShape)layout.getSlideMaster().getPlaceholder(ph2);
assertNotNull(masterShape2.getSpPr().getXfrm());
assertEquals(masterShape2.getAnchor(), shape2.getAnchor());
CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr();
// none of the following properties are set in the shapes and fetched from the master shape
assertTrue(
!bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() &&
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&
!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(VerticalAlignment.TOP, shape2.getVerticalAlignment());
XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(0, pr1.getParentParagraph().getLevel());
assertEquals("Content", pr1.getText());
assertEquals("Calibri", pr1.getFontFamily());
assertEquals(32.0, pr1.getFontSize());
assertEquals(27.0, pr1.getParentParagraph().getLeftMargin());
assertEquals("\u2022", pr1.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr1.getParentParagraph().getBulletFont());
XSLFTextRun pr2 = shape2.getTextParagraphs().get(1).getTextRuns().get(0);
assertEquals(1, pr2.getParentParagraph().getLevel());
assertEquals("Level 2", pr2.getText());
assertEquals("Calibri", pr2.getFontFamily());
assertEquals(28.0, pr2.getFontSize());
assertEquals(58.5, pr2.getParentParagraph().getLeftMargin());
assertEquals("\u2013", pr2.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr2.getParentParagraph().getBulletFont());
XSLFTextRun pr3 = shape2.getTextParagraphs().get(2).getTextRuns().get(0);
assertEquals(2, pr3.getParentParagraph().getLevel());
assertEquals("Level 3", pr3.getText());
assertEquals("Calibri", pr3.getFontFamily());
assertEquals(24.0, pr3.getFontSize());
assertEquals(90.0, pr3.getParentParagraph().getLeftMargin());
assertEquals("\u2022", pr3.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr3.getParentParagraph().getBulletFont());
XSLFTextRun pr4 = shape2.getTextParagraphs().get(3).getTextRuns().get(0);
assertEquals(3, pr4.getParentParagraph().getLevel());
assertEquals("Level 4", pr4.getText());
assertEquals("Calibri", pr4.getFontFamily());
assertEquals(20.0, pr4.getFontSize());
assertEquals(126.0, pr4.getParentParagraph().getLeftMargin());
assertEquals("\u2013", pr4.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr4.getParentParagraph().getBulletFont());
XSLFTextRun pr5 = shape2.getTextParagraphs().get(4).getTextRuns().get(0);
assertEquals(4, pr5.getParentParagraph().getLevel());
assertEquals("Level 5", pr5.getText());
assertEquals("Calibri", pr5.getFontFamily());
assertEquals(20.0, pr5.getFontSize());
assertEquals(162.0, pr5.getParentParagraph().getLeftMargin());
assertEquals("\u00bb", pr5.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr5.getParentParagraph().getBulletFont());
}
void verifySlide3(XSLFSlide slide){
XSLFSlideLayout layout = slide.getSlideLayout();
XSLFShape[] shapes = slide.getShapes();
assertEquals("Section Header",layout.getName());
XSLFTextShape shape1 = (XSLFTextShape)shapes[0];
CTPlaceholder ph1 = shape1.getCTPlaceholder();
assertEquals(STPlaceholderType.TITLE, ph1.getType());
// anchor is not defined in the shape
assertNull(shape1.getSpPr().getXfrm());
XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1);
assertNotNull(masterShape1.getSpPr().getXfrm());
assertEquals(masterShape1.getAnchor(), shape1.getAnchor());
CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr();
// none of the following properties are set in the shapes and fetched from the master shape
assertTrue(
!bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() &&
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&
!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(VerticalAlignment.TOP, shape1.getVerticalAlignment());
// now check text properties
assertEquals("Section Title", shape1.getText());
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(TextAlign.LEFT, r1.getParentParagraph().getTextAlign());
assertEquals("Calibri", r1.getFontFamily());
assertEquals(40.0, r1.getFontSize());
assertEquals(Color.black, r1.getFontColor());
assertTrue(r1.isBold());
assertFalse(r1.isItalic());
assertFalse(r1.isUnderline());
XSLFTextShape shape2 = (XSLFTextShape)shapes[1];
CTPlaceholder ph2 = shape2.getCTPlaceholder();
assertEquals(STPlaceholderType.BODY, ph2.getType());
// anchor is not defined in the shape
assertNull(shape2.getSpPr().getXfrm());
XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2);
assertNotNull(masterShape2.getSpPr().getXfrm());
assertEquals(masterShape2.getAnchor(), shape2.getAnchor());
CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr();
// none of the following properties are set in the shapes and fetched from the master shape
assertTrue(
!bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() &&
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&
!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(VerticalAlignment.BOTTOM, shape2.getVerticalAlignment());
assertEquals("Section Header", shape2.getText());
XSLFTextRun r2 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(TextAlign.LEFT, r2.getParentParagraph().getTextAlign());
assertEquals("Calibri", r2.getFontFamily());
assertEquals(20.0, r2.getFontSize());
// TODO fix calculation of tint
//assertEquals(new Color(137, 137, 137), r2.getFontColor());
}
void verifySlide4(XSLFSlide slide){
XSLFSlideLayout layout = slide.getSlideLayout();
XSLFShape[] shapes = slide.getShapes();
assertEquals("Two Content",layout.getName());
XSLFTextShape shape1 = (XSLFTextShape)shapes[0];
CTPlaceholder ph1 = shape1.getCTPlaceholder();
assertEquals(STPlaceholderType.TITLE, ph1.getType());
// anchor is not defined in the shape
assertNull(shape1.getSpPr().getXfrm());
XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1);
// layout does not have anchor info either, it is in the slide master
assertNull(masterShape1.getSpPr().getXfrm());
masterShape1 = (XSLFTextShape)layout.getSlideMaster().getPlaceholder(ph1);
assertNotNull(masterShape1.getSpPr().getXfrm());
assertEquals(masterShape1.getAnchor(), shape1.getAnchor());
CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr();
// none of the following properties are set in the shapes and fetched from the master shape
assertTrue(
!bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() &&
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&
!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(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());
// now check text properties
assertEquals("Title", shape1.getText());
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign());
assertEquals("Calibri", r1.getFontFamily());
assertEquals(44.0, r1.getFontSize());
assertEquals(Color.black, r1.getFontColor());
XSLFTextShape shape2 = (XSLFTextShape)shapes[1];
CTPlaceholder ph2 = shape2.getCTPlaceholder();
assertFalse(ph2.isSetType());
assertTrue(ph2.isSetIdx());
assertEquals(1, ph2.getIdx()); //<p:ph sz="half" idx="1"/>
// anchor is not defined in the shape
assertNull(shape2.getSpPr().getXfrm());
XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2);
assertNotNull(masterShape2.getSpPr().getXfrm());
assertEquals(masterShape2.getAnchor(), shape2.getAnchor());
CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr();
// none of the following properties are set in the shapes and fetched from the master shape
assertTrue(
!bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() &&
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&
!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(VerticalAlignment.TOP, shape2.getVerticalAlignment());
XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(0, pr1.getParentParagraph().getLevel());
assertEquals("Left", pr1.getText());
assertEquals("Calibri", pr1.getFontFamily());
assertEquals(28.0, pr1.getFontSize());
assertEquals(27.0, pr1.getParentParagraph().getLeftMargin());
assertEquals("\u2022", pr1.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr1.getParentParagraph().getBulletFont());
XSLFTextRun pr2 = shape2.getTextParagraphs().get(1).getTextRuns().get(0);
assertEquals(1, pr2.getParentParagraph().getLevel());
assertEquals("Level 2", pr2.getParentParagraph().getText());
assertEquals("Calibri", pr2.getFontFamily());
assertEquals(24.0, pr2.getFontSize());
assertEquals(58.5, pr2.getParentParagraph().getLeftMargin());
assertEquals("\u2013", pr2.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr2.getParentParagraph().getBulletFont());
XSLFTextRun pr3 = shape2.getTextParagraphs().get(2).getTextRuns().get(0);
assertEquals(2, pr3.getParentParagraph().getLevel());
assertEquals("Level 3", pr3.getParentParagraph().getText());
assertEquals("Calibri", pr3.getFontFamily());
assertEquals(20.0, pr3.getFontSize());
assertEquals(90.0, pr3.getParentParagraph().getLeftMargin());
assertEquals("\u2022", pr3.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr3.getParentParagraph().getBulletFont());
XSLFTextRun pr4 = shape2.getTextParagraphs().get(3).getTextRuns().get(0);
assertEquals(3, pr4.getParentParagraph().getLevel());
assertEquals("Level 4", pr4.getParentParagraph().getText());
assertEquals("Calibri", pr4.getFontFamily());
assertEquals(18.0, pr4.getFontSize());
assertEquals(126.0, pr4.getParentParagraph().getLeftMargin());
assertEquals("\u2013", pr4.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr4.getParentParagraph().getBulletFont());
XSLFTextShape shape3 = (XSLFTextShape)shapes[2];
XSLFTextRun pr5 = shape3.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(0, pr5.getParentParagraph().getLevel());
assertEquals("Right", pr5.getText());
assertEquals("Calibri", pr5.getFontFamily());
assertEquals(Color.black, pr5.getFontColor());
}
void verifySlide5(XSLFSlide slide){
XSLFSlideLayout layout = slide.getSlideLayout();
XSLFShape[] shapes = slide.getShapes();
// TODO
}
void verifySlide7(XSLFSlide slide){
XSLFSlideLayout layout = slide.getSlideLayout();
XSLFShape[] shapes = slide.getShapes();
assertEquals("Blank",layout.getName());
XSLFTextShape shape1 = (XSLFTextShape)shapes[0];
CTPlaceholder ph1 = shape1.getCTPlaceholder();
assertEquals(STPlaceholderType.TITLE, ph1.getType());
// anchor is not defined in the shape
assertNull(shape1.getSpPr().getXfrm());
CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr();
// none of the following properties are set in the shapes and fetched from the master shape
assertTrue(
!bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() &&
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&
!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(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());
// now check text properties
assertEquals("Blank with Default Title", shape1.getText());
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign());
assertEquals("Calibri", r1.getFontFamily());
assertEquals(44.0, r1.getFontSize());
assertEquals(Color.black, r1.getFontColor());
assertFalse(r1.isBold());
XSLFTextShape shape2 = (XSLFTextShape)shapes[1];
CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr();
// none of the following properties are set in the shapes and fetched from the master shape
assertTrue(
!bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() &&
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&
!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(VerticalAlignment.TOP, shape2.getVerticalAlignment());
XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(0, pr1.getParentParagraph().getLevel());
assertEquals("Default Text", pr1.getText());
assertEquals("Calibri", pr1.getFontFamily());
assertEquals(18.0, pr1.getFontSize());
XSLFTextShape shape3 = (XSLFTextShape)shapes[2];
assertEquals("Default", shape3.getTextParagraphs().get(0).getText());
assertEquals("Text with levels", shape3.getTextParagraphs().get(1).getText());
assertEquals("Level 1", shape3.getTextParagraphs().get(2).getText());
assertEquals("Level 2", shape3.getTextParagraphs().get(3).getText());
assertEquals("Level 3", shape3.getTextParagraphs().get(4).getText());
for(int p = 0; p < 5; p++) {
XSLFTextParagraph pr = shape3.getTextParagraphs().get(p);
assertEquals("Calibri", pr.getTextRuns().get(0).getFontFamily());
assertEquals(18.0, pr.getTextRuns().get(0).getFontSize());
}
}
void verifySlide8(XSLFSlide slide){
XSLFSlideLayout layout = slide.getSlideLayout();
XSLFShape[] shapes = slide.getShapes();
assertEquals("Content with Caption",layout.getName());
XSLFTextShape shape1 = (XSLFTextShape)shapes[0];
CTPlaceholder ph1 = shape1.getCTPlaceholder();
assertEquals(STPlaceholderType.TITLE, ph1.getType());
// anchor is not defined in the shape
assertNull(shape1.getSpPr().getXfrm());
XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1);
// layout does not have anchor info either, it is in the slide master
assertNotNull(masterShape1.getSpPr().getXfrm());
assertEquals(masterShape1.getAnchor(), shape1.getAnchor());
CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr();
// none of the following properties are set in the shapes and fetched from the master shape
assertTrue(
!bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() &&
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&
!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(VerticalAlignment.BOTTOM, shape1.getVerticalAlignment());
// now check text properties
assertEquals("Caption", shape1.getText());
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(TextAlign.LEFT, r1.getParentParagraph().getTextAlign());
assertEquals("Calibri", r1.getFontFamily());
assertEquals(20.0, r1.getFontSize());
assertEquals(Color.black, r1.getFontColor());
assertTrue(r1.isBold());
XSLFTextShape shape2 = (XSLFTextShape)shapes[1];
CTPlaceholder ph2 = shape2.getCTPlaceholder();
assertFalse(ph2.isSetType());
assertTrue(ph2.isSetIdx());
assertEquals(1, ph2.getIdx());
// anchor is not defined in the shape
assertNull(shape2.getSpPr().getXfrm());
XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2);
assertNotNull(masterShape2.getSpPr().getXfrm());
assertEquals(masterShape2.getAnchor(), shape2.getAnchor());
CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr();
// none of the following properties are set in the shapes and fetched from the master shape
assertTrue(
!bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() &&
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&
!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(VerticalAlignment.TOP, shape2.getVerticalAlignment());
XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(0, pr1.getParentParagraph().getLevel());
assertEquals("Level 1", pr1.getText());
assertEquals("Calibri", pr1.getFontFamily());
assertEquals(32.0, pr1.getFontSize());
assertEquals(27.0, pr1.getParentParagraph().getLeftMargin());
assertEquals("\u2022", pr1.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr1.getParentParagraph().getBulletFont());
XSLFTextRun pr2 = shape2.getTextParagraphs().get(1).getTextRuns().get(0);
assertEquals(1, pr2.getParentParagraph().getLevel());
assertEquals("Level 2", pr2.getParentParagraph().getText());
assertEquals("Calibri", pr2.getFontFamily());
assertEquals(28.0, pr2.getFontSize());
assertEquals(58.5, pr2.getParentParagraph().getLeftMargin());
assertEquals("\u2013", pr2.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr2.getParentParagraph().getBulletFont());
XSLFTextRun pr3 = shape2.getTextParagraphs().get(2).getTextRuns().get(0);
assertEquals(2, pr3.getParentParagraph().getLevel());
assertEquals("Level 3", pr3.getParentParagraph().getText());
assertEquals("Calibri", pr3.getFontFamily());
assertEquals(24.0, pr3.getFontSize());
assertEquals(90.0, pr3.getParentParagraph().getLeftMargin());
assertEquals("\u2022", pr3.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr3.getParentParagraph().getBulletFont());
XSLFTextRun pr4 = shape2.getTextParagraphs().get(3).getTextRuns().get(0);
assertEquals(3, pr4.getParentParagraph().getLevel());
assertEquals("Level 4", pr4.getParentParagraph().getText());
assertEquals("Calibri", pr4.getFontFamily());
assertEquals(20.0, pr4.getFontSize());
assertEquals(126.0, pr4.getParentParagraph().getLeftMargin());
assertEquals("\u2013", pr4.getParentParagraph().getBulletCharacter());
assertEquals("Arial", pr4.getParentParagraph().getBulletFont());
XSLFTextShape shape3 = (XSLFTextShape)shapes[2];
assertEquals(VerticalAlignment.TOP, shape3.getVerticalAlignment());
assertEquals("Content with caption", shape3.getText());
pr1 = shape3.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(0, pr1.getParentParagraph().getLevel());
assertEquals("Content with caption", pr1.getText());
assertEquals("Calibri", pr1.getFontFamily());
assertEquals(14.0, pr1.getFontSize());
}
void verifySlide10(XSLFSlide slide){
XSLFTextShape footer = (XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_FTR);
// now check text properties
assertEquals("Apache Software Foundation", footer.getText());
assertEquals(VerticalAlignment.MIDDLE, footer.getVerticalAlignment());
XSLFTextRun r1 = footer.getTextParagraphs().get(0).getTextRuns().get(0);
assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign());
assertEquals("Calibri", r1.getFontFamily());
assertEquals(12.0, r1.getFontSize());
// TODO calculation of tint is incorrect
assertEquals(new Color(64,64,64), r1.getFontColor());
XSLFTextShape dt = (XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_DT);
assertEquals("Friday, October 21, 2011", dt.getText());
XSLFTextShape sldNum = (XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_SLD_NUM);
assertEquals("10", sldNum.getText());
}
}

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

@@ -0,0 +1,39 @@
/* ====================================================================
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;
import junit.framework.TestCase;
import org.apache.poi.xslf.XSLFTestDataSamples;
/**
* test common properties for sheets (slides, masters, layouts, etc.)
*
* @author Yegor Kozlov
*/
public class TestXSLFTheme extends TestCase {
public void testRead(){
XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide();
XSLFTheme theme = slide.getSlideLayout().getSlideMaster().getTheme();
assertNotNull(theme);
assertEquals("Office Theme", theme.getName());
XSLFColor accent1 = theme.getColor("accent1");
assertNotNull(accent1);
}
}

+ 19915
- 0
src/resources/scratchpad/org/apache/poi/xslf/usermodel/presetShapeDefinitions.xml
File diff suppressed because it is too large
View File


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


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


Loading…
Cancel
Save