\r
package org.apache.poi.sl.draw;\r
\r
-import org.apache.poi.sl.usermodel.*;\r
+import java.awt.Graphics2D;\r
+\r
+import org.apache.poi.sl.usermodel.MasterSheet;\r
+import org.apache.poi.sl.usermodel.Placeholder;\r
+import org.apache.poi.sl.usermodel.Shape;\r
+import org.apache.poi.sl.usermodel.SimpleShape;\r
+import org.apache.poi.sl.usermodel.Slide;\r
\r
\r
public class DrawMasterSheet extends DrawSheet {\r
* for instance, slide masters and layouts don't display placeholders\r
*/\r
@Override\r
- protected boolean canDraw(Shape<?,?> shape) {\r
+ protected boolean canDraw(Graphics2D graphics, Shape<?,?> shape) {\r
if (shape instanceof SimpleShape) {\r
+ // in XSLF, slidenumber and date shapes aren't marked as placeholders opposed to HSLF\r
Placeholder ph = ((SimpleShape<?,?>)shape).getPlaceholder();\r
- return ph == null;\r
- } else {\r
- return true;\r
+ if (ph != null) {\r
+ Slide<?,?> slide = (Slide<?,?>)graphics.getRenderingHint(Drawable.CURRENT_SLIDE);\r
+ return slide.getDisplayPlaceholder(ph);\r
+ }\r
}\r
+ return true;\r
}\r
}\r
this.shape = shape;\r
}\r
\r
+ /**\r
+ * Sometimes it's necessary to distinguish between XSLF/HSLF for the rendering.\r
+ * Use this method on the shape to determine, if we work on the BIFF implementation\r
+ *\r
+ * @param shape the shape to render\r
+ * @return {@code true} if HSLF implementation is used\r
+ */\r
+ protected static boolean isHSLF(Shape<?,?> shape) {\r
+ return shape.getClass().getCanonicalName().toLowerCase(Locale.ROOT).contains("hslf");\r
+ }\r
+ \r
/**\r
* Apply 2-D transforms before drawing this shape. This includes rotation and flipping.\r
*\r
* @param graphics the graphics whos transform matrix will be modified\r
*/\r
+ @Override\r
public void applyTransform(Graphics2D graphics) {\r
- if (!(shape instanceof PlaceableShape)) return;\r
+ if (!(shape instanceof PlaceableShape)) {\r
+ return;\r
+ }\r
\r
PlaceableShape<?,?> ps = (PlaceableShape<?,?>)shape;\r
- final boolean isHSLF = ps.getClass().getCanonicalName().toLowerCase(Locale.ROOT).contains("hslf");\r
+ final boolean isHSLF = isHSLF(shape);\r
AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM);\r
- if (tx == null) tx = new AffineTransform();\r
+ if (tx == null) {\r
+ tx = new AffineTransform();\r
+ }\r
final Rectangle2D anchor = tx.createTransformedShape(ps.getAnchor()).getBounds2D();\r
\r
char cmds[] = isHSLF ? new char[]{ 'h','v','r' } : new char[]{ 'r','h','v' };\r
\r
// normalize rotation\r
rotation %= 360.;\r
- if (rotation < 0) rotation += 360.;\r
+ if (rotation < 0) {\r
+ rotation += 360.;\r
+ }\r
\r
int quadrant = (((int)rotation+45)/90)%4;\r
double scaleX = 1.0, scaleY = 1.0;\r
return (dim2 == 0.) ? 1 : dim1/dim2;\r
}\r
\r
+ @Override\r
public void draw(Graphics2D graphics) {\r
}\r
\r
+ @Override\r
public void drawContent(Graphics2D graphics) {\r
}\r
\r
\r
protected static BasicStroke getStroke(StrokeStyle strokeStyle) {\r
float lineWidth = (float) strokeStyle.getLineWidth();\r
- if (lineWidth == 0.0f) lineWidth = 0.25f; // Both PowerPoint and OOo draw zero-length lines as 0.25pt\r
+ if (lineWidth == 0.0f) {\r
+ // Both PowerPoint and OOo draw zero-length lines as 0.25pt\r
+ lineWidth = 0.25f;\r
+ }\r
\r
LineDash lineDash = strokeStyle.getLineDash();\r
if (lineDash == null) {\r
}\r
\r
LineCap lineCapE = strokeStyle.getLineCap();\r
- if (lineCapE == null) lineCapE = LineCap.FLAT;\r
+ if (lineCapE == null) {\r
+ lineCapE = LineCap.FLAT;\r
+ }\r
int lineCap;\r
switch (lineCapE) {\r
case ROUND:\r
\r
package org.apache.poi.sl.draw;\r
\r
-import java.awt.Dimension;\r
import java.awt.Color;\r
+import java.awt.Dimension;\r
import java.awt.Graphics2D;\r
-\r
import java.awt.geom.AffineTransform;\r
\r
-import org.apache.poi.sl.usermodel.*;\r
+import org.apache.poi.sl.usermodel.MasterSheet;\r
+import org.apache.poi.sl.usermodel.Shape;\r
+import org.apache.poi.sl.usermodel.Sheet;\r
\r
\r
public class DrawSheet implements Drawable {\r
this.sheet = sheet;\r
}\r
\r
+ @Override\r
public void draw(Graphics2D graphics) {\r
Dimension dim = sheet.getSlideShow().getPageSize();\r
Color whiteTrans = new Color(1f,1f,1f,0f);\r
graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, new AffineTransform());\r
\r
for (Shape<?,?> shape : sheet.getShapes()) {\r
- if(!canDraw(shape)) continue;\r
+ if(!canDraw(graphics, shape)) {\r
+ continue;\r
+ }\r
\r
// remember the initial transform and restore it after we are done with drawing\r
AffineTransform at = graphics.getTransform();\r
}\r
}\r
\r
+ @Override\r
public void applyTransform(Graphics2D context) {\r
}\r
\r
+ @Override\r
public void drawContent(Graphics2D context) {\r
}\r
\r
* Subclasses can override it and skip certain shapes from drawings,\r
* for instance, slide masters and layouts don't display placeholders\r
*/\r
- protected boolean canDraw(Shape<?,?> shape){\r
+ protected boolean canDraw(Graphics2D graphics, Shape<?,?> shape){\r
return true;\r
}\r
}\r
}\r
\r
public void draw(Graphics2D graphics) {\r
+ graphics.setRenderingHint(Drawable.CURRENT_SLIDE, this.sheet);\r
+ \r
Background<?,?> bg = sheet.getBackground();\r
if(bg != null) {\r
DrawFactory drawFact = DrawFactory.getInstance(graphics);\r
}\r
\r
super.draw(graphics);\r
+ graphics.setRenderingHint(Drawable.CURRENT_SLIDE, null);\r
}\r
}\r
import org.apache.poi.sl.usermodel.PlaceableShape;\r
import org.apache.poi.sl.usermodel.ShapeContainer;\r
import org.apache.poi.sl.usermodel.Sheet;\r
+import org.apache.poi.sl.usermodel.Slide;\r
import org.apache.poi.sl.usermodel.TextParagraph;\r
import org.apache.poi.sl.usermodel.TextParagraph.BulletStyle;\r
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;\r
import org.apache.poi.sl.usermodel.TextRun;\r
+import org.apache.poi.sl.usermodel.TextRun.FieldType;\r
import org.apache.poi.sl.usermodel.TextRun.TextCap;\r
import org.apache.poi.sl.usermodel.TextShape;\r
import org.apache.poi.sl.usermodel.TextShape.TextDirection;\r
/**\r
* Resolves instances being deserialized to the predefined constants.\r
*/\r
+ @Override\r
protected Object readResolve() throws InvalidObjectException {\r
if (HYPERLINK_HREF.getName().equals(getName())) {\r
return HYPERLINK_HREF;\r
autoNbrIdx = index;\r
}\r
\r
+ @Override\r
public void draw(Graphics2D graphics){\r
- if (lines.isEmpty()) return;\r
+ if (lines.isEmpty()) {\r
+ return;\r
+ }\r
\r
double penY = y;\r
\r
\r
//The vertical line spacing\r
Double spacing = paragraph.getLineSpacing();\r
- if (spacing == null) spacing = 100d;\r
+ if (spacing == null) {\r
+ spacing = 100d;\r
+ }\r
\r
for(DrawTextFragment line : lines){\r
double penX;\r
double rightInset = insets.right;\r
\r
TextAlign ta = paragraph.getTextAlign();\r
- if (ta == null) ta = TextAlign.LEFT;\r
+ if (ta == null) {\r
+ ta = TextAlign.LEFT;\r
+ }\r
switch (ta) {\r
case CENTER:\r
penX += (anchor.getWidth() - line.getWidth() - leftInset - rightInset - leftMargin) / 2;\r
return (lines.isEmpty() || rawText.trim().isEmpty());\r
}\r
\r
+ @Override\r
public void applyTransform(Graphics2D graphics) {\r
}\r
\r
+ @Override\r
public void drawContent(Graphics2D graphics) {\r
}\r
\r
\r
double wrappingWidth = getWrappingWidth(lines.size() == 0, graphics) + 1; // add a pixel to compensate rounding errors\r
// shape width can be smaller that the sum of insets (this was proved by a test file)\r
- if(wrappingWidth < 0) wrappingWidth = 1;\r
+ if(wrappingWidth < 0) {\r
+ wrappingWidth = 1;\r
+ }\r
\r
int nextBreak = text.indexOf("\n", startIndex + 1);\r
- if (nextBreak == -1) nextBreak = it.getEndIndex();\r
+ if (nextBreak == -1) {\r
+ nextBreak = it.getEndIndex();\r
+ }\r
\r
TextLayout layout = measurer.nextLayout((float)wrappingWidth, nextBreak, true);\r
if (layout == null) {\r
\r
maxLineHeight = Math.max(maxLineHeight, line.getHeight());\r
\r
- if(endIndex == it.getEndIndex()) break;\r
+ if(endIndex == it.getEndIndex()) {\r
+ break;\r
+ }\r
}\r
\r
rawText = text.toString();\r
\r
protected DrawTextFragment getBullet(Graphics2D graphics, AttributedCharacterIterator firstLineAttr) {\r
BulletStyle bulletStyle = paragraph.getBulletStyle();\r
- if (bulletStyle == null) return null;\r
+ if (bulletStyle == null) {\r
+ return null;\r
+ }\r
\r
String buCharacter;\r
AutoNumberingScheme ans = bulletStyle.getAutoNumberingScheme();\r
} else {\r
buCharacter = bulletStyle.getBulletCharacter();\r
}\r
- if (buCharacter == null) return null;\r
+ if (buCharacter == null) {\r
+ return null;\r
+ }\r
\r
String buFont = bulletStyle.getBulletFont();\r
- if (buFont == null) buFont = paragraph.getDefaultFontFamily();\r
+ if (buFont == null) {\r
+ buFont = paragraph.getDefaultFontFamily();\r
+ }\r
assert(buFont != null);\r
\r
PlaceableShape<?,?> ps = getParagraphShape();\r
\r
float fontSize = (Float)firstLineAttr.getAttribute(TextAttribute.SIZE);\r
Double buSz = bulletStyle.getBulletFontSize();\r
- if (buSz == null) buSz = 100d;\r
- if (buSz > 0) fontSize *= buSz* 0.01;\r
- else fontSize = (float)-buSz;\r
+ if (buSz == null) {\r
+ buSz = 100d;\r
+ }\r
+ if (buSz > 0) {\r
+ fontSize *= buSz* 0.01;\r
+ } else {\r
+ fontSize = (float)-buSz;\r
+ }\r
\r
\r
AttributedString str = new AttributedString(mapFontCharset(buCharacter,buFont));\r
return fact.getTextFragment(layout, str);\r
}\r
\r
- protected String getRenderableText(TextRun tr) {\r
+ protected String getRenderableText(Graphics2D graphics, TextRun tr) {\r
+ if (tr.getFieldType() == FieldType.SLIDE_NUMBER) {\r
+ Slide<?,?> slide = (Slide<?,?>)graphics.getRenderingHint(Drawable.CURRENT_SLIDE);\r
+ return (slide == null) ? "" : Integer.toString(slide.getSlideNumber()); \r
+ }\r
StringBuilder buf = new StringBuilder();\r
TextCap cap = tr.getTextCap();\r
String tabs = null;\r
private String tab2space(TextRun tr) {\r
AttributedString string = new AttributedString(" ");\r
String fontFamily = tr.getFontFamily();\r
- if (fontFamily == null) fontFamily = "Lucida Sans";\r
+ if (fontFamily == null) {\r
+ fontFamily = "Lucida Sans";\r
+ }\r
string.addAttribute(TextAttribute.FAMILY, fontFamily);\r
\r
Double fs = tr.getFontSize();\r
- if (fs == null) fs = 12d;\r
+ if (fs == null) {\r
+ fs = 12d;\r
+ }\r
string.addAttribute(TextAttribute.SIZE, fs.floatValue());\r
\r
TextLayout l = new TextLayout(string.getIterator(), new FontRenderContext(null, true, true));\r
double wspace = l.getAdvance();\r
\r
Double tabSz = paragraph.getDefaultTabSize();\r
- if (tabSz == null) tabSz = wspace*4;\r
+ if (tabSz == null) {\r
+ tabSz = wspace*4;\r
+ }\r
\r
int numSpaces = (int)Math.ceil(tabSz / wspace);\r
StringBuilder buf = new StringBuilder();\r
}\r
if (firstLine && !isHSLF()) {\r
if (bullet != null){\r
- if (indent > 0) width -= indent;\r
+ if (indent > 0) {\r
+ width -= indent;\r
+ }\r
} else {\r
- if (indent > 0) width -= indent; // first line indentation\r
- else if (indent < 0) { // hanging indentation: the first line start at the left margin\r
+ if (indent > 0) {\r
+ width -= indent; // first line indentation\r
+ } else if (indent < 0) { // hanging indentation: the first line start at the left margin\r
width += leftMargin;\r
}\r
}\r
@SuppressWarnings("rawtypes")\r
private PlaceableShape<?,?> getParagraphShape() {\r
return new PlaceableShape(){\r
+ @Override\r
public ShapeContainer<?,?> getParent() { return null; }\r
+ @Override\r
public Rectangle2D getAnchor() { return paragraph.getParentShape().getAnchor(); }\r
+ @Override\r
public void setAnchor(Rectangle2D anchor) {}\r
+ @Override\r
public double getRotation() { return 0; }\r
+ @Override\r
public void setRotation(double theta) {}\r
+ @Override\r
public void setFlipHorizontal(boolean flip) {}\r
+ @Override\r
public void setFlipVertical(boolean flip) {}\r
+ @Override\r
public boolean getFlipHorizontal() { return false; }\r
+ @Override\r
public boolean getFlipVertical() { return false; }\r
+ @Override\r
public Sheet<?,?> getSheet() { return paragraph.getParentShape().getSheet(); }\r
};\r
}\r
\r
protected AttributedString getAttributedString(Graphics2D graphics, StringBuilder text){\r
List<AttributedStringData> attList = new ArrayList<AttributedStringData>();\r
- if (text == null) text = new StringBuilder();\r
+ if (text == null) {\r
+ text = new StringBuilder();\r
+ }\r
\r
PlaceableShape<?,?> ps = getParagraphShape();\r
-\r
DrawFontManager fontHandler = (DrawFontManager)graphics.getRenderingHint(Drawable.FONT_HANDLER);\r
@SuppressWarnings("unchecked")\r
Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_MAP);\r
Map<String,String> fallbackMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_FALLBACK);\r
\r
for (TextRun run : paragraph){\r
- String runText = getRenderableText(run);\r
+ String runText = getRenderableText(graphics, run);\r
// skip empty runs\r
- if (runText.isEmpty()) continue;\r
+ if (runText.isEmpty()) {\r
+ continue;\r
+ }\r
\r
// user can pass an custom object to convert fonts\r
String mappedFont = run.getFontFamily();\r
return string;\r
}\r
\r
+ /**\r
+ * @return {@code true} if the HSLF implementation is used\r
+ */\r
protected boolean isHSLF() {\r
- return paragraph.getClass().getName().contains("HSLF");\r
+ return DrawShape.isHSLF(paragraph.getParentShape());\r
}\r
\r
/**\r
\r
double y0 = y;\r
//noinspection RedundantCast\r
+ @SuppressWarnings("cast")\r
Iterator<? extends TextParagraph<?,?,? extends TextRun>> paragraphs =\r
(Iterator<? extends TextParagraph<?,?,? extends TextRun>>) getShape().iterator();\r
\r
DrawableHint GSAVE = new DrawableHint(10);\r
DrawableHint GRESTORE = new DrawableHint(11);\r
\r
+ /**\r
+ * The Common SL Draw API works sometimes cascading, but there are places\r
+ * where the current slide context need to be evaluated, e.g. when slide numbers\r
+ * are printed. In this situation we need to have a way to access the current slide\r
+ */\r
+ DrawableHint CURRENT_SLIDE = new DrawableHint(12);\r
\r
\r
/**\r
this.ooxmlId = ooxmlId;\r
}\r
\r
- public static Placeholder lookupNative(int nativeId) {\r
+ public static Placeholder lookupNativeSlide(int nativeId) {\r
+ return lookupNative(nativeId, 0);\r
+ }\r
+\r
+ public static Placeholder lookupNativeSlideMaster(int nativeId) {\r
+ return lookupNative(nativeId, 1);\r
+ }\r
+\r
+ public static Placeholder lookupNativeNotes(int nativeId) {\r
+ return lookupNative(nativeId, 2);\r
+ }\r
+\r
+ public static Placeholder lookupNativeNotesMaster(int nativeId) {\r
+ return lookupNative(nativeId, 3);\r
+ }\r
+\r
+ \r
+ private static Placeholder lookupNative(int nativeId, int type) {\r
for (Placeholder ph : values()) {\r
- if (ph.nativeSlideId == nativeId ||\r
- ph.nativeSlideMasterId == nativeId || \r
- ph.nativeNotesId == nativeId ||\r
- ph.nativeNotesMasterId == nativeId\r
+ if (\r
+ type == 0 && ph.nativeSlideId == nativeId ||\r
+ type == 1 && ph.nativeSlideMasterId == nativeId || \r
+ type == 2 && ph.nativeNotesId == nativeId ||\r
+ type == 3 && ph.nativeNotesMasterId == nativeId\r
) {\r
return ph;\r
}\r
*/
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);
}
import java.awt.Color;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
+import org.apache.poi.util.Internal;
/**
* Some text.
SMALL,
ALL
}
+
+ enum FieldType {
+ SLIDE_NUMBER, DATE_TIME
+ }
String getRawText();
void setText(String text);
* @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();
}
\r
package org.apache.poi.xslf.usermodel;\r
\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;\r
\r
class XSLFLineBreak extends XSLFTextRun {\r
- private final CTTextCharacterProperties _brProps;\r
-\r
- XSLFLineBreak(CTRegularTextRun r, XSLFTextParagraph p, CTTextCharacterProperties brProps){\r
+ protected XSLFLineBreak(CTTextLineBreak r, XSLFTextParagraph p) {\r
super(r, p);\r
- _brProps = brProps;\r
- }\r
-\r
- @Override\r
- protected CTTextCharacterProperties getRPr(boolean create){\r
- return _brProps;\r
}\r
\r
public void setText(String text){\r
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;
}
import org.apache.poi.sl.draw.DrawFactory;\r
import org.apache.poi.sl.draw.DrawPaint;\r
import org.apache.poi.sl.usermodel.ColorStyle;\r
+import org.apache.poi.sl.usermodel.MasterSheet;\r
import org.apache.poi.sl.usermodel.PaintStyle;\r
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;\r
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference;\r
import org.openxmlformats.schemas.drawingml.x2006.main.STPathShadeType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;\r
\r
protected PaintStyle getFillPaint() {\r
final XSLFTheme theme = getSheet().getTheme();\r
+ final boolean hasPlaceholder = getPlaceholder() != null;\r
PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {\r
public boolean fetch(XSLFShape shape) {\r
XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(shape.getShapeProperties());\r
}\r
\r
PackagePart pp = shape.getSheet().getPackagePart();\r
- PaintStyle paint = selectPaint(fp, null, pp, theme);\r
+ PaintStyle paint = selectPaint(fp, null, pp, theme, hasPlaceholder);\r
if (paint != null) {\r
setValue(paint);\r
return true;\r
CTShapeStyle style = shape.getSpStyle();\r
if (style != null) {\r
fp = XSLFPropertiesDelegate.getFillDelegate(style.getFillRef());\r
- paint = selectPaint(fp, null, pp, theme);\r
+ paint = selectPaint(fp, null, pp, theme, hasPlaceholder);\r
}\r
if (paint != null) {\r
setValue(paint);\r
if (cur.toChild(namespace, nodename)) {\r
child = (T)cur.getObject();\r
}\r
+ if (cur.toChild("http://schemas.openxmlformats.org/drawingml/2006/main", nodename)) {\r
+ child = (T)cur.getObject();\r
+ }\r
cur.dispose();\r
return child;\r
}\r
}\r
\r
/**\r
- * Walk up the inheritance tree and fetch shape properties.\r
+ * Walk up the inheritance tree and fetch shape properties.<p>\r
*\r
- * The following order of inheritance is assumed:\r
- * <p>\r
- * slide <-- slideLayout <-- slideMaster\r
- * </p>\r
+ * The following order of inheritance is assumed:<p>\r
+ * <ol>\r
+ * <li>slide\r
+ * <li>slideLayout\r
+ * <li>slideMaster\r
+ * </ol>\r
+ * \r
+ * Currently themes and their defaults aren't correctly handled\r
*\r
* @param visitor the object that collects the desired property\r
* @return true if the property was fetched\r
*/\r
protected boolean fetchShapeProperty(PropertyFetcher<?> visitor) {\r
- boolean ok = visitor.fetch(this);\r
+ // try shape properties in slide\r
+ if (visitor.fetch(this)) {\r
+ return true;\r
+ }\r
\r
- XSLFSimpleShape masterShape;\r
- XSLFSheet masterSheet = (XSLFSheet)getSheet().getMasterSheet();\r
CTPlaceholder ph = getCTPlaceholder();\r
-\r
- if (masterSheet != null && ph != null) {\r
- if (!ok) {\r
- masterShape = masterSheet.getPlaceholder(ph);\r
- if (masterShape != null) {\r
- ok = visitor.fetch(masterShape);\r
- }\r
+ if (ph == null) {\r
+ return false;\r
+ }\r
+ MasterSheet<XSLFShape,XSLFTextParagraph> sm = getSheet().getMasterSheet();\r
+ \r
+ // try slide layout\r
+ if (sm instanceof XSLFSlideLayout) {\r
+ XSLFSlideLayout slideLayout = (XSLFSlideLayout)sm;\r
+ XSLFSimpleShape placeholderShape = slideLayout.getPlaceholder(ph);\r
+ if (placeholderShape != null && visitor.fetch(placeholderShape)) {\r
+ return true;\r
}\r
-\r
- // try slide master\r
- if (!ok ) {\r
- int textType;\r
- if ( !ph.isSetType()) textType = STPlaceholderType.INT_BODY;\r
- else {\r
- switch (ph.getType().intValue()) {\r
- case STPlaceholderType.INT_TITLE:\r
- case STPlaceholderType.INT_CTR_TITLE:\r
- textType = STPlaceholderType.INT_TITLE;\r
- break;\r
- case STPlaceholderType.INT_FTR:\r
- case STPlaceholderType.INT_SLD_NUM:\r
- case STPlaceholderType.INT_DT:\r
- textType = ph.getType().intValue();\r
- break;\r
- default:\r
- textType = STPlaceholderType.INT_BODY;\r
- break;\r
- }\r
- }\r
- XSLFSheet master = (XSLFSheet)masterSheet.getMasterSheet();\r
- if (master != null) {\r
- masterShape = master.getPlaceholderByType(textType);\r
- if (masterShape != null) {\r
- ok = visitor.fetch(masterShape);\r
- }\r
- }\r
+ sm = slideLayout.getMasterSheet();\r
+ }\r
+ \r
+ // try slide master\r
+ if (sm instanceof XSLFSlideMaster) {\r
+ XSLFSlideMaster master = (XSLFSlideMaster)sm;\r
+ int textType = getPlaceholderType(ph);\r
+ XSLFSimpleShape masterShape = master.getPlaceholderByType(textType);\r
+ if (masterShape != null && visitor.fetch(masterShape)) {\r
+ return true;\r
}\r
}\r
- return ok;\r
+ \r
+ return false;\r
+ }\r
+ \r
+ private static int getPlaceholderType(CTPlaceholder ph) {\r
+ if ( !ph.isSetType()) {\r
+ return STPlaceholderType.INT_BODY;\r
+ }\r
+ \r
+ switch (ph.getType().intValue()) {\r
+ case STPlaceholderType.INT_TITLE:\r
+ case STPlaceholderType.INT_CTR_TITLE:\r
+ return STPlaceholderType.INT_TITLE;\r
+ case STPlaceholderType.INT_FTR:\r
+ case STPlaceholderType.INT_SLD_NUM:\r
+ case STPlaceholderType.INT_DT:\r
+ return ph.getType().intValue();\r
+ default:\r
+ return STPlaceholderType.INT_BODY;\r
+ }\r
}\r
\r
/**\r
*\r
* @return the applied Paint or null if none was applied\r
*/\r
- protected static PaintStyle selectPaint(XSLFFillProperties fp, final CTSchemeColor phClr, final PackagePart parentPart, final XSLFTheme theme) {\r
+ protected static PaintStyle selectPaint(XSLFFillProperties fp, final CTSchemeColor phClr, final PackagePart parentPart, final XSLFTheme theme, boolean hasPlaceholder) {\r
if (fp == null || fp.isSetNoFill()) {\r
return null;\r
} else if (fp.isSetSolidFill()) {\r
} else if (fp.isSetGradFill()) {\r
return selectPaint(fp.getGradFill(), phClr, theme);\r
} else if (fp.isSetMatrixStyle()) {\r
- return selectPaint(fp.getMatrixStyle(), theme, fp.isLineStyle());\r
+ return selectPaint(fp.getMatrixStyle(), theme, fp.isLineStyle(), hasPlaceholder);\r
} else {\r
return null;\r
}\r
}\r
\r
protected static PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr, final XSLFTheme theme) {\r
- if (phClr == null && solidFill.isSetSchemeClr()) {\r
- phClr = solidFill.getSchemeClr();\r
+ if (solidFill.isSetSchemeClr()) {\r
+ // if there's a reference to the placeholder color,\r
+ // stop evaluating further and let the caller select\r
+ // the next style inheritance level\r
+ if (STSchemeColorVal.PH_CLR.equals(solidFill.getSchemeClr().getVal())) {\r
+ return null;\r
+ }\r
+ if (phClr == null) {\r
+ phClr = solidFill.getSchemeClr();\r
+ }\r
}\r
final XSLFColor c = new XSLFColor(solidFill, theme, phClr);\r
return DrawPaint.createSolidPaint(c.getColorStyle());\r
}; \r
}\r
\r
- protected static PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme, boolean isLineStyle) {\r
+ protected static PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme, boolean isLineStyle, boolean hasPlaceholder) {\r
if (fillRef == null) return null;\r
\r
// The idx attribute refers to the index of a fill style or\r
// values 1-999 refer to the index of a fill style within the fillStyleLst element\r
// values 1001 and above refer to the index of a background fill style within the bgFillStyleLst element.\r
int idx = (int)fillRef.getIdx();\r
- CTSchemeColor phClr = fillRef.getSchemeClr();\r
CTStyleMatrix matrix = theme.getXmlObject().getThemeElements().getFmtScheme();\r
final XmlObject styleLst;\r
int childIdx;\r
fp = XSLFPropertiesDelegate.getFillDelegate(cur.getObject());\r
}\r
cur.dispose();\r
- \r
- return selectPaint(fp, phClr, theme.getPackagePart(), theme);\r
+ \r
+ CTSchemeColor phClr = fillRef.getSchemeClr();\r
+ PaintStyle res = selectPaint(fp, phClr, theme.getPackagePart(), theme, hasPlaceholder);\r
+ // check for empty placeholder value\r
+ // see http://officeopenxml.com/prSlide-color.php - "Color Placeholders within Themes"\r
+ if (res != null || hasPlaceholder) {\r
+ return res;\r
+ }\r
+ XSLFColor col = new XSLFColor(fillRef, theme, phClr);\r
+ return DrawPaint.createSolidPaint(col.getColorStyle());\r
}\r
\r
@Override\r
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()) {
*/
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);
}
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;
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);
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();
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;
*/
public double getLineWidth() {
PropertyFetcher<Double> fetcher = new PropertyFetcher<Double>() {
+ @Override
public boolean fetch(XSLFShape shape) {
CTLineProperties ln = getLn(shape, false);
if (ln != null) {
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();
*/
public LineCompound getLineCompound() {
PropertyFetcher<Integer> fetcher = new PropertyFetcher<Integer>() {
+ @Override
public boolean fetch(XSLFShape shape) {
CTLineProperties ln = getLn(shape, false);
if (ln != null) {
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()) {
*/
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()) {
/**
* @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()) {
*
* @return definition of the shape geometry
*/
+ @Override
public CustomGeometry getGeometry() {
XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties());
return ph != null;
}
+ @Override
public Guide getAdjustValue(String name) {
XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties());
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();
}
*
* @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();
}
@Override
public boolean getFollowMasterGraphics(){
- return _slide.isSetShowMasterSp() && _slide.getShowMasterSp();
+ return _slide.getShowMasterSp();
}
/**
Drawable draw = drawFact.getDrawable(this);
draw.draw(graphics);
}
+
+ @Override
+ public boolean getDisplayPlaceholder(Placeholder placeholder) {
+ return false;
+ }
}
@Override
public boolean getFollowMasterGraphics() {
- return _layout.isSetShowMasterSp() && _layout.getShowMasterSp();
+ return _layout.getShowMasterSp();
}
/**
}\r
\r
CTTableCellProperties pr = getCellProperties(create);\r
- if (pr == null) return null;\r
+ if (pr == null) {\r
+ return null;\r
+ }\r
\r
switch (edge) {\r
case bottom:\r
@Override\r
public void removeBorder(BorderEdge edge) {\r
CTTableCellProperties pr = getCellProperties(false);\r
- if (pr == null) return;\r
+ if (pr == null) {\r
+ return;\r
+ }\r
switch (edge) {\r
case bottom:\r
if (pr.isSetLnB()) {\r
public StrokeStyle getBorderStyle(final BorderEdge edge) {\r
final Double width = getBorderWidth(edge);\r
return (width == null) ? null : new StrokeStyle() {\r
+ @Override\r
public PaintStyle getPaint() {\r
return DrawPaint.createSolidPaint(getBorderColor(edge));\r
}\r
\r
+ @Override\r
public LineCap getLineCap() {\r
return getBorderCap(edge);\r
}\r
\r
+ @Override\r
public LineDash getLineDash() {\r
return getBorderDash(edge);\r
}\r
\r
+ @Override\r
public LineCompound getLineCompound() {\r
return getBorderCompound(edge);\r
}\r
\r
+ @Override\r
public double getLineWidth() {\r
return width;\r
}\r
\r
public Color getBorderColor(BorderEdge edge) {\r
CTLineProperties ln = getCTLine(edge, false);\r
- if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) return null;\r
+ if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) {\r
+ return null;\r
+ }\r
\r
CTSolidColorFillProperties fill = ln.getSolidFill();\r
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());\r
public void setFillColor(Color color) {\r
CTTableCellProperties spPr = getCellProperties(true);\r
if (color == null) {\r
- if(spPr.isSetSolidFill()) spPr.unsetSolidFill();\r
+ if(spPr.isSetSolidFill()) {\r
+ spPr.unsetSolidFill();\r
+ }\r
} else {\r
CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill();\r
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());\r
public PaintStyle getFillPaint() {\r
XSLFSheet sheet = getSheet();\r
XSLFTheme theme = sheet.getTheme();\r
+ final boolean hasPlaceholder = getPlaceholder() != null;\r
XmlObject props = getCellProperties(false);\r
XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props);\r
if (fp != null) {\r
- PaintStyle paint = selectPaint(fp, null, sheet.getPackagePart(), theme);\r
+ PaintStyle paint = selectPaint(fp, null, sheet.getPackagePart(), theme, hasPlaceholder);\r
if (paint != null) {\r
return paint;\r
}\r
\r
fp = XSLFPropertiesDelegate.getFillDelegate(props);\r
if (fp != null) {\r
- PaintStyle paint = XSLFShape.selectPaint(fp, null, slideShow.getPackagePart(), theme);\r
+ PaintStyle paint = XSLFShape.selectPaint(fp, null, slideShow.getPackagePart(), theme, hasPlaceholder);\r
if (paint != null) {\r
return paint;\r
}\r
_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();
}
}
* @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;
}
\r
import java.awt.Color;\r
\r
+import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;\r
import org.apache.poi.openxml4j.opc.PackagePart;\r
import org.apache.poi.sl.draw.DrawPaint;\r
import org.apache.poi.sl.usermodel.PaintStyle;\r
import org.apache.poi.util.Beta;\r
import org.apache.poi.xslf.model.CharacterPropertyFetcher;\r
import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;\r
+import org.apache.xmlbeans.XmlObject;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;\r
import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;\r
*/\r
@Beta\r
public class XSLFTextRun implements TextRun {\r
- private final CTRegularTextRun _r;\r
+ private final XmlObject _r;\r
private final XSLFTextParagraph _p;\r
\r
- protected XSLFTextRun(CTRegularTextRun r, XSLFTextParagraph p){\r
+ protected XSLFTextRun(XmlObject r, XSLFTextParagraph p){\r
_r = r;\r
_p = p;\r
+ if (!(r instanceof CTRegularTextRun || r instanceof CTTextLineBreak || r instanceof CTTextField)) {\r
+ throw new OpenXML4JRuntimeException("unsupported text run of type "+r.getClass());\r
+ }\r
}\r
\r
XSLFTextParagraph getParentParagraph(){\r
}\r
\r
public String getRawText(){\r
- return _r.getT();\r
+ if (_r instanceof CTTextField) {\r
+ return ((CTTextField)_r).getT();\r
+ } else if (_r instanceof CTTextLineBreak) {\r
+ return "\n";\r
+ }\r
+ return ((CTRegularTextRun)_r).getT();\r
}\r
\r
String getRenderableText(){\r
- String txt = _r.getT();\r
+ if (_r instanceof CTTextField) {\r
+ CTTextField tf = (CTTextField)_r;\r
+ XSLFSheet sheet = _p.getParentShape().getSheet();\r
+ if ("slidenum".equals(tf.getType()) && sheet instanceof XSLFSlide) {\r
+ return Integer.toString(((XSLFSlide)sheet).getSlideNumber());\r
+ }\r
+ return tf.getT();\r
+ } else if (_r instanceof CTTextLineBreak) {\r
+ return "\n";\r
+ }\r
+ \r
+ \r
+ String txt = ((CTRegularTextRun)_r).getT();\r
TextCap cap = getTextCap();\r
StringBuffer buf = new StringBuffer();\r
for(int i = 0; i < txt.length(); i++) {\r
}\r
\r
public void setText(String text){\r
- _r.setT(text);\r
+ if (_r instanceof CTTextField) {\r
+ ((CTTextField)_r).setT(text);\r
+ } else if (_r instanceof CTTextLineBreak) {\r
+ // ignored\r
+ return;\r
+ } else {\r
+ ((CTRegularTextRun)_r).setT(text);\r
+ }\r
}\r
\r
- public CTRegularTextRun getXmlObject(){\r
+ /**\r
+ * Return the text run xmlbeans object.\r
+ * Depending on the type of text run, this can be {@link CTTextField},\r
+ * {@link CTTextLineBreak} or usually a {@link CTRegularTextRun}\r
+ *\r
+ * @return the xmlbeans object\r
+ */\r
+ public XmlObject getXmlObject(){\r
return _r;\r
}\r
\r
\r
@Override\r
public PaintStyle getFontColor(){\r
+ final boolean hasPlaceholder = getParentParagraph().getParentShape().getPlaceholder() != null;\r
CharacterPropertyFetcher<PaintStyle> fetcher = new CharacterPropertyFetcher<PaintStyle>(_p.getIndentLevel()){\r
public boolean fetch(CTTextCharacterProperties props){\r
if (props == null) {\r
XSLFSheet sheet = shape.getSheet();\r
PackagePart pp = sheet.getPackagePart();\r
XSLFTheme theme = sheet.getTheme();\r
- PaintStyle ps = XSLFShape.selectPaint(fp, phClr, pp, theme);\r
+ PaintStyle ps = XSLFShape.selectPaint(fp, phClr, pp, theme, hasPlaceholder);\r
\r
if (ps != null) {\r
setValue(ps);\r
* @return the character properties or null if create was false and the properties haven't exist\r
*/\r
protected CTTextCharacterProperties getRPr(boolean create) {\r
- if (_r.isSetRPr()) {\r
- return _r.getRPr();\r
- } else if (create) {\r
- return _r.addNewRPr();\r
+ if (_r instanceof CTTextField) {\r
+ CTTextField tf = (CTTextField)_r;\r
+ if (tf.isSetRPr()) {\r
+ return tf.getRPr();\r
+ } else if (create) {\r
+ return tf.addNewRPr();\r
+ }\r
+ } else if (_r instanceof CTTextLineBreak) {\r
+ CTTextLineBreak tlb = (CTTextLineBreak)_r;\r
+ if (tlb.isSetRPr()) {\r
+ return tlb.getRPr();\r
+ } else if (create) {\r
+ return tlb.addNewRPr();\r
+ }\r
} else {\r
- return null;\r
+ CTRegularTextRun tr = (CTRegularTextRun)_r;\r
+ if (tr.isSetRPr()) {\r
+ return tr.getRPr();\r
+ } else if (create) {\r
+ return tr.addNewRPr();\r
+ }\r
}\r
+ return null;\r
}\r
\r
@Override\r
@Override\r
public XSLFHyperlink createHyperlink(){\r
XSLFHyperlink hl = getHyperlink();\r
- if (hl == null) {\r
- hl = new XSLFHyperlink(_r.getRPr().addNewHlinkClick(), _p.getParentShape().getSheet());\r
+ if (hl != null) {\r
+ return hl;\r
}\r
- return hl;\r
+\r
+ CTTextCharacterProperties rPr = getRPr(true);\r
+ return new XSLFHyperlink(rPr.addNewHlinkClick(), _p.getParentShape().getSheet());\r
}\r
\r
@Override\r
public XSLFHyperlink getHyperlink(){\r
- CTTextCharacterProperties rPr = _r.getRPr();\r
+ CTTextCharacterProperties rPr = getRPr(false);\r
if (rPr == null) { \r
return null;\r
}\r
private boolean fetchCharacterProperty(CharacterPropertyFetcher<?> fetcher){\r
XSLFTextShape shape = _p.getParentShape();\r
XSLFSheet sheet = shape.getSheet();\r
- boolean ok = false;\r
\r
- if (_r.isSetRPr()) ok = fetcher.fetch(getRPr(false));\r
- if (ok) return true;\r
+ CTTextCharacterProperties rPr = getRPr(false);\r
+ if (rPr != null && fetcher.fetch(rPr)) {\r
+ return true;\r
+ }\r
\r
- ok = shape.fetchShapeProperty(fetcher);\r
- if (ok) return true;\r
+ if (shape.fetchShapeProperty(fetcher)) {\r
+ return true;\r
+ }\r
\r
CTPlaceholder ph = shape.getCTPlaceholder();\r
if (ph == null){\r
// if it is a plain text box then take defaults from presentation.xml\r
@SuppressWarnings("resource")\r
XMLSlideShow ppt = sheet.getSlideShow();\r
+ // TODO: determine master shape\r
CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(_p.getIndentLevel());\r
- if (themeProps != null) {\r
- // TODO: determine master shape\r
- ok = fetcher.fetch(themeProps);\r
+ if (themeProps != null && fetcher.fetch(themeProps)) {\r
+ return true;\r
}\r
}\r
- if (ok) return true;\r
\r
+ // TODO: determine master shape\r
CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle();\r
- if(defaultProps != null) {\r
- // TODO: determine master shape\r
- ok = fetcher.fetch(defaultProps);\r
+ if(defaultProps != null && fetcher.fetch(defaultProps)) {\r
+ return true;\r
}\r
- if (ok) return true;\r
\r
return false;\r
}\r
boolean strike = r.isStrikethrough();\r
if(strike != isStrikethrough()) setStrikethrough(strike);\r
}\r
+ \r
+ \r
+ @Override\r
+ public FieldType getFieldType() {\r
+ if (_r instanceof CTTextField) {\r
+ CTTextField tf = (CTTextField)_r;\r
+ if ("slidenum".equals(tf.getType())) {\r
+ return FieldType.SLIDE_NUMBER;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
}\r
// 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]));
// 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));
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import static org.junit.Assert.*;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertFalse;\r
+import static org.junit.Assert.assertNotNull;\r
+import static org.junit.Assert.assertNull;\r
+import static org.junit.Assert.assertSame;\r
+import static org.junit.Assert.assertTrue;\r
\r
import java.io.IOException;\r
\r
-import org.apache.poi.sl.usermodel.*;\r
+import org.apache.poi.sl.usermodel.ShapeType;\r
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;\r
import org.apache.poi.sl.usermodel.TextShape.TextAutofit;\r
import org.apache.poi.sl.usermodel.TextShape.TextDirection;\r
+import org.apache.poi.sl.usermodel.VerticalAlignment;\r
import org.apache.poi.util.Units;\r
import org.junit.Test;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;\r
import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;\r
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;\r
\r
-/**\r
- * @author Yegor Kozlov\r
- */\r
public class TestXSLFAutoShape {\r
@Test\r
public void testTextBodyProperies() throws IOException {\r
assertEquals(1, shape.getTextParagraphs().size());\r
assertEquals(0, p.getTextRuns().size());\r
XSLFTextRun r = p.addNewTextRun();\r
+ CTTextCharacterProperties rPr = r.getRPr(false);\r
+ assertNotNull(rPr);\r
assertEquals(1, p.getTextRuns().size());\r
assertSame(r, p.getTextRuns().get(0));\r
\r
+ \r
assertEquals(18.0, r.getFontSize(), 0); // default font size for text boxes\r
- assertFalse(r.getXmlObject().getRPr().isSetSz());\r
+ assertFalse(rPr.isSetSz());\r
r.setFontSize(10.0);\r
- assertTrue(r.getXmlObject().isSetRPr());\r
- assertEquals(1000, r.getXmlObject().getRPr().getSz());\r
+ assertEquals(1000, rPr.getSz());\r
r.setFontSize(12.5);\r
- assertEquals(1250, r.getXmlObject().getRPr().getSz());\r
+ assertEquals(1250, rPr.getSz());\r
r.setFontSize(null);\r
- assertFalse(r.getXmlObject().getRPr().isSetSz());\r
+ assertFalse(rPr.isSetSz());\r
\r
- assertFalse(r.getXmlObject().getRPr().isSetLatin());\r
+ assertFalse(rPr.isSetLatin());\r
assertEquals("Calibri", r.getFontFamily()); // comes from the slide master\r
r.setFontFamily(null);\r
assertEquals("Calibri", r.getFontFamily()); // comes from the slide master\r
r.setFontFamily("Arial");\r
assertEquals("Arial", r.getFontFamily());\r
- assertEquals("Arial", r.getXmlObject().getRPr().getLatin().getTypeface());\r
+ assertEquals("Arial", rPr.getLatin().getTypeface());\r
r.setFontFamily("Symbol");\r
assertEquals("Symbol", r.getFontFamily());\r
- assertEquals("Symbol", r.getXmlObject().getRPr().getLatin().getTypeface());\r
+ assertEquals("Symbol", rPr.getLatin().getTypeface());\r
r.setFontFamily(null);\r
assertEquals("Calibri", r.getFontFamily()); // comes from the slide master\r
- assertFalse(r.getXmlObject().getRPr().isSetLatin());\r
+ assertFalse(rPr.isSetLatin());\r
\r
assertFalse(r.isStrikethrough());\r
- assertFalse(r.getXmlObject().getRPr().isSetStrike());\r
+ assertFalse(rPr.isSetStrike());\r
r.setStrikethrough(true);\r
assertTrue(r.isStrikethrough());\r
- assertEquals(STTextStrikeType.SNG_STRIKE, r.getXmlObject().getRPr().getStrike());\r
+ assertEquals(STTextStrikeType.SNG_STRIKE, rPr.getStrike());\r
\r
assertFalse(r.isBold());\r
- assertFalse(r.getXmlObject().getRPr().isSetB());\r
+ assertFalse(rPr.isSetB());\r
r.setBold(true);\r
assertTrue(r.isBold());\r
- assertEquals(true, r.getXmlObject().getRPr().getB());\r
+ assertEquals(true, rPr.getB());\r
\r
assertFalse(r.isItalic());\r
- assertFalse(r.getXmlObject().getRPr().isSetI());\r
+ assertFalse(rPr.isSetI());\r
r.setItalic(true);\r
assertTrue(r.isItalic());\r
- assertEquals(true, r.getXmlObject().getRPr().getI());\r
+ assertEquals(true, rPr.getI());\r
\r
assertFalse(r.isUnderlined());\r
- assertFalse(r.getXmlObject().getRPr().isSetU());\r
+ assertFalse(rPr.isSetU());\r
r.setUnderlined(true);\r
assertTrue(r.isUnderlined());\r
- assertEquals(STTextUnderlineType.SNG, r.getXmlObject().getRPr().getU());\r
+ assertEquals(STTextUnderlineType.SNG, rPr.getU());\r
\r
r.setText("Apache");\r
assertEquals("Apache", r.getRawText());\r
XSLFTextBox tb3 = sl3.createTextBox();\r
tb3.setAnchor(anchor);\r
tb3.setText("text1 ");\r
- XSLFTextRun r3 = tb3.appendText("lin\u000bk", false);\r
+ tb3.appendText("lin\u000bk", false);\r
tb3.appendText(" text2", false);\r
- XSLFHyperlink hl3 = r3.createHyperlink();\r
- hl3.linkToSlide(slide1);\r
+ List<XSLFTextRun> tb3runs = tb3.getTextParagraphs().get(0).getTextRuns();\r
+ tb3runs.get(1).createHyperlink().linkToSlide(slide1); // "lin"\r
+ tb3runs.get(3).createHyperlink().linkToSlide(slide1); // "k"\r
XSLFTextBox tb4 = ppt1.createSlide().createTextBox();\r
tb4.setAnchor(anchor);\r
XSLFTextRun r4 = tb4.setText("page4");\r
assertEquals(HyperlinkType.DOCUMENT, hl2.getTypeEnum());\r
\r
tb3 = (XSLFTextBox)slides.get(2).getShapes().get(0);\r
+ XSLFHyperlink hl3 = tb3.getTextParagraphs().get(0).getTextRuns().get(1).getHyperlink();\r
+ assertNotNull(hl3);\r
hl3 = tb3.getTextParagraphs().get(0).getTextRuns().get(3).getHyperlink();\r
assertNotNull(hl3);\r
assertEquals("/ppt/slides/slide1.xml", hl3.getAddress());\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import static org.junit.Assert.*;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertSame;\r
+import static org.junit.Assert.assertTrue;\r
+\r
+import java.io.IOException;\r
+import java.util.List;\r
\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
import org.junit.Test;\r
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;\r
\r
-import java.io.IOException;\r
-import java.util.List;\r
-\r
-/**\r
- * @author Yegor Kozlov\r
- */\r
public class TestXSLFShape {\r
\r
@Test\r
assertEquals("PPTX ", r2.get(0).getRawText());\r
assertEquals("Title", r2.get(1).getRawText());\r
// Title is underlined\r
- assertEquals(STTextUnderlineType.SNG, r2.get(1).getXmlObject().getRPr().getU());\r
+ assertEquals(STTextUnderlineType.SNG, r2.get(1).getRPr(false).getU());\r
\r
\r
assertTrue(shapes2.get(1) instanceof XSLFAutoShape);\r
assertEquals(1, paragraphs2.get(1).getTextRuns().size());\r
\r
assertEquals("Subtitle", paragraphs2.get(0).getTextRuns().get(0).getRawText());\r
- assertTrue(paragraphs2.get(0).getTextRuns().get(0).getXmlObject().getRPr().getB());\r
+ assertTrue(paragraphs2.get(0).getTextRuns().get(0).getRPr(false).getB());\r
assertEquals("And second line", paragraphs2.get(1).getTextRuns().get(0).getRawText());\r
\r
ppt.close();\r
assertEquals(0, ppt.getSlides().size());\r
\r
XSLFSlide slide = ppt.createSlide();\r
- assertFalse(slide.getFollowMasterGraphics());\r
+ assertTrue(slide.getFollowMasterGraphics());\r
slide.setFollowMasterGraphics(false);\r
assertFalse(slide.getFollowMasterGraphics());\r
slide.setFollowMasterGraphics(true);\r
\r
// level 5: text properties are defined in the text run\r
CTTextParagraphProperties lv5PPr = paragraph.getXmlObject().addNewPPr();\r
- CTTextCharacterProperties lv5CPr = textRun.getXmlObject().getRPr();\r
+ CTTextCharacterProperties lv5CPr = textRun.getRPr(false);\r
lv5CPr.setSz(3600);\r
assertEquals(36.0, textRun.getFontSize(), 0);\r
lv5CPr.addNewLatin().setTypeface("Calibri");\r
\r
// level 5: text properties are defined in the text run\r
lv1PPr = p1.getXmlObject().isSetPPr() ? p1.getXmlObject().getPPr() : p1.getXmlObject().addNewPPr();\r
- lv1CPr = r1.getXmlObject().getRPr();\r
+ lv1CPr = r1.getRPr(false);\r
lv2PPr = p2.getXmlObject().isSetPPr() ? p2.getXmlObject().getPPr() : p2.getXmlObject().addNewPPr();\r
- lv2CPr = r2.getXmlObject().getRPr();\r
+ lv2CPr = r2.getRPr(false);\r
lv3PPr = p3.getXmlObject().isSetPPr() ? p3.getXmlObject().getPPr() : p3.getXmlObject().addNewPPr();\r
- lv3CPr = r3.getXmlObject().getRPr();\r
+ lv3CPr = r3.getRPr(false);\r
\r
lv1CPr.setSz(3600);\r
assertEquals(36.0, r1.getFontSize(), 0);\r
package org.apache.poi.xslf.usermodel;\r
\r
import static org.apache.poi.sl.TestCommonSL.sameColor;\r
-import static org.junit.Assert.*;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertFalse;\r
+import static org.junit.Assert.assertNull;\r
+import static org.junit.Assert.assertTrue;\r
\r
import java.awt.Color;\r
import java.util.List;\r
\r
-import org.apache.poi.sl.usermodel.*;\r
+import org.apache.poi.sl.usermodel.PaintStyle;\r
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;\r
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;\r
\r
private XSLFShape getShape(XSLFSheet sheet, String name){\r
for(XSLFShape sh : sheet.getShapes()){\r
- if(sh.getShapeName().equals(name)) return sh;\r
+ if(sh.getShapeName().equals(name)) {\r
+ return sh;\r
+ }\r
}\r
throw new IllegalArgumentException("Shape not found: " + name);\r
}\r
assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor()));\r
assertNull(sh2.getFillColor()); // no fill\r
\r
- assertFalse(slide.getSlideLayout().getFollowMasterGraphics());\r
+ assertTrue(slide.getSlideLayout().getFollowMasterGraphics());\r
}\r
\r
void slide5(XSLFSlide slide){\r
// font size is 40pt and scale factor is 90%\r
assertEquals(36.0, run2.getFontSize(), 0);\r
\r
- assertFalse(slide.getSlideLayout().getFollowMasterGraphics());\r
+ assertTrue(slide.getSlideLayout().getFollowMasterGraphics());\r
}\r
\r
void slide6(XSLFSlide slide){\r
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.
*/
public String getHeaderText(){
CString cs = _container == null ? null : _container.getHeaderAtom();
- return getPlaceholderText(OEPlaceholderAtom.MasterHeader, cs);
+ return getPlaceholderText(Placeholder.HEADER, cs);
}
/**
*/
public String getFooterText(){
CString cs = _container == null ? null : _container.getFooterAtom();
- return getPlaceholderText(OEPlaceholderAtom.MasterFooter, cs);
+ return getPlaceholderText(Placeholder.FOOTER, cs);
}
/**
*/
public String getDateTimeText(){
CString cs = _container == null ? null : _container.getUserDateAtom();
- return getPlaceholderText(OEPlaceholderAtom.MasterDate, cs);
+ return getPlaceholderText(Placeholder.DATETIME, cs);
}
/**
* whether the footer text is displayed.
*/
public boolean isFooterVisible(){
- return isVisible(HeadersFootersAtom.fHasFooter, OEPlaceholderAtom.MasterFooter);
+ return isVisible(HeadersFootersAtom.fHasFooter, Placeholder.FOOTER);
}
/**
* whether the header text is displayed.
*/
public boolean isHeaderVisible(){
- return isVisible(HeadersFootersAtom.fHasHeader, OEPlaceholderAtom.MasterHeader);
+ return isVisible(HeadersFootersAtom.fHasHeader, Placeholder.HEADER);
}
/**
* whether the date is displayed in the footer.
*/
public boolean isDateTimeVisible(){
- return isVisible(HeadersFootersAtom.fHasDate, OEPlaceholderAtom.MasterDate);
+ return isVisible(HeadersFootersAtom.fHasDate, Placeholder.DATETIME);
}
/**
* 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);
}
/**
* 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);
}
/**
_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;
}
package org.apache.poi.hslf.record;
-import org.apache.poi.util.LittleEndian;
import java.io.IOException;
import java.io.OutputStream;
+import org.apache.poi.sl.usermodel.Placeholder;
+import org.apache.poi.util.LittleEndian;
+
/**
- * OEPlaceholderAtom (3011).
- * <p>
- * An atom record that specifies whether a shape is a placeholder shape.
- * </p>
+ * OEPlaceholderAtom (3011).<p>
+ *
+ * An atom record that specifies whether a shape is a placeholder shape.
*
- * @author Yegor Kozlov
+ * @see Placeholder
*/
public final class OEPlaceholderAtom extends RecordAtom{
*/
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;
/**
- * Create a new instance of <code>OEPlaceholderAtom</code>
+ * Create a new instance of {@code OEPlaceholderAtom}
*/
public OEPlaceholderAtom(){
_header = new byte[8];
}
/**
- * 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];
/**
* @return type of this record {@link RecordTypes#OEPlaceholderAtom}.
*/
- public long getRecordType() { return RecordTypes.OEPlaceholderAtom.typeID; }
+ @Override
+ public long getRecordType() { return RecordTypes.OEPlaceholderAtom.typeID; }
/**
- * Returns the placement Id.
- * <p>
+ * Returns the placement Id.<p>
+ *
* The placement Id is a number assigned to the placeholder. It goes from -1 to the number of placeholders.
* It SHOULD be unique among all PlacholderAtom records contained in the corresponding slide.
* The value 0xFFFFFFFF specifies that the corresponding shape is not a placeholder shape.
- * </p>
*
* @return the placement Id.
*/
}
/**
- * 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.
*/
}
/**
- * 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.
*/
}
/**
- * 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){
}
/**
- * Write the contents of the record back, so it can be written
- * to disk
+ * Write the contents of the record back, so it can be written to disk
*/
- public void writeOut(OutputStream out) throws IOException {
+ @Override
+ public void writeOut(OutputStream out) throws IOException {
out.write(_header);
byte[] recdata = new byte[8];
import java.io.IOException;
import java.io.OutputStream;
-import org.apache.poi.hslf.exceptions.HSLFException;
+import org.apache.poi.hslf.record.SlideAtomLayout.SlideLayoutType;
import org.apache.poi.util.LittleEndian;
/**
* A Slide Atom (type 1007). Holds information on the parent Slide, what
- * Master Slide it uses, what Notes is attached to it, that sort of thing.
- * It also has a SSlideLayoutAtom embeded in it, but without the Atom header
- *
- * @author Nick Burch
+ * Master Slide it uses, what Notes is attached to it, that sort of thing.
+ * It also has a SSlideLayoutAtom embedded in it, but without the Atom header
*/
-public final class SlideAtom extends RecordAtom
-{
- private byte[] _header;
+public final class SlideAtom extends RecordAtom {
+ public static final int USES_MASTER_SLIDE_ID = 0x80000000;
+ // private static final int MASTER_SLIDE_ID = 0x00000000;
+
+ private byte[] _header;
private static long _type = 1007l;
- public static final int MASTER_SLIDE_ID = 0;
- public static final int USES_MASTER_SLIDE_ID = -2147483648;
private int masterID;
private int notesID;
private boolean followMasterObjects;
private boolean followMasterScheme;
private boolean followMasterBackground;
- private SSlideLayoutAtom layoutAtom;
+ private SlideAtomLayout layoutAtom;
private byte[] reserved;
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; }
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);
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];
}
// 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);
- }
- }
}
--- /dev/null
+/* ====================================================================
+ 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);
+ }
+
+}
* 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
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;
/**
* We are of type 4008
*/
- public long getRecordType() { return _type; }
+ @Override
+ public long getRecordType() { return _type; }
/**
* Write the contents of the record back, so it can be written
* to disk
*/
- public void writeOut(OutputStream out) throws IOException {
+ @Override
+ public void writeOut(OutputStream out) throws IOException {
// Header - size or type unchanged
out.write(_header);
* dump debug info; use getText() to return a string
* representation of the atom
*/
- public String toString() {
+ @Override
+ public String toString() {
StringBuffer out = new StringBuffer();
out.append( "TextBytesAtom:\n");
out.append( HexDump.dump(_text, 0, 0) );
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;
/**
* We are of type 4000
*/
- public long getRecordType() { return _type; }
+ @Override
+ public long getRecordType() { return _type; }
/**
* Write the contents of the record back, so it can be written
* to disk
*/
- public void writeOut(OutputStream out) throws IOException {
+ @Override
+ public void writeOut(OutputStream out) throws IOException {
// Header - size or type unchanged
out.write(_header);
* dump debug info; use getText() to return a string
* representation of the atom
*/
- public String toString() {
+ @Override
+ public String toString() {
StringBuffer out = new StringBuffer();
out.append( "TextCharsAtom:\n");
out.append( HexDump.dump(_text, 0, 0) );
* 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;
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;
/**
* Fetch the SlideShow we're attached to
*/
+ @Override
public HSLFSlideShow getSlideShow() {
return _slideShow;
}
_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);
*
* @param shape - the Shape to add
*/
+ @Override
public void addShape(HSLFShape shape) {
PPDrawing ppdrawing = getPPDrawing();
c.incrementShapeId();
dg.setNumShapes( dg.getNumShapes() + 1 );
dg.setLastMSOSPID( result );
- if (result >= dgg.getShapeIdMax())
+ if (result >= dgg.getShapeIdMax()) {
dgg.setShapeIdMax( result + 1 );
+ }
return result;
}
}
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;
}
* @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();
/**
* Return the master sheet .
*/
+ @Override
public abstract HSLFMasterSheet getMasterSheet();
/**
*
* @return the background shape for this sheet.
*/
+ @Override
public HSLFBackground getBackground() {
if (_background == null) {
PPDrawing ppdrawing = getPPDrawing();
}
/**
- * 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;
}
}
}
progBinaryTag.findFirstOfType(
RecordTypes.CString.typeID
);
- if(binaryTag != null) tag = binaryTag.getText();
+ if(binaryTag != null) {
+ tag = binaryTag.getText();
+ }
}
}
}
+ @Override
public Iterator<HSLFShape> iterator() {
return getShapes().iterator();
}
* Sheets that support the notion of master (slide, slideLayout) should override it and
* check this setting
*/
+ @Override
public boolean getFollowMasterGraphics() {
return false;
}
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;
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);
}
}
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;
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;
+ }
}
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;
/**
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;
}
/**
* Returns <code>null</code> since SlideMasters doen't have master sheet.
*/
+ @Override
public HSLFMasterSheet getMasterSheet() {
return null;
}
* 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();
prop = styles.get(i).findByName(name);
}
- if (prop != null) return prop;
+ if (prop != null) {
+ return prop;
+ }
switch (txtype) {
case TextHeaderAtom.CENTRE_BODY_TYPE:
}
}
+ @Override
protected void onAddTextShape(HSLFTextShape shape) {
List<HSLFTextParagraph> runs = shape.getTextParagraphs();
_paragraphs.add(runs);
import org.apache.poi.hslf.model.textproperties.TextProp;\r
import org.apache.poi.hslf.model.textproperties.TextPropCollection;\r
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;\r
-import org.apache.poi.hslf.record.*;\r
+import org.apache.poi.hslf.record.ColorSchemeAtom;\r
+import org.apache.poi.hslf.record.EscherTextboxWrapper;\r
+import org.apache.poi.hslf.record.FontCollection;\r
+import org.apache.poi.hslf.record.InteractiveInfo;\r
+import org.apache.poi.hslf.record.MasterTextPropAtom;\r
+import org.apache.poi.hslf.record.OutlineTextRefAtom;\r
+import org.apache.poi.hslf.record.PPDrawing;\r
+import org.apache.poi.hslf.record.Record;\r
+import org.apache.poi.hslf.record.RecordContainer;\r
+import org.apache.poi.hslf.record.RecordTypes;\r
+import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;\r
+import org.apache.poi.hslf.record.SlideListWithText;\r
+import org.apache.poi.hslf.record.SlidePersistAtom;\r
+import org.apache.poi.hslf.record.StyleTextProp9Atom;\r
+import org.apache.poi.hslf.record.StyleTextPropAtom;\r
+import org.apache.poi.hslf.record.TextBytesAtom;\r
+import org.apache.poi.hslf.record.TextCharsAtom;\r
+import org.apache.poi.hslf.record.TextHeaderAtom;\r
+import org.apache.poi.hslf.record.TextRulerAtom;\r
+import org.apache.poi.hslf.record.TextSpecInfoAtom;\r
+import org.apache.poi.hslf.record.TxInteractiveInfoAtom;\r
import org.apache.poi.sl.draw.DrawPaint;\r
import org.apache.poi.sl.usermodel.AutoNumberingScheme;\r
+import org.apache.poi.sl.usermodel.MasterSheet;\r
import org.apache.poi.sl.usermodel.PaintStyle;\r
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
+import org.apache.poi.sl.usermodel.Placeholder;\r
import org.apache.poi.sl.usermodel.TextParagraph;\r
import org.apache.poi.util.Internal;\r
-import org.apache.poi.util.LocaleUtil;\r
import org.apache.poi.util.POILogFactory;\r
import org.apache.poi.util.POILogger;\r
import org.apache.poi.util.StringUtil;\r
* This class represents a run of text in a powerpoint document. That\r
* run could be text on a sheet, or text in a note.\r
* It is only a very basic class for now\r
- *\r
- * @author Nick Burch\r
*/\r
\r
public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFTextParagraph,HSLFTextRun> {\r
private TextBytesAtom _byteAtom;\r
private TextCharsAtom _charAtom;\r
private TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);\r
+ private TextPropCollection _masterStyle;\r
\r
protected TextRulerAtom _ruler;\r
protected final List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>();\r
public void setParagraphStyle(TextPropCollection paragraphStyle) {\r
_paragraphStyle.copy(paragraphStyle);\r
}\r
-\r
+ \r
/**\r
* Setting a master style reference\r
*\r
* @since POI 3.14-Beta1\r
*/\r
@Internal\r
- /* package */ void setMasterStyleReference(TextPropCollection paragraphStyle) {\r
- _paragraphStyle = paragraphStyle;\r
+ /* package */ void setMasterStyleReference(TextPropCollection masterStyle) {\r
+ _masterStyle = masterStyle;\r
}\r
\r
/**\r
\r
@Override\r
public Double getLeftMargin() {\r
- TextProp val = getPropVal(_paragraphStyle, "text.offset", this);\r
- return (val == null) ? null : Units.masterToPoints(val.getValue());\r
+ TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "text.offset");\r
+ return (tp == null) ? null : Units.masterToPoints(tp.getValue());\r
}\r
\r
@Override\r
\r
@Override\r
public Double getIndent() {\r
- TextProp val = getPropVal(_paragraphStyle, "bullet.offset", this);\r
- return (val == null) ? null : Units.masterToPoints(val.getValue());\r
+ TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.offset");\r
+ return (tp == null) ? null : Units.masterToPoints(tp.getValue());\r
}\r
\r
@Override\r
\r
@Override\r
public TextAlign getTextAlign() {\r
- TextProp tp = getPropVal(_paragraphStyle, "alignment", this);\r
+ TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "alignment");\r
if (tp == null) {\r
return null;\r
}\r
\r
@Override\r
public FontAlign getFontAlign() {\r
- TextProp tp = getPropVal(_paragraphStyle, FontAlignmentProp.NAME, this);\r
+ TextProp tp = getPropVal(_paragraphStyle, _masterStyle, FontAlignmentProp.NAME);\r
if (tp == null) {\r
return null;\r
}\r
* Returns the bullet character\r
*/\r
public Character getBulletChar() {\r
- TextProp tp = getPropVal(_paragraphStyle, "bullet.char", this);\r
+ TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.char");\r
return (tp == null) ? null : (char)tp.getValue();\r
}\r
\r
* Returns the bullet color\r
*/\r
public Color getBulletColor() {\r
- TextProp tp = getPropVal(_paragraphStyle, "bullet.color", this);\r
+ TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.color");\r
boolean hasColor = getFlag(ParagraphFlagsTextProp.BULLET_HARDCOLOR_IDX);\r
if (tp == null || !hasColor) {\r
// if bullet color is undefined, return color of first run\r
*/\r
public void setBulletFont(String typeface) {\r
if (typeface == null) {\r
- setPropVal(_paragraphStyle, "bullet.font", null);\r
+ setPropVal(_paragraphStyle, _masterStyle, "bullet.font", null);\r
setFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, false);\r
+ return;\r
}\r
\r
FontCollection fc = getSheet().getSlideShow().getFontCollection();\r
* Returns the bullet font\r
*/\r
public String getBulletFont() {\r
- TextProp tp = getPropVal(_paragraphStyle, "bullet.font", this);\r
+ TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.font");\r
boolean hasFont = getFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX);\r
if (tp == null || !hasFont) {\r
return getDefaultFontFamily();\r
}\r
\r
private Double getPctOrPoints(String propName) {\r
- TextProp tp = getPropVal(_paragraphStyle, propName, this);\r
+ TextProp tp = getPropVal(_paragraphStyle, _masterStyle, propName);\r
if (tp == null) {\r
return null;\r
}\r
}\r
\r
private boolean getFlag(int index) {\r
- BitMaskTextProp tp = (BitMaskTextProp)getPropVal(_paragraphStyle, ParagraphFlagsTextProp.NAME, this);\r
+ BitMaskTextProp tp = (BitMaskTextProp)getPropVal(_paragraphStyle, _masterStyle, ParagraphFlagsTextProp.NAME);\r
return (tp == null) ? false : tp.getSubValue(index);\r
}\r
\r
* The propName can be a comma-separated list, in case multiple equivalent values\r
* are queried\r
*/\r
- protected static TextProp getPropVal(TextPropCollection props, String propName, HSLFTextParagraph paragraph) {\r
+ protected TextProp getPropVal(TextPropCollection props, TextPropCollection masterProps, String propName) {\r
String propNames[] = propName.split(",");\r
for (String pn : propNames) {\r
TextProp prop = props.findByName(pn);\r
// Font properties (maybe other too???) can have an index of -1\r
// so we check the master for this font index then\r
if (pn.contains("font") && prop.getValue() == -1) {\r
- return getMasterPropVal(props, pn, paragraph);\r
+ return getMasterPropVal(props, masterProps, pn);\r
}\r
\r
return prop;\r
}\r
\r
- return getMasterPropVal(props, propName, paragraph);\r
+ return getMasterPropVal(props, masterProps, propName);\r
}\r
\r
- private static TextProp getMasterPropVal(TextPropCollection props, String propName, HSLFTextParagraph paragraph) {\r
- String propNames[] = propName.split(",");\r
- \r
- BitMaskTextProp maskProp = (BitMaskTextProp) props.findByName(ParagraphFlagsTextProp.NAME);\r
- boolean hardAttribute = (maskProp != null && maskProp.getValue() == 0);\r
- if (hardAttribute) {\r
- return null;\r
- }\r
+ private TextProp getMasterPropVal(TextPropCollection props, TextPropCollection masterProps, String propName) {\r
+ boolean isChar = props.getTextPropType() == TextPropType.character;\r
\r
- HSLFSheet sheet = paragraph.getSheet();\r
- int txtype = paragraph.getRunType();\r
- HSLFMasterSheet master = sheet.getMasterSheet();\r
- if (master == null) {\r
- logger.log(POILogger.WARN, "MasterSheet is not available");\r
- return null;\r
+ // check if we can delegate to master for the property\r
+ if (!isChar) {\r
+ BitMaskTextProp maskProp = (BitMaskTextProp) props.findByName(ParagraphFlagsTextProp.NAME);\r
+ boolean hardAttribute = (maskProp != null && maskProp.getValue() == 0);\r
+ if (hardAttribute) {\r
+ return null;\r
+ }\r
}\r
\r
- boolean isChar = props.getTextPropType() == TextPropType.character;\r
+ String propNames[] = propName.split(",");\r
+ if (masterProps == null) { \r
+ HSLFSheet sheet = getSheet();\r
+ int txtype = getRunType();\r
+ HSLFMasterSheet master = sheet.getMasterSheet();\r
+ if (master == null) {\r
+ logger.log(POILogger.WARN, "MasterSheet is not available");\r
+ return null;\r
+ }\r
\r
- for (String pn : propNames) {\r
- TextProp prop = master.getStyleAttribute(txtype, paragraph.getIndentLevel(), pn, isChar);\r
- if (prop != null) {\r
- return prop;\r
+ for (String pn : propNames) {\r
+ TextProp prop = master.getStyleAttribute(txtype, getIndentLevel(), pn, isChar);\r
+ if (prop != null) {\r
+ return prop;\r
+ }\r
+ }\r
+ } else {\r
+ for (String pn : propNames) {\r
+ TextProp prop = masterProps.findByName(pn);\r
+ if (prop != null) {\r
+ return prop;\r
+ }\r
}\r
}\r
-\r
+ \r
return null;\r
}\r
\r
* @param name the name of the TextProp to fetch/add\r
* @param val the value, null if unset\r
*/\r
- protected static void setPropVal(TextPropCollection props, String name, Integer val) {\r
+ protected void setPropVal(TextPropCollection props, TextPropCollection masterProps, String name, Integer val) {\r
+ TextPropCollection pc = props;\r
+ if (getSheet() instanceof MasterSheet && masterProps != null) {\r
+ pc = masterProps;\r
+ }\r
+ \r
if (val == null) {\r
- props.removeByName(name);\r
+ pc.removeByName(name);\r
return;\r
}\r
\r
// Fetch / Add the TextProp\r
- TextProp tp = props.addWithName(name);\r
+ TextProp tp = pc.addWithName(name);\r
tp.setValue(val);\r
}\r
\r
}\r
}\r
\r
- protected static List<HSLFTextParagraph> createEmptyParagraph() {\r
- EscherTextboxWrapper wrapper = new EscherTextboxWrapper();\r
- return createEmptyParagraph(wrapper);\r
- }\r
-\r
- protected static List<HSLFTextParagraph> createEmptyParagraph(EscherTextboxWrapper wrapper) {\r
- TextHeaderAtom tha = new TextHeaderAtom();\r
- tha.setParentRecord(wrapper);\r
- wrapper.appendChildRecord(tha);\r
-\r
- TextBytesAtom tba = new TextBytesAtom();\r
- tba.setText("".getBytes(LocaleUtil.CHARSET_1252));\r
- wrapper.appendChildRecord(tba);\r
-\r
- StyleTextPropAtom sta = new StyleTextPropAtom(1);\r
- TextPropCollection paraStyle = sta.addParagraphTextPropCollection(1);\r
- TextPropCollection charStyle = sta.addCharacterTextPropCollection(1);\r
- wrapper.appendChildRecord(sta);\r
-\r
- List<HSLFTextParagraph> paragraphs = new ArrayList<HSLFTextParagraph>(1);\r
- HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null, paragraphs);\r
- htp.setParagraphStyle(paraStyle);\r
- paragraphs.add(htp);\r
-\r
- HSLFTextRun htr = new HSLFTextRun(htp);\r
- htr.setCharacterStyle(charStyle);\r
- htr.setText("");\r
- htp.addTextRun(htr);\r
-\r
- return paragraphs;\r
- }\r
-\r
public EscherTextboxWrapper getTextboxWrapper() {\r
return (EscherTextboxWrapper) _headerAtom.getParentRecord();\r
}\r
* @param val The value to set for the TextProp\r
*/\r
public void setParagraphTextPropVal(String propName, Integer val) {\r
- setPropVal(_paragraphStyle, propName, val);\r
+ setPropVal(_paragraphStyle, _masterStyle, propName, val);\r
setDirty();\r
}\r
\r
*/\r
@Override\r
public boolean isHeaderOrFooter() {\r
- HSLFShape s = getParentShape();\r
+ HSLFTextShape s = getParentShape();\r
if (s == null) {\r
return false;\r
}\r
- RoundTripHFPlaceholder12 hfPl = s.getClientDataRecord(RecordTypes.RoundTripHFPlaceholder12.typeID);\r
- if (hfPl == null) {\r
+ Placeholder ph = s.getPlaceholder();\r
+ if (ph == null) {\r
return false;\r
}\r
-\r
- int plId = hfPl.getPlaceholderId();\r
- switch (plId) {\r
- case OEPlaceholderAtom.MasterDate:\r
- case OEPlaceholderAtom.MasterSlideNumber:\r
- case OEPlaceholderAtom.MasterFooter:\r
- case OEPlaceholderAtom.MasterHeader:\r
+ switch (ph) {\r
+ case DATETIME:\r
+ case SLIDE_NUMBER:\r
+ case FOOTER:\r
+ case HEADER:\r
return true;\r
default:\r
return false;\r
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;
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;
* Note - we may share these styles with other RichTextRuns
*/
private TextPropCollection characterStyle = new TextPropCollection(1, TextPropType.character);
+
+ private TextPropCollection masterStyle;
/**
* Create a new wrapper around a rich text string
* @since POI 3.14-Beta1
*/
@Internal
- /* package */ void setMasterStyleReference(TextPropCollection characterStyle) {
- this.characterStyle = characterStyle;
+ /* package */ void setMasterStyleReference(TextPropCollection masterStyle) {
+ this.masterStyle = masterStyle;
}
/**
* Fetch the text, in raw storage form
*/
- public String getRawText() {
+ @Override
+ public String getRawText() {
return _runText;
}
/**
* Change the text
*/
- public void setText(String text) {
+ @Override
+ public void setText(String text) {
if (text == null) {
throw new HSLFException("text must not be null");
}
}
protected boolean getFlag(int index) {
- if (characterStyle == null) return false;
+ if (characterStyle == null) {
+ return false;
+ }
BitMaskTextProp prop = (BitMaskTextProp)characterStyle.findByName(CharFlagsTextProp.NAME);
* @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();
}
* @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();
}
@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();
}
* 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();
}
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());
}
*/
@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;
return parentParagraph;
}
+ @Override
public TextCap getTextCap() {
return TextCap.NONE;
}
return getSuperscript() > 0;
}
+ @Override
public byte getPitchAndFamily() {
return 0;
}
}
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;
+ }
}
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;
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;
BOTTOM_BASELINE (7, VerticalAlignment.BOTTOM, false, true),
TOP_CENTER_BASELINE (8, VerticalAlignment.TOP, true, true),
BOTTOM_CENTER_BASELINE(9, VerticalAlignment.BOTTOM, true, true);
-
+
public final int nativeId;
public final VerticalAlignment vAlign;
public final boolean centered;
public final Boolean baseline;
-
+
HSLFTextAnchor(int nativeId, VerticalAlignment vAlign, boolean centered, Boolean baseline) {
this.nativeId = nativeId;
this.vAlign = vAlign;
static HSLFTextAnchor fromNativeId(int nativeId) {
for (HSLFTextAnchor ta : values()) {
- if (ta.nativeId == nativeId) return ta;
+ if (ta.nativeId == nativeId) {
+ return ta;
+ }
}
return null;
}
/**
* 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
*/
// 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.
*
}
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) {
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.
*
*/
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();
}
*/
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);
@Override
public List<HSLFTextParagraph> getTextParagraphs(){
- if (!_paragraphs.isEmpty()) return _paragraphs;
+ if (!_paragraphs.isEmpty()) {
+ return _paragraphs;
+ }
_txtbox = getEscherTextboxWrapper();
if (_txtbox == null) {
- _paragraphs.addAll(HSLFTextParagraph.createEmptyParagraph());
- _txtbox = _paragraphs.get(0).getTextboxWrapper();
+ _txtbox = new EscherTextboxWrapper();
+ createEmptyParagraph();
} else {
- _paragraphs = HSLFTextParagraph.findTextParagraphs(_txtbox, getSheet());
- if (_paragraphs == null) {
+ List<HSLFTextParagraph> pList = HSLFTextParagraph.findTextParagraphs(_txtbox, getSheet());
+ if (pList == null) {
// there are actually TextBoxRecords without extra data - see #54722
- _paragraphs = HSLFTextParagraph.createEmptyParagraph(_txtbox);
+ createEmptyParagraph();
+ } else {
+ _paragraphs = pList;
}
-
+
if (_paragraphs.isEmpty()) {
LOG.log(POILogger.WARN, "TextRecord didn't contained any text lines");
}
return _paragraphs;
}
+
@Override
public void setSheet(HSLFSheet sheet) {
super.setSheet(sheet);
/**
* Return {@link RoundTripHFPlaceholder12}, the atom that describes a header/footer placeholder.
* Compare the {@link RoundTripHFPlaceholder12#getPlaceholderId()} with
- * {@link OEPlaceholderAtom#MasterHeader} or {@link OEPlaceholderAtom#MasterFooter}, to find out
+ * {@link Placeholder#HEADER} or {@link Placeholder#FOOTER}, to find out
* what kind of placeholder this is.
*
* @return {@link RoundTripHFPlaceholder12} or {@code null} if not found
- *
+ *
* @since POI 3.14-Beta2
*/
public RoundTripHFPlaceholder12 getHFPlaceholderAtom() {
// special case for files saved in Office 2007
return getClientDataRecord(RoundTripHFPlaceholder12.typeID);
}
-
+
@Override
public boolean isPlaceholder() {
OEPlaceholderAtom oep = getPlaceholderAtom();
- if (oep != null) return true;
+ if (oep != null) {
+ return true;
+ }
//special case for files saved in Office 2007
RoundTripHFPlaceholder12 hldr = getHFPlaceholderAtom();
- if (hldr != null) return true;
+ if (hldr != null) {
+ return true;
+ }
return false;
}
}
setEscherProperty(opt, EscherProperties.TEXT__TEXTFLOW, msotxfl);
}
-
+
@Override
public Double getTextRotation() {
// see 2.4.6 MSOCDIR
EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__FONTROTATION);
return (prop == null) ? null : (90. * prop.getPropertyValue());
}
-
+
@Override
public void setTextRotation(Double rotation) {
AbstractEscherOptRecord opt = getEscherOptRecord();
setEscherProperty(EscherProperties.TEXT__FONTROTATION, rot);
}
}
-
+
/**
* Returns the raw text content of the shape. This hasn't had any
* changes applied to it, and so is probably unlikely to print
List<HSLFTextParagraph> paras = getTextParagraphs();
HSLFTextRun htr = HSLFTextParagraph.appendText(paras, text, newParagraph);
setTextId(getRawText().hashCode());
- return htr;
+ return htr;
}
@Override
/**
* 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>>();
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;
}
/**
* 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;
}
package org.apache.poi.hslf.record;
-import java.io.ByteArrayInputStream;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
-import org.apache.poi.hslf.record.SlideAtom.SSlideLayoutAtom;
+import org.apache.poi.hslf.HSLFTestDataSamples;
+import org.apache.poi.hslf.record.SlideAtomLayout.SlideLayoutType;
+import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-
-import junit.framework.TestCase;
+import org.junit.Test;
/**
* Tests that SlideAtom works properly
- *
- * @author Nick Burch (nick at torchbox dot com)
*/
-public final class TestSlideAtom extends TestCase {
+public final class TestSlideAtom {
// From a real file
- private final byte[] data_a = new byte[] { 1, 0, 0xEF-256, 3, 0x18, 0, 0, 0,
+ private static final byte[] data_a = new byte[] { 1, 0, 0xEF-256, 3, 0x18, 0, 0, 0,
0, 0, 0, 0, 0x0F, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80-256,
0, 1, 0, 0, 7, 0, 0x0C, 0x30 };
- public void testRecordType() {
+ @Test
+ public void testRecordType() {
SlideAtom sa = new SlideAtom(data_a, 0, data_a.length);
assertEquals(1007l, sa.getRecordType());
}
+
+ @Test
public void testFlags() {
SlideAtom sa = new SlideAtom(data_a, 0, data_a.length);
// First 12 bytes are a SSlideLayoutAtom, checked elsewhere
// Check the IDs
- assertEquals(0x80000000, sa.getMasterID());
+ assertEquals(SlideAtom.USES_MASTER_SLIDE_ID, sa.getMasterID());
assertEquals(256, sa.getNotesID());
// Check the flags
assertEquals(true, sa.getFollowMasterScheme());
assertEquals(true, sa.getFollowMasterBackground());
}
- public void testSSlideLayoutAtom() {
+
+ @Test
+ public void testSSlideLayoutAtom() {
SlideAtom sa = new SlideAtom(data_a, 0, data_a.length);
- SSlideLayoutAtom ssla = sa.getSSlideLayoutAtom();
+ SlideAtomLayout ssla = sa.getSSlideLayoutAtom();
- assertEquals(0, ssla.getGeometryType());
+ assertEquals(SlideLayoutType.TITLE_SLIDE, ssla.getGeometryType());
- // Should also check the placehold IDs at some point
+ // Should also check the placeholder IDs at some point
}
- public void testWrite() throws Exception {
+ @Test
+ public void testWrite() throws IOException {
SlideAtom sa = new SlideAtom(data_a, 0, data_a.length);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
sa.writeOut(baos);
- byte[] b = baos.toByteArray();
-
- assertEquals(data_a.length, b.length);
- for(int i=0; i<data_a.length; i++) {
- assertEquals(data_a[i],b[i]);
- }
+ assertArrayEquals(data_a, baos.toByteArray());
}
- public void testSSSlideInfoAtom() throws Exception {
- HSLFSlideShow ss = new HSLFSlideShow();
- org.apache.poi.hslf.usermodel.HSLFSlide slide1 = ss.createSlide(), slide2 = ss.createSlide();
+ @Test
+ public void testSSSlideInfoAtom() throws IOException {
+ HSLFSlideShow ss1 = new HSLFSlideShow();
+ HSLFSlide slide1 = ss1.createSlide(), slide2 = ss1.createSlide();
slide2.setHidden(true);
- ByteArrayOutputStream bos = new ByteArrayOutputStream(4096);
- ss.write(bos);
- ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
- ss = new HSLFSlideShow(bis);
- slide1 = ss.getSlides().get(0);
- slide2 = ss.getSlides().get(1);
+ HSLFSlideShow ss2 = HSLFTestDataSamples.writeOutAndReadBack(ss1);
+ slide1 = ss2.getSlides().get(0);
+ slide2 = ss2.getSlides().get(1);
assertFalse(slide1.getHidden());
assertTrue(slide2.getHidden());
+ ss2.close();
+ ss1.close();
}
}
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;
// 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);
int tha = 0;
for (Record r : s1.getSlideRecords()) {
- if (r instanceof TextHeaderAtom) tha++;
+ if (r instanceof TextHeaderAtom) {
+ tha++;
+ }
}
assertEquals(2, tha);
// 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);
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");
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();
StringBuffer sb = new StringBuffer();
for (char c = iterator.first();
- c != AttributedCharacterIterator.DONE;
+ c != CharacterIterator.DONE;
c = iterator.next()) {
sb.append(c);
attributes = iterator.getAttributes();
package org.apache.poi.hslf.usermodel;
-import java.util.List;
+import static org.junit.Assert.assertEquals;
-import junit.framework.TestCase;
+import java.io.IOException;
+import java.util.List;
-import org.apache.poi.POIDataSamples;
+import org.apache.poi.hslf.HSLFTestDataSamples;
+import org.junit.Test;
/**
* Tests that SlideShow returns the right number of Sheets and MetaSheets
- *
- * @author Nick Burch (nick at torchbox dot com)
*/
-public final class TestCounts extends TestCase {
- // SlideShow primed on the test data
- private final HSLFSlideShow ss;
-
- public TestCounts() throws Exception {
- POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
- HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt"));
- ss = new HSLFSlideShow(hss);
- }
-
- public void testSheetsCount() {
- List<HSLFSlide> slides = ss.getSlides();
+public final class TestCounts {
+ @Test
+ public void testSheetsCount() throws IOException {
+ HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt");
+
+ List<HSLFSlide> slides = ppt.getSlides();
// Two sheets - master sheet is separate
assertEquals(2, slides.size());
// 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
// 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();
}
}