瀏覽代碼

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 年之前
父節點
當前提交
2490ebd2ff
共有 39 個文件被更改,包括 23961 次插入337 次删除
  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. 二進制
      test-data/slideshow/layouts.pptx
  39. 二進制
      test-data/slideshow/shapes.pptx

+ 1
- 0
src/documentation/content/xdocs/status.xml 查看文件



<changes> <changes>
<release version="3.8-beta5" date="2011-??-??"> <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="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">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> <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 查看文件

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */package org.apache.poi.util;
==================================================================== */
package org.apache.poi.util;
/** /**
* @author Yegor Kozlov * @author Yegor Kozlov

+ 45
- 0
src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java 查看文件

/*
* ====================================================================
* 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 查看文件

/*
* ====================================================================
* 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 查看文件

/*
* ====================================================================
* 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 查看文件

/*
* ====================================================================
* 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 查看文件

import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
import org.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.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
import java.awt.*; import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/** /**
* Represents a preset geometric shape. * Represents a preset geometric shape.
*/ */
@Beta @Beta
public class XSLFAutoShape extends XSLFTextShape { public class XSLFAutoShape extends XSLFTextShape {
private static final Pattern adjPtrn = Pattern.compile("val\\s+(\\d+)");
/*package*/ XSLFAutoShape(CTShape shape, XSLFSheet sheet) { /*package*/ XSLFAutoShape(CTShape shape, XSLFSheet sheet) {
super(shape, sheet); super(shape, sheet);
return ct; 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){ protected CTTextBody getTextBody(boolean create){
CTShape shape = (CTShape) getXmlObject(); CTShape shape = (CTShape) getXmlObject();
CTTextBody txBody = shape.getTxBody(); CTTextBody txBody = shape.getTxBody();
return txBody; 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 查看文件

/* ====================================================================
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 查看文件

/*
* ====================================================================
* 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 查看文件

import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;
import org.openxmlformats.schemas.presentationml.x2006.main.CTConnectorNonVisual; import org.openxmlformats.schemas.presentationml.x2006.main.CTConnectorNonVisual;
import java.awt.*;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
/** /**
* *
* Specifies a connection shape. * Specifies a connection shape.
return len == null ? null : LineEndLength.values()[len.intValue() - 1]; 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 查看文件

return numPoints; 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() { public GeneralPath getPath() {
GeneralPath path = new GeneralPath(); GeneralPath path = new GeneralPath();
Rectangle2D bounds = getAnchor(); Rectangle2D bounds = getAnchor();
int x0 = Units.toEMU(bounds.getX());
int y0 = Units.toEMU(bounds.getY());
CTCustomGeometry2D geom = getSpPr().getCustGeom(); CTCustomGeometry2D geom = getSpPr().getCustGeom();
for(CTPath2D spPath : geom.getPathLst().getPathList()){ 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("*")){ for(XmlObject ch : spPath.selectPath("*")){
if(ch instanceof CTPath2DMoveTo){ if(ch instanceof CTPath2DMoveTo){
CTAdjPoint2D pt = ((CTPath2DMoveTo)ch).getPt(); 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){ } else if (ch instanceof CTPath2DLineTo){
CTAdjPoint2D pt = ((CTPath2DLineTo)ch).getPt(); 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){ } else if (ch instanceof CTPath2DCubicBezierTo){
CTPath2DCubicBezierTo bez = ((CTPath2DCubicBezierTo)ch); CTPath2DCubicBezierTo bez = ((CTPath2DCubicBezierTo)ch);
CTAdjPoint2D pt1 = bez.getPtArray(0); CTAdjPoint2D pt1 = bez.getPtArray(0);
CTAdjPoint2D pt2 = bez.getPtArray(1); CTAdjPoint2D pt2 = bez.getPtArray(1);
CTAdjPoint2D pt3 = bez.getPtArray(2); CTAdjPoint2D pt3 = bez.getPtArray(2);
path.curveTo( 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){ } else if (ch instanceof CTPath2DClose){
} }
} }
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 * @param shapeId 1-based shapeId
return ct; return ct;
} }
@Override
protected java.awt.Shape getOutline(){
return getPath();
}
} }

+ 82
- 2
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java 查看文件

import org.apache.poi.sl.usermodel.ShapeContainer; import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeGroup; import org.apache.poi.sl.usermodel.ShapeGroup;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.util.Units;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; 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; import java.awt.geom.Rectangle2D;
/** /**
} }
public Rectangle2D getAnchor(){ 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){ 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);
} }
} }
} }
/**
* 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 查看文件

import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; 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.CTConnector;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual; import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.util.List; import java.util.List;
import java.util.regex.Pattern; import java.util.regex.Pattern;
return sh; 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 查看文件

import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.sl.usermodel.ShapeContainer; import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.util.Beta; 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.CTBlip;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; 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.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPictureNonVisual; import org.openxmlformats.schemas.presentationml.x2006.main.CTPictureNonVisual;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
} }
return _data; 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 查看文件

/*
* ====================================================================
* 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 查看文件

/*
* ====================================================================
* 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 查看文件

/* ====================================================================
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 查看文件

package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
/** /**
public abstract String getShapeName(); public abstract String getShapeName();
public abstract int getShapeId(); 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 查看文件

import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode; import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions; import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import 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 javax.xml.namespace.QName;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
private XSLFDrawing _drawing; private XSLFDrawing _drawing;
private List<XSLFShape> _shapes; private List<XSLFShape> _shapes;
private CTGroupShape _spTree; private CTGroupShape _spTree;
private Map<Integer, XSLFSimpleShape> _placeholderByIdMap;
private Map<Integer, XSLFSimpleShape> _placeholderByTypeMap;


public XSLFSheet() { public XSLFSheet() {
super(); super();
return getShapeList().remove(xShape); return getShapeList().remove(xShape);
} }


public XSLFBackground getBackground(){
return null;
}

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


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


public XSLFTheme getTheme(){
return null;
}

public XSLFSlideMaster getSlideMaster(){
return 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 查看文件

import org.apache.poi.xslf.usermodel.LineCap; import org.apache.poi.xslf.usermodel.LineCap;
import org.apache.poi.xslf.usermodel.LineDash; 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.Beta;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; 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.CTPresetLineDashProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; 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.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap; import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; 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.*;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
private final XmlObject _shape; private final XmlObject _shape;
private final XSLFSheet _sheet; private final XSLFSheet _sheet;
private CTShapeProperties _spPr; private CTShapeProperties _spPr;
private CTShapeStyle _spStyle;
private CTNonVisualDrawingProps _nvPr; private CTNonVisualDrawingProps _nvPr;
private CTPlaceholder _ph;
/*package*/ XSLFSimpleShape(XmlObject shape, XSLFSheet sheet){
/* package */XSLFSimpleShape(XmlObject shape, XSLFSheet sheet) {
_shape = shape; _shape = shape;
_sheet = sheet; _sheet = sheet;
} }
public XmlObject getXmlObject(){
public XmlObject getXmlObject() {
return _shape; return _shape;
} }
public XSLFSheet getSheet(){
public XSLFSheet getSheet() {
return _sheet; 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() { 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() { public String getShapeName() {
} }
public int getShapeId() { 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; 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."); throw new IllegalStateException("CTShapeProperties was not found.");
} }
return _spPr; 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(); CTPoint2D off = xfrm.getOff();
long x = off.getX(); long x = off.getX();
long y = off.getY(); long y = off.getY();
Units.toPoints(cx), Units.toPoints(cy)); Units.toPoints(cx), Units.toPoints(cy));
} }
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(); CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
long x = Units.toEMU(anchor.getX()); long x = Units.toEMU(anchor.getX());
long y = Units.toEMU(anchor.getY()); long y = Units.toEMU(anchor.getY());
off.setX(x); off.setX(x);
off.setY(y); 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 cx = Units.toEMU(anchor.getWidth());
long cy = Units.toEMU(anchor.getHeight()); long cy = Units.toEMU(anchor.getHeight());
ext.setCx(cx); ext.setCx(cx);
* Rotate this shape. * Rotate this shape.
* <p> * <p>
* Positive angles are clockwise (i.e., towards the positive y axis); * 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> * </p>
* *
* @param theta the rotation angle in degrees. * @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 * Rotation angle in degrees
* <p> * <p>
* Positive angles are clockwise (i.e., towards the positive y axis); * 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> * </p>
* *
* @return rotation angle in degrees * @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); 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); xfrm.setFlipV(flip);
} }
/** /**
* Whether the shape is horizontally flipped * Whether the shape is horizontally flipped
* *
* @return 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(); 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); 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(); 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)); 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(); 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)); 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); 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(); 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(); 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 查看文件

==================================================================== */ ==================================================================== */
package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;


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


import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; 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.CTCommonSlideData;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual; import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide; import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;
import org.openxmlformats.schemas.presentationml.x2006.main.SldDocument; import org.openxmlformats.schemas.presentationml.x2006.main.SldDocument;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;


@Beta @Beta
public final class XSLFSlide extends XSLFSheet { public final class XSLFSlide extends XSLFSheet {
return getSlideLayout().getSlideMaster(); return getSlideLayout().getSlideMaster();
} }


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

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

public XSLFComments getComments() { public XSLFComments getComments() {
if(_comments == null) { if(_comments == null) {
for (POIXMLDocumentPart p : getRelations()) { for (POIXMLDocumentPart p : getRelations()) {
public boolean getFollowMasterBackground(){ public boolean getFollowMasterBackground(){
return !_slide.isSetShowMasterSp() || _slide.getShowMasterSp(); 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 查看文件

import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideLayout; import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideLayout;
import org.openxmlformats.schemas.presentationml.x2006.main.SldLayoutDocument; import org.openxmlformats.schemas.presentationml.x2006.main.SldLayoutDocument;
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.io.IOException;
import java.util.Map;
import java.util.HashMap;
import java.awt.*;
import java.awt.geom.AffineTransform;


@Beta @Beta
public class XSLFSlideLayout extends XSLFSheet { public class XSLFSlideLayout extends XSLFSheet {
* @return slide master. Never null. * @return slide master. Never null.
* @throws IllegalStateException if slide master was not found * @throws IllegalStateException if slide master was not found
*/ */
@Override
public XSLFSlideMaster getSlideMaster(){ public XSLFSlideMaster getSlideMaster(){
if(_master == null){ if(_master == null){
for (POIXMLDocumentPart p : getRelations()) { for (POIXMLDocumentPart p : getRelations()) {
public XMLSlideShow getSlideShow() { public XMLSlideShow getSlideShow() {
return (XMLSlideShow)getParent().getParent(); 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 查看文件

import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMaster; import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMaster;
import org.openxmlformats.schemas.presentationml.x2006.main.SldMasterDocument; 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.io.IOException;
import java.util.HashMap; import java.util.HashMap;
} }
return _theme; 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 查看文件

gr.setUri(TABLE_URI); gr.setUri(TABLE_URI);
return frame; 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 查看文件

import org.apache.poi.sl.usermodel.ShapeContainer; import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.util.Beta; 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.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; 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.CTApplicationNonVisualDrawingProps;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
import java.awt.geom.Rectangle2D;
/** /**
* @author Yegor Kozlov * @author Yegor Kozlov
nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ordinal() + 1)); 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 查看文件

import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.Units; 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.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType; 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.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; 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. * Represents a paragraph of text within the containing text body.
private final CTTextParagraph _p; private final CTTextParagraph _p;
private final List<XSLFTextRun> _runs; private final List<XSLFTextRun> _runs;
private final XSLFTextShape _shape; private final XSLFTextShape _shape;
private List<TextFragment> _lines;
private TextFragment _bullet;
XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){ XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){
_p = p; _p = p;
_runs = new ArrayList<XSLFTextRun>(); _runs = new ArrayList<XSLFTextRun>();
_shape = shape; _shape = shape;
for (CTRegularTextRun r : _p.getRList()) { for (CTRegularTextRun r : _p.getRList()) {
_runs.add(new XSLFTextRun(r, this)); _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(){ public String getText(){
StringBuilder out = new StringBuilder(); StringBuilder out = new StringBuilder();
for (CTRegularTextRun r : _p.getRList()) {
out.append(r.getT());
for (XSLFTextRun r : _runs) {
out.append(r.getText());
} }
return out.toString(); return out.toString();
} }
* @return ??? alignment that is applied to the paragraph * @return ??? alignment that is applied to the paragraph
*/ */
public TextAlign getTextAlign(){ 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();
} }
/** /**
} }
} }
/**
* @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. * Specifies the indent size that will be applied to the first line of text in the paragraph.
* *
* @return the indent applied to the first line of text in the paragraph. * @return the indent applied to the first line of text in the paragraph.
*/ */
public double getIndent(){ 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();
} }
/** /**
* @return the left margin of the paragraph * @return the left margin of the paragraph
*/ */
public double getLeftMargin(){ 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();
} }
/** /**
* @return the vertical line spacing. * @return the vertical line spacing.
*/ */
public double getLineSpacing(){ 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();
} }
/** /**
* @return the vertical white space before the paragraph * @return the vertical white space before the paragraph
*/ */
public double getSpaceBefore(){ 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();
} }
/** /**
* @return the vertical white space after the paragraph * @return the vertical white space after the paragraph
*/ */
public double getSpaceAfter(){ 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();
} }
/** /**
} }
/**
* 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 @Override
public String toString(){ public String toString(){
return "[" + getClass() + "]" + getText(); 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 查看文件

package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.xslf.model.CharacterPropertyFetcher;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;
import 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.*; import java.awt.*;
clr.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()}); 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. * @param fontSize font size in points.
* @return font size in points or -1 if font size is not set. * @return font size in points or -1 if font size is not set.
*/ */
public double getFontSize(){ public double getFontSize(){
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();
} }
/** /**
} }
/** /**
* @return font family or null if niot set
* @return font family or null if not set
*/ */
public String getFontFamily(){ 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();
} }
/** /**
/** /**
* @return whether a run of text will be formatted as strikethrough text. Default is false. * @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();
} }
/** /**
* @return whether this run of text is formatted as bold text * @return whether this run of text is formatted as bold text
*/ */
public boolean isBold(){ 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();
} }
/** /**
* @return whether this run of text is formatted as italic text * @return whether this run of text is formatted as italic text
*/ */
public boolean isItalic(){ 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();
} }
/** /**
* @return whether this run of text is formatted as underlined text * @return whether this run of text is formatted as underlined text
*/ */
public boolean isUnderline(){ 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(){ protected CTTextCharacterProperties getRpR(){
return new XSLFHyperlink(_r.getRPr().getHlinkClick(), this); 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 查看文件



import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
import org.apache.poi.xslf.model.PropertyFetcher;
import org.apache.poi.xslf.model.TextBodyPropertyFetcher;
import org.apache.xmlbeans.XmlObject; 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.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;


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


return paragraph; 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. * Sets the type of vertical alignment for the text.
* @return the type of alignment * @return the type of alignment
*/ */
public VerticalAlignment getVerticalAlignment(){ 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();
} }


/** /**
* @return the bottom margin or -1 if not set * @return the bottom margin or -1 if not set
*/ */
public double getMarginBottom(){ 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();
} }


/** /**
* @return the left margin * @return the left margin
*/ */
public double getMarginLeft(){ 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();
} }


/** /**
* @return the right margin * @return the right margin
*/ */
public double getMarginRight(){ 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();
} }


/** /**
* @return the top margin * @return the top margin
*/ */
public double getMarginTop(){ 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();
} }


/** /**
* @return the value indicating word wrap * @return the value indicating word wrap
*/ */
public boolean getWordWrap(){ 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();
} }


/** /**




protected abstract CTTextBody getTextBody(boolean create); 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 查看文件

import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions; 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.ThemeDocument;
import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeStyleSheet; 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 javax.xml.namespace.QName;

import java.awt.Color;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Map; import java.util.Map;
@Beta @Beta
public class XSLFTheme extends POIXMLDocumentPart { public class XSLFTheme extends POIXMLDocumentPart {
private CTOfficeStyleSheet _theme; private CTOfficeStyleSheet _theme;

private Map<String, XSLFColor> _schemeColors;
XSLFTheme() { XSLFTheme() {
super(); super();
_theme = CTOfficeStyleSheet.Factory.newInstance(); _theme = CTOfficeStyleSheet.Factory.newInstance();
ThemeDocument doc = ThemeDocument doc =
ThemeDocument.Factory.parse(getPackagePart().getInputStream()); ThemeDocument.Factory.parse(getPackagePart().getInputStream());
_theme = doc.getTheme(); _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(){ public String getName(){
return _theme.getName(); return _theme.getName();
} }


/** /**
* 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! * While developing only!
*/ */
@Internal @Internal
out.close(); 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 查看文件

/*
* ====================================================================
* 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 查看文件

if(part.getContentType().equals(XSLFRelation.MAIN.getContentType())) { if(part.getContentType().equals(XSLFRelation.MAIN.getContentType())) {
found = true; found = true;
} }
//System.out.println(part);
} }
assertTrue(found); assertTrue(found);
} }

+ 16
- 15
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java 查看文件

XSLFAutoShape shape = slide.createAutoShape(); XSLFAutoShape shape = slide.createAutoShape();
shape.addNewTextParagraph().addNewTextRun().setText("POI"); 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); shape.setMarginBottom(1.0);
assertEquals(1.0, shape.getMarginBottom()); assertEquals(1.0, shape.getMarginBottom());
shape.setMarginRight(0.0); shape.setMarginRight(0.0);
assertEquals(0.0, shape.getMarginRight()); assertEquals(0.0, shape.getMarginRight());
// unset to defauls
shape.setMarginBottom(-1); shape.setMarginBottom(-1);
assertEquals(-1., shape.getMarginBottom());
assertEquals(3.6, shape.getMarginBottom());
shape.setMarginTop(-1); shape.setMarginTop(-1);
assertEquals(-1.0, shape.getMarginTop());
assertEquals(3.6, shape.getMarginTop());
shape.setMarginLeft(-1); shape.setMarginLeft(-1);
assertEquals(-1.0, shape.getMarginLeft());
assertEquals(7.2, shape.getMarginLeft());
shape.setMarginRight(-1); shape.setMarginRight(-1);
assertEquals(-1.0, shape.getMarginRight());
assertEquals(7.2, shape.getMarginRight());
// shape // shape
assertFalse(shape.getWordWrap());
shape.setWordWrap(true);
assertTrue(shape.getWordWrap()); assertTrue(shape.getWordWrap());
shape.setWordWrap(false); shape.setWordWrap(false);
assertFalse(shape.getWordWrap()); assertFalse(shape.getWordWrap());
shape.setWordWrap(true);
assertTrue(shape.getWordWrap());
// shape // shape
assertEquals(TextAutofit.NORMAL, shape.getTextAutofit()); assertEquals(TextAutofit.NORMAL, shape.getTextAutofit());
assertEquals(1, p.getTextRuns().size()); assertEquals(1, p.getTextRuns().size());
assertSame(r, p.getTextRuns().get(0)); 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()); assertFalse(r.getXmlObject().getRPr().isSetSz());
r.setFontSize(10.0); r.setFontSize(10.0);
assertTrue(r.getXmlObject().isSetRPr()); assertTrue(r.getXmlObject().isSetRPr());
assertFalse(r.getXmlObject().getRPr().isSetSz()); assertFalse(r.getXmlObject().getRPr().isSetSz());
assertFalse(r.getXmlObject().getRPr().isSetLatin()); assertFalse(r.getXmlObject().getRPr().isSetLatin());
assertNull(r.getFontFamily());
assertEquals("Calibri", r.getFontFamily()); // comes from the slide master
r.setFontFamily(null); r.setFontFamily(null);
assertNull(r.getFontFamily());
assertEquals("Calibri", r.getFontFamily()); // comes from the slide master
r.setFontFamily("Arial"); r.setFontFamily("Arial");
assertEquals("Arial", r.getFontFamily()); assertEquals("Arial", r.getFontFamily());
assertEquals("Arial", r.getXmlObject().getRPr().getLatin().getTypeface()); assertEquals("Arial", r.getXmlObject().getRPr().getLatin().getTypeface());
assertEquals("Symbol", r.getFontFamily()); assertEquals("Symbol", r.getFontFamily());
assertEquals("Symbol", r.getXmlObject().getRPr().getLatin().getTypeface()); assertEquals("Symbol", r.getXmlObject().getRPr().getLatin().getTypeface());
r.setFontFamily(null); r.setFontFamily(null);
assertNull(r.getFontFamily());
assertEquals("Calibri", r.getFontFamily()); // comes from the slide master
assertFalse(r.getXmlObject().getRPr().isSetLatin()); assertFalse(r.getXmlObject().getRPr().isSetLatin());
assertFalse(r.isStrikethrough()); assertFalse(r.isStrikethrough());

+ 105
- 0
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java 查看文件

import org.apache.poi.util.Units; import org.apache.poi.util.Units;
import org.apache.poi.xslf.usermodel.LineCap; import org.apache.poi.xslf.usermodel.LineCap;
import org.apache.poi.xslf.usermodel.LineDash; 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.STLineCap;
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import java.awt.*; import java.awt.*;
assertFalse(shape.getSpPr().isSetSolidFill()); 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 查看文件

XSLFSlide slide = ppt.createSlide(); XSLFSlide slide = ppt.createSlide();
XSLFTextBox shape = slide.createTextBox(); XSLFTextBox shape = slide.createTextBox();
assertNull(shape.getPlaceholder());
assertNull(shape.getTextType());
shape.setPlaceholder(Placeholder.TITLE); shape.setPlaceholder(Placeholder.TITLE);
assertEquals(Placeholder.TITLE, shape.getPlaceholder());
assertEquals(Placeholder.TITLE, shape.getTextType());
shape.setPlaceholder(null); shape.setPlaceholder(null);
assertNull(shape.getPlaceholder());
assertNull(shape.getTextType());
} }
} }

+ 609
- 0
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java 查看文件

/* ====================================================================
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 查看文件

/* ====================================================================
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
文件差異過大導致無法顯示
查看文件


二進制
test-data/slideshow/layouts.pptx 查看文件


二進制
test-data/slideshow/shapes.pptx 查看文件


Loading…
取消
儲存