git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1205902 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_8_BETA5
@@ -65,6 +65,7 @@ import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.Comparator; | |||
import java.util.List; | |||
/** | |||
* Encapsulates logic to translate DrawingML objects to Java2D | |||
@@ -125,6 +126,8 @@ class RenderableShape { | |||
CTPathShadeProperties ps = gradFill.getPath(); | |||
if(ps.getPath() == STPathShadeType.CIRCLE){ | |||
paint = createRadialGradientPaint(gradFill, anchor, theme, phClr); | |||
} else if (ps.getPath() == STPathShadeType.SHAPE){ | |||
paint = toRadialGradientPaint(gradFill, anchor, theme, phClr); | |||
} | |||
} | |||
} | |||
@@ -165,7 +168,7 @@ class RenderableShape { | |||
return paint; | |||
} | |||
private static Paint createLinearGradientPaint( | |||
private Paint createLinearGradientPaint( | |||
Graphics2D graphics, | |||
CTGradientFillProperties gradFill, Rectangle2D anchor, | |||
XSLFTheme theme, CTSchemeColor phClr) { | |||
@@ -205,15 +208,16 @@ class RenderableShape { | |||
fractions[i] = stop.getPos() / 100000.f; | |||
} | |||
AffineTransform grAt; | |||
if(gradFill.getRotWithShape()) grAt = new AffineTransform(); | |||
else { | |||
// gradient fill is not rotated with the shape | |||
try { | |||
grAt = graphics.getTransform().createInverse(); | |||
} catch (Exception e){ | |||
// should not happen. | |||
grAt = new AffineTransform(); | |||
AffineTransform grAt = new AffineTransform(); | |||
if(gradFill.isSetRotWithShape() || !gradFill.getRotWithShape()) { | |||
double rotation = _shape.getRotation(); | |||
if (rotation != 0.) { | |||
double centerX = anchor.getX() + anchor.getWidth() / 2; | |||
double centerY = anchor.getY() + anchor.getHeight() / 2; | |||
grAt.translate(centerX, centerY); | |||
grAt.rotate(Math.toRadians(-rotation)); | |||
grAt.translate(-centerX, -centerY); | |||
} | |||
} | |||
@@ -237,6 +241,30 @@ class RenderableShape { | |||
return paint; | |||
} | |||
/** | |||
* gradients with type=shape are enot supported by Java graphics. | |||
* We approximate it with a radial gradient. | |||
*/ | |||
private static Paint toRadialGradientPaint( | |||
CTGradientFillProperties gradFill, Rectangle2D anchor, | |||
XSLFTheme theme, CTSchemeColor phClr) { | |||
CTGradientStop[] gs = gradFill.getGsLst().getGsArray(); | |||
Arrays.sort(gs, new Comparator<CTGradientStop>() { | |||
public int compare(CTGradientStop o1, CTGradientStop o2) { | |||
Integer pos1 = o1.getPos(); | |||
Integer pos2 = o2.getPos(); | |||
return pos1.compareTo(pos2); | |||
} | |||
}); | |||
gs[1].setPos(50000); | |||
CTGradientFillProperties g = CTGradientFillProperties.Factory.newInstance(); | |||
g.set(gradFill); | |||
g.getGsLst().setGsArray(new CTGradientStop[]{gs[0], gs[1]}); | |||
return createRadialGradientPaint(g, anchor, theme, phClr); | |||
} | |||
private static Paint createRadialGradientPaint( | |||
CTGradientFillProperties gradFill, Rectangle2D anchor, | |||
XSLFTheme theme, CTSchemeColor phClr) { | |||
@@ -498,7 +526,7 @@ class RenderableShape { | |||
if(shadow != null) for(Outline o : elems){ | |||
if(o.getPath().isFilled()){ | |||
if(fill != null) shadow.fill(graphics, o.getOutline()); | |||
if(line != null) shadow.draw(graphics, o.getOutline()); | |||
else if(line != null) shadow.draw(graphics, o.getOutline()); | |||
} | |||
} | |||
// then fill the shape interior |
@@ -32,7 +32,9 @@ import org.apache.poi.util.PackageHelper; | |||
import org.apache.poi.util.Units; | |||
import org.apache.poi.xslf.XSLFSlideShow; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.apache.xmlbeans.XmlObject; | |||
import org.apache.xmlbeans.XmlOptions; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; | |||
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPresentation; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdList; | |||
@@ -355,4 +357,15 @@ public class XMLSlideShow extends POIXMLDocument { | |||
return _tableStyles; | |||
} | |||
CTTextParagraphProperties getDefaultParagraphStyle(int level) { | |||
XmlObject[] o = _presentation.selectPath( | |||
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + | |||
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " + | |||
".//p:defaultTextStyle/a:lvl" +(level+1)+ "pPr"); | |||
if(o.length == 1){ | |||
return (CTTextParagraphProperties)o[0]; | |||
} | |||
return null; | |||
} | |||
} |
@@ -20,7 +20,9 @@ package org.apache.poi.xslf.usermodel; | |||
import org.apache.xmlbeans.XmlObject; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTBackgroundFillStyleList; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground; | |||
import java.awt.Color; | |||
@@ -91,4 +93,15 @@ public class XSLFBackground extends XSLFSimpleShape { | |||
} | |||
return null; | |||
} | |||
/** | |||
* background does not have a associated transform. | |||
* we return a dummy transform object to prevent exceptions in inherited methods. | |||
* | |||
* @return dummy CTTransform2D bean | |||
*/ | |||
@Override | |||
CTTransform2D getXfrm() { | |||
return CTTransform2D.Factory.newInstance(); | |||
} | |||
} |
@@ -24,6 +24,8 @@ import org.apache.poi.util.Beta; | |||
import javax.imageio.ImageIO; | |||
import java.awt.Graphics2D; | |||
import java.awt.Image; | |||
import java.awt.geom.AffineTransform; | |||
import java.awt.geom.Rectangle2D; | |||
import java.awt.image.BufferedImage; | |||
import java.io.ByteArrayInputStream; | |||
@@ -78,9 +80,19 @@ public class XSLFImageRendener { | |||
Rectangle2D anchor) { | |||
try { | |||
BufferedImage img = ImageIO.read(data.getPackagePart().getInputStream()); | |||
graphics.drawImage(img, | |||
(int) anchor.getX(), (int) anchor.getY(), | |||
(int) anchor.getWidth(), (int) anchor.getHeight(), null); | |||
Number groupScale = (Number)graphics.getRenderingHint(XSLFRenderingHint.GROUP_SCALE); | |||
if(groupScale != null) { | |||
double sx = anchor.getWidth()/img.getWidth(); | |||
double sy = anchor.getHeight()/img.getHeight(); | |||
double tx = anchor.getX(); | |||
double ty = anchor.getY(); | |||
AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ; | |||
graphics.drawRenderedImage(img, at); | |||
} else { | |||
graphics.drawImage(img, | |||
(int) anchor.getX(), (int) anchor.getY(), | |||
(int) anchor.getWidth(), (int) anchor.getHeight(), null); | |||
} | |||
return true; | |||
} catch (Exception e) { | |||
return false; |
@@ -44,7 +44,11 @@ public class XSLFShadow extends XSLFSimpleShape { | |||
public void fill(Graphics2D graphics, Shape outline) { | |||
double angle = getAngle(); | |||
double shapeRotation = _parent.getRotation(); | |||
if(_parent.getFlipVertical()){ | |||
shapeRotation += 180; | |||
} | |||
double angle = getAngle() - shapeRotation; | |||
double dist = getDistance(); | |||
double dx = dist * Math.cos(Math.toRadians(angle)); | |||
double dy = dist * Math.sin(Math.toRadians(angle)); |
@@ -413,6 +413,14 @@ public abstract class XSLFSheet extends POIXMLDocumentPart implements Iterable<X | |||
return false; | |||
} | |||
/** | |||
* | |||
* @return background for this sheet | |||
*/ | |||
public XSLFBackground getBackground() { | |||
return null; | |||
} | |||
/** | |||
* Render this sheet into the supplied graphics object | |||
* |
@@ -154,7 +154,7 @@ public abstract class XSLFSimpleShape extends XSLFShape { | |||
return _ph; | |||
} | |||
private CTTransform2D getXfrm() { | |||
CTTransform2D getXfrm() { | |||
PropertyFetcher<CTTransform2D> fetcher = new PropertyFetcher<CTTransform2D>() { | |||
public boolean fetch(XSLFSimpleShape shape) { | |||
CTShapeProperties pr = shape.getSpPr(); | |||
@@ -561,7 +561,7 @@ public abstract class XSLFSimpleShape extends XSLFShape { | |||
* | |||
* The following order of inheritance is assumed: | |||
* <p> | |||
* slide <-- slideLayout <-- slideMaster <-- default styles in the slideMaster | |||
* slide <-- slideLayout <-- slideMaster | |||
* </p> | |||
* | |||
* @param visitor the object that collects the desired property | |||
@@ -571,24 +571,21 @@ public abstract class XSLFSimpleShape extends XSLFShape { | |||
boolean ok = visitor.fetch(this); | |||
XSLFSimpleShape masterShape; | |||
XSLFSheet layout = getSheet().getMasterSheet(); | |||
if (layout != null) { | |||
XSLFSheet masterSheet = getSheet().getMasterSheet(); | |||
CTPlaceholder ph = getCTPlaceholder(); | |||
if (masterSheet != null && ph != null) { | |||
if (!ok) { | |||
// first try to fetch from the slide layout | |||
CTPlaceholder ph = getCTPlaceholder(); | |||
if (ph != null) { | |||
masterShape = layout.getPlaceholder(ph); | |||
if (masterShape != null) { | |||
ok = visitor.fetch(masterShape); | |||
} | |||
masterShape = masterSheet.getPlaceholder(ph); | |||
if (masterShape != null) { | |||
ok = visitor.fetch(masterShape); | |||
} | |||
} | |||
// try slide master | |||
if (!ok) { | |||
if (!ok ) { | |||
int textType; | |||
CTPlaceholder ph = getCTPlaceholder(); | |||
if (ph == null || !ph.isSetType()) textType = STPlaceholderType.INT_BODY; | |||
if ( !ph.isSetType()) textType = STPlaceholderType.INT_BODY; | |||
else { | |||
switch (ph.getType().intValue()) { | |||
case STPlaceholderType.INT_TITLE: | |||
@@ -605,7 +602,7 @@ public abstract class XSLFSimpleShape extends XSLFShape { | |||
break; | |||
} | |||
} | |||
XSLFSheet master = layout.getMasterSheet(); | |||
XSLFSheet master = masterSheet.getMasterSheet(); | |||
if (master != null) { | |||
masterShape = master.getPlaceholderByType(textType); | |||
if (masterShape != null) { |
@@ -184,23 +184,14 @@ public final class XSLFSlide extends XSLFSheet { | |||
* | |||
* @return the information about background appearance of this slide | |||
*/ | |||
@Override | |||
public XSLFBackground getBackground() { | |||
if(_slide.getCSld().isSetBg()) { | |||
return new XSLFBackground(_slide.getCSld().getBg(), this); | |||
} | |||
XSLFSlideLayout layout = getMasterSheet(); | |||
if(layout.getXmlObject().getCSld().isSetBg()) { | |||
return new XSLFBackground(layout.getXmlObject().getCSld().getBg(), this); | |||
} | |||
XSLFSlideMaster master = layout.getMasterSheet(); | |||
if(master.getXmlObject().getCSld().isSetBg()) { | |||
return new XSLFBackground(master.getXmlObject().getCSld().getBg(), this); | |||
CTBackground bg = _slide.getCSld().getBg(); | |||
if(bg != null) { | |||
return new XSLFBackground(bg, this); | |||
} else { | |||
return getMasterSheet().getBackground(); | |||
} | |||
return null; | |||
} | |||
/** |
@@ -22,6 +22,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.util.Beta; | |||
import org.apache.poi.util.Internal; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideLayout; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.SldLayoutDocument; | |||
@@ -115,6 +116,17 @@ public class XSLFSlideLayout extends XSLFSheet { | |||
return true; | |||
} | |||
@Override | |||
public XSLFBackground getBackground() { | |||
CTBackground bg = _layout.getCSld().getBg(); | |||
if(bg != null) { | |||
return new XSLFBackground(bg, this); | |||
} else { | |||
return getMasterSheet().getBackground(); | |||
} | |||
} | |||
/** | |||
* Copy placeholders from this layout to the destination slide | |||
* |
@@ -23,6 +23,7 @@ import org.apache.poi.util.Beta; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMaster; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMasterTextStyles; | |||
@@ -167,4 +168,14 @@ import java.util.Map; | |||
return true; | |||
} | |||
@Override | |||
public XSLFBackground getBackground() { | |||
CTBackground bg = _slide.getCSld().getBg(); | |||
if(bg != null) { | |||
return new XSLFBackground(bg, this); | |||
} else { | |||
return null; | |||
} | |||
} | |||
} |
@@ -570,7 +570,7 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{ | |||
/** | |||
* | |||
* @return the text level of this paragraph. Default is 0. | |||
* @return the text level of this paragraph (0-based). Default is 0. | |||
*/ | |||
public int getLevel(){ | |||
CTTextParagraphProperties pr = _p.getPPr(); | |||
@@ -823,7 +823,7 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{ | |||
AttributedString at = getAttributedString(graphics); | |||
AttributedCharacterIterator it = at.getIterator(); | |||
LineBreakMeasurer measurer = new LineBreakMeasurer(it, graphics.getFontRenderContext()); | |||
LineBreakMeasurer measurer = new LineBreakMeasurer(it, graphics.getFontRenderContext()) ; | |||
for (;;) { | |||
int startIndex = measurer.getPosition(); | |||
@@ -898,29 +898,27 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{ | |||
return _lines; | |||
} | |||
CTTextParagraphProperties getDefaultStyle(){ | |||
CTTextParagraphProperties getDefaultMasterStyle(){ | |||
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; | |||
} | |||
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(); | |||
// wind up and find the root master sheet which must be slide master | |||
XSLFSheet masterSheet = _shape.getSheet(); | |||
while (masterSheet.getMasterSheet() != null){ | |||
masterSheet = masterSheet.getMasterSheet(); | |||
@@ -946,9 +944,18 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{ | |||
if(!ok) { | |||
XSLFTextShape shape = getParentShape(); | |||
ok = shape.fetchShapeProperty(visitor); | |||
if(!ok) { | |||
CTTextParagraphProperties defaultProps = getDefaultStyle(); | |||
if(defaultProps != null) ok = visitor.fetch(defaultProps); | |||
if(!ok){ | |||
CTPlaceholder ph = shape.getCTPlaceholder(); | |||
if(ph == null){ | |||
// if it is a plain text box then take defaults from presentation.xml | |||
XMLSlideShow ppt = getParentShape().getSheet().getSlideShow(); | |||
CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getLevel()); | |||
if(themeProps != null) ok = visitor.fetch(themeProps); | |||
} else { | |||
// defaults for placeholders are defined in the slide master | |||
CTTextParagraphProperties defaultProps = getDefaultMasterStyle(); | |||
if(defaultProps != null) ok = visitor.fetch(defaultProps); | |||
} | |||
} | |||
} | |||
@@ -30,6 +30,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties | |||
import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; | |||
import java.awt.Color; | |||
import java.awt.font.FontRenderContext; | |||
@@ -467,11 +468,23 @@ public class XSLFTextRun { | |||
if(!ok) { | |||
XSLFTextShape shape = _p.getParentShape(); | |||
ok = shape.fetchShapeProperty(fetcher); | |||
if(!ok) { | |||
CTTextParagraphProperties defaultProps = _p.getDefaultStyle(); | |||
if(defaultProps != null) { | |||
fetcher.isFetchingFromMaster = true; | |||
ok = fetcher.fetch(defaultProps); | |||
if(!ok){ | |||
CTPlaceholder ph = shape.getCTPlaceholder(); | |||
if(ph == null){ | |||
// if it is a plain text box then take defaults from presentation.xml | |||
XMLSlideShow ppt = shape.getSheet().getSlideShow(); | |||
CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(_p.getLevel()); | |||
if(themeProps != null) { | |||
fetcher.isFetchingFromMaster = true; | |||
ok = fetcher.fetch(themeProps); | |||
} | |||
} else { | |||
// defaults for placeholders are defined in the slide master | |||
CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle(); | |||
if(defaultProps != null) { | |||
fetcher.isFetchingFromMaster = true; | |||
ok = fetcher.fetch(defaultProps); | |||
} | |||
} | |||
} | |||
} |
@@ -51,6 +51,11 @@ import java.util.List; | |||
public abstract class XSLFTextShape extends XSLFSimpleShape implements Iterable<XSLFTextParagraph>{ | |||
private final List<XSLFTextParagraph> _paragraphs; | |||
/** | |||
* whether the text was broken into lines. | |||
*/ | |||
private boolean _isTextBroken; | |||
/*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) { | |||
super(shape, sheet); | |||
@@ -441,17 +446,23 @@ public abstract class XSLFTextShape extends XSLFSimpleShape implements Iterable< | |||
/** | |||
* Compute the cumulative height occupied by the text | |||
*/ | |||
private double getTextHeight(){ | |||
public 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); | |||
Graphics2D graphics = img.createGraphics(); | |||
breakText(graphics); | |||
return drawParagraphs(graphics, 0, 0); | |||
} | |||
/** | |||
* break the contained text into lines | |||
*/ | |||
private void breakText(Graphics2D graphics){ | |||
for(XSLFTextParagraph p : _paragraphs) p.breakText(graphics); | |||
if(!_isTextBroken) { | |||
for(XSLFTextParagraph p : _paragraphs) p.breakText(graphics); | |||
_isTextBroken = true; | |||
} | |||
} | |||
@Override |
@@ -29,6 +29,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTColor; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorScheme; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeStyleSheet; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.ThemeDocument; | |||
import javax.xml.namespace.QName; | |||
@@ -150,4 +151,17 @@ public class XSLFTheme extends POIXMLDocumentPart { | |||
public String getMinorFont(){ | |||
return _theme.getThemeElements().getFontScheme().getMinorFont().getLatin().getTypeface(); | |||
} | |||
CTTextParagraphProperties getDefaultParagraphStyle(){ | |||
XmlObject[] o = _theme.selectPath( | |||
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + | |||
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " + | |||
".//a:objectDefaults/a:spDef/a:lstStyle/a:defPPr"); | |||
if(o.length == 1){ | |||
return (CTTextParagraphProperties)o[0]; | |||
} | |||
return null; | |||
} | |||
} |
@@ -17,6 +17,7 @@ | |||
package org.apache.poi.xslf.usermodel; | |||
import junit.framework.TestCase; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; | |||
/** | |||
* @author Yegor Kozlov | |||
@@ -33,5 +34,33 @@ public class TestXSLFTextBox extends TestCase { | |||
assertEquals(Placeholder.TITLE, shape.getTextType()); | |||
shape.setPlaceholder(null); | |||
assertNull(shape.getTextType()); | |||
shape.setText("Apache POI"); | |||
} | |||
/** | |||
* text box inherits default text proeprties from presentation.xml | |||
*/ | |||
public void testDefaultTextStyle() { | |||
XMLSlideShow ppt = new XMLSlideShow(); | |||
XSLFSlide slide = ppt.createSlide(); | |||
// default character properties for paragraphs with level=1 | |||
CTTextCharacterProperties pPr = ppt.getCTPresentation().getDefaultTextStyle().getLvl1PPr().getDefRPr(); | |||
XSLFTextBox shape = slide.createTextBox(); | |||
shape.setText("Apache POI"); | |||
assertEquals(1, shape.getTextParagraphs().size()); | |||
assertEquals(1, shape.getTextParagraphs().get(0).getTextRuns().size()); | |||
XSLFTextRun r = shape.getTextParagraphs().get(0).getTextRuns().get(0); | |||
assertEquals(1800, pPr.getSz()); | |||
assertEquals(18.0, r.getFontSize()); | |||
assertEquals("Calibri", r.getFontFamily()); | |||
pPr.setSz(900); | |||
pPr.getLatin().setTypeface("Arial"); | |||
assertEquals(9.0, r.getFontSize()); | |||
assertEquals("Arial", r.getFontFamily()); | |||
} | |||
} |
@@ -3,6 +3,7 @@ package org.apache.poi.xslf.usermodel; | |||
import junit.framework.TestCase; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.xslf.XSLFTestDataSamples; | |||
import java.awt.*; | |||
import java.awt.geom.Rectangle2D; | |||
@@ -105,22 +106,13 @@ public class TestXSLFTextParagraph extends TestCase { | |||
/** | |||
* test breaking test into lines. | |||
* This test is platform-dependent and will run only if the test fonr (Arial) | |||
* is present in local graphics environment | |||
* This test requires that the Arial font is available and will run only on windows | |||
*/ | |||
public void testBreakLines(){ | |||
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); | |||
String testFont = "Arial"; | |||
boolean testFontAvailable = false; | |||
for(String family : env.getAvailableFontFamilyNames()) { | |||
if(family.equals(testFont)) { | |||
testFontAvailable = true; | |||
break; | |||
} | |||
} | |||
if(!testFontAvailable) { | |||
_logger.log(POILogger.WARN, "the Arial font family is not available in local graphics environment"); | |||
String os = System.getProperty("os.name"); | |||
if(os == null || !os.contains("Windows")) { | |||
_logger.log(POILogger.WARN, "Skipping testBreakLines(), it is executed only on Windows machines"); | |||
return; | |||
} | |||
XMLSlideShow ppt = new XMLSlideShow(); | |||
@@ -198,4 +190,20 @@ public class TestXSLFTextParagraph extends TestCase { | |||
assertTrue(lines.get(0).getHeight() > lines.get(1).getHeight()*2); | |||
} | |||
public void testThemeInheritance(){ | |||
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("prProps.pptx"); | |||
XSLFShape[] shapes = ppt.getSlides()[0].getShapes(); | |||
XSLFTextShape sh1 = (XSLFTextShape)shapes[0]; | |||
assertEquals("Apache", sh1.getText()); | |||
assertEquals(TextAlign.CENTER, sh1.getTextParagraphs().get(0).getTextAlign()); | |||
XSLFTextShape sh2 = (XSLFTextShape)shapes[1]; | |||
assertEquals("Software", sh2.getText()); | |||
assertEquals(TextAlign.CENTER, sh2.getTextParagraphs().get(0).getTextAlign()); | |||
XSLFTextShape sh3 = (XSLFTextShape)shapes[2]; | |||
assertEquals("Foundation", sh3.getText()); | |||
assertEquals(TextAlign.CENTER, sh3.getTextParagraphs().get(0).getTextAlign()); | |||
} | |||
} |
@@ -19,6 +19,9 @@ package org.apache.poi.xslf.usermodel; | |||
import junit.framework.TestCase; | |||
import org.apache.poi.xslf.XSLFTestDataSamples; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; | |||
@@ -606,4 +609,288 @@ public class TestXSLFTextShape extends TestCase { | |||
XSLFTextShape sldNum = (XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_SLD_NUM); | |||
assertEquals("10", sldNum.getText()); | |||
} | |||
public void testTitleStyles(){ | |||
XMLSlideShow ppt = new XMLSlideShow(); | |||
XSLFSlideMaster master = ppt.getSlideMasters()[0]; | |||
XSLFTheme theme = master.getTheme(); | |||
XSLFSlideLayout layout = master.getLayout(SlideLayout.TITLE); | |||
XSLFSlide slide = ppt.createSlide(layout) ; | |||
assertSame(layout, slide.getSlideLayout()); | |||
assertSame(master, slide.getSlideMaster()); | |||
XSLFTextShape titleShape = (XSLFTextShape)slide.getPlaceholder(0); | |||
titleShape.setText("Apache POI"); | |||
XSLFTextParagraph paragraph = titleShape.getTextParagraphs().get(0); | |||
XSLFTextRun textRun = paragraph.getTextRuns().get(0); | |||
// level 1 : default title style on the master slide | |||
// /p:sldMaster/p:txStyles/p:titleStyle/a:lvl1pPr | |||
CTTextParagraphProperties lv1PPr = master.getXmlObject().getTxStyles().getTitleStyle().getLvl1PPr(); | |||
CTTextCharacterProperties lv1CPr = lv1PPr.getDefRPr(); | |||
assertEquals(4400, lv1CPr.getSz()); | |||
assertEquals(44.0, textRun.getFontSize()); | |||
assertEquals("+mj-lt", lv1CPr.getLatin().getTypeface()); | |||
assertEquals("Calibri", theme.getMajorFont()); | |||
assertEquals("Calibri", textRun.getFontFamily()); | |||
lv1CPr.setSz(3200); | |||
assertEquals(32.0, textRun.getFontSize()); | |||
lv1CPr.getLatin().setTypeface("Arial"); | |||
assertEquals("Arial", textRun.getFontFamily()); | |||
assertEquals(STTextAlignType.CTR, lv1PPr.getAlgn()); | |||
assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); | |||
lv1PPr.setAlgn(STTextAlignType.L); | |||
assertEquals(TextAlign.LEFT, paragraph.getTextAlign()); | |||
// level 2: title placeholder on the master slide | |||
// /p:sldMaster/p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="title"] | |||
XSLFTextShape tx2 = master.getPlaceholder(0); | |||
CTTextParagraphProperties lv2PPr = tx2.getTextBody(true).getLstStyle().addNewLvl1PPr(); | |||
CTTextCharacterProperties lv2CPr = lv2PPr.addNewDefRPr(); | |||
lv2CPr.setSz(3300); | |||
assertEquals(33.0, textRun.getFontSize()); | |||
lv2CPr.addNewLatin().setTypeface("Times"); | |||
assertEquals("Times", textRun.getFontFamily()); | |||
lv2PPr.setAlgn(STTextAlignType.R); | |||
assertEquals(TextAlign.RIGHT, paragraph.getTextAlign()); | |||
// level 3: title placeholder on the slide layout | |||
// /p:sldLayout /p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="ctrTitle"] | |||
XSLFTextShape tx3 = layout.getPlaceholder(0); | |||
CTTextParagraphProperties lv3PPr = tx3.getTextBody(true).getLstStyle().addNewLvl1PPr(); | |||
CTTextCharacterProperties lv3CPr = lv3PPr.addNewDefRPr(); | |||
lv3CPr.setSz(3400); | |||
assertEquals(34.0, textRun.getFontSize()); | |||
lv3CPr.addNewLatin().setTypeface("Courier New"); | |||
assertEquals("Courier New", textRun.getFontFamily()); | |||
lv3PPr.setAlgn(STTextAlignType.CTR); | |||
assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); | |||
// level 4: default text properties in the shape itself | |||
// ./p:sp/p:txBody/a:lstStyle/a:lvl1pPr | |||
CTTextParagraphProperties lv4PPr = titleShape.getTextBody(true).getLstStyle().addNewLvl1PPr(); | |||
CTTextCharacterProperties lv4CPr = lv4PPr.addNewDefRPr(); | |||
lv4CPr.setSz(3500); | |||
assertEquals(35.0, textRun.getFontSize()); | |||
lv4CPr.addNewLatin().setTypeface("Arial"); | |||
assertEquals("Arial", textRun.getFontFamily()); | |||
lv4PPr.setAlgn(STTextAlignType.L); | |||
assertEquals(TextAlign.LEFT, paragraph.getTextAlign()); | |||
// level 5: text properties are defined in the text run | |||
CTTextParagraphProperties lv5PPr = paragraph.getXmlObject().addNewPPr(); | |||
CTTextCharacterProperties lv5CPr = textRun.getXmlObject().getRPr(); | |||
lv5CPr.setSz(3600); | |||
assertEquals(36.0, textRun.getFontSize()); | |||
lv5CPr.addNewLatin().setTypeface("Calibri"); | |||
assertEquals("Calibri", textRun.getFontFamily()); | |||
lv5PPr.setAlgn(STTextAlignType.CTR); | |||
assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); | |||
} | |||
public void testBodyStyles(){ | |||
XMLSlideShow ppt = new XMLSlideShow(); | |||
XSLFSlideMaster master = ppt.getSlideMasters()[0]; | |||
XSLFTheme theme = master.getTheme(); | |||
XSLFSlideLayout layout = master.getLayout(SlideLayout.TITLE_AND_CONTENT); | |||
XSLFSlide slide = ppt.createSlide(layout) ; | |||
assertSame(layout, slide.getSlideLayout()); | |||
assertSame(master, slide.getSlideMaster()); | |||
XSLFTextShape tx1 = (XSLFTextShape)slide.getPlaceholder(1); | |||
tx1.clearText(); | |||
XSLFTextParagraph p1 = tx1.addNewTextParagraph(); | |||
assertEquals(0, p1.getLevel()); | |||
XSLFTextRun r1 = p1.addNewTextRun(); | |||
r1.setText("Apache POI"); | |||
XSLFTextParagraph p2 = tx1.addNewTextParagraph(); | |||
p2.setLevel(1); | |||
assertEquals(1, p2.getLevel()); | |||
XSLFTextRun r2 = p2.addNewTextRun(); | |||
r2.setText("HSLF"); | |||
XSLFTextParagraph p3 = tx1.addNewTextParagraph(); | |||
p3.setLevel(2); | |||
assertEquals(2, p3.getLevel()); | |||
XSLFTextRun r3 = p3.addNewTextRun(); | |||
r3.setText("XSLF"); | |||
// level 1 : default title style on the master slide | |||
// /p:sldMaster/p:txStyles/p:bodyStyle/a:lvl1pPr | |||
CTTextParagraphProperties lv1PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl1PPr(); | |||
CTTextCharacterProperties lv1CPr = lv1PPr.getDefRPr(); | |||
CTTextParagraphProperties lv2PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl2PPr(); | |||
CTTextCharacterProperties lv2CPr = lv2PPr.getDefRPr(); | |||
CTTextParagraphProperties lv3PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl3PPr(); | |||
CTTextCharacterProperties lv3CPr = lv3PPr.getDefRPr(); | |||
// lv1 | |||
assertEquals(3200, lv1CPr.getSz()); | |||
assertEquals(32.0, r1.getFontSize()); | |||
assertEquals("+mn-lt", lv1CPr.getLatin().getTypeface()); | |||
assertEquals("Calibri", theme.getMinorFont()); | |||
assertEquals("Calibri", r1.getFontFamily()); | |||
lv1CPr.setSz(3300); | |||
assertEquals(33.0, r1.getFontSize()); | |||
lv1CPr.getLatin().setTypeface("Arial"); | |||
assertEquals("Arial", r1.getFontFamily()); | |||
assertEquals(STTextAlignType.L, lv1PPr.getAlgn()); | |||
assertEquals(TextAlign.LEFT, p1.getTextAlign()); | |||
lv1PPr.setAlgn(STTextAlignType.R); | |||
assertEquals(TextAlign.RIGHT, p1.getTextAlign()); | |||
//lv2 | |||
assertEquals(2800, lv2CPr.getSz()); | |||
assertEquals(28.0, r2.getFontSize()); | |||
lv2CPr.setSz(3300); | |||
assertEquals(33.0, r2.getFontSize()); | |||
lv2CPr.getLatin().setTypeface("Times"); | |||
assertEquals("Times", r2.getFontFamily()); | |||
assertEquals(STTextAlignType.L, lv2PPr.getAlgn()); | |||
assertEquals(TextAlign.LEFT, p2.getTextAlign()); | |||
lv2PPr.setAlgn(STTextAlignType.R); | |||
assertEquals(TextAlign.RIGHT, p2.getTextAlign()); | |||
//lv3 | |||
assertEquals(2400, lv3CPr.getSz()); | |||
assertEquals(24.0, r3.getFontSize()); | |||
lv3CPr.setSz(2500); | |||
assertEquals(25.0, r3.getFontSize()); | |||
lv3CPr.getLatin().setTypeface("Courier New"); | |||
assertEquals("Courier New", r3.getFontFamily()); | |||
assertEquals(STTextAlignType.L, lv3PPr.getAlgn()); | |||
assertEquals(TextAlign.LEFT, p3.getTextAlign()); | |||
lv3PPr.setAlgn(STTextAlignType.R); | |||
assertEquals(TextAlign.RIGHT, p3.getTextAlign()); | |||
// level 2: body placeholder on the master slide | |||
// /p:sldMaster/p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="body"] | |||
XSLFTextShape tx2 = master.getPlaceholder(1); | |||
assertEquals(Placeholder.BODY, tx2.getTextType()); | |||
lv1PPr = tx2.getTextBody(true).getLstStyle().addNewLvl1PPr(); | |||
lv1CPr = lv1PPr.addNewDefRPr(); | |||
lv2PPr = tx2.getTextBody(true).getLstStyle().addNewLvl2PPr(); | |||
lv2CPr = lv2PPr.addNewDefRPr(); | |||
lv3PPr = tx2.getTextBody(true).getLstStyle().addNewLvl3PPr(); | |||
lv3CPr = lv3PPr.addNewDefRPr(); | |||
lv1CPr.setSz(3300); | |||
assertEquals(33.0, r1.getFontSize()); | |||
lv1CPr.addNewLatin().setTypeface("Times"); | |||
assertEquals("Times", r1.getFontFamily()); | |||
lv1PPr.setAlgn(STTextAlignType.L); | |||
assertEquals(TextAlign.LEFT, p1.getTextAlign()); | |||
lv2CPr.setSz(3300); | |||
assertEquals(33.0, r2.getFontSize()); | |||
lv2CPr.addNewLatin().setTypeface("Times"); | |||
assertEquals("Times", r2.getFontFamily()); | |||
lv2PPr.setAlgn(STTextAlignType.L); | |||
assertEquals(TextAlign.LEFT, p2.getTextAlign()); | |||
lv3CPr.setSz(3300); | |||
assertEquals(33.0, r3.getFontSize()); | |||
lv3CPr.addNewLatin().setTypeface("Times"); | |||
assertEquals("Times", r3.getFontFamily()); | |||
lv3PPr.setAlgn(STTextAlignType.L); | |||
assertEquals(TextAlign.LEFT, p3.getTextAlign()); | |||
// level 3: body placeholder on the slide layout | |||
// /p:sldLayout /p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="ctrTitle"] | |||
XSLFTextShape tx3 = layout.getPlaceholder(1); | |||
assertEquals(Placeholder.BODY, tx2.getTextType()); | |||
lv1PPr = tx3.getTextBody(true).getLstStyle().addNewLvl1PPr(); | |||
lv1CPr = lv1PPr.addNewDefRPr(); | |||
lv2PPr = tx3.getTextBody(true).getLstStyle().addNewLvl2PPr(); | |||
lv2CPr = lv2PPr.addNewDefRPr(); | |||
lv3PPr = tx3.getTextBody(true).getLstStyle().addNewLvl3PPr(); | |||
lv3CPr = lv3PPr.addNewDefRPr(); | |||
lv1CPr.setSz(3400); | |||
assertEquals(34.0, r1.getFontSize()); | |||
lv1CPr.addNewLatin().setTypeface("Courier New"); | |||
assertEquals("Courier New", r1.getFontFamily()); | |||
lv1PPr.setAlgn(STTextAlignType.CTR); | |||
assertEquals(TextAlign.CENTER, p1.getTextAlign()); | |||
lv2CPr.setSz(3400); | |||
assertEquals(34.0, r2.getFontSize()); | |||
lv2CPr.addNewLatin().setTypeface("Courier New"); | |||
assertEquals("Courier New", r2.getFontFamily()); | |||
lv2PPr.setAlgn(STTextAlignType.CTR); | |||
assertEquals(TextAlign.CENTER, p2.getTextAlign()); | |||
lv3CPr.setSz(3400); | |||
assertEquals(34.0, r3.getFontSize()); | |||
lv3CPr.addNewLatin().setTypeface("Courier New"); | |||
assertEquals("Courier New", r3.getFontFamily()); | |||
lv3PPr.setAlgn(STTextAlignType.CTR); | |||
assertEquals(TextAlign.CENTER, p3.getTextAlign()); | |||
// level 4: default text properties in the shape itself | |||
// ./p:sp/p:txBody/a:lstStyle/a:lvl1pPr | |||
lv1PPr = tx1.getTextBody(true).getLstStyle().addNewLvl1PPr(); | |||
lv1CPr = lv1PPr.addNewDefRPr(); | |||
lv2PPr = tx1.getTextBody(true).getLstStyle().addNewLvl2PPr(); | |||
lv2CPr = lv2PPr.addNewDefRPr(); | |||
lv3PPr = tx1.getTextBody(true).getLstStyle().addNewLvl3PPr(); | |||
lv3CPr = lv3PPr.addNewDefRPr(); | |||
lv1CPr.setSz(3500); | |||
assertEquals(35.0, r1.getFontSize()); | |||
lv1CPr.addNewLatin().setTypeface("Arial"); | |||
assertEquals("Arial", r1.getFontFamily()); | |||
lv1PPr.setAlgn(STTextAlignType.L); | |||
assertEquals(TextAlign.LEFT, p1.getTextAlign()); | |||
lv2CPr.setSz(3500); | |||
assertEquals(35.0, r2.getFontSize()); | |||
lv2CPr.addNewLatin().setTypeface("Arial"); | |||
assertEquals("Arial", r2.getFontFamily()); | |||
lv2PPr.setAlgn(STTextAlignType.L); | |||
assertEquals(TextAlign.LEFT, p2.getTextAlign()); | |||
lv3CPr.setSz(3500); | |||
assertEquals(35.0, r3.getFontSize()); | |||
lv3CPr.addNewLatin().setTypeface("Arial"); | |||
assertEquals("Arial", r3.getFontFamily()); | |||
lv3PPr.setAlgn(STTextAlignType.L); | |||
assertEquals(TextAlign.LEFT, p3.getTextAlign()); | |||
// level 5: text properties are defined in the text run | |||
lv1PPr = p1.getXmlObject().isSetPPr() ? p1.getXmlObject().getPPr() : p1.getXmlObject().addNewPPr(); | |||
lv1CPr = r1.getXmlObject().getRPr(); | |||
lv2PPr = p2.getXmlObject().isSetPPr() ? p2.getXmlObject().getPPr() : p2.getXmlObject().addNewPPr(); | |||
lv2CPr = r2.getXmlObject().getRPr(); | |||
lv3PPr = p3.getXmlObject().isSetPPr() ? p3.getXmlObject().getPPr() : p3.getXmlObject().addNewPPr(); | |||
lv3CPr = r3.getXmlObject().getRPr(); | |||
lv1CPr.setSz(3600); | |||
assertEquals(36.0, r1.getFontSize()); | |||
lv1CPr.addNewLatin().setTypeface("Calibri"); | |||
assertEquals("Calibri", r1.getFontFamily()); | |||
lv1PPr.setAlgn(STTextAlignType.CTR); | |||
assertEquals(TextAlign.CENTER, p1.getTextAlign()); | |||
lv2CPr.setSz(3600); | |||
assertEquals(36.0, r2.getFontSize()); | |||
lv2CPr.addNewLatin().setTypeface("Calibri"); | |||
assertEquals("Calibri", r2.getFontFamily()); | |||
lv2PPr.setAlgn(STTextAlignType.CTR); | |||
assertEquals(TextAlign.CENTER, p2.getTextAlign()); | |||
lv3CPr.setSz(3600); | |||
assertEquals(36.0, r3.getFontSize()); | |||
lv3CPr.addNewLatin().setTypeface("Calibri"); | |||
assertEquals("Calibri", r3.getFontFamily()); | |||
lv3PPr.setAlgn(STTextAlignType.CTR); | |||
assertEquals(TextAlign.CENTER, p3.getTextAlign()); | |||
} | |||
} |