#60625 - Rendering issue with background and shape overlayed by image

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1782096 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2017-02-08 01:12:22 +00:00
parent ac3d63926a
commit 5c4ab1dbdf
47 changed files with 1205 additions and 764 deletions

View File

@ -17,7 +17,13 @@
package org.apache.poi.sl.draw;
import org.apache.poi.sl.usermodel.*;
import java.awt.Graphics2D;
import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.SimpleShape;
import org.apache.poi.sl.usermodel.Slide;
public class DrawMasterSheet extends DrawSheet {
@ -33,12 +39,15 @@ public class DrawMasterSheet extends DrawSheet {
* for instance, slide masters and layouts don't display placeholders
*/
@Override
protected boolean canDraw(Shape<?,?> shape) {
protected boolean canDraw(Graphics2D graphics, Shape<?,?> shape) {
if (shape instanceof SimpleShape) {
// in XSLF, slidenumber and date shapes aren't marked as placeholders opposed to HSLF
Placeholder ph = ((SimpleShape<?,?>)shape).getPlaceholder();
return ph == null;
} else {
return true;
if (ph != null) {
Slide<?,?> slide = (Slide<?,?>)graphics.getRenderingHint(Drawable.CURRENT_SLIDE);
return slide.getDisplayPlaceholder(ph);
}
}
return true;
}
}

View File

@ -38,18 +38,34 @@ public class DrawShape implements Drawable {
this.shape = shape;
}
/**
* Sometimes it's necessary to distinguish between XSLF/HSLF for the rendering.
* Use this method on the shape to determine, if we work on the BIFF implementation
*
* @param shape the shape to render
* @return {@code true} if HSLF implementation is used
*/
protected static boolean isHSLF(Shape<?,?> shape) {
return shape.getClass().getCanonicalName().toLowerCase(Locale.ROOT).contains("hslf");
}
/**
* Apply 2-D transforms before drawing this shape. This includes rotation and flipping.
*
* @param graphics the graphics whos transform matrix will be modified
*/
@Override
public void applyTransform(Graphics2D graphics) {
if (!(shape instanceof PlaceableShape)) return;
if (!(shape instanceof PlaceableShape)) {
return;
}
PlaceableShape<?,?> ps = (PlaceableShape<?,?>)shape;
final boolean isHSLF = ps.getClass().getCanonicalName().toLowerCase(Locale.ROOT).contains("hslf");
final boolean isHSLF = isHSLF(shape);
AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM);
if (tx == null) tx = new AffineTransform();
if (tx == null) {
tx = new AffineTransform();
}
final Rectangle2D anchor = tx.createTransformedShape(ps.getAnchor()).getBounds2D();
char cmds[] = isHSLF ? new char[]{ 'h','v','r' } : new char[]{ 'r','h','v' };
@ -81,7 +97,9 @@ public class DrawShape implements Drawable {
// normalize rotation
rotation %= 360.;
if (rotation < 0) rotation += 360.;
if (rotation < 0) {
rotation += 360.;
}
int quadrant = (((int)rotation+45)/90)%4;
double scaleX = 1.0, scaleY = 1.0;
@ -148,9 +166,11 @@ public class DrawShape implements Drawable {
return (dim2 == 0.) ? 1 : dim1/dim2;
}
@Override
public void draw(Graphics2D graphics) {
}
@Override
public void drawContent(Graphics2D graphics) {
}
@ -176,7 +196,10 @@ public class DrawShape implements Drawable {
protected static BasicStroke getStroke(StrokeStyle strokeStyle) {
float lineWidth = (float) strokeStyle.getLineWidth();
if (lineWidth == 0.0f) lineWidth = 0.25f; // Both PowerPoint and OOo draw zero-length lines as 0.25pt
if (lineWidth == 0.0f) {
// Both PowerPoint and OOo draw zero-length lines as 0.25pt
lineWidth = 0.25f;
}
LineDash lineDash = strokeStyle.getLineDash();
if (lineDash == null) {
@ -194,7 +217,9 @@ public class DrawShape implements Drawable {
}
LineCap lineCapE = strokeStyle.getLineCap();
if (lineCapE == null) lineCapE = LineCap.FLAT;
if (lineCapE == null) {
lineCapE = LineCap.FLAT;
}
int lineCap;
switch (lineCapE) {
case ROUND:

View File

@ -17,13 +17,14 @@
package org.apache.poi.sl.draw;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import org.apache.poi.sl.usermodel.*;
import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.Sheet;
public class DrawSheet implements Drawable {
@ -34,6 +35,7 @@ public class DrawSheet implements Drawable {
this.sheet = sheet;
}
@Override
public void draw(Graphics2D graphics) {
Dimension dim = sheet.getSlideShow().getPageSize();
Color whiteTrans = new Color(1f,1f,1f,0f);
@ -51,7 +53,9 @@ public class DrawSheet implements Drawable {
graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, new AffineTransform());
for (Shape<?,?> shape : sheet.getShapes()) {
if(!canDraw(shape)) continue;
if(!canDraw(graphics, shape)) {
continue;
}
// remember the initial transform and restore it after we are done with drawing
AffineTransform at = graphics.getTransform();
@ -73,9 +77,11 @@ public class DrawSheet implements Drawable {
}
}
@Override
public void applyTransform(Graphics2D context) {
}
@Override
public void drawContent(Graphics2D context) {
}
@ -85,7 +91,7 @@ public class DrawSheet implements Drawable {
* Subclasses can override it and skip certain shapes from drawings,
* for instance, slide masters and layouts don't display placeholders
*/
protected boolean canDraw(Shape<?,?> shape){
protected boolean canDraw(Graphics2D graphics, Shape<?,?> shape){
return true;
}
}

View File

@ -29,6 +29,8 @@ public class DrawSlide extends DrawSheet {
}
public void draw(Graphics2D graphics) {
graphics.setRenderingHint(Drawable.CURRENT_SLIDE, this.sheet);
Background<?,?> bg = sheet.getBackground();
if(bg != null) {
DrawFactory drawFact = DrawFactory.getInstance(graphics);
@ -37,5 +39,6 @@ public class DrawSlide extends DrawSheet {
}
super.draw(graphics);
graphics.setRenderingHint(Drawable.CURRENT_SLIDE, null);
}
}

View File

@ -41,10 +41,12 @@ import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PlaceableShape;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.Sheet;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.sl.usermodel.TextParagraph.BulletStyle;
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.sl.usermodel.TextRun.FieldType;
import org.apache.poi.sl.usermodel.TextRun.TextCap;
import org.apache.poi.sl.usermodel.TextShape;
import org.apache.poi.sl.usermodel.TextShape.TextDirection;
@ -82,6 +84,7 @@ public class DrawTextParagraph implements Drawable {
/**
* Resolves instances being deserialized to the predefined constants.
*/
@Override
protected Object readResolve() throws InvalidObjectException {
if (HYPERLINK_HREF.getName().equals(getName())) {
return HYPERLINK_HREF;
@ -116,8 +119,11 @@ public class DrawTextParagraph implements Drawable {
autoNbrIdx = index;
}
@Override
public void draw(Graphics2D graphics){
if (lines.isEmpty()) return;
if (lines.isEmpty()) {
return;
}
double penY = y;
@ -144,7 +150,9 @@ public class DrawTextParagraph implements Drawable {
//The vertical line spacing
Double spacing = paragraph.getLineSpacing();
if (spacing == null) spacing = 100d;
if (spacing == null) {
spacing = 100d;
}
for(DrawTextFragment line : lines){
double penX;
@ -176,7 +184,9 @@ public class DrawTextParagraph implements Drawable {
double rightInset = insets.right;
TextAlign ta = paragraph.getTextAlign();
if (ta == null) ta = TextAlign.LEFT;
if (ta == null) {
ta = TextAlign.LEFT;
}
switch (ta) {
case CENTER:
penX += (anchor.getWidth() - line.getWidth() - leftInset - rightInset - leftMargin) / 2;
@ -217,9 +227,11 @@ public class DrawTextParagraph implements Drawable {
return (lines.isEmpty() || rawText.trim().isEmpty());
}
@Override
public void applyTransform(Graphics2D graphics) {
}
@Override
public void drawContent(Graphics2D graphics) {
}
@ -243,10 +255,14 @@ public class DrawTextParagraph implements Drawable {
double wrappingWidth = getWrappingWidth(lines.size() == 0, graphics) + 1; // add a pixel to compensate rounding errors
// shape width can be smaller that the sum of insets (this was proved by a test file)
if(wrappingWidth < 0) wrappingWidth = 1;
if(wrappingWidth < 0) {
wrappingWidth = 1;
}
int nextBreak = text.indexOf("\n", startIndex + 1);
if (nextBreak == -1) nextBreak = it.getEndIndex();
if (nextBreak == -1) {
nextBreak = it.getEndIndex();
}
TextLayout layout = measurer.nextLayout((float)wrappingWidth, nextBreak, true);
if (layout == null) {
@ -279,7 +295,9 @@ public class DrawTextParagraph implements Drawable {
maxLineHeight = Math.max(maxLineHeight, line.getHeight());
if(endIndex == it.getEndIndex()) break;
if(endIndex == it.getEndIndex()) {
break;
}
}
rawText = text.toString();
@ -287,7 +305,9 @@ public class DrawTextParagraph implements Drawable {
protected DrawTextFragment getBullet(Graphics2D graphics, AttributedCharacterIterator firstLineAttr) {
BulletStyle bulletStyle = paragraph.getBulletStyle();
if (bulletStyle == null) return null;
if (bulletStyle == null) {
return null;
}
String buCharacter;
AutoNumberingScheme ans = bulletStyle.getAutoNumberingScheme();
@ -296,10 +316,14 @@ public class DrawTextParagraph implements Drawable {
} else {
buCharacter = bulletStyle.getBulletCharacter();
}
if (buCharacter == null) return null;
if (buCharacter == null) {
return null;
}
String buFont = bulletStyle.getBulletFont();
if (buFont == null) buFont = paragraph.getDefaultFontFamily();
if (buFont == null) {
buFont = paragraph.getDefaultFontFamily();
}
assert(buFont != null);
PlaceableShape<?,?> ps = getParagraphShape();
@ -313,9 +337,14 @@ public class DrawTextParagraph implements Drawable {
float fontSize = (Float)firstLineAttr.getAttribute(TextAttribute.SIZE);
Double buSz = bulletStyle.getBulletFontSize();
if (buSz == null) buSz = 100d;
if (buSz > 0) fontSize *= buSz* 0.01;
else fontSize = (float)-buSz;
if (buSz == null) {
buSz = 100d;
}
if (buSz > 0) {
fontSize *= buSz* 0.01;
} else {
fontSize = (float)-buSz;
}
AttributedString str = new AttributedString(mapFontCharset(buCharacter,buFont));
@ -328,7 +357,11 @@ public class DrawTextParagraph implements Drawable {
return fact.getTextFragment(layout, str);
}
protected String getRenderableText(TextRun tr) {
protected String getRenderableText(Graphics2D graphics, TextRun tr) {
if (tr.getFieldType() == FieldType.SLIDE_NUMBER) {
Slide<?,?> slide = (Slide<?,?>)graphics.getRenderingHint(Drawable.CURRENT_SLIDE);
return (slide == null) ? "" : Integer.toString(slide.getSlideNumber());
}
StringBuilder buf = new StringBuilder();
TextCap cap = tr.getTextCap();
String tabs = null;
@ -364,18 +397,24 @@ public class DrawTextParagraph implements Drawable {
private String tab2space(TextRun tr) {
AttributedString string = new AttributedString(" ");
String fontFamily = tr.getFontFamily();
if (fontFamily == null) fontFamily = "Lucida Sans";
if (fontFamily == null) {
fontFamily = "Lucida Sans";
}
string.addAttribute(TextAttribute.FAMILY, fontFamily);
Double fs = tr.getFontSize();
if (fs == null) fs = 12d;
if (fs == null) {
fs = 12d;
}
string.addAttribute(TextAttribute.SIZE, fs.floatValue());
TextLayout l = new TextLayout(string.getIterator(), new FontRenderContext(null, true, true));
double wspace = l.getAdvance();
Double tabSz = paragraph.getDefaultTabSize();
if (tabSz == null) tabSz = wspace*4;
if (tabSz == null) {
tabSz = wspace*4;
}
int numSpaces = (int)Math.ceil(tabSz / wspace);
StringBuilder buf = new StringBuilder();
@ -449,10 +488,13 @@ public class DrawTextParagraph implements Drawable {
}
if (firstLine && !isHSLF()) {
if (bullet != null){
if (indent > 0) width -= indent;
if (indent > 0) {
width -= indent;
}
} else {
if (indent > 0) width -= indent; // first line indentation
else if (indent < 0) { // hanging indentation: the first line start at the left margin
if (indent > 0) {
width -= indent; // first line indentation
} else if (indent < 0) { // hanging indentation: the first line start at the left margin
width += leftMargin;
}
}
@ -480,25 +522,36 @@ public class DrawTextParagraph implements Drawable {
@SuppressWarnings("rawtypes")
private PlaceableShape<?,?> getParagraphShape() {
return new PlaceableShape(){
@Override
public ShapeContainer<?,?> getParent() { return null; }
@Override
public Rectangle2D getAnchor() { return paragraph.getParentShape().getAnchor(); }
@Override
public void setAnchor(Rectangle2D anchor) {}
@Override
public double getRotation() { return 0; }
@Override
public void setRotation(double theta) {}
@Override
public void setFlipHorizontal(boolean flip) {}
@Override
public void setFlipVertical(boolean flip) {}
@Override
public boolean getFlipHorizontal() { return false; }
@Override
public boolean getFlipVertical() { return false; }
@Override
public Sheet<?,?> getSheet() { return paragraph.getParentShape().getSheet(); }
};
}
protected AttributedString getAttributedString(Graphics2D graphics, StringBuilder text){
List<AttributedStringData> attList = new ArrayList<AttributedStringData>();
if (text == null) text = new StringBuilder();
if (text == null) {
text = new StringBuilder();
}
PlaceableShape<?,?> ps = getParagraphShape();
DrawFontManager fontHandler = (DrawFontManager)graphics.getRenderingHint(Drawable.FONT_HANDLER);
@SuppressWarnings("unchecked")
Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_MAP);
@ -506,9 +559,11 @@ public class DrawTextParagraph implements Drawable {
Map<String,String> fallbackMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_FALLBACK);
for (TextRun run : paragraph){
String runText = getRenderableText(run);
String runText = getRenderableText(graphics, run);
// skip empty runs
if (runText.isEmpty()) continue;
if (runText.isEmpty()) {
continue;
}
// user can pass an custom object to convert fonts
String mappedFont = run.getFontFamily();
@ -633,8 +688,11 @@ public class DrawTextParagraph implements Drawable {
return string;
}
/**
* @return {@code true} if the HSLF implementation is used
*/
protected boolean isHSLF() {
return paragraph.getClass().getName().contains("HSLF");
return DrawShape.isHSLF(paragraph.getParentShape());
}
/**

View File

@ -138,6 +138,7 @@ public class DrawTextShape extends DrawSimpleShape {
double y0 = y;
//noinspection RedundantCast
@SuppressWarnings("cast")
Iterator<? extends TextParagraph<?,?,? extends TextRun>> paragraphs =
(Iterator<? extends TextParagraph<?,?,? extends TextRun>>) getShape().iterator();

View File

@ -130,6 +130,12 @@ public interface Drawable {
DrawableHint GSAVE = new DrawableHint(10);
DrawableHint GRESTORE = new DrawableHint(11);
/**
* The Common SL Draw API works sometimes cascading, but there are places
* where the current slide context need to be evaluated, e.g. when slide numbers
* are printed. In this situation we need to have a way to access the current slide
*/
DrawableHint CURRENT_SLIDE = new DrawableHint(12);
/**

View File

@ -114,12 +114,30 @@ public enum Placeholder {
this.ooxmlId = ooxmlId;
}
public static Placeholder lookupNative(int nativeId) {
public static Placeholder lookupNativeSlide(int nativeId) {
return lookupNative(nativeId, 0);
}
public static Placeholder lookupNativeSlideMaster(int nativeId) {
return lookupNative(nativeId, 1);
}
public static Placeholder lookupNativeNotes(int nativeId) {
return lookupNative(nativeId, 2);
}
public static Placeholder lookupNativeNotesMaster(int nativeId) {
return lookupNative(nativeId, 3);
}
private static Placeholder lookupNative(int nativeId, int type) {
for (Placeholder ph : values()) {
if (ph.nativeSlideId == nativeId ||
ph.nativeSlideMasterId == nativeId ||
ph.nativeNotesId == nativeId ||
ph.nativeNotesMasterId == nativeId
if (
type == 0 && ph.nativeSlideId == nativeId ||
type == 1 && ph.nativeSlideMasterId == nativeId ||
type == 2 && ph.nativeNotesId == nativeId ||
type == 3 && ph.nativeNotesMasterId == nativeId
) {
return ph;
}

View File

@ -43,4 +43,14 @@ public interface Slide<
*/
String getTitle();
/**
* In XSLF, slidenumber and date shapes aren't marked as placeholders
* whereas in HSLF they are activated via a HeadersFooter configuration.
* This method is used to generalize that handling.
*
* @param placeholder
* @return {@code true} if the placeholder should be displayed/rendered
* @since POI 3.16-beta2
*/
boolean getDisplayPlaceholder(Placeholder placeholder);
}

View File

@ -20,6 +20,7 @@ package org.apache.poi.sl.usermodel;
import java.awt.Color;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.util.Internal;
/**
* Some text.
@ -30,6 +31,10 @@ public interface TextRun {
SMALL,
ALL
}
enum FieldType {
SLIDE_NUMBER, DATE_TIME
}
String getRawText();
void setText(String text);
@ -176,4 +181,12 @@ public interface TextRun {
* @since POI 3.14-Beta2
*/
Hyperlink<?,?> createHyperlink();
/**
* Experimental method to determine the field type, e.g. slide number
*
* @return the field type or {@code null} if text run is not a field
*/
@Internal
FieldType getFieldType();
}

View File

@ -19,20 +19,11 @@
package org.apache.poi.xslf.usermodel;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
class XSLFLineBreak extends XSLFTextRun {
private final CTTextCharacterProperties _brProps;
XSLFLineBreak(CTRegularTextRun r, XSLFTextParagraph p, CTTextCharacterProperties brProps){
protected XSLFLineBreak(CTTextLineBreak r, XSLFTextParagraph p) {
super(r, p);
_brProps = brProps;
}
@Override
protected CTTextCharacterProperties getRPr(boolean create){
return _brProps;
}
public void setText(String text){

View File

@ -1341,106 +1341,138 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperti
this.props = props;
}
@Override
public CTNoFillProperties getNoFill() {
return isSetNoFill() ? (CTNoFillProperties)props : null;
}
@Override
public boolean isSetNoFill() {
return (props instanceof CTNoFillProperties);
}
@Override
public void setNoFill(CTNoFillProperties noFill) {}
@Override
public CTNoFillProperties addNewNoFill() {
return null;
}
@Override
public void unsetNoFill() {}
@Override
public CTSolidColorFillProperties getSolidFill() {
return isSetSolidFill() ? (CTSolidColorFillProperties)props : null;
}
@Override
public boolean isSetSolidFill() {
return (props instanceof CTSolidColorFillProperties);
}
@Override
public void setSolidFill(CTSolidColorFillProperties solidFill) {}
@Override
public CTSolidColorFillProperties addNewSolidFill() {
return null;
}
@Override
public void unsetSolidFill() {}
@Override
public CTGradientFillProperties getGradFill() {
return isSetGradFill() ? (CTGradientFillProperties)props : null;
}
@Override
public boolean isSetGradFill() {
return (props instanceof CTGradientFillProperties);
}
@Override
public void setGradFill(CTGradientFillProperties gradFill) {}
@Override
public CTGradientFillProperties addNewGradFill() {
return null;
}
@Override
public void unsetGradFill() {}
@Override
public CTBlipFillProperties getBlipFill() {
return isSetBlipFill() ? (CTBlipFillProperties)props : null;
}
@Override
public boolean isSetBlipFill() {
return (props instanceof CTBlipFillProperties);
}
@Override
public void setBlipFill(CTBlipFillProperties blipFill) {}
@Override
public CTBlipFillProperties addNewBlipFill() {
return null;
}
@Override
public void unsetBlipFill() {}
@Override
public CTPatternFillProperties getPattFill() {
return isSetPattFill() ? (CTPatternFillProperties)props : null;
}
@Override
public boolean isSetPattFill() {
return (props instanceof CTPatternFillProperties);
}
@Override
public void setPattFill(CTPatternFillProperties pattFill) {}
@Override
public CTPatternFillProperties addNewPattFill() {
return null;
}
@Override
public void unsetPattFill() {}
@Override
public CTGroupFillProperties getGrpFill() {
return isSetGrpFill() ? (CTGroupFillProperties)props : null;
}
@Override
public boolean isSetGrpFill() {
return (props instanceof CTGroupFillProperties);
}
@Override
public void setGrpFill(CTGroupFillProperties grpFill) {}
@Override
public CTGroupFillProperties addNewGrpFill() {
return null;
}
@Override
public void unsetGrpFill() {}
@Override
public boolean isSetMatrixStyle() {
return false;
}
@Override
public CTStyleMatrixReference getMatrixStyle() {
return null;
}

View File

@ -32,6 +32,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.ColorStyle;
import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
@ -57,6 +58,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillPropertie
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix;
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference;
import org.openxmlformats.schemas.drawingml.x2006.main.STPathShadeType;
import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal;
import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
@ -150,6 +152,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
protected PaintStyle getFillPaint() {
final XSLFTheme theme = getSheet().getTheme();
final boolean hasPlaceholder = getPlaceholder() != null;
PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {
public boolean fetch(XSLFShape shape) {
XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(shape.getShapeProperties());
@ -163,7 +166,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
}
PackagePart pp = shape.getSheet().getPackagePart();
PaintStyle paint = selectPaint(fp, null, pp, theme);
PaintStyle paint = selectPaint(fp, null, pp, theme, hasPlaceholder);
if (paint != null) {
setValue(paint);
return true;
@ -172,7 +175,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
CTShapeStyle style = shape.getSpStyle();
if (style != null) {
fp = XSLFPropertiesDelegate.getFillDelegate(style.getFillRef());
paint = selectPaint(fp, null, pp, theme);
paint = selectPaint(fp, null, pp, theme, hasPlaceholder);
}
if (paint != null) {
setValue(paint);
@ -230,6 +233,9 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
if (cur.toChild(namespace, nodename)) {
child = (T)cur.getObject();
}
if (cur.toChild("http://schemas.openxmlformats.org/drawingml/2006/main", nodename)) {
child = (T)cur.getObject();
}
cur.dispose();
return child;
}
@ -290,61 +296,71 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
}
/**
* Walk up the inheritance tree and fetch shape properties.
* Walk up the inheritance tree and fetch shape properties.<p>
*
* The following order of inheritance is assumed:
* <p>
* slide <-- slideLayout <-- slideMaster
* </p>
* The following order of inheritance is assumed:<p>
* <ol>
* <li>slide
* <li>slideLayout
* <li>slideMaster
* </ol>
*
* Currently themes and their defaults aren't correctly handled
*
* @param visitor the object that collects the desired property
* @return true if the property was fetched
*/
protected boolean fetchShapeProperty(PropertyFetcher<?> visitor) {
boolean ok = visitor.fetch(this);
// try shape properties in slide
if (visitor.fetch(this)) {
return true;
}
XSLFSimpleShape masterShape;
XSLFSheet masterSheet = (XSLFSheet)getSheet().getMasterSheet();
CTPlaceholder ph = getCTPlaceholder();
if (masterSheet != null && ph != null) {
if (!ok) {
masterShape = masterSheet.getPlaceholder(ph);
if (masterShape != null) {
ok = visitor.fetch(masterShape);
}
if (ph == null) {
return false;
}
MasterSheet<XSLFShape,XSLFTextParagraph> sm = getSheet().getMasterSheet();
// try slide layout
if (sm instanceof XSLFSlideLayout) {
XSLFSlideLayout slideLayout = (XSLFSlideLayout)sm;
XSLFSimpleShape placeholderShape = slideLayout.getPlaceholder(ph);
if (placeholderShape != null && visitor.fetch(placeholderShape)) {
return true;
}
// try slide master
if (!ok ) {
int textType;
if ( !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;
}
}
XSLFSheet master = (XSLFSheet)masterSheet.getMasterSheet();
if (master != null) {
masterShape = master.getPlaceholderByType(textType);
if (masterShape != null) {
ok = visitor.fetch(masterShape);
}
}
sm = slideLayout.getMasterSheet();
}
// try slide master
if (sm instanceof XSLFSlideMaster) {
XSLFSlideMaster master = (XSLFSlideMaster)sm;
int textType = getPlaceholderType(ph);
XSLFSimpleShape masterShape = master.getPlaceholderByType(textType);
if (masterShape != null && visitor.fetch(masterShape)) {
return true;
}
}
return ok;
return false;
}
private static int getPlaceholderType(CTPlaceholder ph) {
if ( !ph.isSetType()) {
return STPlaceholderType.INT_BODY;
}
switch (ph.getType().intValue()) {
case STPlaceholderType.INT_TITLE:
case STPlaceholderType.INT_CTR_TITLE:
return STPlaceholderType.INT_TITLE;
case STPlaceholderType.INT_FTR:
case STPlaceholderType.INT_SLD_NUM:
case STPlaceholderType.INT_DT:
return ph.getType().intValue();
default:
return STPlaceholderType.INT_BODY;
}
}
/**
@ -358,7 +374,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
*
* @return the applied Paint or null if none was applied
*/
protected static PaintStyle selectPaint(XSLFFillProperties fp, final CTSchemeColor phClr, final PackagePart parentPart, final XSLFTheme theme) {
protected static PaintStyle selectPaint(XSLFFillProperties fp, final CTSchemeColor phClr, final PackagePart parentPart, final XSLFTheme theme, boolean hasPlaceholder) {
if (fp == null || fp.isSetNoFill()) {
return null;
} else if (fp.isSetSolidFill()) {
@ -368,15 +384,23 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
} else if (fp.isSetGradFill()) {
return selectPaint(fp.getGradFill(), phClr, theme);
} else if (fp.isSetMatrixStyle()) {
return selectPaint(fp.getMatrixStyle(), theme, fp.isLineStyle());
return selectPaint(fp.getMatrixStyle(), theme, fp.isLineStyle(), hasPlaceholder);
} else {
return null;
}
}
protected static PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr, final XSLFTheme theme) {
if (phClr == null && solidFill.isSetSchemeClr()) {
phClr = solidFill.getSchemeClr();
if (solidFill.isSetSchemeClr()) {
// if there's a reference to the placeholder color,
// stop evaluating further and let the caller select
// the next style inheritance level
if (STSchemeColorVal.PH_CLR.equals(solidFill.getSchemeClr().getVal())) {
return null;
}
if (phClr == null) {
phClr = solidFill.getSchemeClr();
}
}
final XSLFColor c = new XSLFColor(solidFill, theme, phClr);
return DrawPaint.createSolidPaint(c.getColorStyle());
@ -483,7 +507,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
};
}
protected static PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme, boolean isLineStyle) {
protected static PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme, boolean isLineStyle, boolean hasPlaceholder) {
if (fillRef == null) return null;
// The idx attribute refers to the index of a fill style or
@ -492,7 +516,6 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
// values 1-999 refer to the index of a fill style within the fillStyleLst element
// values 1001 and above refer to the index of a background fill style within the bgFillStyleLst element.
int idx = (int)fillRef.getIdx();
CTSchemeColor phClr = fillRef.getSchemeClr();
CTStyleMatrix matrix = theme.getXmlObject().getThemeElements().getFmtScheme();
final XmlObject styleLst;
int childIdx;
@ -511,8 +534,16 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
fp = XSLFPropertiesDelegate.getFillDelegate(cur.getObject());
}
cur.dispose();
return selectPaint(fp, phClr, theme.getPackagePart(), theme);
CTSchemeColor phClr = fillRef.getSchemeClr();
PaintStyle res = selectPaint(fp, phClr, theme.getPackagePart(), theme, hasPlaceholder);
// check for empty placeholder value
// see http://officeopenxml.com/prSlide-color.php - "Color Placeholders within Themes"
if (res != null || hasPlaceholder) {
return res;
}
XSLFColor col = new XSLFColor(fillRef, theme, phClr);
return DrawPaint.createSolidPaint(col.getColorStyle());
}
@Override

View File

@ -121,6 +121,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
protected CTTransform2D getXfrm(boolean create) {
PropertyFetcher<CTTransform2D> fetcher = new PropertyFetcher<CTTransform2D>() {
@Override
public boolean fetch(XSLFShape shape) {
XmlObject xo = shape.getShapeProperties();
if (xo instanceof CTShapeProperties && ((CTShapeProperties)xo).isSetXfrm()) {
@ -234,20 +235,32 @@ public abstract class XSLFSimpleShape extends XSLFShape
*/
CTLineProperties getDefaultLineProperties() {
CTShapeStyle style = getSpStyle();
if (style == null) return null;
if (style == null) {
return null;
}
CTStyleMatrixReference lnRef = style.getLnRef();
if (lnRef == null) return null;
if (lnRef == null) {
return null;
}
// 1-based index of a line style within the style matrix
int idx = (int)lnRef.getIdx();
XSLFTheme theme = getSheet().getTheme();
if (theme == null) return null;
if (theme == null) {
return null;
}
CTBaseStyles styles = theme.getXmlObject().getThemeElements();
if (styles == null) return null;
if (styles == null) {
return null;
}
CTStyleMatrix styleMatrix = styles.getFmtScheme();
if (styleMatrix == null) return null;
if (styleMatrix == null) {
return null;
}
CTLineStyleList lineStyles = styleMatrix.getLnStyleLst();
if (lineStyles == null || lineStyles.sizeOfLnArray() < idx) return null;
if (lineStyles == null || lineStyles.sizeOfLnArray() < idx) {
return null;
}
return lineStyles.getLnArray(idx - 1);
}
@ -301,12 +314,14 @@ public abstract class XSLFSimpleShape extends XSLFShape
protected PaintStyle getLinePaint() {
XSLFSheet sheet = getSheet();
final XSLFTheme theme = sheet.getTheme();
final boolean hasPlaceholder = getPlaceholder() != null;
PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {
@Override
public boolean fetch(XSLFShape shape) {
CTLineProperties spPr = getLn(shape, false);
XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(spPr);
PackagePart pp = shape.getSheet().getPackagePart();
PaintStyle paint = selectPaint(fp, null, pp, theme);
PaintStyle paint = selectPaint(fp, null, pp, theme, hasPlaceholder);
if (paint != null) {
setValue(paint);
return true;
@ -315,7 +330,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
CTShapeStyle style = shape.getSpStyle();
if (style != null) {
fp = XSLFPropertiesDelegate.getFillDelegate(style.getLnRef());
paint = selectPaint(fp, null, pp, theme);
paint = selectPaint(fp, null, pp, theme, hasPlaceholder);
}
if (paint != null) {
setValue(paint);
@ -327,11 +342,15 @@ public abstract class XSLFSimpleShape extends XSLFShape
fetchShapeProperty(fetcher);
PaintStyle paint = fetcher.getValue();
if (paint != null) return paint;
if (paint != null) {
return paint;
}
// line color was not found, check if it is defined in the theme
CTShapeStyle style = getSpStyle();
if (style == null) return null;
if (style == null) {
return null;
}
// get a reference to a line style within the style matrix.
CTStyleMatrixReference lnRef = style.getLnRef();
@ -341,7 +360,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
CTLineProperties props = theme.getXmlObject().getThemeElements().getFmtScheme().getLnStyleLst().getLnArray(idx - 1);
XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props);
PackagePart pp = sheet.getPackagePart();
paint = selectPaint(fp, phClr, pp, theme);
paint = selectPaint(fp, phClr, pp, theme, hasPlaceholder);
}
return paint;
@ -387,6 +406,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
*/
public double getLineWidth() {
PropertyFetcher<Double> fetcher = new PropertyFetcher<Double>() {
@Override
public boolean fetch(XSLFShape shape) {
CTLineProperties ln = getLn(shape, false);
if (ln != null) {
@ -409,7 +429,9 @@ public abstract class XSLFSimpleShape extends XSLFShape
if (fetcher.getValue() == null) {
CTLineProperties defaultLn = getDefaultLineProperties();
if (defaultLn != null) {
if (defaultLn.isSetW()) lineWidth = Units.toPoints(defaultLn.getW());
if (defaultLn.isSetW()) {
lineWidth = Units.toPoints(defaultLn.getW());
}
}
} else {
lineWidth = fetcher.getValue();
@ -460,6 +482,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
*/
public LineCompound getLineCompound() {
PropertyFetcher<Integer> fetcher = new PropertyFetcher<Integer>() {
@Override
public boolean fetch(XSLFShape shape) {
CTLineProperties ln = getLn(shape, false);
if (ln != null) {
@ -522,6 +545,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
public LineDash getLineDash() {
PropertyFetcher<LineDash> fetcher = new PropertyFetcher<LineDash>() {
@Override
public boolean fetch(XSLFShape shape) {
CTLineProperties ln = getLn(shape, false);
if (ln == null || !ln.isSetPrstDash()) {
@ -569,6 +593,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
*/
public LineCap getLineCap() {
PropertyFetcher<LineCap> fetcher = new PropertyFetcher<LineCap>() {
@Override
public boolean fetch(XSLFShape shape) {
CTLineProperties ln = getLn(shape, false);
if (ln != null && ln.isSetCap()) {
@ -640,8 +665,10 @@ public abstract class XSLFSimpleShape extends XSLFShape
/**
* @return shadow of this shape or null if shadow is disabled
*/
@Override
public XSLFShadow getShadow() {
PropertyFetcher<CTOuterShadowEffect> fetcher = new PropertyFetcher<CTOuterShadowEffect>() {
@Override
public boolean fetch(XSLFShape shape) {
XSLFEffectProperties ep = XSLFPropertiesDelegate.getEffectDelegate(shape.getShapeProperties());
if (ep != null && ep.isSetEffectLst()) {
@ -675,6 +702,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
*
* @return definition of the shape geometry
*/
@Override
public CustomGeometry getGeometry() {
XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties());
@ -949,6 +977,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
return ph != null;
}
@Override
public Guide getAdjustValue(String name) {
XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties());
@ -963,28 +992,35 @@ public abstract class XSLFSimpleShape extends XSLFShape
return null;
}
@Override
public LineDecoration getLineDecoration() {
return new LineDecoration() {
@Override
public DecorationShape getHeadShape() {
return getLineHeadDecoration();
}
@Override
public DecorationSize getHeadWidth() {
return getLineHeadWidth();
}
@Override
public DecorationSize getHeadLength() {
return getLineHeadLength();
}
@Override
public DecorationShape getTailShape() {
return getLineTailDecoration();
}
@Override
public DecorationSize getTailWidth() {
return getLineTailWidth();
}
@Override
public DecorationSize getTailLength() {
return getLineTailLength();
}
@ -996,32 +1032,40 @@ public abstract class XSLFSimpleShape extends XSLFShape
*
* @return either Color or GradientPaint or TexturePaint or null
*/
@Override
public FillStyle getFillStyle() {
return new FillStyle() {
@Override
public PaintStyle getPaint() {
return XSLFSimpleShape.this.getFillPaint();
}
};
}
@Override
public StrokeStyle getStrokeStyle() {
return new StrokeStyle() {
@Override
public PaintStyle getPaint() {
return XSLFSimpleShape.this.getLinePaint();
}
@Override
public LineCap getLineCap() {
return XSLFSimpleShape.this.getLineCap();
}
@Override
public LineDash getLineDash() {
return XSLFSimpleShape.this.getLineDash();
}
@Override
public double getLineWidth() {
return XSLFSimpleShape.this.getLineWidth();
}
@Override
public LineCompound getLineCompound() {
return XSLFSimpleShape.this.getLineCompound();
}

View File

@ -207,7 +207,7 @@ implements Slide<XSLFShape,XSLFTextParagraph> {
@Override
public boolean getFollowMasterGraphics(){
return _slide.isSetShowMasterSp() && _slide.getShowMasterSp();
return _slide.getShowMasterSp();
}
/**
@ -306,4 +306,9 @@ implements Slide<XSLFShape,XSLFTextParagraph> {
Drawable draw = drawFact.getDrawable(this);
draw.draw(graphics);
}
@Override
public boolean getDisplayPlaceholder(Placeholder placeholder) {
return false;
}
}

View File

@ -104,7 +104,7 @@ implements MasterSheet<XSLFShape,XSLFTextParagraph> {
@Override
public boolean getFollowMasterGraphics() {
return _layout.isSetShowMasterSp() && _layout.getShowMasterSp();
return _layout.getShowMasterSp();
}
/**

View File

@ -145,7 +145,9 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
}
CTTableCellProperties pr = getCellProperties(create);
if (pr == null) return null;
if (pr == null) {
return null;
}
switch (edge) {
case bottom:
@ -164,7 +166,9 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
@Override
public void removeBorder(BorderEdge edge) {
CTTableCellProperties pr = getCellProperties(false);
if (pr == null) return;
if (pr == null) {
return;
}
switch (edge) {
case bottom:
if (pr.isSetLnB()) {
@ -195,22 +199,27 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
public StrokeStyle getBorderStyle(final BorderEdge edge) {
final Double width = getBorderWidth(edge);
return (width == null) ? null : new StrokeStyle() {
@Override
public PaintStyle getPaint() {
return DrawPaint.createSolidPaint(getBorderColor(edge));
}
@Override
public LineCap getLineCap() {
return getBorderCap(edge);
}
@Override
public LineDash getLineDash() {
return getBorderDash(edge);
}
@Override
public LineCompound getLineCompound() {
return getBorderCompound(edge);
}
@Override
public double getLineWidth() {
return width;
}
@ -306,7 +315,9 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
public Color getBorderColor(BorderEdge edge) {
CTLineProperties ln = getCTLine(edge, false);
if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) return null;
if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) {
return null;
}
CTSolidColorFillProperties fill = ln.getSolidFill();
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
@ -381,7 +392,9 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
public void setFillColor(Color color) {
CTTableCellProperties spPr = getCellProperties(true);
if (color == null) {
if(spPr.isSetSolidFill()) spPr.unsetSolidFill();
if(spPr.isSetSolidFill()) {
spPr.unsetSolidFill();
}
} else {
CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill();
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
@ -409,10 +422,11 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
public PaintStyle getFillPaint() {
XSLFSheet sheet = getSheet();
XSLFTheme theme = sheet.getTheme();
final boolean hasPlaceholder = getPlaceholder() != null;
XmlObject props = getCellProperties(false);
XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props);
if (fp != null) {
PaintStyle paint = selectPaint(fp, null, sheet.getPackagePart(), theme);
PaintStyle paint = selectPaint(fp, null, sheet.getPackagePart(), theme, hasPlaceholder);
if (paint != null) {
return paint;
}
@ -438,7 +452,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
fp = XSLFPropertiesDelegate.getFillDelegate(props);
if (fp != null) {
PaintStyle paint = XSLFShape.selectPaint(fp, null, slideShow.getPackagePart(), theme);
PaintStyle paint = XSLFShape.selectPaint(fp, null, slideShow.getPackagePart(), theme, hasPlaceholder);
if (paint != null) {
return paint;
}

View File

@ -72,23 +72,20 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr
_runs = new ArrayList<XSLFTextRun>();
_shape = shape;
for(XmlObject ch : _p.selectPath("*")){
if(ch instanceof CTRegularTextRun){
CTRegularTextRun r = (CTRegularTextRun)ch;
_runs.add(newTextRun(r));
} else if (ch instanceof CTTextLineBreak){
CTTextLineBreak br = (CTTextLineBreak)ch;
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
r.setRPr(br.getRPr());
r.setT("\n");
_runs.add(newTextRun(r));
} else if (ch instanceof CTTextField){
CTTextField f = (CTTextField)ch;
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
r.setRPr(f.getRPr());
r.setT(f.getT());
_runs.add(newTextRun(r));
XmlCursor c = _p.newCursor();
try {
if (c.toFirstChild()) {
do {
XmlObject r = c.getObject();
if (r instanceof CTTextLineBreak) {
_runs.add(new XSLFLineBreak((CTTextLineBreak)r, this));
} else if (r instanceof CTRegularTextRun || r instanceof CTTextField) {
_runs.add(new XSLFTextRun(r, this));
}
} while (c.toNextSibling());
}
} finally {
c.dispose();
}
}
@ -147,17 +144,13 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr
* @return text run representing this line break ('\n')
*/
public XSLFTextRun addLineBreak(){
CTTextLineBreak br = _p.addNewBr();
CTTextCharacterProperties brProps = br.addNewRPr();
XSLFLineBreak run = new XSLFLineBreak(_p.addNewBr(), this);
CTTextCharacterProperties brProps = run.getRPr(true);
if(_runs.size() > 0){
// by default line break has the font size of the last text run
CTTextCharacterProperties prevRun = _runs.get(_runs.size() - 1).getRPr(true);
brProps.set(prevRun);
}
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
r.setRPr(brProps);
r.setT("\n");
XSLFTextRun run = new XSLFLineBreak(r, this, brProps);
_runs.add(run);
return run;
}

View File

@ -18,6 +18,7 @@ package org.apache.poi.xslf.usermodel;
import java.awt.Color;
import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.PaintStyle;
@ -26,13 +27,16 @@ import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.util.Beta;
import org.apache.poi.xslf.model.CharacterPropertyFetcher;
import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;
@ -45,12 +49,15 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
*/
@Beta
public class XSLFTextRun implements TextRun {
private final CTRegularTextRun _r;
private final XmlObject _r;
private final XSLFTextParagraph _p;
protected XSLFTextRun(CTRegularTextRun r, XSLFTextParagraph p){
protected XSLFTextRun(XmlObject r, XSLFTextParagraph p){
_r = r;
_p = p;
if (!(r instanceof CTRegularTextRun || r instanceof CTTextLineBreak || r instanceof CTTextField)) {
throw new OpenXML4JRuntimeException("unsupported text run of type "+r.getClass());
}
}
XSLFTextParagraph getParentParagraph(){
@ -58,11 +65,28 @@ public class XSLFTextRun implements TextRun {
}
public String getRawText(){
return _r.getT();
if (_r instanceof CTTextField) {
return ((CTTextField)_r).getT();
} else if (_r instanceof CTTextLineBreak) {
return "\n";
}
return ((CTRegularTextRun)_r).getT();
}
String getRenderableText(){
String txt = _r.getT();
if (_r instanceof CTTextField) {
CTTextField tf = (CTTextField)_r;
XSLFSheet sheet = _p.getParentShape().getSheet();
if ("slidenum".equals(tf.getType()) && sheet instanceof XSLFSlide) {
return Integer.toString(((XSLFSlide)sheet).getSlideNumber());
}
return tf.getT();
} else if (_r instanceof CTTextLineBreak) {
return "\n";
}
String txt = ((CTRegularTextRun)_r).getT();
TextCap cap = getTextCap();
StringBuffer buf = new StringBuffer();
for(int i = 0; i < txt.length(); i++) {
@ -88,10 +112,24 @@ public class XSLFTextRun implements TextRun {
}
public void setText(String text){
_r.setT(text);
if (_r instanceof CTTextField) {
((CTTextField)_r).setT(text);
} else if (_r instanceof CTTextLineBreak) {
// ignored
return;
} else {
((CTRegularTextRun)_r).setT(text);
}
}
public CTRegularTextRun getXmlObject(){
/**
* Return the text run xmlbeans object.
* Depending on the type of text run, this can be {@link CTTextField},
* {@link CTTextLineBreak} or usually a {@link CTRegularTextRun}
*
* @return the xmlbeans object
*/
public XmlObject getXmlObject(){
return _r;
}
@ -117,6 +155,7 @@ public class XSLFTextRun implements TextRun {
@Override
public PaintStyle getFontColor(){
final boolean hasPlaceholder = getParentParagraph().getParentShape().getPlaceholder() != null;
CharacterPropertyFetcher<PaintStyle> fetcher = new CharacterPropertyFetcher<PaintStyle>(_p.getIndentLevel()){
public boolean fetch(CTTextCharacterProperties props){
if (props == null) {
@ -134,7 +173,7 @@ public class XSLFTextRun implements TextRun {
XSLFSheet sheet = shape.getSheet();
PackagePart pp = sheet.getPackagePart();
XSLFTheme theme = sheet.getTheme();
PaintStyle ps = XSLFShape.selectPaint(fp, phClr, pp, theme);
PaintStyle ps = XSLFShape.selectPaint(fp, phClr, pp, theme, hasPlaceholder);
if (ps != null) {
setValue(ps);
@ -459,13 +498,29 @@ public class XSLFTextRun implements TextRun {
* @return the character properties or null if create was false and the properties haven't exist
*/
protected CTTextCharacterProperties getRPr(boolean create) {
if (_r.isSetRPr()) {
return _r.getRPr();
} else if (create) {
return _r.addNewRPr();
if (_r instanceof CTTextField) {
CTTextField tf = (CTTextField)_r;
if (tf.isSetRPr()) {
return tf.getRPr();
} else if (create) {
return tf.addNewRPr();
}
} else if (_r instanceof CTTextLineBreak) {
CTTextLineBreak tlb = (CTTextLineBreak)_r;
if (tlb.isSetRPr()) {
return tlb.getRPr();
} else if (create) {
return tlb.addNewRPr();
}
} else {
return null;
CTRegularTextRun tr = (CTRegularTextRun)_r;
if (tr.isSetRPr()) {
return tr.getRPr();
} else if (create) {
return tr.addNewRPr();
}
}
return null;
}
@Override
@ -476,15 +531,17 @@ public class XSLFTextRun implements TextRun {
@Override
public XSLFHyperlink createHyperlink(){
XSLFHyperlink hl = getHyperlink();
if (hl == null) {
hl = new XSLFHyperlink(_r.getRPr().addNewHlinkClick(), _p.getParentShape().getSheet());
if (hl != null) {
return hl;
}
return hl;
CTTextCharacterProperties rPr = getRPr(true);
return new XSLFHyperlink(rPr.addNewHlinkClick(), _p.getParentShape().getSheet());
}
@Override
public XSLFHyperlink getHyperlink(){
CTTextCharacterProperties rPr = _r.getRPr();
CTTextCharacterProperties rPr = getRPr(false);
if (rPr == null) {
return null;
}
@ -498,33 +555,33 @@ public class XSLFTextRun implements TextRun {
private boolean fetchCharacterProperty(CharacterPropertyFetcher<?> fetcher){
XSLFTextShape shape = _p.getParentShape();
XSLFSheet sheet = shape.getSheet();
boolean ok = false;
if (_r.isSetRPr()) ok = fetcher.fetch(getRPr(false));
if (ok) return true;
CTTextCharacterProperties rPr = getRPr(false);
if (rPr != null && fetcher.fetch(rPr)) {
return true;
}
ok = shape.fetchShapeProperty(fetcher);
if (ok) return true;
if (shape.fetchShapeProperty(fetcher)) {
return true;
}
CTPlaceholder ph = shape.getCTPlaceholder();
if (ph == null){
// if it is a plain text box then take defaults from presentation.xml
@SuppressWarnings("resource")
XMLSlideShow ppt = sheet.getSlideShow();
// TODO: determine master shape
CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(_p.getIndentLevel());
if (themeProps != null) {
// TODO: determine master shape
ok = fetcher.fetch(themeProps);
if (themeProps != null && fetcher.fetch(themeProps)) {
return true;
}
}
if (ok) return true;
// TODO: determine master shape
CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle();
if(defaultProps != null) {
// TODO: determine master shape
ok = fetcher.fetch(defaultProps);
if(defaultProps != null && fetcher.fetch(defaultProps)) {
return true;
}
if (ok) return true;
return false;
}
@ -557,4 +614,16 @@ public class XSLFTextRun implements TextRun {
boolean strike = r.isStrikethrough();
if(strike != isStrikethrough()) setStrikethrough(strike);
}
@Override
public FieldType getFieldType() {
if (_r instanceof CTTextField) {
CTTextField tf = (CTTextField)_r;
if ("slidenum".equals(tf.getType())) {
return FieldType.SLIDE_NUMBER;
}
}
return null;
}
}

View File

@ -169,5 +169,4 @@ public class XSLFTheme extends POIXMLDocumentPart {
}
return null;
}
}

View File

@ -108,7 +108,8 @@ public class TestXSLFSlideShow {
// And again for the master
CTSlideMasterIdListEntry[] masters = xml.getSlideMasterReferences().getSldMasterIdArray();
assertEquals(2147483648l, masters[0].getId());
// see SlideAtom.USES_MASTER_SLIDE_ID
assertEquals(0x80000000L, masters[0].getId());
assertEquals("rId1", masters[0].getId2());
assertNotNull(xml.getSlideMaster(masters[0]));

View File

@ -105,7 +105,8 @@ public class TestXMLSlideShow extends BaseTestSlideShow {
// Next up look for the slide master
CTSlideMasterIdListEntry[] masters = xml.getCTPresentation().getSldMasterIdLst().getSldMasterIdArray();
assertEquals(2147483648l, masters[0].getId());
// see SlideAtom.USES_MASTER_SLIDE_ID
assertEquals(0x80000000L, masters[0].getId());
assertEquals("rId1", masters[0].getId2());
assertNotNull(xml.getSlideMasters().get(0));

View File

@ -16,22 +16,26 @@
==================================================================== */
package org.apache.poi.xslf.usermodel;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import org.apache.poi.sl.usermodel.*;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
import org.apache.poi.sl.usermodel.TextShape.TextAutofit;
import org.apache.poi.sl.usermodel.TextShape.TextDirection;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.Units;
import org.junit.Test;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;
/**
* @author Yegor Kozlov
*/
public class TestXSLFAutoShape {
@Test
public void testTextBodyProperies() throws IOException {
@ -222,56 +226,58 @@ public class TestXSLFAutoShape {
assertEquals(1, shape.getTextParagraphs().size());
assertEquals(0, p.getTextRuns().size());
XSLFTextRun r = p.addNewTextRun();
CTTextCharacterProperties rPr = r.getRPr(false);
assertNotNull(rPr);
assertEquals(1, p.getTextRuns().size());
assertSame(r, p.getTextRuns().get(0));
assertEquals(18.0, r.getFontSize(), 0); // default font size for text boxes
assertFalse(r.getXmlObject().getRPr().isSetSz());
assertFalse(rPr.isSetSz());
r.setFontSize(10.0);
assertTrue(r.getXmlObject().isSetRPr());
assertEquals(1000, r.getXmlObject().getRPr().getSz());
assertEquals(1000, rPr.getSz());
r.setFontSize(12.5);
assertEquals(1250, r.getXmlObject().getRPr().getSz());
assertEquals(1250, rPr.getSz());
r.setFontSize(null);
assertFalse(r.getXmlObject().getRPr().isSetSz());
assertFalse(rPr.isSetSz());
assertFalse(r.getXmlObject().getRPr().isSetLatin());
assertFalse(rPr.isSetLatin());
assertEquals("Calibri", r.getFontFamily()); // comes from the slide master
r.setFontFamily(null);
assertEquals("Calibri", r.getFontFamily()); // comes from the slide master
r.setFontFamily("Arial");
assertEquals("Arial", r.getFontFamily());
assertEquals("Arial", r.getXmlObject().getRPr().getLatin().getTypeface());
assertEquals("Arial", rPr.getLatin().getTypeface());
r.setFontFamily("Symbol");
assertEquals("Symbol", r.getFontFamily());
assertEquals("Symbol", r.getXmlObject().getRPr().getLatin().getTypeface());
assertEquals("Symbol", rPr.getLatin().getTypeface());
r.setFontFamily(null);
assertEquals("Calibri", r.getFontFamily()); // comes from the slide master
assertFalse(r.getXmlObject().getRPr().isSetLatin());
assertFalse(rPr.isSetLatin());
assertFalse(r.isStrikethrough());
assertFalse(r.getXmlObject().getRPr().isSetStrike());
assertFalse(rPr.isSetStrike());
r.setStrikethrough(true);
assertTrue(r.isStrikethrough());
assertEquals(STTextStrikeType.SNG_STRIKE, r.getXmlObject().getRPr().getStrike());
assertEquals(STTextStrikeType.SNG_STRIKE, rPr.getStrike());
assertFalse(r.isBold());
assertFalse(r.getXmlObject().getRPr().isSetB());
assertFalse(rPr.isSetB());
r.setBold(true);
assertTrue(r.isBold());
assertEquals(true, r.getXmlObject().getRPr().getB());
assertEquals(true, rPr.getB());
assertFalse(r.isItalic());
assertFalse(r.getXmlObject().getRPr().isSetI());
assertFalse(rPr.isSetI());
r.setItalic(true);
assertTrue(r.isItalic());
assertEquals(true, r.getXmlObject().getRPr().getI());
assertEquals(true, rPr.getI());
assertFalse(r.isUnderlined());
assertFalse(r.getXmlObject().getRPr().isSetU());
assertFalse(rPr.isSetU());
r.setUnderlined(true);
assertTrue(r.isUnderlined());
assertEquals(STTextUnderlineType.SNG, r.getXmlObject().getRPr().getU());
assertEquals(STTextUnderlineType.SNG, rPr.getU());
r.setText("Apache");
assertEquals("Apache", r.getRawText());

View File

@ -123,10 +123,11 @@ public class TestXSLFHyperlink {
XSLFTextBox tb3 = sl3.createTextBox();
tb3.setAnchor(anchor);
tb3.setText("text1 ");
XSLFTextRun r3 = tb3.appendText("lin\u000bk", false);
tb3.appendText("lin\u000bk", false);
tb3.appendText(" text2", false);
XSLFHyperlink hl3 = r3.createHyperlink();
hl3.linkToSlide(slide1);
List<XSLFTextRun> tb3runs = tb3.getTextParagraphs().get(0).getTextRuns();
tb3runs.get(1).createHyperlink().linkToSlide(slide1); // "lin"
tb3runs.get(3).createHyperlink().linkToSlide(slide1); // "k"
XSLFTextBox tb4 = ppt1.createSlide().createTextBox();
tb4.setAnchor(anchor);
XSLFTextRun r4 = tb4.setText("page4");
@ -155,6 +156,8 @@ public class TestXSLFHyperlink {
assertEquals(HyperlinkType.DOCUMENT, hl2.getTypeEnum());
tb3 = (XSLFTextBox)slides.get(2).getShapes().get(0);
XSLFHyperlink hl3 = tb3.getTextParagraphs().get(0).getTextRuns().get(1).getHyperlink();
assertNotNull(hl3);
hl3 = tb3.getTextParagraphs().get(0).getTextRuns().get(3).getHyperlink();
assertNotNull(hl3);
assertEquals("/ppt/slides/slide1.xml", hl3.getAddress());

View File

@ -16,18 +16,17 @@
==================================================================== */
package org.apache.poi.xslf.usermodel;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.List;
import org.apache.poi.xslf.XSLFTestDataSamples;
import org.junit.Test;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;
import java.io.IOException;
import java.util.List;
/**
* @author Yegor Kozlov
*/
public class TestXSLFShape {
@Test
@ -63,7 +62,7 @@ public class TestXSLFShape {
assertEquals("PPTX ", r2.get(0).getRawText());
assertEquals("Title", r2.get(1).getRawText());
// Title is underlined
assertEquals(STTextUnderlineType.SNG, r2.get(1).getXmlObject().getRPr().getU());
assertEquals(STTextUnderlineType.SNG, r2.get(1).getRPr(false).getU());
assertTrue(shapes2.get(1) instanceof XSLFAutoShape);
@ -78,7 +77,7 @@ public class TestXSLFShape {
assertEquals(1, paragraphs2.get(1).getTextRuns().size());
assertEquals("Subtitle", paragraphs2.get(0).getTextRuns().get(0).getRawText());
assertTrue(paragraphs2.get(0).getTextRuns().get(0).getXmlObject().getRPr().getB());
assertTrue(paragraphs2.get(0).getTextRuns().get(0).getRPr(false).getB());
assertEquals("And second line", paragraphs2.get(1).getTextRuns().get(0).getRawText());
ppt.close();

View File

@ -111,7 +111,7 @@ public class TestXSLFSlide {
assertEquals(0, ppt.getSlides().size());
XSLFSlide slide = ppt.createSlide();
assertFalse(slide.getFollowMasterGraphics());
assertTrue(slide.getFollowMasterGraphics());
slide.setFollowMasterGraphics(false);
assertFalse(slide.getFollowMasterGraphics());
slide.setFollowMasterGraphics(true);

View File

@ -714,7 +714,7 @@ public class TestXSLFTextShape {
// level 5: text properties are defined in the text run
CTTextParagraphProperties lv5PPr = paragraph.getXmlObject().addNewPPr();
CTTextCharacterProperties lv5CPr = textRun.getXmlObject().getRPr();
CTTextCharacterProperties lv5CPr = textRun.getRPr(false);
lv5CPr.setSz(3600);
assertEquals(36.0, textRun.getFontSize(), 0);
lv5CPr.addNewLatin().setTypeface("Calibri");
@ -899,11 +899,11 @@ public class TestXSLFTextShape {
// level 5: text properties are defined in the text run
lv1PPr = p1.getXmlObject().isSetPPr() ? p1.getXmlObject().getPPr() : p1.getXmlObject().addNewPPr();
lv1CPr = r1.getXmlObject().getRPr();
lv1CPr = r1.getRPr(false);
lv2PPr = p2.getXmlObject().isSetPPr() ? p2.getXmlObject().getPPr() : p2.getXmlObject().addNewPPr();
lv2CPr = r2.getXmlObject().getRPr();
lv2CPr = r2.getRPr(false);
lv3PPr = p3.getXmlObject().isSetPPr() ? p3.getXmlObject().getPPr() : p3.getXmlObject().addNewPPr();
lv3CPr = r3.getXmlObject().getRPr();
lv3CPr = r3.getRPr(false);
lv1CPr.setSz(3600);
assertEquals(36.0, r1.getFontSize(), 0);

View File

@ -17,12 +17,15 @@
package org.apache.poi.xslf.usermodel;
import static org.apache.poi.sl.TestCommonSL.sameColor;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.awt.Color;
import java.util.List;
import org.apache.poi.sl.usermodel.*;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
@ -54,7 +57,9 @@ public class TestXSLFTheme {
private XSLFShape getShape(XSLFSheet sheet, String name){
for(XSLFShape sh : sheet.getShapes()){
if(sh.getShapeName().equals(name)) return sh;
if(sh.getShapeName().equals(name)) {
return sh;
}
}
throw new IllegalArgumentException("Shape not found: " + name);
}
@ -99,7 +104,7 @@ public class TestXSLFTheme {
assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor()));
assertNull(sh2.getFillColor()); // no fill
assertFalse(slide.getSlideLayout().getFollowMasterGraphics());
assertTrue(slide.getSlideLayout().getFollowMasterGraphics());
}
void slide5(XSLFSlide slide){
@ -113,7 +118,7 @@ public class TestXSLFTheme {
// font size is 40pt and scale factor is 90%
assertEquals(36.0, run2.getFontSize(), 0);
assertFalse(slide.getSlideLayout().getFollowMasterGraphics());
assertTrue(slide.getSlideLayout().getFollowMasterGraphics());
}
void slide6(XSLFSlide slide){

View File

@ -21,13 +21,14 @@ import org.apache.poi.hslf.record.CString;
import org.apache.poi.hslf.record.Document;
import org.apache.poi.hslf.record.HeadersFootersAtom;
import org.apache.poi.hslf.record.HeadersFootersContainer;
import org.apache.poi.hslf.record.OEPlaceholderAtom;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.record.SheetContainer;
import org.apache.poi.hslf.usermodel.HSLFSheet;
import org.apache.poi.hslf.usermodel.HSLFSimpleShape;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.hslf.usermodel.HSLFTextShape;
import org.apache.poi.sl.usermodel.Placeholder;
/**
* Header / Footer settings.
@ -87,7 +88,7 @@ public final class HeadersFooters {
*/
public String getHeaderText(){
CString cs = _container == null ? null : _container.getHeaderAtom();
return getPlaceholderText(OEPlaceholderAtom.MasterHeader, cs);
return getPlaceholderText(Placeholder.HEADER, cs);
}
/**
@ -112,7 +113,7 @@ public final class HeadersFooters {
*/
public String getFooterText(){
CString cs = _container == null ? null : _container.getFooterAtom();
return getPlaceholderText(OEPlaceholderAtom.MasterFooter, cs);
return getPlaceholderText(Placeholder.FOOTER, cs);
}
/**
@ -137,7 +138,7 @@ public final class HeadersFooters {
*/
public String getDateTimeText(){
CString cs = _container == null ? null : _container.getUserDateAtom();
return getPlaceholderText(OEPlaceholderAtom.MasterDate, cs);
return getPlaceholderText(Placeholder.DATETIME, cs);
}
/**
@ -160,7 +161,7 @@ public final class HeadersFooters {
* whether the footer text is displayed.
*/
public boolean isFooterVisible(){
return isVisible(HeadersFootersAtom.fHasFooter, OEPlaceholderAtom.MasterFooter);
return isVisible(HeadersFootersAtom.fHasFooter, Placeholder.FOOTER);
}
/**
@ -174,7 +175,7 @@ public final class HeadersFooters {
* whether the header text is displayed.
*/
public boolean isHeaderVisible(){
return isVisible(HeadersFootersAtom.fHasHeader, OEPlaceholderAtom.MasterHeader);
return isVisible(HeadersFootersAtom.fHasHeader, Placeholder.HEADER);
}
/**
@ -188,7 +189,7 @@ public final class HeadersFooters {
* whether the date is displayed in the footer.
*/
public boolean isDateTimeVisible(){
return isVisible(HeadersFootersAtom.fHasDate, OEPlaceholderAtom.MasterDate);
return isVisible(HeadersFootersAtom.fHasDate, Placeholder.DATETIME);
}
/**
@ -202,7 +203,7 @@ public final class HeadersFooters {
* whether the custom user date is used instead of today's date.
*/
public boolean isUserDateVisible(){
return isVisible(HeadersFootersAtom.fHasUserDate, OEPlaceholderAtom.MasterDate);
return isVisible(HeadersFootersAtom.fHasUserDate, Placeholder.DATETIME);
}
/**
@ -216,7 +217,7 @@ public final class HeadersFooters {
* whether the slide number is displayed in the footer.
*/
public boolean isSlideNumberVisible(){
return isVisible(HeadersFootersAtom.fHasSlideNumber, OEPlaceholderAtom.MasterSlideNumber);
return isVisible(HeadersFootersAtom.fHasSlideNumber, Placeholder.SLIDE_NUMBER);
}
/**
@ -244,31 +245,29 @@ public final class HeadersFooters {
_container.getHeadersFootersAtom().setFormatId(formatId);
}
private boolean isVisible(int flag, int placeholderId){
private boolean isVisible(int flag, Placeholder placeholderId){
boolean visible;
if(_ppt2007){
HSLFTextShape placeholder = _sheet.getPlaceholder(placeholderId);
visible = placeholder != null && placeholder.getText() != null;
HSLFSimpleShape ss = _sheet.getPlaceholder(placeholderId);
visible = ss instanceof HSLFTextShape && ((HSLFTextShape)ss).getText() != null;
} else {
visible = _container.getHeadersFootersAtom().getFlag(flag);
}
return visible;
}
private String getPlaceholderText(int placeholderId, CString cs){
String text = null;
private String getPlaceholderText(Placeholder ph, CString cs) {
String text;
if (_ppt2007) {
HSLFTextShape placeholder = _sheet.getPlaceholder(placeholderId);
if (placeholder != null) {
text = placeholder.getText();
}
HSLFSimpleShape ss = _sheet.getPlaceholder(ph);
text = (ss instanceof HSLFTextShape) ? ((HSLFTextShape)ss).getText() : null;
// default text in master placeholders is not visible
if("*".equals(text)) {
text = null;
}
} else {
text = cs == null ? null : cs.getText();
text = (cs == null) ? null : cs.getText();
}
return text;
}

View File

@ -17,17 +17,18 @@
package org.apache.poi.hslf.record;
import org.apache.poi.util.LittleEndian;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.util.LittleEndian;
/**
* OEPlaceholderAtom (3011).
* <p>
* An atom record that specifies whether a shape is a placeholder shape.
* </p>
* OEPlaceholderAtom (3011).<p>
*
* An atom record that specifies whether a shape is a placeholder shape.
*
* @author Yegor Kozlov
* @see Placeholder
*/
public final class OEPlaceholderAtom extends RecordAtom{
@ -47,155 +48,6 @@ public final class OEPlaceholderAtom extends RecordAtom{
*/
public static final int PLACEHOLDER_QUARTSIZE = 2;
/**
* MUST NOT be used for this field.
*/
public static final byte None = 0;
/**
* The corresponding shape contains the master title text.
* The corresponding slide MUST be a main master slide.
*/
public static final byte MasterTitle = 1;
/**
* The corresponding shape contains the master body text.
* The corresponding slide MUST be a main master slide.
*/
public static final byte MasterBody = 2;
/**
* The corresponding shape contains the master center title text.
* The corresponding slide MUST be a title master slide.
*/
public static final byte MasterCenteredTitle = 3;
/**
* The corresponding shape contains the master sub-title text.
* The corresponding slide MUST be a title master slide.
*/
public static final byte MasterSubTitle = 4;
/**
* The corresponding shape contains the shared properties for slide image shapes.
* The corresponding slide MUST be a notes master slide.
*/
public static final byte MasterNotesSlideImage = 5;
/**
* The corresponding shape contains the master body text.
* The corresponding slide MUST be a notes master slide.
*/
public static final byte MasterNotesBody = 6;
/**
* The corresponding shape contains the date text field.
* The corresponding slide MUST be a main master slide, title master slide, notes master slide, or handout master slide.
*/
public static final byte MasterDate = 7;
/**
* The corresponding shape contains a slide number text field.
* The corresponding slide MUST be a main master slide, title master slide, notes master slide, or handout master slide.
*/
public static final byte MasterSlideNumber = 8;
/**
* The corresponding shape contains a footer text field.
* The corresponding slide MUST be a main master slide, title master slide, notes master slide, or handout master slide.
*/
public static final byte MasterFooter = 9;
/**
* The corresponding shape contains a header text field.
* The corresponding slide must be a notes master slide or handout master slide.
*/
public static final byte MasterHeader = 10;
/**
* The corresponding shape contains a presentation slide image.
* The corresponding slide MUST be a notes slide.
*/
public static final byte NotesSlideImage = 11;
/**
* The corresponding shape contains the notes text.
* The corresponding slide MUST be a notes slide.
*/
public static final byte NotesBody = 12;
/**
* The corresponding shape contains the title text.
* The corresponding slide MUST be a presentation slide.
*/
public static final byte Title = 13;
/**
* The corresponding shape contains the body text.
* The corresponding slide MUST be a presentation slide.
*/
public static final byte Body = 14;
/**
* The corresponding shape contains the title text.
* The corresponding slide MUST be a presentation slide.
*/
public static final byte CenteredTitle = 15;
/**
* The corresponding shape contains the sub-title text.
* The corresponding slide MUST be a presentation slide.
*/
public static final byte Subtitle = 16;
/**
* The corresponding shape contains the title text with vertical text flow.
* The corresponding slide MUST be a presentation slide.
*/
public static final byte VerticalTextTitle = 17;
/**
* The corresponding shape contains the body text with vertical text flow.
* The corresponding slide MUST be a presentation slide.
*/
public static final byte VerticalTextBody = 18;
/**
* The corresponding shape contains a generic object.
* The corresponding slide MUST be a presentation slide.
*/
public static final byte Object = 19;
/**
* The corresponding shape contains a chart object.
* The corresponding slide MUST be a presentation slide.
*/
public static final byte Graph = 20;
/**
* The corresponding shape contains a table object.
* The corresponding slide MUST be a presentation slide.
*/
public static final byte Table = 21;
/**
* The corresponding shape contains a clipart object.
* The corresponding slide MUST be a presentation slide.
*/
public static final byte ClipArt = 22;
/**
* The corresponding shape contains an organization chart object.
* The corresponding slide MUST be a presentation slide.
*/
public static final byte OrganizationChart = 23;
/**
* The corresponding shape contains a media object.
* The corresponding slide MUST be a presentation slide.
*/
public static final byte MediaClip = 24;
private byte[] _header;
private int placementId;
@ -205,7 +57,7 @@ public final class OEPlaceholderAtom extends RecordAtom{
/**
* Create a new instance of <code>OEPlaceholderAtom</code>
* Create a new instance of {@code OEPlaceholderAtom}
*/
public OEPlaceholderAtom(){
_header = new byte[8];
@ -219,7 +71,7 @@ public final class OEPlaceholderAtom extends RecordAtom{
}
/**
* Build an instance of <code>OEPlaceholderAtom</code> from on-disk data
* Build an instance of {@code OEPlaceholderAtom} from on-disk data
*/
protected OEPlaceholderAtom(byte[] source, int start, int len) {
_header = new byte[8];
@ -236,15 +88,15 @@ public final class OEPlaceholderAtom extends RecordAtom{
/**
* @return type of this record {@link RecordTypes#OEPlaceholderAtom}.
*/
public long getRecordType() { return RecordTypes.OEPlaceholderAtom.typeID; }
@Override
public long getRecordType() { return RecordTypes.OEPlaceholderAtom.typeID; }
/**
* Returns the placement Id.
* <p>
* Returns the placement Id.<p>
*
* The placement Id is a number assigned to the placeholder. It goes from -1 to the number of placeholders.
* It SHOULD be unique among all PlacholderAtom records contained in the corresponding slide.
* The value 0xFFFFFFFF specifies that the corresponding shape is not a placeholder shape.
* </p>
*
* @return the placement Id.
*/
@ -253,12 +105,11 @@ public final class OEPlaceholderAtom extends RecordAtom{
}
/**
* Sets the placement Id.
* <p>
* Sets the placement Id.<p>
*
* The placement Id is a number assigned to the placeholder. It goes from -1 to the number of placeholders.
* It SHOULD be unique among all PlacholderAtom records contained in the corresponding slide.
* The value 0xFFFFFFFF specifies that the corresponding shape is not a placeholder shape.
* </p>
*
* @param id the placement Id.
*/
@ -267,12 +118,10 @@ public final class OEPlaceholderAtom extends RecordAtom{
}
/**
* Returns the placeholder Id.
* Returns the placeholder Id.<p>
*
* <p>
* placeholder Id specifies the type of the placeholder shape.
* The value MUST be one of the static constants defined in this class
* </p>
*
* @return the placeholder Id.
*/
@ -281,12 +130,11 @@ public final class OEPlaceholderAtom extends RecordAtom{
}
/**
* Sets the placeholder Id.
* Sets the placeholder Id.<p>
*
* <p>
* placeholder Id specifies the type of the placeholder shape.
* The value MUST be one of the static constants defined in this class
* </p>
*
* @param id the placeholder Id.
*/
public void setPlaceholderId(byte id){
@ -314,10 +162,10 @@ public final class OEPlaceholderAtom extends RecordAtom{
}
/**
* Write the contents of the record back, so it can be written
* to disk
* Write the contents of the record back, so it can be written to disk
*/
public void writeOut(OutputStream out) throws IOException {
@Override
public void writeOut(OutputStream out) throws IOException {
out.write(_header);
byte[] recdata = new byte[8];

View File

@ -20,23 +20,21 @@ package org.apache.poi.hslf.record;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.record.SlideAtomLayout.SlideLayoutType;
import org.apache.poi.util.LittleEndian;
/**
* A Slide Atom (type 1007). Holds information on the parent Slide, what
* Master Slide it uses, what Notes is attached to it, that sort of thing.
* It also has a SSlideLayoutAtom embeded in it, but without the Atom header
*
* @author Nick Burch
* Master Slide it uses, what Notes is attached to it, that sort of thing.
* It also has a SSlideLayoutAtom embedded in it, but without the Atom header
*/
public final class SlideAtom extends RecordAtom
{
private byte[] _header;
public final class SlideAtom extends RecordAtom {
public static final int USES_MASTER_SLIDE_ID = 0x80000000;
// private static final int MASTER_SLIDE_ID = 0x00000000;
private byte[] _header;
private static long _type = 1007l;
public static final int MASTER_SLIDE_ID = 0;
public static final int USES_MASTER_SLIDE_ID = -2147483648;
private int masterID;
private int notesID;
@ -44,7 +42,7 @@ public final class SlideAtom extends RecordAtom
private boolean followMasterObjects;
private boolean followMasterScheme;
private boolean followMasterBackground;
private SSlideLayoutAtom layoutAtom;
private SlideAtomLayout layoutAtom;
private byte[] reserved;
@ -54,8 +52,8 @@ public final class SlideAtom extends RecordAtom
public void setMasterID(int id) { masterID = id; }
/** Get the ID of the notes for this slide. 0 if doesn't have one */
public int getNotesID() { return notesID; }
/** Get the embeded SSlideLayoutAtom */
public SSlideLayoutAtom getSSlideLayoutAtom() { return layoutAtom; }
/** Get the embedded SSlideLayoutAtom */
public SlideAtomLayout getSSlideLayoutAtom() { return layoutAtom; }
/** Change the ID of the notes for this slide. 0 if it no longer has one */
public void setNotesID(int id) { notesID = id; }
@ -85,7 +83,7 @@ public final class SlideAtom extends RecordAtom
byte[] SSlideLayoutAtomData = new byte[12];
System.arraycopy(source,start+8,SSlideLayoutAtomData,0,12);
// Use them to build up the SSlideLayoutAtom
layoutAtom = new SSlideLayoutAtom(SSlideLayoutAtomData);
layoutAtom = new SlideAtomLayout(SSlideLayoutAtomData);
// Get the IDs of the master and notes
masterID = LittleEndian.getInt(source,start+12+8);
@ -125,13 +123,13 @@ public final class SlideAtom extends RecordAtom
LittleEndian.putInt(_header, 4, 24);
byte[] ssdate = new byte[12];
layoutAtom = new SSlideLayoutAtom(ssdate);
layoutAtom.setGeometryType(SSlideLayoutAtom.BLANK_SLIDE);
layoutAtom = new SlideAtomLayout(ssdate);
layoutAtom.setGeometryType(SlideLayoutType.BLANK_SLIDE);
followMasterObjects = true;
followMasterScheme = true;
followMasterBackground = true;
masterID = -2147483648;
masterID = USES_MASTER_SLIDE_ID; // -2147483648;
notesID = 0;
reserved = new byte[2];
}
@ -168,70 +166,4 @@ public final class SlideAtom extends RecordAtom
// Reserved data
out.write(reserved);
}
/**
* Holds the geometry of the Slide, and the ID of the placeholders
* on the slide.
* (Embeded inside SlideAtom is a SSlideLayoutAtom, without the
* usual record header. Since it's a fixed size and tied to
* the SlideAtom, we'll hold it here.)
*/
public static class SSlideLayoutAtom {
// The different kinds of geometry
public static final int TITLE_SLIDE = 0;
public static final int TITLE_BODY_SLIDE = 1;
public static final int TITLE_MASTER_SLIDE = 2;
public static final int MASTER_SLIDE = 3;
public static final int MASTER_NOTES = 4;
public static final int NOTES_TITLE_BODY = 5;
public static final int HANDOUT = 6; // Only header, footer and date placeholders
public static final int TITLE_ONLY = 7;
public static final int TITLE_2_COLUMN_BODY = 8;
public static final int TITLE_2_ROW_BODY = 9;
public static final int TITLE_2_COLUNM_RIGHT_2_ROW_BODY = 10;
public static final int TITLE_2_COLUNM_LEFT_2_ROW_BODY = 11;
public static final int TITLE_2_ROW_BOTTOM_2_COLUMN_BODY = 12;
public static final int TITLE_2_ROW_TOP_2_COLUMN_BODY = 13;
public static final int FOUR_OBJECTS = 14;
public static final int BIG_OBJECT = 15;
public static final int BLANK_SLIDE = 16;
public static final int VERTICAL_TITLE_BODY_LEFT = 17;
public static final int VERTICAL_TITLE_2_ROW_BODY_LEFT = 17;
/** What geometry type we are */
private int geometry;
/** What placeholder IDs we have */
private byte[] placeholderIDs;
/** Retrieve the geometry type */
public int getGeometryType() { return geometry; }
/** Set the geometry type */
public void setGeometryType(int geom) { geometry = geom; }
/**
* Create a new Embeded SSlideLayoutAtom, from 12 bytes of data
*/
public SSlideLayoutAtom(byte[] data) {
if(data.length != 12) {
throw new HSLFException("SSlideLayoutAtom created with byte array not 12 bytes long - was " + data.length + " bytes in size");
}
// Grab out our data
geometry = LittleEndian.getInt(data,0);
placeholderIDs = new byte[8];
System.arraycopy(data,4,placeholderIDs,0,8);
}
/**
* Write the contents of the record back, so it can be written
* to disk. Skips the record header
*/
public void writeOut(OutputStream out) throws IOException {
// Write the geometry
writeLittleEndian(geometry,out);
// Write the placeholder IDs
out.write(placeholderIDs);
}
}
}

View File

@ -0,0 +1,133 @@
/* ====================================================================
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.hslf.record;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
/**
* Holds the geometry of the Slide, and the ID of the placeholders on the slide.
* Embedded inside a SlideAtom is a SlideAtomLayout, without the usual record header.
* Since it's a fixed size and tied to the SlideAtom, we'll hold it here.<p>
*
* This might eventually merged with the XSLF counterpart
*/
@Internal
public class SlideAtomLayout {
// The different kinds of geometry
public enum SlideLayoutType {
/** One title and one subtitle placeholder shapes. */
TITLE_SLIDE(0x0000),
/** Presentation slide or main master slide layout with one title and one body placeholder shape. */
TITLE_BODY(0x0001),
/** Title master slide layout with one title and one subtitle placeholder shape. */
MASTER_TITLE(0x0002),
/** ??? (not documented in spec) */
MASTER_SLIDE(0x0003),
/** ??? (not documented in spec) */
MASTER_NOTES(0x0004),
/** ??? (not documented in spec) */
NOTES_TITLE_BODY(0x0005),
/** Only header, footer and date placeholders */
HANDOUT(0x0006),
/** Presentation slide layout with one title placeholder shape. */
TITLE_ONLY(0x0007),
/** Presentation slide layout with one title and two body placeholder shapes stacked horizontally. */
TWO_COLUMNS(0x0008),
/** Presentation slide layout with one title and two body placeholder shapes stacked vertically. */
TWO_ROWS(0x0009),
/** Presentation slide layout with one title and three body placeholder shapes split into two columns. The right column has two rows. */
COLUMN_TWO_ROWS(0x000A),
/** Presentation slide layout with one title and three body placeholder shapes split into two columns. The left column has two rows. */
TWO_ROWS_COLUMN(0x000B),
/** ??? (not documented in spec) */
TITLE_2_ROW_BOTTOM_2_COLUMN_BODY(0x000C),
/** Presentation slide layout with one title and three body placeholder shapes split into two rows. The top row has two columns. */
TWO_COLUMNS_ROW(0x000D),
/** Presentation slide layout with one title and four body placeholder shapes. */
FOUR_OBJECTS(0x000E),
/** Presentation slide layout with one body placeholder shape. */
BIG_OBJECT(0x000F),
/** Presentation slide layout with no placeholder shape. */
BLANK_SLIDE(0x0010),
/** Presentation slide layout with a vertical title placeholder shape on the right and a body placeholder shape on the left. */
VERTICAL_TITLE_BODY(0x0011),
/** Presentation slide layout with a vertical title placeholder shape on the right and two body placeholder shapes in two columns on the left. */
VERTICAL_TWO_ROWS(0x0012);
private int nativeId;
SlideLayoutType(int nativeId) {
this.nativeId = nativeId;
}
public int getNativeId() {
return nativeId;
}
public static SlideLayoutType forNativeID(int nativeId) {
for (SlideLayoutType ans : values()) {
if (ans.nativeId == nativeId) {
return ans;
}
}
return null;
}
}
/** What geometry type we are */
private SlideLayoutType geometry;
/** What placeholder IDs we have */
private byte[] placeholderIDs;
/** Retrieve the geometry type */
public SlideLayoutType getGeometryType() { return geometry; }
/** Set the geometry type */
public void setGeometryType(SlideLayoutType geom) { geometry = geom; }
/**
* Create a new Embedded SSlideLayoutAtom, from 12 bytes of data
*/
public SlideAtomLayout(byte[] data) {
if(data.length != 12) {
throw new HSLFException("SSlideLayoutAtom created with byte array not 12 bytes long - was " + data.length + " bytes in size");
}
// Grab out our data
geometry = SlideLayoutType.forNativeID(LittleEndian.getInt(data,0));
placeholderIDs = new byte[8];
System.arraycopy(data,4,placeholderIDs,0,8);
}
/**
* Write the contents of the record back, so it can be written
* to disk. Skips the record header
*/
public void writeOut(OutputStream out) throws IOException {
// Write the geometry
byte[] buf = new byte[4];
LittleEndian.putInt(buf, 0, geometry.getNativeId());
out.write(buf);
// Write the placeholder IDs
out.write(placeholderIDs);
}
}

View File

@ -42,15 +42,11 @@ import org.apache.poi.util.POILogger;
* the style applies to, and what style elements make up the style (another
* list, this time of TextProps). Each TextProp has a value, which somehow
* encapsulates a property of the style
*
* @author Nick Burch
* @author Yegor Kozlov
*/
public final class StyleTextPropAtom extends RecordAtom
{
public final class StyleTextPropAtom extends RecordAtom {
public static final long _type = RecordTypes.StyleTextPropAtom.typeID;
private byte[] _header;
private static final long _type = RecordTypes.StyleTextPropAtom.typeID;
private byte[] reserved;
private byte[] rawContents; // Holds the contents between write-outs

View File

@ -17,25 +17,23 @@
package org.apache.poi.hslf.record;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;
import java.io.IOException;
import java.io.OutputStream;
/**
* A TextBytesAtom (type 4008). Holds text in ascii form (unknown
* code page, for now assumed to be the default of
* org.apache.poi.util.StringUtil, which is the Excel default).
* The trailing return character is always stripped from this
*
* @author Nick Burch
*/
public final class TextBytesAtom extends RecordAtom
{
public final class TextBytesAtom extends RecordAtom {
public static final long _type = RecordTypes.TextBytesAtom.typeID;
private byte[] _header;
private static long _type = RecordTypes.TextBytesAtom.typeID;
/** The bytes that make up the text */
private byte[] _text;
@ -87,13 +85,15 @@ public final class TextBytesAtom extends RecordAtom
/**
* We are of type 4008
*/
public long getRecordType() { return _type; }
@Override
public long getRecordType() { return _type; }
/**
* Write the contents of the record back, so it can be written
* to disk
*/
public void writeOut(OutputStream out) throws IOException {
@Override
public void writeOut(OutputStream out) throws IOException {
// Header - size or type unchanged
out.write(_header);
@ -105,7 +105,8 @@ public final class TextBytesAtom extends RecordAtom
* dump debug info; use getText() to return a string
* representation of the atom
*/
public String toString() {
@Override
public String toString() {
StringBuffer out = new StringBuffer();
out.append( "TextBytesAtom:\n");
out.append( HexDump.dump(_text, 0, 0) );

View File

@ -17,23 +17,21 @@
package org.apache.poi.hslf.record;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;
import java.io.IOException;
import java.io.OutputStream;
/**
* A TextCharsAtom (type 4000). Holds text in byte swapped unicode form.
* The trailing return character is always stripped from this
*
* @author Nick Burch
*/
public final class TextCharsAtom extends RecordAtom
{
public final class TextCharsAtom extends RecordAtom {
public static final long _type = RecordTypes.TextCharsAtom.typeID;
private byte[] _header;
private static long _type = RecordTypes.TextCharsAtom.typeID;
/** The bytes that make up the text */
private byte[] _text;
@ -83,13 +81,15 @@ public final class TextCharsAtom extends RecordAtom
/**
* We are of type 4000
*/
public long getRecordType() { return _type; }
@Override
public long getRecordType() { return _type; }
/**
* Write the contents of the record back, so it can be written
* to disk
*/
public void writeOut(OutputStream out) throws IOException {
@Override
public void writeOut(OutputStream out) throws IOException {
// Header - size or type unchanged
out.write(_header);
@ -101,7 +101,8 @@ public final class TextCharsAtom extends RecordAtom
* dump debug info; use getText() to return a string
* representation of the atom
*/
public String toString() {
@Override
public String toString() {
StringBuffer out = new StringBuffer();
out.append( "TextCharsAtom:\n");
out.append( HexDump.dump(_text, 0, 0) );

View File

@ -27,14 +27,11 @@ import org.apache.poi.util.LittleEndian;
* A TextHeaderAtom (type 3999). Holds information on what kind of
* text is contained in the TextBytesAtom / TextCharsAtom that follows
* straight after
*
* @author Nick Burch
*/
public final class TextHeaderAtom extends RecordAtom implements ParentAwareRecord
{
public final class TextHeaderAtom extends RecordAtom implements ParentAwareRecord {
public static final long _type = RecordTypes.TextHeaderAtom.typeID;
private byte[] _header;
private static long _type = RecordTypes.TextHeaderAtom.typeID;
private RecordContainer parentRecord;
public static final int TITLE_TYPE = 0;

View File

@ -30,15 +30,14 @@ import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.record.CString;
import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.hslf.record.OEPlaceholderAtom;
import org.apache.poi.hslf.record.PPDrawing;
import org.apache.poi.hslf.record.RecordContainer;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
import org.apache.poi.hslf.record.SheetContainer;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.Drawable;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.sl.usermodel.Sheet;
import org.apache.poi.util.Internal;
@ -108,6 +107,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
/**
* Fetch the SlideShow we're attached to
*/
@Override
public HSLFSlideShow getSlideShow() {
return _slideShow;
}
@ -131,7 +131,9 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
_slideShow = ss;
List<List<HSLFTextParagraph>> trs = getTextParagraphs();
if (trs == null) return;
if (trs == null) {
return;
}
for (List<HSLFTextParagraph> ltp : trs) {
HSLFTextParagraph.supplySheet(ltp, this);
HSLFTextParagraph.applyHyperlinks(ltp);
@ -192,6 +194,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
*
* @param shape - the Shape to add
*/
@Override
public void addShape(HSLFShape shape) {
PPDrawing ppdrawing = getPPDrawing();
@ -226,8 +229,9 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
c.incrementShapeId();
dg.setNumShapes( dg.getNumShapes() + 1 );
dg.setLastMSOSPID( result );
if (result >= dgg.getShapeIdMax())
if (result >= dgg.getShapeIdMax()) {
dgg.setShapeIdMax( result + 1 );
}
return result;
}
}
@ -238,8 +242,9 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
dg.setNumShapes( dg.getNumShapes() + 1 );
int result = (1024 * dgg.getFileIdClusters().length);
dg.setLastMSOSPID( result );
if (result >= dgg.getShapeIdMax())
if (result >= dgg.getShapeIdMax()) {
dgg.setShapeIdMax( result + 1 );
}
return result;
}
@ -249,6 +254,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
* @param shape shape to be removed from this sheet, if present.
* @return <tt>true</tt> if the shape was deleted.
*/
@Override
public boolean removeShape(HSLFShape shape) {
PPDrawing ppdrawing = getPPDrawing();
@ -274,6 +280,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
/**
* Return the master sheet .
*/
@Override
public abstract HSLFMasterSheet getMasterSheet();
/**
@ -288,6 +295,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
*
* @return the background shape for this sheet.
*/
@Override
public HSLFBackground getBackground() {
if (_background == null) {
PPDrawing ppdrawing = getPPDrawing();
@ -335,26 +343,17 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
}
/**
* Search text placeholer by its type
* Search placeholder by its type
*
* @param type type of placeholder to search. See {@link org.apache.poi.hslf.record.OEPlaceholderAtom}
* @return <code>TextShape</code> or <code>null</code>
* @return {@code SimpleShape} or {@code null}
*/
public HSLFTextShape getPlaceholder(int type){
public HSLFSimpleShape getPlaceholder(Placeholder type){
for (HSLFShape shape : getShapes()) {
if(shape instanceof HSLFTextShape){
HSLFTextShape tx = (HSLFTextShape)shape;
int placeholderId = 0;
OEPlaceholderAtom oep = tx.getPlaceholderAtom();
if(oep != null) {
placeholderId = oep.getPlaceholderId();
} else {
//special case for files saved in Office 2007
RoundTripHFPlaceholder12 hldr = tx.getClientDataRecord(RecordTypes.RoundTripHFPlaceholder12.typeID);
if(hldr != null) placeholderId = hldr.getPlaceholderId();
}
if(placeholderId == type){
return tx;
if (shape instanceof HSLFSimpleShape) {
HSLFSimpleShape ss = (HSLFSimpleShape)shape;
if (type == ss.getPlaceholder()) {
return ss;
}
}
}
@ -382,7 +381,9 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
progBinaryTag.findFirstOfType(
RecordTypes.CString.typeID
);
if(binaryTag != null) tag = binaryTag.getText();
if(binaryTag != null) {
tag = binaryTag.getText();
}
}
}
@ -390,6 +391,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
}
@Override
public Iterator<HSLFShape> iterator() {
return getShapes().iterator();
}
@ -400,6 +402,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
* Sheets that support the notion of master (slide, slideLayout) should override it and
* check this setting
*/
@Override
public boolean getFollowMasterGraphics() {
return false;
}

View File

@ -42,6 +42,7 @@ import org.apache.poi.sl.draw.geom.PresetGeometries;
import org.apache.poi.sl.usermodel.LineDecoration;
import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;
import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.Placeholder;
@ -546,13 +547,40 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
if (clRecords == null) {
return null;
}
int phSource;
HSLFSheet sheet = getSheet();
if (sheet instanceof HSLFSlideMaster) {
phSource = 1;
} else if (sheet instanceof HSLFNotes) {
phSource = 2;
} else if (sheet instanceof MasterSheet) {
// notes master aren't yet supported ...
phSource = 3;
} else {
phSource = 0;
}
for (Record r : clRecords) {
int phId;
if (r instanceof OEPlaceholderAtom) {
OEPlaceholderAtom oep = (OEPlaceholderAtom)r;
return Placeholder.lookupNative(oep.getPlaceholderId());
phId = ((OEPlaceholderAtom)r).getPlaceholderId();
} else if (r instanceof RoundTripHFPlaceholder12) {
RoundTripHFPlaceholder12 rtp = (RoundTripHFPlaceholder12)r;
return Placeholder.lookupNative(rtp.getPlaceholderId());
//special case for files saved in Office 2007
phId = ((RoundTripHFPlaceholder12)r).getPlaceholderId();
} else {
continue;
}
switch (phSource) {
case 0:
return Placeholder.lookupNativeSlide(phId);
default:
case 1:
return Placeholder.lookupNativeSlideMaster(phId);
case 2:
return Placeholder.lookupNativeNotes(phId);
case 3:
return Placeholder.lookupNativeNotesMaster(phId);
}
}

View File

@ -36,6 +36,7 @@ import org.apache.poi.hslf.record.RecordContainer;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.record.SSSlideInfoAtom;
import org.apache.poi.hslf.record.SlideAtom;
import org.apache.poi.hslf.record.SlideAtomLayout.SlideLayoutType;
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
import org.apache.poi.hslf.record.StyleTextProp9Atom;
import org.apache.poi.hslf.record.TextHeaderAtom;
@ -501,4 +502,27 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFTe
public boolean getFollowMasterGraphics() {
return getFollowMasterObjects();
}
@Override
public boolean getDisplayPlaceholder(Placeholder placeholder) {
HeadersFooters hf = getHeadersFooters();
SlideLayoutType slt = getSlideRecord().getSlideAtom().getSSlideLayoutAtom().getGeometryType();
boolean isTitle =
(slt == SlideLayoutType.TITLE_SLIDE || slt == SlideLayoutType.TITLE_ONLY || slt == SlideLayoutType.MASTER_TITLE);
if (hf != null) {
switch (placeholder) {
case DATETIME:
return hf.isDateTimeVisible() && !isTitle;
case SLIDE_NUMBER:
return hf.isSlideNumberVisible() && !isTitle;
case HEADER:
return hf.isHeaderVisible() && !isTitle;
case FOOTER:
return hf.isFooterVisible() && !isTitle;
default:
break;
}
}
return false;
}
}

View File

@ -23,7 +23,9 @@ import java.util.List;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.model.textproperties.TextProp;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.record.*;
import org.apache.poi.hslf.record.MainMaster;
import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.hslf.record.TxMasterStyleAtom;
import org.apache.poi.util.Internal;
/**
@ -49,13 +51,16 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
super(record, sheetNo);
for (List<HSLFTextParagraph> l : HSLFTextParagraph.findTextParagraphs(getPPDrawing(), this)) {
if (!_paragraphs.contains(l)) _paragraphs.add(l);
if (!_paragraphs.contains(l)) {
_paragraphs.add(l);
}
}
}
/**
* Returns an array of all the TextRuns found
*/
@Override
public List<List<HSLFTextParagraph>> getTextParagraphs() {
return _paragraphs;
}
@ -63,6 +68,7 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
/**
* Returns <code>null</code> since SlideMasters doen't have master sheet.
*/
@Override
public HSLFMasterSheet getMasterSheet() {
return null;
}
@ -71,8 +77,11 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
* Pickup a style attribute from the master.
* This is the "workhorse" which returns the default style attributes.
*/
@Override
public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) {
if (_txmaster.length <= txtype) return null;
if (_txmaster.length <= txtype) {
return null;
}
TxMasterStyleAtom t = _txmaster[txtype];
List<TextPropCollection> styles = isCharacter ? t.getCharacterStyles() : t.getParagraphStyles();
@ -81,7 +90,9 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
prop = styles.get(i).findByName(name);
}
if (prop != null) return prop;
if (prop != null) {
return prop;
}
switch (txtype) {
case TextHeaderAtom.CENTRE_BODY_TYPE:
@ -146,6 +157,7 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
}
}
@Override
protected void onAddTextShape(HSLFTextShape shape) {
List<HSLFTextParagraph> runs = shape.getTextParagraphs();
_paragraphs.add(runs);

View File

@ -36,14 +36,35 @@ import org.apache.poi.hslf.model.textproperties.TextPFException9;
import org.apache.poi.hslf.model.textproperties.TextProp;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
import org.apache.poi.hslf.record.*;
import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.hslf.record.EscherTextboxWrapper;
import org.apache.poi.hslf.record.FontCollection;
import org.apache.poi.hslf.record.InteractiveInfo;
import org.apache.poi.hslf.record.MasterTextPropAtom;
import org.apache.poi.hslf.record.OutlineTextRefAtom;
import org.apache.poi.hslf.record.PPDrawing;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RecordContainer;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
import org.apache.poi.hslf.record.SlideListWithText;
import org.apache.poi.hslf.record.SlidePersistAtom;
import org.apache.poi.hslf.record.StyleTextProp9Atom;
import org.apache.poi.hslf.record.StyleTextPropAtom;
import org.apache.poi.hslf.record.TextBytesAtom;
import org.apache.poi.hslf.record.TextCharsAtom;
import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.hslf.record.TextRulerAtom;
import org.apache.poi.hslf.record.TextSpecInfoAtom;
import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.StringUtil;
@ -53,8 +74,6 @@ import org.apache.poi.util.Units;
* This class represents a run of text in a powerpoint document. That
* run could be text on a sheet, or text in a note.
* It is only a very basic class for now
*
* @author Nick Burch
*/
public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFTextParagraph,HSLFTextRun> {
@ -74,6 +93,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
private TextBytesAtom _byteAtom;
private TextCharsAtom _charAtom;
private TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);
private TextPropCollection _masterStyle;
protected TextRulerAtom _ruler;
protected final List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>();
@ -139,7 +159,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
public void setParagraphStyle(TextPropCollection paragraphStyle) {
_paragraphStyle.copy(paragraphStyle);
}
/**
* Setting a master style reference
*
@ -148,8 +168,8 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
* @since POI 3.14-Beta1
*/
@Internal
/* package */ void setMasterStyleReference(TextPropCollection paragraphStyle) {
_paragraphStyle = paragraphStyle;
/* package */ void setMasterStyleReference(TextPropCollection masterStyle) {
_masterStyle = masterStyle;
}
/**
@ -321,8 +341,8 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
@Override
public Double getLeftMargin() {
TextProp val = getPropVal(_paragraphStyle, "text.offset", this);
return (val == null) ? null : Units.masterToPoints(val.getValue());
TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "text.offset");
return (tp == null) ? null : Units.masterToPoints(tp.getValue());
}
@Override
@ -344,8 +364,8 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
@Override
public Double getIndent() {
TextProp val = getPropVal(_paragraphStyle, "bullet.offset", this);
return (val == null) ? null : Units.masterToPoints(val.getValue());
TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.offset");
return (tp == null) ? null : Units.masterToPoints(tp.getValue());
}
@Override
@ -393,7 +413,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
@Override
public TextAlign getTextAlign() {
TextProp tp = getPropVal(_paragraphStyle, "alignment", this);
TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "alignment");
if (tp == null) {
return null;
}
@ -411,7 +431,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
@Override
public FontAlign getFontAlign() {
TextProp tp = getPropVal(_paragraphStyle, FontAlignmentProp.NAME, this);
TextProp tp = getPropVal(_paragraphStyle, _masterStyle, FontAlignmentProp.NAME);
if (tp == null) {
return null;
}
@ -577,7 +597,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
* Returns the bullet character
*/
public Character getBulletChar() {
TextProp tp = getPropVal(_paragraphStyle, "bullet.char", this);
TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.char");
return (tp == null) ? null : (char)tp.getValue();
}
@ -608,7 +628,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
* Returns the bullet color
*/
public Color getBulletColor() {
TextProp tp = getPropVal(_paragraphStyle, "bullet.color", this);
TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.color");
boolean hasColor = getFlag(ParagraphFlagsTextProp.BULLET_HARDCOLOR_IDX);
if (tp == null || !hasColor) {
// if bullet color is undefined, return color of first run
@ -632,8 +652,9 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
*/
public void setBulletFont(String typeface) {
if (typeface == null) {
setPropVal(_paragraphStyle, "bullet.font", null);
setPropVal(_paragraphStyle, _masterStyle, "bullet.font", null);
setFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, false);
return;
}
FontCollection fc = getSheet().getSlideShow().getFontCollection();
@ -647,7 +668,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
* Returns the bullet font
*/
public String getBulletFont() {
TextProp tp = getPropVal(_paragraphStyle, "bullet.font", this);
TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.font");
boolean hasFont = getFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX);
if (tp == null || !hasFont) {
return getDefaultFontFamily();
@ -694,7 +715,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
}
private Double getPctOrPoints(String propName) {
TextProp tp = getPropVal(_paragraphStyle, propName, this);
TextProp tp = getPropVal(_paragraphStyle, _masterStyle, propName);
if (tp == null) {
return null;
}
@ -711,7 +732,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
}
private boolean getFlag(int index) {
BitMaskTextProp tp = (BitMaskTextProp)getPropVal(_paragraphStyle, ParagraphFlagsTextProp.NAME, this);
BitMaskTextProp tp = (BitMaskTextProp)getPropVal(_paragraphStyle, _masterStyle, ParagraphFlagsTextProp.NAME);
return (tp == null) ? false : tp.getSubValue(index);
}
@ -729,7 +750,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
* The propName can be a comma-separated list, in case multiple equivalent values
* are queried
*/
protected static TextProp getPropVal(TextPropCollection props, String propName, HSLFTextParagraph paragraph) {
protected TextProp getPropVal(TextPropCollection props, TextPropCollection masterProps, String propName) {
String propNames[] = propName.split(",");
for (String pn : propNames) {
TextProp prop = props.findByName(pn);
@ -740,41 +761,52 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
// Font properties (maybe other too???) can have an index of -1
// so we check the master for this font index then
if (pn.contains("font") && prop.getValue() == -1) {
return getMasterPropVal(props, pn, paragraph);
return getMasterPropVal(props, masterProps, pn);
}
return prop;
}
return getMasterPropVal(props, propName, paragraph);
return getMasterPropVal(props, masterProps, propName);
}
private static TextProp getMasterPropVal(TextPropCollection props, String propName, HSLFTextParagraph paragraph) {
String propNames[] = propName.split(",");
BitMaskTextProp maskProp = (BitMaskTextProp) props.findByName(ParagraphFlagsTextProp.NAME);
boolean hardAttribute = (maskProp != null && maskProp.getValue() == 0);
if (hardAttribute) {
return null;
}
HSLFSheet sheet = paragraph.getSheet();
int txtype = paragraph.getRunType();
HSLFMasterSheet master = sheet.getMasterSheet();
if (master == null) {
logger.log(POILogger.WARN, "MasterSheet is not available");
return null;
}
private TextProp getMasterPropVal(TextPropCollection props, TextPropCollection masterProps, String propName) {
boolean isChar = props.getTextPropType() == TextPropType.character;
for (String pn : propNames) {
TextProp prop = master.getStyleAttribute(txtype, paragraph.getIndentLevel(), pn, isChar);
if (prop != null) {
return prop;
// check if we can delegate to master for the property
if (!isChar) {
BitMaskTextProp maskProp = (BitMaskTextProp) props.findByName(ParagraphFlagsTextProp.NAME);
boolean hardAttribute = (maskProp != null && maskProp.getValue() == 0);
if (hardAttribute) {
return null;
}
}
String propNames[] = propName.split(",");
if (masterProps == null) {
HSLFSheet sheet = getSheet();
int txtype = getRunType();
HSLFMasterSheet master = sheet.getMasterSheet();
if (master == null) {
logger.log(POILogger.WARN, "MasterSheet is not available");
return null;
}
for (String pn : propNames) {
TextProp prop = master.getStyleAttribute(txtype, getIndentLevel(), pn, isChar);
if (prop != null) {
return prop;
}
}
} else {
for (String pn : propNames) {
TextProp prop = masterProps.findByName(pn);
if (prop != null) {
return prop;
}
}
}
return null;
}
@ -786,14 +818,19 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
* @param name the name of the TextProp to fetch/add
* @param val the value, null if unset
*/
protected static void setPropVal(TextPropCollection props, String name, Integer val) {
protected void setPropVal(TextPropCollection props, TextPropCollection masterProps, String name, Integer val) {
TextPropCollection pc = props;
if (getSheet() instanceof MasterSheet && masterProps != null) {
pc = masterProps;
}
if (val == null) {
props.removeByName(name);
pc.removeByName(name);
return;
}
// Fetch / Add the TextProp
TextProp tp = props.addWithName(name);
TextProp tp = pc.addWithName(name);
tp.setValue(val);
}
@ -1517,38 +1554,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
}
}
protected static List<HSLFTextParagraph> createEmptyParagraph() {
EscherTextboxWrapper wrapper = new EscherTextboxWrapper();
return createEmptyParagraph(wrapper);
}
protected static List<HSLFTextParagraph> createEmptyParagraph(EscherTextboxWrapper wrapper) {
TextHeaderAtom tha = new TextHeaderAtom();
tha.setParentRecord(wrapper);
wrapper.appendChildRecord(tha);
TextBytesAtom tba = new TextBytesAtom();
tba.setText("".getBytes(LocaleUtil.CHARSET_1252));
wrapper.appendChildRecord(tba);
StyleTextPropAtom sta = new StyleTextPropAtom(1);
TextPropCollection paraStyle = sta.addParagraphTextPropCollection(1);
TextPropCollection charStyle = sta.addCharacterTextPropCollection(1);
wrapper.appendChildRecord(sta);
List<HSLFTextParagraph> paragraphs = new ArrayList<HSLFTextParagraph>(1);
HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null, paragraphs);
htp.setParagraphStyle(paraStyle);
paragraphs.add(htp);
HSLFTextRun htr = new HSLFTextRun(htp);
htr.setCharacterStyle(charStyle);
htr.setText("");
htp.addTextRun(htr);
return paragraphs;
}
public EscherTextboxWrapper getTextboxWrapper() {
return (EscherTextboxWrapper) _headerAtom.getParentRecord();
}
@ -1583,7 +1588,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
* @param val The value to set for the TextProp
*/
public void setParagraphTextPropVal(String propName, Integer val) {
setPropVal(_paragraphStyle, propName, val);
setPropVal(_paragraphStyle, _masterStyle, propName, val);
setDirty();
}
@ -1624,21 +1629,19 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
*/
@Override
public boolean isHeaderOrFooter() {
HSLFShape s = getParentShape();
HSLFTextShape s = getParentShape();
if (s == null) {
return false;
}
RoundTripHFPlaceholder12 hfPl = s.getClientDataRecord(RecordTypes.RoundTripHFPlaceholder12.typeID);
if (hfPl == null) {
Placeholder ph = s.getPlaceholder();
if (ph == null) {
return false;
}
int plId = hfPl.getPlaceholderId();
switch (plId) {
case OEPlaceholderAtom.MasterDate:
case OEPlaceholderAtom.MasterSlideNumber:
case OEPlaceholderAtom.MasterFooter:
case OEPlaceholderAtom.MasterHeader:
switch (ph) {
case DATETIME:
case SLIDE_NUMBER:
case FOOTER:
case HEADER:
return true;
default:
return false;

View File

@ -17,8 +17,6 @@
package org.apache.poi.hslf.usermodel;
import static org.apache.poi.hslf.usermodel.HSLFTextParagraph.getPropVal;
import java.awt.Color;
import org.apache.poi.hslf.exceptions.HSLFException;
@ -30,6 +28,7 @@ import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.util.Internal;
import org.apache.poi.util.POILogFactory;
@ -54,6 +53,8 @@ public final class HSLFTextRun implements TextRun {
* Note - we may share these styles with other RichTextRuns
*/
private TextPropCollection characterStyle = new TextPropCollection(1, TextPropType.character);
private TextPropCollection masterStyle;
/**
* Create a new wrapper around a rich text string
@ -80,8 +81,8 @@ public final class HSLFTextRun implements TextRun {
* @since POI 3.14-Beta1
*/
@Internal
/* package */ void setMasterStyleReference(TextPropCollection characterStyle) {
this.characterStyle = characterStyle;
/* package */ void setMasterStyleReference(TextPropCollection masterStyle) {
this.masterStyle = masterStyle;
}
@ -105,14 +106,16 @@ public final class HSLFTextRun implements TextRun {
/**
* Fetch the text, in raw storage form
*/
public String getRawText() {
@Override
public String getRawText() {
return _runText;
}
/**
* Change the text
*/
public void setText(String text) {
@Override
public void setText(String text) {
if (text == null) {
throw new HSLFException("text must not be null");
}
@ -137,7 +140,9 @@ public final class HSLFTextRun implements TextRun {
}
protected boolean getFlag(int index) {
if (characterStyle == null) return false;
if (characterStyle == null) {
return false;
}
BitMaskTextProp prop = (BitMaskTextProp)characterStyle.findByName(CharFlagsTextProp.NAME);
@ -175,8 +180,8 @@ public final class HSLFTextRun implements TextRun {
* @param val The value to set for the TextProp
*/
public void setCharTextPropVal(String propName, Integer val) {
HSLFTextParagraph.setPropVal(characterStyle, propName, val);
parentParagraph.setDirty();
getTextParagraph().setPropVal(characterStyle, masterStyle, propName, val);
getTextParagraph().setDirty();
}
@ -256,7 +261,7 @@ public final class HSLFTextRun implements TextRun {
* @return the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript
*/
public int getSuperscript() {
TextProp tp = getPropVal(characterStyle, "superscript", parentParagraph);
TextProp tp = getTextParagraph().getPropVal(characterStyle, masterStyle, "superscript");
return tp == null ? 0 : tp.getValue();
}
@ -271,7 +276,7 @@ public final class HSLFTextRun implements TextRun {
@Override
public Double getFontSize() {
TextProp tp = getPropVal(characterStyle, "font.size", parentParagraph);
TextProp tp = getTextParagraph().getPropVal(characterStyle, masterStyle, "font.size");
return tp == null ? null : (double)tp.getValue();
}
@ -286,7 +291,7 @@ public final class HSLFTextRun implements TextRun {
* Gets the font index
*/
public int getFontIndex() {
TextProp tp = getPropVal(characterStyle, "font.index", parentParagraph);
TextProp tp = getTextParagraph().getPropVal(characterStyle, masterStyle, "font.index");
return tp == null ? -1 : tp.getValue();
}
@ -320,7 +325,7 @@ public final class HSLFTextRun implements TextRun {
if (sheet == null || slideShow == null) {
return _fontFamily;
}
TextProp tp = getPropVal(characterStyle, "font.index,asian.font.index,ansi.font.index,symbol.font.index", parentParagraph);
TextProp tp = getTextParagraph().getPropVal(characterStyle, masterStyle, "font.index,asian.font.index,ansi.font.index,symbol.font.index");
if (tp == null) { return null; }
return slideShow.getFontCollection().getFontWithId(tp.getValue());
}
@ -330,8 +335,10 @@ public final class HSLFTextRun implements TextRun {
*/
@Override
public SolidPaint getFontColor() {
TextProp tp = getPropVal(characterStyle, "font.color", parentParagraph);
if (tp == null) return null;
TextProp tp = getTextParagraph().getPropVal(characterStyle, masterStyle, "font.color");
if (tp == null) {
return null;
}
Color color = HSLFTextParagraph.getColorFromColorIndexStruct(tp.getValue(), parentParagraph.getSheet());
SolidPaint ps = DrawPaint.createSolidPaint(color);
return ps;
@ -374,6 +381,7 @@ public final class HSLFTextRun implements TextRun {
return parentParagraph;
}
@Override
public TextCap getTextCap() {
return TextCap.NONE;
}
@ -388,6 +396,7 @@ public final class HSLFTextRun implements TextRun {
return getSuperscript() > 0;
}
@Override
public byte getPitchAndFamily() {
return 0;
}
@ -414,4 +423,20 @@ public final class HSLFTextRun implements TextRun {
}
return link;
}
@Override
public FieldType getFieldType() {
Placeholder ph = getTextParagraph().getParentShape().getPlaceholder();
if (ph != null) {
switch (ph) {
case SLIDE_NUMBER:
return FieldType.SLIDE_NUMBER;
case DATETIME:
return FieldType.DATE_TIME;
default:
break;
}
}
return null;
}
}

View File

@ -20,7 +20,6 @@ package org.apache.poi.hslf.usermodel;
import static org.apache.poi.hslf.record.RecordTypes.OEPlaceholderAtom;
import static org.apache.poi.hslf.record.RecordTypes.RoundTripHFPlaceholder12;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.ArrayList;
@ -34,10 +33,14 @@ import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.model.HSLFMetroShape;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.record.EscherTextboxWrapper;
import org.apache.poi.hslf.record.OEPlaceholderAtom;
import org.apache.poi.hslf.record.PPDrawing;
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
import org.apache.poi.hslf.record.StyleTextPropAtom;
import org.apache.poi.hslf.record.TextBytesAtom;
import org.apache.poi.hslf.record.TextCharsAtom;
import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.DrawTextShape;
@ -71,12 +74,12 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
BOTTOM_BASELINE (7, VerticalAlignment.BOTTOM, false, true),
TOP_CENTER_BASELINE (8, VerticalAlignment.TOP, true, true),
BOTTOM_CENTER_BASELINE(9, VerticalAlignment.BOTTOM, true, true);
public final int nativeId;
public final VerticalAlignment vAlign;
public final boolean centered;
public final Boolean baseline;
HSLFTextAnchor(int nativeId, VerticalAlignment vAlign, boolean centered, Boolean baseline) {
this.nativeId = nativeId;
this.vAlign = vAlign;
@ -86,7 +89,9 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
static HSLFTextAnchor fromNativeId(int nativeId) {
for (HSLFTextAnchor ta : values()) {
if (ta.nativeId == nativeId) return ta;
if (ta.nativeId == nativeId) {
return ta;
}
}
return null;
}
@ -125,13 +130,13 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
/**
* TextRun object which holds actual text and format data
*/
protected List<HSLFTextParagraph> _paragraphs = new ArrayList<HSLFTextParagraph>();
private List<HSLFTextParagraph> _paragraphs = new ArrayList<HSLFTextParagraph>();
/**
* Escher container which holds text attributes such as
* TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc.
* TextHeaderAtom, TextBytesAtom or TextCharsAtom, StyleTextPropAtom etc.
*/
protected EscherTextboxWrapper _txtbox;
private EscherTextboxWrapper _txtbox;
/**
* This setting is used for supporting a deprecated alignment
@ -140,11 +145,6 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
*/
// boolean alignToBaseline = false;
/**
* Used to calculate text bounds
*/
protected static final FontRenderContext _frc = new FontRenderContext(null, true, true);
/**
* Create a TextBox object and initialize it from the supplied Record container.
*
@ -222,10 +222,14 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
}
protected EscherTextboxWrapper getEscherTextboxWrapper(){
if(_txtbox != null) return _txtbox;
if(_txtbox != null) {
return _txtbox;
}
EscherTextboxRecord textRecord = getEscherChild(EscherTextboxRecord.RECORD_ID);
if (textRecord == null) return null;
if (textRecord == null) {
return null;
}
HSLFSheet sheet = getSheet();
if (sheet != null) {
@ -248,6 +252,66 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
return _txtbox;
}
private void createEmptyParagraph() {
TextHeaderAtom tha = (TextHeaderAtom)_txtbox.findFirstOfType(TextHeaderAtom._type);
if (tha == null) {
tha = new TextHeaderAtom();
tha.setParentRecord(_txtbox);
_txtbox.appendChildRecord(tha);
}
TextBytesAtom tba = (TextBytesAtom)_txtbox.findFirstOfType(TextBytesAtom._type);
TextCharsAtom tca = (TextCharsAtom)_txtbox.findFirstOfType(TextCharsAtom._type);
if (tba == null && tca == null) {
tba = new TextBytesAtom();
tba.setText(new byte[0]);
_txtbox.appendChildRecord(tba);
}
final String text = ((tba != null) ? tba.getText() : tca.getText());
StyleTextPropAtom sta = (StyleTextPropAtom)_txtbox.findFirstOfType(StyleTextPropAtom._type);
TextPropCollection paraStyle = null, charStyle = null;
if (sta == null) {
int parSiz = text.length();
sta = new StyleTextPropAtom(parSiz+1);
if (_paragraphs.isEmpty()) {
paraStyle = sta.addParagraphTextPropCollection(parSiz+1);
charStyle = sta.addCharacterTextPropCollection(parSiz+1);
} else {
for (HSLFTextParagraph htp : _paragraphs) {
int runsLen = 0;
for (HSLFTextRun htr : htp.getTextRuns()) {
runsLen += htr.getLength();
charStyle = sta.addCharacterTextPropCollection(htr.getLength());
htr.setCharacterStyle(charStyle);
}
paraStyle = sta.addParagraphTextPropCollection(runsLen);
htp.setParagraphStyle(paraStyle);
}
assert (paraStyle != null && charStyle != null);
}
_txtbox.appendChildRecord(sta);
} else {
paraStyle = sta.getParagraphStyles().get(0);
charStyle = sta.getCharacterStyles().get(0);
}
if (_paragraphs.isEmpty()) {
HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, tca, _paragraphs);
htp.setParagraphStyle(paraStyle);
htp.setParentShape(this);
_paragraphs.add(htp);
HSLFTextRun htr = new HSLFTextRun(htp);
htr.setCharacterStyle(charStyle);
htr.setText(text);
htp.addTextRun(htr);
}
}
/**
* Adjust the size of the shape so it encompasses the text inside it.
*
@ -276,7 +340,9 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
*/
public int getRunType() {
getEscherTextboxWrapper();
if (_txtbox == null) return -1;
if (_txtbox == null) {
return -1;
}
List<HSLFTextParagraph> paras = HSLFTextParagraph.findTextParagraphs(_txtbox, getSheet());
return (paras.isEmpty()) ? -1 : paras.get(0).getRunType();
}
@ -289,7 +355,9 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
*/
public void setRunType(int type) {
getEscherTextboxWrapper();
if (_txtbox == null) return;
if (_txtbox == null) {
return;
}
List<HSLFTextParagraph> paras = HSLFTextParagraph.findTextParagraphs(_txtbox, getSheet());
if (!paras.isEmpty()) {
paras.get(0).setRunType(type);
@ -562,19 +630,23 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
@Override
public List<HSLFTextParagraph> getTextParagraphs(){
if (!_paragraphs.isEmpty()) return _paragraphs;
if (!_paragraphs.isEmpty()) {
return _paragraphs;
}
_txtbox = getEscherTextboxWrapper();
if (_txtbox == null) {
_paragraphs.addAll(HSLFTextParagraph.createEmptyParagraph());
_txtbox = _paragraphs.get(0).getTextboxWrapper();
_txtbox = new EscherTextboxWrapper();
createEmptyParagraph();
} else {
_paragraphs = HSLFTextParagraph.findTextParagraphs(_txtbox, getSheet());
if (_paragraphs == null) {
List<HSLFTextParagraph> pList = HSLFTextParagraph.findTextParagraphs(_txtbox, getSheet());
if (pList == null) {
// there are actually TextBoxRecords without extra data - see #54722
_paragraphs = HSLFTextParagraph.createEmptyParagraph(_txtbox);
createEmptyParagraph();
} else {
_paragraphs = pList;
}
if (_paragraphs.isEmpty()) {
LOG.log(POILogger.WARN, "TextRecord didn't contained any text lines");
}
@ -587,6 +659,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
return _paragraphs;
}
@Override
public void setSheet(HSLFSheet sheet) {
super.setSheet(sheet);
@ -611,26 +684,30 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
/**
* Return {@link RoundTripHFPlaceholder12}, the atom that describes a header/footer placeholder.
* Compare the {@link RoundTripHFPlaceholder12#getPlaceholderId()} with
* {@link OEPlaceholderAtom#MasterHeader} or {@link OEPlaceholderAtom#MasterFooter}, to find out
* {@link Placeholder#HEADER} or {@link Placeholder#FOOTER}, to find out
* what kind of placeholder this is.
*
* @return {@link RoundTripHFPlaceholder12} or {@code null} if not found
*
*
* @since POI 3.14-Beta2
*/
public RoundTripHFPlaceholder12 getHFPlaceholderAtom() {
// special case for files saved in Office 2007
return getClientDataRecord(RoundTripHFPlaceholder12.typeID);
}
@Override
public boolean isPlaceholder() {
OEPlaceholderAtom oep = getPlaceholderAtom();
if (oep != null) return true;
if (oep != null) {
return true;
}
//special case for files saved in Office 2007
RoundTripHFPlaceholder12 hldr = getHFPlaceholderAtom();
if (hldr != null) return true;
if (hldr != null) {
return true;
}
return false;
}
@ -710,7 +787,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
}
setEscherProperty(opt, EscherProperties.TEXT__TEXTFLOW, msotxfl);
}
@Override
public Double getTextRotation() {
// see 2.4.6 MSOCDIR
@ -718,7 +795,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__FONTROTATION);
return (prop == null) ? null : (90. * prop.getPropertyValue());
}
@Override
public void setTextRotation(Double rotation) {
AbstractEscherOptRecord opt = getEscherOptRecord();
@ -729,7 +806,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
setEscherProperty(EscherProperties.TEXT__FONTROTATION, rot);
}
}
/**
* Returns the raw text content of the shape. This hasn't had any
* changes applied to it, and so is probably unlikely to print
@ -751,7 +828,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
List<HSLFTextParagraph> paras = getTextParagraphs();
HSLFTextRun htr = HSLFTextParagraph.appendText(paras, text, newParagraph);
setTextId(getRawText().hashCode());
return htr;
return htr;
}
@Override

View File

@ -25,8 +25,6 @@ import org.apache.poi.hslf.record.SlideAtom;
/**
* Title masters define the design template for slides with a Title Slide layout.
*
* @author Yegor Kozlov
*/
public final class HSLFTitleMaster extends HSLFMasterSheet {
private final List<List<HSLFTextParagraph>> _paragraphs = new ArrayList<List<HSLFTextParagraph>>();
@ -39,13 +37,16 @@ public final class HSLFTitleMaster extends HSLFMasterSheet {
super(record, sheetNo);
for (List<HSLFTextParagraph> l : HSLFTextParagraph.findTextParagraphs(getPPDrawing(), this)) {
if (!_paragraphs.contains(l)) _paragraphs.add(l);
if (!_paragraphs.contains(l)) {
_paragraphs.add(l);
}
}
}
/**
* Returns an array of all the TextRuns found
*/
@Override
public List<List<HSLFTextParagraph>> getTextParagraphs() {
return _paragraphs;
}
@ -53,20 +54,23 @@ public final class HSLFTitleMaster extends HSLFMasterSheet {
/**
* Delegate the call to the underlying slide master.
*/
@Override
public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) {
HSLFMasterSheet master = getMasterSheet();
return master == null ? null : master.getStyleAttribute(txtype, level, name, isCharacter);
return (master == null) ? null : master.getStyleAttribute(txtype, level, name, isCharacter);
}
/**
* Returns the slide master for this title master.
*/
@Override
public HSLFMasterSheet getMasterSheet(){
List<HSLFSlideMaster> master = getSlideShow().getSlideMasters();
SlideAtom sa = ((org.apache.poi.hslf.record.Slide)getSheetContainer()).getSlideAtom();
int masterId = sa.getMasterID();
for (HSLFSlideMaster sm : master) {
if (masterId == sm._getSheetNumber()) return sm;
for (HSLFSlideMaster sm : getSlideShow().getSlideMasters()) {
if (masterId == sm._getSheetNumber()) {
return sm;
}
}
return null;
}

View File

@ -17,36 +17,43 @@
package org.apache.poi.hslf.record;
import java.io.ByteArrayInputStream;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.poi.hslf.record.SlideAtom.SSlideLayoutAtom;
import org.apache.poi.hslf.HSLFTestDataSamples;
import org.apache.poi.hslf.record.SlideAtomLayout.SlideLayoutType;
import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import junit.framework.TestCase;
import org.junit.Test;
/**
* Tests that SlideAtom works properly
*
* @author Nick Burch (nick at torchbox dot com)
*/
public final class TestSlideAtom extends TestCase {
public final class TestSlideAtom {
// From a real file
private final byte[] data_a = new byte[] { 1, 0, 0xEF-256, 3, 0x18, 0, 0, 0,
private static final byte[] data_a = new byte[] { 1, 0, 0xEF-256, 3, 0x18, 0, 0, 0,
0, 0, 0, 0, 0x0F, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80-256,
0, 1, 0, 0, 7, 0, 0x0C, 0x30 };
public void testRecordType() {
@Test
public void testRecordType() {
SlideAtom sa = new SlideAtom(data_a, 0, data_a.length);
assertEquals(1007l, sa.getRecordType());
}
@Test
public void testFlags() {
SlideAtom sa = new SlideAtom(data_a, 0, data_a.length);
// First 12 bytes are a SSlideLayoutAtom, checked elsewhere
// Check the IDs
assertEquals(0x80000000, sa.getMasterID());
assertEquals(SlideAtom.USES_MASTER_SLIDE_ID, sa.getMasterID());
assertEquals(256, sa.getNotesID());
// Check the flags
@ -54,39 +61,37 @@ public final class TestSlideAtom extends TestCase {
assertEquals(true, sa.getFollowMasterScheme());
assertEquals(true, sa.getFollowMasterBackground());
}
public void testSSlideLayoutAtom() {
@Test
public void testSSlideLayoutAtom() {
SlideAtom sa = new SlideAtom(data_a, 0, data_a.length);
SSlideLayoutAtom ssla = sa.getSSlideLayoutAtom();
SlideAtomLayout ssla = sa.getSSlideLayoutAtom();
assertEquals(0, ssla.getGeometryType());
assertEquals(SlideLayoutType.TITLE_SLIDE, ssla.getGeometryType());
// Should also check the placehold IDs at some point
// Should also check the placeholder IDs at some point
}
public void testWrite() throws Exception {
@Test
public void testWrite() throws IOException {
SlideAtom sa = new SlideAtom(data_a, 0, data_a.length);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
sa.writeOut(baos);
byte[] b = baos.toByteArray();
assertEquals(data_a.length, b.length);
for(int i=0; i<data_a.length; i++) {
assertEquals(data_a[i],b[i]);
}
assertArrayEquals(data_a, baos.toByteArray());
}
public void testSSSlideInfoAtom() throws Exception {
HSLFSlideShow ss = new HSLFSlideShow();
org.apache.poi.hslf.usermodel.HSLFSlide slide1 = ss.createSlide(), slide2 = ss.createSlide();
@Test
public void testSSSlideInfoAtom() throws IOException {
HSLFSlideShow ss1 = new HSLFSlideShow();
HSLFSlide slide1 = ss1.createSlide(), slide2 = ss1.createSlide();
slide2.setHidden(true);
ByteArrayOutputStream bos = new ByteArrayOutputStream(4096);
ss.write(bos);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ss = new HSLFSlideShow(bis);
slide1 = ss.getSlides().get(0);
slide2 = ss.getSlides().get(1);
HSLFSlideShow ss2 = HSLFTestDataSamples.writeOutAndReadBack(ss1);
slide1 = ss2.getSlides().get(0);
slide2 = ss2.getSlides().get(1);
assertFalse(slide1.getHidden());
assertTrue(slide2.getHidden());
ss2.close();
ss1.close();
}
}

View File

@ -38,6 +38,7 @@ import java.io.OutputStream;
import java.io.PrintStream;
import java.text.AttributedCharacterIterator;
import java.text.AttributedCharacterIterator.Attribute;
import java.text.CharacterIterator;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@ -466,12 +467,16 @@ public final class TestBugs {
// get slides
for (HSLFSlide slide : ppt.getSlides()) {
for (HSLFShape shape : slide.getShapes()) {
if (!(shape instanceof HSLFTextBox)) continue;
if (!(shape instanceof HSLFTextBox)) {
continue;
}
HSLFTextBox tb = (HSLFTextBox) shape;
// work with TextBox
String str = tb.getText();
if (!str.contains("$$DATE$$")) continue;
if (!str.contains("$$DATE$$")) {
continue;
}
str = str.replace("$$DATE$$", new Date().toString());
tb.setText(str);
@ -512,7 +517,9 @@ public final class TestBugs {
int tha = 0;
for (Record r : s1.getSlideRecords()) {
if (r instanceof TextHeaderAtom) tha++;
if (r instanceof TextHeaderAtom) {
tha++;
}
}
assertEquals(2, tha);
@ -525,7 +532,9 @@ public final class TestBugs {
// Will have skipped the empty one
int str = 0;
for (List<HSLFTextParagraph> tr : _slides.get(0).getTextParagraphs()) {
if (! tr.get(0).isDrawingBased()) str++;
if (! tr.get(0).isDrawingBased()) {
str++;
}
}
assertEquals(2, str);
@ -758,7 +767,7 @@ public final class TestBugs {
public void bug47904() throws IOException {
HSLFSlideShow ppt1 = new HSLFSlideShow();
HSLFSlideMaster sm = ppt1.getSlideMasters().get(0);
HSLFAutoShape as = (HSLFAutoShape)sm.getShapes().get(0);
HSLFAutoShape as = (HSLFAutoShape)sm.getPlaceholder(Placeholder.TITLE);
HSLFTextParagraph tp = as.getTextParagraphs().get(0);
HSLFTextRun tr = tp.getTextRuns().get(0);
tr.setFontFamily("Tahoma");
@ -766,8 +775,9 @@ public final class TestBugs {
tr.setFontSize(44.);
tr.setFontColor(Color.red);
tp.setTextAlign(TextAlign.RIGHT);
ppt1.createSlide().addTitle().setText("foobaa");
HSLFTextBox tb = ppt1.createSlide().addTitle();
tb.setText("foobaa");
HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1);
ppt1.close();
@ -877,7 +887,7 @@ public final class TestBugs {
StringBuffer sb = new StringBuffer();
for (char c = iterator.first();
c != AttributedCharacterIterator.DONE;
c != CharacterIterator.DONE;
c = iterator.next()) {
sb.append(c);
attributes = iterator.getAttributes();

View File

@ -18,29 +18,23 @@
package org.apache.poi.hslf.usermodel;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.util.List;
import junit.framework.TestCase;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hslf.HSLFTestDataSamples;
import org.junit.Test;
/**
* Tests that SlideShow returns the right number of Sheets and MetaSheets
*
* @author Nick Burch (nick at torchbox dot com)
*/
public final class TestCounts extends TestCase {
// SlideShow primed on the test data
private final HSLFSlideShow ss;
public TestCounts() throws Exception {
POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt"));
ss = new HSLFSlideShow(hss);
}
public void testSheetsCount() {
List<HSLFSlide> slides = ss.getSlides();
public final class TestCounts {
@Test
public void testSheetsCount() throws IOException {
HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt");
List<HSLFSlide> slides = ppt.getSlides();
// Two sheets - master sheet is separate
assertEquals(2, slides.size());
@ -55,10 +49,15 @@ public final class TestCounts extends TestCase {
// These are slides 1+2 -> 256+257
assertEquals(256, slides.get(0)._getSheetNumber());
assertEquals(257, slides.get(1)._getSheetNumber());
ppt.close();
}
public void testNotesCount() {
List<HSLFNotes> notes = ss.getNotes();
@Test
public void testNotesCount() throws IOException {
HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt");
List<HSLFNotes> notes = ppt.getNotes();
// Two sheets -> two notes
// Note: there are also notes on the slide master
//assertEquals(3, notes.length); // When we do slide masters
@ -74,5 +73,7 @@ public final class TestCounts extends TestCase {
// They happen to go between the two slides in Ref terms
assertEquals(5, notes.get(0)._getSheetRefId());
assertEquals(7, notes.get(1)._getSheetRefId());
ppt.close();
}
}