#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:
parent
ac3d63926a
commit
5c4ab1dbdf
@ -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 {
|
||||
if (ph != null) {
|
||||
Slide<?,?> slide = (Slide<?,?>)graphics.getRenderingHint(Drawable.CURRENT_SLIDE);
|
||||
return slide.getDisplayPlaceholder(ph);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
@ -31,6 +32,10 @@ public interface TextRun {
|
||||
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();
|
||||
}
|
||||
|
@ -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){
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,62 +296,72 @@ 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);
|
||||
|
||||
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);
|
||||
// try shape properties in slide
|
||||
if (visitor.fetch(this)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CTPlaceholder ph = getCTPlaceholder();
|
||||
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;
|
||||
}
|
||||
sm = slideLayout.getMasterSheet();
|
||||
}
|
||||
|
||||
// try slide master
|
||||
if (!ok ) {
|
||||
int textType;
|
||||
if ( !ph.isSetType()) textType = STPlaceholderType.INT_BODY;
|
||||
else {
|
||||
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 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:
|
||||
textType = STPlaceholderType.INT_TITLE;
|
||||
break;
|
||||
return STPlaceholderType.INT_TITLE;
|
||||
case STPlaceholderType.INT_FTR:
|
||||
case STPlaceholderType.INT_SLD_NUM:
|
||||
case STPlaceholderType.INT_DT:
|
||||
textType = ph.getType().intValue();
|
||||
break;
|
||||
return ph.getType().intValue();
|
||||
default:
|
||||
textType = STPlaceholderType.INT_BODY;
|
||||
break;
|
||||
return STPlaceholderType.INT_BODY;
|
||||
}
|
||||
}
|
||||
XSLFSheet master = (XSLFSheet)masterSheet.getMasterSheet();
|
||||
if (master != null) {
|
||||
masterShape = master.getPlaceholderByType(textType);
|
||||
if (masterShape != null) {
|
||||
ok = visitor.fetch(masterShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert shape fill into java.awt.Paint. The result is either Color or
|
||||
@ -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,16 +384,24 @@ 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()) {
|
||||
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;
|
||||
@ -512,7 +535,15 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
||||
}
|
||||
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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ implements MasterSheet<XSLFShape,XSLFTextParagraph> {
|
||||
|
||||
@Override
|
||||
public boolean getFollowMasterGraphics() {
|
||||
return _layout.isSetShowMasterSp() && _layout.getShowMasterSp();
|
||||
return _layout.getShowMasterSp();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
if (_r instanceof CTTextField) {
|
||||
CTTextField tf = (CTTextField)_r;
|
||||
if (tf.isSetRPr()) {
|
||||
return tf.getRPr();
|
||||
} else if (create) {
|
||||
return _r.addNewRPr();
|
||||
} else {
|
||||
return null;
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle();
|
||||
if(defaultProps != null) {
|
||||
// TODO: determine master shape
|
||||
ok = fetcher.fetch(defaultProps);
|
||||
CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -169,5 +169,4 @@ public class XSLFTheme extends POIXMLDocumentPart {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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]));
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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());
|
||||
r.setFontSize(10.0);
|
||||
assertTrue(r.getXmlObject().isSetRPr());
|
||||
assertEquals(1000, r.getXmlObject().getRPr().getSz());
|
||||
r.setFontSize(12.5);
|
||||
assertEquals(1250, r.getXmlObject().getRPr().getSz());
|
||||
r.setFontSize(null);
|
||||
assertFalse(r.getXmlObject().getRPr().isSetSz());
|
||||
|
||||
assertFalse(r.getXmlObject().getRPr().isSetLatin());
|
||||
assertEquals(18.0, r.getFontSize(), 0); // default font size for text boxes
|
||||
assertFalse(rPr.isSetSz());
|
||||
r.setFontSize(10.0);
|
||||
assertEquals(1000, rPr.getSz());
|
||||
r.setFontSize(12.5);
|
||||
assertEquals(1250, rPr.getSz());
|
||||
r.setFontSize(null);
|
||||
assertFalse(rPr.isSetSz());
|
||||
|
||||
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());
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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){
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
* An atom record that specifies whether a shape is a placeholder shape.
|
||||
*
|
||||
* @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}.
|
||||
*/
|
||||
@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,9 +162,9 @@ 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
|
||||
*/
|
||||
@Override
|
||||
public void writeOut(OutputStream out) throws IOException {
|
||||
out.write(_header);
|
||||
|
||||
|
@ -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
|
||||
* It also has a SSlideLayoutAtom embedded in it, but without the Atom header
|
||||
*/
|
||||
|
||||
public final class SlideAtom extends RecordAtom
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
|
@ -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,12 +85,14 @@ public final class TextBytesAtom extends RecordAtom
|
||||
/**
|
||||
* We are of type 4008
|
||||
*/
|
||||
@Override
|
||||
public long getRecordType() { return _type; }
|
||||
|
||||
/**
|
||||
* Write the contents of the record back, so it can be written
|
||||
* to disk
|
||||
*/
|
||||
@Override
|
||||
public void writeOut(OutputStream out) throws IOException {
|
||||
// Header - size or type unchanged
|
||||
out.write(_header);
|
||||
@ -105,6 +105,7 @@ public final class TextBytesAtom extends RecordAtom
|
||||
* dump debug info; use getText() to return a string
|
||||
* representation of the atom
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer out = new StringBuffer();
|
||||
out.append( "TextBytesAtom:\n");
|
||||
|
@ -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,12 +81,14 @@ public final class TextCharsAtom extends RecordAtom
|
||||
/**
|
||||
* We are of type 4000
|
||||
*/
|
||||
@Override
|
||||
public long getRecordType() { return _type; }
|
||||
|
||||
/**
|
||||
* Write the contents of the record back, so it can be written
|
||||
* to disk
|
||||
*/
|
||||
@Override
|
||||
public void writeOut(OutputStream out) throws IOException {
|
||||
// Header - size or type unchanged
|
||||
out.write(_header);
|
||||
@ -101,6 +101,7 @@ public final class TextCharsAtom extends RecordAtom
|
||||
* dump debug info; use getText() to return a string
|
||||
* representation of the atom
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer out = new StringBuffer();
|
||||
out.append( "TextCharsAtom:\n");
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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>();
|
||||
@ -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,40 +761,51 @@ 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(",");
|
||||
private TextProp getMasterPropVal(TextPropCollection props, TextPropCollection masterProps, String propName) {
|
||||
boolean isChar = props.getTextPropType() == TextPropType.character;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
HSLFSheet sheet = paragraph.getSheet();
|
||||
int txtype = paragraph.getRunType();
|
||||
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;
|
||||
}
|
||||
|
||||
boolean isChar = props.getTextPropType() == TextPropType.character;
|
||||
|
||||
for (String pn : propNames) {
|
||||
TextProp prop = master.getStyleAttribute(txtype, paragraph.getIndentLevel(), pn, isChar);
|
||||
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;
|
||||
|
@ -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;
|
||||
@ -55,6 +54,8 @@ public final class HSLFTextRun implements TextRun {
|
||||
*/
|
||||
private TextPropCollection characterStyle = new TextPropCollection(1, TextPropType.character);
|
||||
|
||||
private TextPropCollection masterStyle;
|
||||
|
||||
/**
|
||||
* Create a new wrapper around a rich text string
|
||||
* @param parentParagraph the parent paragraph
|
||||
@ -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,6 +106,7 @@ public final class HSLFTextRun implements TextRun {
|
||||
/**
|
||||
* Fetch the text, in raw storage form
|
||||
*/
|
||||
@Override
|
||||
public String getRawText() {
|
||||
return _runText;
|
||||
}
|
||||
@ -112,6 +114,7 @@ public final class HSLFTextRun implements TextRun {
|
||||
/**
|
||||
* Change the 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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
@ -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,17 +630,21 @@ 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()) {
|
||||
@ -587,6 +659,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
|
||||
return _paragraphs;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setSheet(HSLFSheet sheet) {
|
||||
super.setSheet(sheet);
|
||||
@ -611,7 +684,7 @@ 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
|
||||
@ -626,11 +699,15 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
|
||||
@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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 };
|
||||
|
||||
@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());
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
@ -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,7 +775,8 @@ 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();
|
||||
|
@ -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 final class TestCounts {
|
||||
@Test
|
||||
public void testSheetsCount() throws IOException {
|
||||
HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt");
|
||||
|
||||
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();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user