浏览代码

#57766 - XSLFTable isn't exported on convert slides of a .pptx slide show to a PNG/SVG image

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1746856 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_15_BETA2
Andreas Beeker 8 年前
父节点
当前提交
65b2f6f23a
共有 21 个文件被更改,包括 890 次插入261 次删除
  1. 8
    0
      src/java/org/apache/poi/sl/draw/DrawFactory.java
  2. 44
    0
      src/java/org/apache/poi/sl/draw/DrawShape.java
  3. 1
    42
      src/java/org/apache/poi/sl/draw/DrawSimpleShape.java
  4. 95
    15
      src/java/org/apache/poi/sl/draw/DrawTableShape.java
  5. 30
    8
      src/java/org/apache/poi/sl/draw/DrawTextParagraph.java
  6. 17
    2
      src/java/org/apache/poi/sl/draw/DrawTextShape.java
  7. 28
    0
      src/java/org/apache/poi/sl/usermodel/TableCell.java
  8. 3
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java
  9. 16
    19
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java
  10. 3
    5
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java
  11. 119
    5
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java
  12. 287
    40
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java
  13. 3
    4
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableRow.java
  14. 41
    3
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableStyle.java
  15. 6
    3
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableStyles.java
  16. 33
    17
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java
  17. 1
    3
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
  18. 40
    29
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java
  19. 5
    12
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTableStyles.java
  20. 46
    37
      src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java
  21. 64
    17
      src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java

+ 8
- 0
src/java/org/apache/poi/sl/draw/DrawFactory.java 查看文件

defaultFactory.set(factory); defaultFactory.set(factory);
} }
/**
* Returns the DrawFactory, preferably via a graphics instance.
* If graphics is null, the current thread local is checked or
* if it is not set, a new factory is created.
*
* @param graphics the current graphics context or null
* @return the draw factory
*/
public static DrawFactory getInstance(Graphics2D graphics) { public static DrawFactory getInstance(Graphics2D graphics) {
// first try to find the factory over the rendering hint // first try to find the factory over the rendering hint
DrawFactory factory = null; DrawFactory factory = null;

+ 44
- 0
src/java/org/apache/poi/sl/draw/DrawShape.java 查看文件

package org.apache.poi.sl.draw; package org.apache.poi.sl.draw;
import java.awt.BasicStroke;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import org.apache.poi.sl.usermodel.PlaceableShape; import org.apache.poi.sl.usermodel.PlaceableShape;
import org.apache.poi.sl.usermodel.Shape; import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.StrokeStyle;
import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
public class DrawShape implements Drawable { public class DrawShape implements Drawable {
protected Shape<?,?> getShape() { protected Shape<?,?> getShape() {
return shape; return shape;
} }
protected static BasicStroke getStroke(StrokeStyle strokeStyle) {
float lineWidth = (float) strokeStyle.getLineWidth();
if (lineWidth == 0.0f) lineWidth = 0.25f; // Both PowerPoint and OOo draw zero-length lines as 0.25pt
LineDash lineDash = strokeStyle.getLineDash();
if (lineDash == null) {
lineDash = LineDash.SOLID;
}
int dashPatI[] = lineDash.pattern;
final float dash_phase = 0;
float[] dashPatF = null;
if (dashPatI != null) {
dashPatF = new float[dashPatI.length];
for (int i=0; i<dashPatI.length; i++) {
dashPatF[i] = dashPatI[i]*Math.max(1, lineWidth);
}
}
LineCap lineCapE = strokeStyle.getLineCap();
if (lineCapE == null) lineCapE = LineCap.FLAT;
int lineCap;
switch (lineCapE) {
case ROUND:
lineCap = BasicStroke.CAP_ROUND;
break;
case SQUARE:
lineCap = BasicStroke.CAP_SQUARE;
break;
default:
case FLAT:
lineCap = BasicStroke.CAP_BUTT;
break;
}
int lineJoin = BasicStroke.JOIN_ROUND;
return new BasicStroke(lineWidth, lineCap, lineJoin, lineWidth, dashPatF, dash_phase);
}
} }

+ 1
- 42
src/java/org/apache/poi/sl/draw/DrawSimpleShape.java 查看文件

import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.Shadow; import org.apache.poi.sl.usermodel.Shadow;
import org.apache.poi.sl.usermodel.SimpleShape; import org.apache.poi.sl.usermodel.SimpleShape;
import org.apache.poi.sl.usermodel.StrokeStyle;
import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
} }
public BasicStroke getStroke() { public BasicStroke getStroke() {
StrokeStyle strokeStyle = getShape().getStrokeStyle();
float lineWidth = (float) strokeStyle.getLineWidth();
if (lineWidth == 0.0f) lineWidth = 0.25f; // Both PowerPoint and OOo draw zero-length lines as 0.25pt
LineDash lineDash = strokeStyle.getLineDash();
if (lineDash == null) {
lineDash = LineDash.SOLID;
}
int dashPatI[] = lineDash.pattern;
final float dash_phase = 0;
float[] dashPatF = null;
if (dashPatI != null) {
dashPatF = new float[dashPatI.length];
for (int i=0; i<dashPatI.length; i++) {
dashPatF[i] = dashPatI[i]*Math.max(1, lineWidth);
}
}
LineCap lineCapE = strokeStyle.getLineCap();
if (lineCapE == null) lineCapE = LineCap.FLAT;
int lineCap;
switch (lineCapE) {
case ROUND:
lineCap = BasicStroke.CAP_ROUND;
break;
case SQUARE:
lineCap = BasicStroke.CAP_SQUARE;
break;
default:
case FLAT:
lineCap = BasicStroke.CAP_BUTT;
break;
}
int lineJoin = BasicStroke.JOIN_ROUND;
return new BasicStroke(lineWidth, lineCap, lineJoin, lineWidth, dashPatF, dash_phase);
return getStroke(getShape().getStrokeStyle());
} }
protected void drawShadow( protected void drawShadow(

+ 95
- 15
src/java/org/apache/poi/sl/draw/DrawTableShape.java 查看文件

import java.awt.Color; import java.awt.Color;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import org.apache.poi.sl.usermodel.GroupShape; import org.apache.poi.sl.usermodel.GroupShape;
import org.apache.poi.sl.usermodel.StrokeStyle;
import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound; import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
import org.apache.poi.sl.usermodel.TableCell; import org.apache.poi.sl.usermodel.TableCell;
import org.apache.poi.sl.usermodel.TableCell.BorderEdge; import org.apache.poi.sl.usermodel.TableCell.BorderEdge;
import org.apache.poi.util.Internal;
import org.apache.poi.sl.usermodel.TableShape; import org.apache.poi.sl.usermodel.TableShape;
public class DrawTableShape extends DrawShape { public class DrawTableShape extends DrawShape {
// to be implemented ...
/**
* Additional spacing between cells
*/
@Internal
public static final int borderSize = 2;
public DrawTableShape(TableShape<?,?> shape) { public DrawTableShape(TableShape<?,?> shape) {
super(shape); super(shape);
} }
protected Drawable getDrawable(Graphics2D graphics) {
protected Drawable getGroupShape(Graphics2D graphics) {
if (shape instanceof GroupShape) { if (shape instanceof GroupShape) {
DrawFactory df = DrawFactory.getInstance(graphics); DrawFactory df = DrawFactory.getInstance(graphics);
return df.getDrawable((GroupShape<?,?>)shape); return df.getDrawable((GroupShape<?,?>)shape);
} }
public void applyTransform(Graphics2D graphics) { public void applyTransform(Graphics2D graphics) {
Drawable d = getDrawable(graphics);
Drawable d = getGroupShape(graphics);
if (d != null) { if (d != null) {
d.applyTransform(graphics); d.applyTransform(graphics);
} else {
super.applyTransform(graphics);
} }
} }
public void draw(Graphics2D graphics) { public void draw(Graphics2D graphics) {
Drawable d = getDrawable(graphics);
Drawable d = getGroupShape(graphics);
if (d != null) { if (d != null) {
d.draw(graphics); d.draw(graphics);
return;
} }
TableShape<?,?> ts = getShape();
DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(ts);
final int rows = ts.getNumberOfRows();
final int cols = ts.getNumberOfColumns();
// draw background boxes
for (int row=0; row<rows; row++) {
for (int col=0; col<cols; col++) {
TableCell<?,?> tc = ts.getCell(row, col);
if (tc == null || tc.isMerged()) {
continue;
}
Paint fillPaint = drawPaint.getPaint(graphics, tc.getFillStyle().getPaint());
graphics.setPaint(fillPaint);
Rectangle2D cellAnc = tc.getAnchor();
graphics.fill(cellAnc);
for (BorderEdge edge : BorderEdge.values()) {
StrokeStyle stroke = tc.getBorderStyle(edge);
if (stroke == null) {
continue;
}
graphics.setStroke(getStroke(stroke));
Paint linePaint = drawPaint.getPaint(graphics, stroke.getPaint());
graphics.setPaint(linePaint);
double x=cellAnc.getX(), y=cellAnc.getY(), w=cellAnc.getWidth(), h=cellAnc.getHeight();
Line2D line;
switch (edge) {
default:
case bottom:
line = new Line2D.Double(x-borderSize, y+h, x+w+borderSize, y+h);
break;
case left:
line = new Line2D.Double(x, y, x, y+h+borderSize);
break;
case right:
line = new Line2D.Double(x+w, y, x+w, y+h+borderSize);
break;
case top:
line = new Line2D.Double(x-borderSize, y, x+w+borderSize, y);
break;
}
graphics.draw(line);
}
}
}
// draw text
drawContent(graphics);
} }
public void drawContent(Graphics2D graphics) { public void drawContent(Graphics2D graphics) {
Drawable d = getDrawable(graphics);
Drawable d = getGroupShape(graphics);
if (d != null) { if (d != null) {
d.drawContent(graphics); d.drawContent(graphics);
return;
}
TableShape<?,?> ts = getShape();
DrawFactory df = DrawFactory.getInstance(graphics);
final int rows = ts.getNumberOfRows();
final int cols = ts.getNumberOfColumns();
for (int row=0; row<rows; row++) {
for (int col=0; col<cols; col++) {
TableCell<?,?> tc = ts.getCell(row, col);
DrawTextShape dts = df.getDrawable(tc);
dts.drawContent(graphics);
}
} }
} }
@Override @Override
protected TableShape<?,?> getShape() { protected TableShape<?,?> getShape() {
return (TableShape<?,?>)shape; return (TableShape<?,?>)shape;
}
}
/** /**
* Format the table and apply the specified Line to all cell boundaries, * Format the table and apply the specified Line to all cell boundaries,
* both outside and inside. * both outside and inside.
TableShape<?,?> table = getShape(); TableShape<?,?> table = getShape();
final int rows = table.getNumberOfRows(); final int rows = table.getNumberOfRows();
final int cols = table.getNumberOfColumns(); final int cols = table.getNumberOfColumns();
BorderEdge edges[] = { BorderEdge.top, BorderEdge.left, null, null }; BorderEdge edges[] = { BorderEdge.top, BorderEdge.left, null, null };
for (int row = 0; row < rows; row++) { for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) { for (int col = 0; col < cols; col++) {
*/ */
public void setOutsideBorders(Object... args){ public void setOutsideBorders(Object... args){
if (args.length == 0) return; if (args.length == 0) return;
TableShape<?,?> table = getShape(); TableShape<?,?> table = getShape();
final int rows = table.getNumberOfRows(); final int rows = table.getNumberOfRows();
final int cols = table.getNumberOfColumns(); final int cols = table.getNumberOfColumns();
BorderEdge edges[] = new BorderEdge[4]; BorderEdge edges[] = new BorderEdge[4];
for (int row = 0; row < rows; row++) { for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) { for (int col = 0; col < cols; col++) {
*/ */
public void setInsideBorders(Object... args) { public void setInsideBorders(Object... args) {
if (args.length == 0) return; if (args.length == 0) return;
TableShape<?,?> table = getShape(); TableShape<?,?> table = getShape();
final int rows = table.getNumberOfRows(); final int rows = table.getNumberOfRows();
final int cols = table.getNumberOfColumns(); final int cols = table.getNumberOfColumns();
BorderEdge edges[] = new BorderEdge[2]; BorderEdge edges[] = new BorderEdge[2];
for (int row = 0; row < rows; row++) { for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) { for (int col = 0; col < cols; col++) {
} }
} }
} }
/** /**
* Apply the border attributes (args) to the given cell and edges * Apply the border attributes (args) to the given cell and edges
* *
} }
} }
} }
} }

+ 30
- 8
src/java/org/apache/poi/sl/draw/DrawTextParagraph.java 查看文件

package org.apache.poi.sl.draw; package org.apache.poi.sl.draw;
import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Paint; import java.awt.Paint;
import java.awt.font.FontRenderContext; import java.awt.font.FontRenderContext;
import org.apache.poi.sl.usermodel.TextRun; import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.sl.usermodel.TextRun.TextCap; import org.apache.poi.sl.usermodel.TextRun.TextCap;
import org.apache.poi.sl.usermodel.TextShape; import org.apache.poi.sl.usermodel.TextShape;
import org.apache.poi.sl.usermodel.TextShape.TextDirection;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
public class DrawTextParagraph implements Drawable { public class DrawTextParagraph implements Drawable {
/** Keys for passing hyperlinks to the graphics context */ /** Keys for passing hyperlinks to the graphics context */
public static final XlinkAttribute HYPERLINK_HREF = new XlinkAttribute("href"); public static final XlinkAttribute HYPERLINK_HREF = new XlinkAttribute("href");
* @return wrapping width in points * @return wrapping width in points
*/ */
protected double getWrappingWidth(boolean firstLine, Graphics2D graphics){ protected double getWrappingWidth(boolean firstLine, Graphics2D graphics){
// internal margins for the text box
TextShape<?,?> ts = paragraph.getParentShape();
Insets2D insets = paragraph.getParentShape().getInsets();
// internal margins for the text box
Insets2D insets = ts.getInsets();
double leftInset = insets.left; double leftInset = insets.left;
double rightInset = insets.right; double rightInset = insets.right;
Rectangle2D anchor = DrawShape.getAnchor(graphics, paragraph.getParentShape());
int indentLevel = paragraph.getIndentLevel(); int indentLevel = paragraph.getIndentLevel();
if (indentLevel == -1) { if (indentLevel == -1) {
// default to 0, if indentLevel is not set // default to 0, if indentLevel is not set
rightMargin = 0d; rightMargin = 0d;
} }
Rectangle2D anchor = DrawShape.getAnchor(graphics, ts);
TextDirection textDir = ts.getTextDirection();
double width; double width;
TextShape<?,?> ts = paragraph.getParentShape();
if (!ts.getWordWrap()) { if (!ts.getWordWrap()) {
// if wordWrap == false then we return the advance to the right border of the sheet
width = ts.getSheet().getSlideShow().getPageSize().getWidth() - anchor.getX();
Dimension pageDim = ts.getSheet().getSlideShow().getPageSize();
// if wordWrap == false then we return the advance to the (right) border of the sheet
switch (textDir) {
default:
width = pageDim.getWidth() - anchor.getX();
break;
case VERTICAL:
width = pageDim.getHeight() - anchor.getX();
break;
case VERTICAL_270:
width = anchor.getX();
break;
}
} else { } else {
width = anchor.getWidth() - leftInset - rightInset - leftMargin - rightMargin;
switch (textDir) {
default:
width = anchor.getWidth() - leftInset - rightInset - leftMargin - rightMargin;
break;
case VERTICAL:
case VERTICAL_270:
width = anchor.getHeight() - leftInset - rightInset - leftMargin - rightMargin;
break;
}
if (firstLine && !isHSLF()) { if (firstLine && !isHSLF()) {
if (bullet != null){ if (bullet != null){
if (indent > 0) width -= indent; if (indent > 0) width -= indent;

+ 17
- 2
src/java/org/apache/poi/sl/draw/DrawTextShape.java 查看文件

import org.apache.poi.sl.usermodel.TextParagraph.BulletStyle; import org.apache.poi.sl.usermodel.TextParagraph.BulletStyle;
import org.apache.poi.sl.usermodel.TextRun; import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.sl.usermodel.TextShape; import org.apache.poi.sl.usermodel.TextShape;
import org.apache.poi.sl.usermodel.TextShape.TextDirection;
public class DrawTextShape extends DrawSimpleShape { public class DrawTextShape extends DrawSimpleShape {
// remember the initial transform // remember the initial transform
AffineTransform tx = graphics.getTransform(); AffineTransform tx = graphics.getTransform();
// Transform of text in flipped shapes is special. // Transform of text in flipped shapes is special.
// At this point the flip and rotation transform is already applied // At this point the flip and rotation transform is already applied
// (see DrawShape#applyTransform ), but we need to restore it to avoid painting "upside down". // (see DrawShape#applyTransform ), but we need to restore it to avoid painting "upside down".
graphics.scale(-1, 1); graphics.scale(-1, 1);
graphics.translate(-anchor.getX(), -anchor.getY()); graphics.translate(-anchor.getX(), -anchor.getY());
} }
Double textRot = s.getTextRotation(); Double textRot = s.getTextRotation();
if (textRot != null && textRot != 0) { if (textRot != null && textRot != 0) {
graphics.translate(anchor.getCenterX(), anchor.getCenterY()); graphics.translate(anchor.getCenterX(), anchor.getCenterY());
break; break;
} }
TextDirection textDir = s.getTextDirection();
if (textDir == TextDirection.VERTICAL || textDir == TextDirection.VERTICAL_270) {
double deg = (textDir == TextDirection.VERTICAL) ? 90 : 270;
graphics.translate(anchor.getCenterX(), anchor.getCenterY());
graphics.rotate(Math.toRadians(deg));
graphics.translate(-anchor.getCenterX(), -anchor.getCenterY());
// old top/left edge is now bottom/left or top/right - as we operate on the already
// rotated drawing context, both verticals can be moved in the same direction
double w = anchor.getWidth();
double h = anchor.getHeight();
graphics.translate((w-h)/2d,(h-w)/2d);
}
drawParagraphs(graphics, x, y); drawParagraphs(graphics, x, y);
// restore the transform // restore the transform

+ 28
- 0
src/java/org/apache/poi/sl/usermodel/TableCell.java 查看文件

* @param edge the border edge to be cleared * @param edge the border edge to be cleared
*/ */
void removeBorder(BorderEdge edge); void removeBorder(BorderEdge edge);
/**
* Get the number of columns to be spanned/merged
*
* @return the grid span
*
* @since POI 3.15-beta2
*/
int getGridSpan();
/**
* Get the number of rows to be spanned/merged
*
* @return the row span
*
* @since POI 3.15-beta2
*/
int getRowSpan();
/**
* Return if this cell is part of a merged cell. The top/left cell of a merged region is not regarded as merged -
* its grid and/or row span is greater than one.
*
* @return true if this a merged cell
*
* @since POI 3.15-beta2
*/
boolean isMerged();
} }

+ 3
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java 查看文件

import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTFontReference;
import org.openxmlformats.schemas.drawingml.x2006.main.CTHslColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTHslColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveFixedPercentage; import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveFixedPercentage;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetColor;
color = Color.black; color = Color.black;
} }
} }
} else if (ch instanceof CTFontReference) {
// try next ...
} else { } else {
throw new IllegalArgumentException("Unexpected color choice: " + ch.getClass()); throw new IllegalArgumentException("Unexpected color choice: " + ch.getClass());
} }

+ 16
- 19
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java 查看文件

/** /**
* Base super-class class for all shapes in PresentationML * Base super-class class for all shapes in PresentationML
*
* @author Yegor Kozlov
*/ */
@Beta @Beta
public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
} }
protected PaintStyle getFillPaint() { protected PaintStyle getFillPaint() {
final XSLFTheme theme = getSheet().getTheme();
PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() { PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {
public boolean fetch(XSLFShape shape) { public boolean fetch(XSLFShape shape) {
XmlObject pr = null; XmlObject pr = null;
PaintStyle paint = null; PaintStyle paint = null;
PackagePart pp = getSheet().getPackagePart(); PackagePart pp = getSheet().getPackagePart();
for (XmlObject obj : pr.selectPath("*")) { for (XmlObject obj : pr.selectPath("*")) {
paint = selectPaint(obj, null, pp);
paint = selectPaint(obj, null, pp, theme);
if (paint != null) { if (paint != null) {
setValue(paint); setValue(paint);
return true; return true;
if (fillRef == null) { if (fillRef == null) {
fillRef = getBgRef(); fillRef = getBgRef();
} }
paint = selectPaint(fillRef);
paint = selectPaint(fillRef, theme);
return paint; return paint;
} }
protected PaintStyle getPaint(XmlObject spPr, CTSchemeColor phClr) { protected PaintStyle getPaint(XmlObject spPr, CTSchemeColor phClr) {
PaintStyle paint = null; PaintStyle paint = null;
PackagePart pp = getSheet().getPackagePart();
XSLFSheet sheet = getSheet();
PackagePart pp = sheet.getPackagePart();
XSLFTheme theme = sheet.getTheme();
for (XmlObject obj : spPr.selectPath("*")) { for (XmlObject obj : spPr.selectPath("*")) {
paint = selectPaint(obj, phClr, pp);
paint = selectPaint(obj, phClr, pp, theme);
if(paint != null) break; if(paint != null) break;
} }
return paint; return paint;
* *
* @return the applied Paint or null if none was applied * @return the applied Paint or null if none was applied
*/ */
protected PaintStyle selectPaint(XmlObject obj, final CTSchemeColor phClr, final PackagePart parentPart) {
protected static PaintStyle selectPaint(XmlObject obj, final CTSchemeColor phClr, final PackagePart parentPart, final XSLFTheme theme) {
if (obj instanceof CTNoFillProperties) { if (obj instanceof CTNoFillProperties) {
return null; return null;
} else if (obj instanceof CTSolidColorFillProperties) { } else if (obj instanceof CTSolidColorFillProperties) {
return selectPaint((CTSolidColorFillProperties)obj, phClr);
return selectPaint((CTSolidColorFillProperties)obj, phClr, theme);
} else if (obj instanceof CTBlipFillProperties) { } else if (obj instanceof CTBlipFillProperties) {
return selectPaint((CTBlipFillProperties)obj, parentPart); return selectPaint((CTBlipFillProperties)obj, parentPart);
} else if (obj instanceof CTGradientFillProperties) { } else if (obj instanceof CTGradientFillProperties) {
return selectPaint((CTGradientFillProperties) obj, phClr);
return selectPaint((CTGradientFillProperties) obj, phClr, theme);
} else if (obj instanceof CTStyleMatrixReference) { } else if (obj instanceof CTStyleMatrixReference) {
return selectPaint((CTStyleMatrixReference)obj);
return selectPaint((CTStyleMatrixReference)obj, theme);
} else { } else {
return null; return null;
} }
} }
protected PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr) {
final XSLFTheme theme = getSheet().getTheme();
protected static PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr, final XSLFTheme theme) {
if (phClr == null && solidFill.isSetSchemeClr()) { if (phClr == null && solidFill.isSetSchemeClr()) {
phClr = solidFill.getSchemeClr(); phClr = solidFill.getSchemeClr();
} }
return DrawPaint.createSolidPaint(c.getColorStyle()); return DrawPaint.createSolidPaint(c.getColorStyle());
} }
protected PaintStyle selectPaint(final CTBlipFillProperties blipFill, final PackagePart parentPart) {
protected static PaintStyle selectPaint(final CTBlipFillProperties blipFill, final PackagePart parentPart) {
final CTBlip blip = blipFill.getBlip(); final CTBlip blip = blipFill.getBlip();
return new TexturePaint() { return new TexturePaint() {
private PackagePart getPart() { private PackagePart getPart() {
}; };
} }
protected PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr) {
protected static PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr, final XSLFTheme theme) {
final CTGradientStop[] gs = gradFill.getGsLst().getGsArray(); final CTGradientStop[] gs = gradFill.getGsLst().getGsArray();
final ColorStyle cs[] = new ColorStyle[gs.length]; final ColorStyle cs[] = new ColorStyle[gs.length];
final float fractions[] = new float[gs.length]; final float fractions[] = new float[gs.length];
XSLFTheme theme = getSheet().getTheme();
int i=0; int i=0;
for (CTGradientStop cgs : gs) { for (CTGradientStop cgs : gs) {
}; };
} }
protected PaintStyle selectPaint(CTStyleMatrixReference fillRef) {
protected static PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme) {
if (fillRef == null) return null; if (fillRef == null) return null;
// The idx attribute refers to the index of a fill style or // The idx attribute refers to the index of a fill style or
// values 1001 and above refer to the index of a background fill style within the bgFillStyleLst element. // values 1001 and above refer to the index of a background fill style within the bgFillStyleLst element.
int idx = (int)fillRef.getIdx(); int idx = (int)fillRef.getIdx();
CTSchemeColor phClr = fillRef.getSchemeClr(); CTSchemeColor phClr = fillRef.getSchemeClr();
XSLFSheet sheet = getSheet();
XSLFTheme theme = sheet.getTheme();
XmlObject fillProps = null; XmlObject fillProps = null;
CTStyleMatrix matrix = theme.getXmlObject().getThemeElements().getFmtScheme(); CTStyleMatrix matrix = theme.getXmlObject().getThemeElements().getFmtScheme();
if (idx >= 1 && idx <= 999) { if (idx >= 1 && idx <= 999) {
} else if (idx >= 1001 ){ } else if (idx >= 1001 ){
fillProps = matrix.getBgFillStyleLst().selectPath("*")[idx - 1001]; fillProps = matrix.getBgFillStyleLst().selectPath("*")[idx - 1001];
} }
return (fillProps == null) ? null : selectPaint(fillProps, phClr, theme.getPackagePart());
return (fillProps == null) ? null : selectPaint(fillProps, phClr, theme.getPackagePart(), theme);
} }
@Override @Override

+ 3
- 5
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java 查看文件

/** /**
* Represents a single (non-group) shape in a .pptx slide show * Represents a single (non-group) shape in a .pptx slide show
*
* @author Yegor Kozlov
*/ */
@Beta @Beta
public abstract class XSLFSimpleShape extends XSLFShape public abstract class XSLFSimpleShape extends XSLFShape
} }
protected PaintStyle getLinePaint() { protected PaintStyle getLinePaint() {
final XSLFTheme theme = getSheet().getTheme();
PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() { PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {
public boolean fetch(XSLFShape shape) { public boolean fetch(XSLFShape shape) {
CTLineProperties spPr = shape.getSpPr().getLn(); CTLineProperties spPr = shape.getSpPr().getLn();
PaintStyle paint = null; PaintStyle paint = null;
PackagePart pp = getSheet().getPackagePart(); PackagePart pp = getSheet().getPackagePart();
for (XmlObject obj : spPr.selectPath("*")) { for (XmlObject obj : spPr.selectPath("*")) {
paint = selectPaint(obj, null, pp);
paint = selectPaint(obj, null, pp, theme);
if (paint != null) { if (paint != null) {
setValue(paint); setValue(paint);
return true; return true;
CTShapeStyle style = shape.getSpStyle(); CTShapeStyle style = shape.getSpStyle();
if (style != null) { if (style != null) {
paint = selectPaint(style.getLnRef());
paint = selectPaint(style.getLnRef(), theme);
if (paint != null) { if (paint != null) {
setValue(paint); setValue(paint);
return true; return true;
int idx = (int)lnRef.getIdx(); int idx = (int)lnRef.getIdx();
CTSchemeColor phClr = lnRef.getSchemeClr(); CTSchemeColor phClr = lnRef.getSchemeClr();
if(idx > 0){ if(idx > 0){
XSLFTheme theme = getSheet().getTheme();
XmlObject lnProps = theme.getXmlObject(). XmlObject lnProps = theme.getXmlObject().
getThemeElements().getFmtScheme().getLnStyleLst().selectPath("*")[idx - 1]; getThemeElements().getFmtScheme().getLnStyleLst().selectPath("*")[idx - 1];
paint = getPaint(lnProps, phClr); paint = getPaint(lnProps, phClr);

+ 119
- 5
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java 查看文件

import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import org.apache.poi.POIXMLException; import org.apache.poi.POIXMLException;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.DrawTableShape;
import org.apache.poi.sl.draw.DrawTextShape;
import org.apache.poi.sl.usermodel.TableShape; import org.apache.poi.sl.usermodel.TableShape;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
/** /**
* Represents a table in a .pptx presentation * Represents a table in a .pptx presentation
*
* @author Yegor Kozlov
*/ */
public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow>, public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow>,
TableShape<XSLFShape,XSLFTextParagraph> { TableShape<XSLFShape,XSLFTextParagraph> {
static String TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";
/* package */ static final String TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";
private CTTable _table; private CTTable _table;
private List<XSLFTableRow> _rows; private List<XSLFTableRow> _rows;
_table = (CTTable) rs[0]; _table = (CTTable) rs[0];
CTTableRow[] trArray = _table.getTrArray(); CTTableRow[] trArray = _table.getTrArray();
_rows = new ArrayList<XSLFTableRow>(trArray.length); _rows = new ArrayList<XSLFTableRow>(trArray.length);
for(CTTableRow row : trArray) _rows.add(new XSLFTableRow(row, this));
for(CTTableRow row : trArray) {
XSLFTableRow xr = new XSLFTableRow(row, this);
_rows.add(xr);
}
updateRowColIndexes();
} }
@Override @Override
public XSLFTableRow addRow(){ public XSLFTableRow addRow(){
CTTableRow tr = _table.addNewTr(); CTTableRow tr = _table.addNewTr();
XSLFTableRow row = new XSLFTableRow(tr, this); XSLFTableRow row = new XSLFTableRow(tr, this);
row.setHeight(20.0); // default height is 20 points
// default height is 20 points
row.setHeight(20.0);
_rows.add(row); _rows.add(row);
updateRowColIndexes();
return row; return row;
} }
} }
} }
} }
/**
* Get assigned TableStyle
*
* @return the assigned TableStyle
*
* @since POI 3.15-beta2
*/
protected XSLFTableStyle getTableStyle() {
CTTable tab = getCTTable();
// TODO: support inline table style
if (!tab.isSetTblPr() || !tab.getTblPr().isSetTableStyleId()) {
return null;
}
String styleId = tab.getTblPr().getTableStyleId();
XSLFTableStyles styles = getSheet().getSlideShow().getTableStyles();
for (XSLFTableStyle style : styles.getStyles()) {
if (style.getStyleId().equals(styleId)) {
return style;
}
}
return null;
}
/* package */ void updateRowColIndexes() {
int rowIdx = 0;
for (XSLFTableRow xr : this) {
int colIdx = 0;
for (XSLFTableCell tc : xr) {
tc.setRowColIndex(rowIdx, colIdx);
colIdx++;
}
rowIdx++;
}
}
/* package */ void updateCellAnchor() {
int rows = getNumberOfRows();
int cols = getNumberOfColumns();
double colWidths[] = new double[cols];
double rowHeights[] = new double[rows];
for (int row=0; row<rows; row++) {
rowHeights[row] = getRowHeight(row);
}
for (int col=0; col<cols; col++) {
colWidths[col] = getColumnWidth(col);
}
Rectangle2D tblAnc = getAnchor();
DrawFactory df = DrawFactory.getInstance(null);
double newY = tblAnc.getY();
// #1 pass - determine row heights, the height values might be too low or 0 ...
for (int row=0; row<rows; row++) {
double maxHeight = 0;
for (int col=0; col<cols; col++) {
XSLFTableCell tc = getCell(row, col);
if (tc.getGridSpan() != 1 || tc.getRowSpan() != 1) {
continue;
}
// need to set the anchor before height calculation
tc.setAnchor(new Rectangle2D.Double(0,0,colWidths[col],0));
DrawTextShape dts = df.getDrawable(tc);
maxHeight = Math.max(maxHeight, dts.getTextHeight());
}
rowHeights[row] = Math.max(rowHeights[row],maxHeight);
}
// #2 pass - init properties
for (int row=0; row<rows; row++) {
double newX = tblAnc.getX();
for (int col=0; col<cols; col++) {
Rectangle2D bounds = new Rectangle2D.Double(newX, newY, colWidths[col], rowHeights[row]);
XSLFTableCell tc = getCell(row, col);
tc.setAnchor(bounds);
newX += colWidths[col]+DrawTableShape.borderSize;
}
newY += rowHeights[row]+DrawTableShape.borderSize;
}
// #3 pass - update merge info
for (int row=0; row<rows; row++) {
for (int col=0; col<cols; col++) {
XSLFTableCell tc = getCell(row, col);
Rectangle2D mergedBounds = tc.getAnchor();
for (int col2=col+1; col2<col+tc.getGridSpan(); col2++) {
assert(col2 < cols);
XSLFTableCell tc2 = getCell(row, col2);
assert(tc2.getGridSpan() == 1 && tc2.getRowSpan() == 1);
mergedBounds.add(tc2.getAnchor());
}
for (int row2=row+1; row2<row+tc.getRowSpan(); row2++) {
assert(row2 < rows);
XSLFTableCell tc2 = getCell(row2, col);
assert(tc2.getGridSpan() == 1 && tc2.getRowSpan() == 1);
mergedBounds.add(tc2.getAnchor());
}
tc.setAnchor(mergedBounds);
}
}
}
} }

+ 287
- 40
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java 查看文件

package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import java.awt.Color; import java.awt.Color;
import java.awt.geom.Rectangle2D;
import org.apache.poi.sl.draw.DrawPaint; import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.PaintStyle; import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.TableCell; import org.apache.poi.sl.usermodel.TableCell;
import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
import org.apache.poi.xslf.usermodel.XSLFTableStyle.TablePartStyle;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTFontReference;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTable;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell; import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCellProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCellProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTablePartStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyleTextStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine; import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap; import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength; import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType; import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth; import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth;
import org.openxmlformats.schemas.drawingml.x2006.main.STOnOffStyleType;
import org.openxmlformats.schemas.drawingml.x2006.main.STPenAlignment; import org.openxmlformats.schemas.drawingml.x2006.main.STPenAlignment;
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
*/ */
public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,XSLFTextParagraph> { public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,XSLFTextParagraph> {
private CTTableCellProperties _tcPr = null; private CTTableCellProperties _tcPr = null;
private final XSLFTable table;
private int row = 0, col = 0;
/*package*/ XSLFTableCell(CTTableCell cell, XSLFSheet sheet){
super(cell, sheet);
/**
* Volatile/temporary anchor - e.g. for rendering
*/
private Rectangle2D anchor = null;
/*package*/ XSLFTableCell(CTTableCell cell, XSLFTable table){
super(cell, table.getSheet());
this.table = table;
} }
@Override @Override
protected CTTextBody getTextBody(boolean create){ protected CTTextBody getTextBody(boolean create){
CTTableCell cell = (CTTableCell)getXmlObject();
CTTableCell cell = getCell();
CTTextBody txBody = cell.getTxBody(); CTTextBody txBody = cell.getTxBody();
if (txBody == null && create) { if (txBody == null && create) {
txBody = cell.addNewTxBody(); txBody = cell.addNewTxBody();
protected CTTableCellProperties getCellProperties(boolean create) { protected CTTableCellProperties getCellProperties(boolean create) {
if (_tcPr == null) { if (_tcPr == null) {
CTTableCell cell = (CTTableCell)getXmlObject();
CTTableCell cell = getCell();
_tcPr = cell.getTcPr(); _tcPr = cell.getTcPr();
if (_tcPr == null && create) { if (_tcPr == null && create) {
_tcPr = cell.addNewTcPr(); _tcPr = cell.addNewTcPr();
} }
}; };
} }
@Override @Override
public void setBorderStyle(BorderEdge edge, StrokeStyle style) { public void setBorderStyle(BorderEdge edge, StrokeStyle style) {
if (style == null) { if (style == null) {
throw new IllegalArgumentException("StrokeStyle needs to be specified."); throw new IllegalArgumentException("StrokeStyle needs to be specified.");
} }
LineCap cap = style.getLineCap(); LineCap cap = style.getLineCap();
if (cap != null) { if (cap != null) {
setBorderCap(edge, cap); setBorderCap(edge, cap);
} }
LineCompound compound = style.getLineCompound(); LineCompound compound = style.getLineCompound();
if (compound != null) { if (compound != null) {
setBorderCompound(edge, compound); setBorderCompound(edge, compound);
} }
LineDash dash = style.getLineDash(); LineDash dash = style.getLineDash();
if (dash != null) { if (dash != null) {
setBorderDash(edge, dash); setBorderDash(edge, dash);
} }
double width = style.getLineWidth(); double width = style.getLineWidth();
setBorderWidth(edge, width); setBorderWidth(edge, width);
} }
} }
CTLineProperties ln = setBorderDefaults(edge); CTLineProperties ln = setBorderDefaults(edge);
CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
rgb.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});
ln.addNewSolidFill().setSrgbClr(rgb);
CTSolidColorFillProperties fill = ln.addNewSolidFill();
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
c.setColor(color);
} }
public Color getBorderColor(BorderEdge edge) { public Color getBorderColor(BorderEdge edge) {
if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) return null; if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) return null;
CTSolidColorFillProperties fill = ln.getSolidFill(); CTSolidColorFillProperties fill = ln.getSolidFill();
if (!fill.isSetSrgbClr()) {
// TODO for now return null for all colors except explicit RGB
return null;
}
byte[] val = fill.getSrgbClr().getVal();
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
return c.getColor();
} }
public LineCompound getBorderCompound(BorderEdge edge) { public LineCompound getBorderCompound(BorderEdge edge) {
if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCap()) { if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCap()) {
return null; return null;
} }
return LineCap.fromOoxmlId(ln.getCap().intValue()); return LineCap.fromOoxmlId(ln.getCap().intValue());
} }
CTTableCellProperties spPr = getCellProperties(true); CTTableCellProperties spPr = getCellProperties(true);
if (color == null) { if (color == null) {
if(spPr.isSetSolidFill()) spPr.unsetSolidFill(); if(spPr.isSetSolidFill()) spPr.unsetSolidFill();
}
else {
} else {
CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill(); CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill();
CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
rgb.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()});
fill.setSrgbClr(rgb);
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
c.setColor(color);
} }
} }
@Override @Override
public Color getFillColor(){ public Color getFillColor(){
CTTableCellProperties spPr = getCellProperties(false); CTTableCellProperties spPr = getCellProperties(false);
if (spPr == null || !spPr.isSetSolidFill()) return null;
if (spPr == null || !spPr.isSetSolidFill()) {
return null;
}
CTSolidColorFillProperties fill = spPr.getSolidFill(); CTSolidColorFillProperties fill = spPr.getSolidFill();
if (!fill.isSetSrgbClr()) {
// TODO for now return null for all colors except explicit RGB
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
return c.getColor();
}
@SuppressWarnings("resource")
@Override
public PaintStyle getFillPaint() {
Color c = getFillColor();
if (c != null) {
return DrawPaint.createSolidPaint(c);
}
CTTablePartStyle tps = getTablePartStyle(null);
if (tps == null || !tps.isSetTcStyle()) {
tps = getTablePartStyle(TablePartStyle.wholeTbl);
if (tps == null || !tps.isSetTcStyle()) {
return null;
}
}
XMLSlideShow slideShow = table.getSheet().getSlideShow();
assert(slideShow != null);
XSLFTheme theme = slideShow.getSlides().get(0).getTheme();
CTFillProperties pr = tps.getTcStyle().getFill();
for (XmlObject obj : pr.selectPath("*")) {
PaintStyle paint = XSLFShape.selectPaint(obj, null, slideShow.getPackagePart(), theme);
if (paint != null) {
return paint;
}
}
return null;
}
/**
* Retrieves the part style depending on the location of this cell
*
* @param tablePartStyle the part to be returned, usually this is null
* and only set when used as a helper method
* @return the table part style
*/
private CTTablePartStyle getTablePartStyle(TablePartStyle tablePartStyle) {
CTTable ct = table.getCTTable();
if (!ct.isSetTblPr()) {
return null;
}
CTTableProperties pr = ct.getTblPr();
boolean bandRow = (pr.isSetBandRow() && pr.getBandRow());
boolean firstRow = (pr.isSetFirstRow() && pr.getFirstRow());
boolean lastRow = (pr.isSetLastRow() && pr.getLastRow());
boolean bandCol = (pr.isSetBandCol() && pr.getBandCol());
boolean firstCol = (pr.isSetFirstCol() && pr.getFirstCol());
boolean lastCol = (pr.isSetLastCol() && pr.getLastCol());
TablePartStyle tps;
if (tablePartStyle != null) {
tps = tablePartStyle;
} else if (row == 0 && firstRow) {
tps = TablePartStyle.firstRow;
} else if (row == table.getNumberOfRows()-1 && lastRow) {
tps = TablePartStyle.lastRow;
} else if (col == 0 && firstCol) {
tps = TablePartStyle.firstCol;
} else if (col == table.getNumberOfColumns()-1 && lastCol) {
tps = TablePartStyle.lastCol;
} else {
tps = TablePartStyle.wholeTbl;
int br = row + (firstRow ? 1 : 0);
int bc = col + (firstCol ? 1 : 0);
if (bandRow && (br & 1) == 0) {
tps = TablePartStyle.band1H;
} else if (bandCol && (bc & 1) == 0) {
tps = TablePartStyle.band1V;
}
}
XSLFTableStyle tabStyle = table.getTableStyle();
if (tabStyle == null) {
return null; return null;
} }
byte[] val = fill.getSrgbClr().getVal();
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
CTTablePartStyle part = tabStyle.getTablePartStyle(tps);
return (part == null) ? tabStyle.getTablePartStyle(TablePartStyle.wholeTbl) : part;
} }
void setGridSpan(int gridSpan_) { void setGridSpan(int gridSpan_) {
((CTTableCell)getXmlObject()).setGridSpan(gridSpan_);
getCell().setGridSpan(gridSpan_);
}
@Override
public int getGridSpan() {
CTTableCell c = getCell();
return (c.isSetGridSpan()) ? c.getGridSpan() : 1;
} }
void setRowSpan(int rowSpan_) { void setRowSpan(int rowSpan_) {
((CTTableCell)getXmlObject()).setRowSpan(rowSpan_);
getCell().setRowSpan(rowSpan_);
}
@Override
public int getRowSpan() {
CTTableCell c = getCell();
return (c.isSetRowSpan()) ? c.getRowSpan() : 1;
} }
void setHMerge(boolean merge_) { void setHMerge(boolean merge_) {
((CTTableCell)getXmlObject()).setHMerge(merge_);
getCell().setHMerge(merge_);
} }
void setVMerge(boolean merge_) { void setVMerge(boolean merge_) {
((CTTableCell)getXmlObject()).setVMerge(merge_);
getCell().setVMerge(merge_);
} }
@Override @Override
vt = STTextVerticalType.WORD_ART_VERT; vt = STTextVerticalType.WORD_ART_VERT;
break; break;
} }
cellProps.setVert(vt); cellProps.setVert(vt);
} }
} }
} else { } else {
orientation = STTextVerticalType.HORZ; orientation = STTextVerticalType.HORZ;
} }
switch (orientation.intValue()) { switch (orientation.intValue()) {
default: default:
case STTextVerticalType.INT_HORZ: case STTextVerticalType.INT_HORZ:
return TextDirection.STACKED; return TextDirection.STACKED;
} }
} }
}
private CTTableCell getCell() {
return (CTTableCell)getXmlObject();
}
/* package */ void setRowColIndex(int row, int col) {
this.row = row;
this.col = col;
}
/**
* Return a fake-xfrm which is used for calculating the text height
*/
protected CTTransform2D getXfrm() {
Rectangle2D anc = getAnchor();
CTTransform2D xfrm = CTTransform2D.Factory.newInstance();
CTPoint2D off = xfrm.addNewOff();
off.setX(Units.toEMU(anc.getX()));
off.setY(Units.toEMU(anc.getY()));
CTPositiveSize2D size = xfrm.addNewExt();
size.setCx(Units.toEMU(anc.getWidth()));
size.setCy(Units.toEMU(anc.getHeight()));
return xfrm;
}
/**
* There's no real anchor for table cells - this method is used to temporarily store the location
* of the cell for a later retrieval, e.g. for rendering
*
* @since POI 3.15-beta2
*/
@Override
public void setAnchor(Rectangle2D anchor) {
if (this.anchor == null) {
this.anchor = (Rectangle2D)anchor.clone();
} else {
this.anchor.setRect(anchor);
}
}
/**
* @since POI 3.15-beta2
*/
@Override
public Rectangle2D getAnchor() {
if (anchor == null) {
table.updateCellAnchor();
}
// anchor should be set, after updateCellAnchor is through
assert(anchor != null);
return anchor;
}
/**
* @since POI 3.15-beta2
*/
@Override
public boolean isMerged() {
CTTableCell c = getCell();
return (c.isSetHMerge() && c.getHMerge()) || (c.isSetVMerge() && c.getVMerge());
}
/**
* @since POI 3.15-beta2
*/
@Override
protected XSLFCellTextParagraph newTextParagraph(CTTextParagraph p) {
return new XSLFCellTextParagraph(p, this);
}
/**
* @since POI 3.15-beta2
*/
private class XSLFCellTextParagraph extends XSLFTextParagraph {
protected XSLFCellTextParagraph(CTTextParagraph p, XSLFTextShape shape) {
super(p, shape);
}
@Override
protected XSLFCellTextRun newTextRun(CTRegularTextRun r) {
return new XSLFCellTextRun(r, this);
}
}
/**
* @since POI 3.15-beta2
*/
private class XSLFCellTextRun extends XSLFTextRun {
protected XSLFCellTextRun(CTRegularTextRun r, XSLFTextParagraph p) {
super(r, p);
}
@Override
public PaintStyle getFontColor(){
CTTableStyleTextStyle txStyle = getTextStyle();
if (txStyle == null) {
return super.getFontColor();
}
CTSchemeColor phClr = null;
CTFontReference fontRef = txStyle.getFontRef();
if (fontRef != null) {
phClr = fontRef.getSchemeClr();
}
XSLFTheme theme = getSheet().getTheme();
final XSLFColor c = new XSLFColor(txStyle, theme, phClr);
return DrawPaint.createSolidPaint(c.getColorStyle());
}
@Override
public boolean isBold() {
CTTableStyleTextStyle txStyle = getTextStyle();
if (txStyle == null) {
return super.isBold();
} else {
return txStyle.isSetB() && txStyle.getB().intValue() == STOnOffStyleType.INT_ON;
}
}
@Override
public boolean isItalic() {
CTTableStyleTextStyle txStyle = getTextStyle();
if (txStyle == null) {
return super.isItalic();
} else {
return txStyle.isSetI() && txStyle.getI().intValue() == STOnOffStyleType.INT_ON;
}
}
private CTTableStyleTextStyle getTextStyle() {
CTTablePartStyle tps = getTablePartStyle(null);
if (tps == null || !tps.isSetTcTxStyle()) {
tps = getTablePartStyle(TablePartStyle.wholeTbl);
}
return (tps == null) ? null : tps.getTcTxStyle();
}
}
}

+ 3
- 4
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableRow.java 查看文件

/** /**
* Represents a table in a .pptx presentation * Represents a table in a .pptx presentation
*
* @author Yegor Kozlov
*/ */
public class XSLFTableRow implements Iterable<XSLFTableCell> { public class XSLFTableRow implements Iterable<XSLFTableCell> {
private CTTableRow _row; private CTTableRow _row;
CTTableCell[] tcArray = _row.getTcArray(); CTTableCell[] tcArray = _row.getTcArray();
_cells = new ArrayList<XSLFTableCell>(tcArray.length); _cells = new ArrayList<XSLFTableCell>(tcArray.length);
for(CTTableCell cell : tcArray) { for(CTTableCell cell : tcArray) {
_cells.add(new XSLFTableCell(cell, table.getSheet()));
_cells.add(new XSLFTableCell(cell, table));
} }
} }
public XSLFTableCell addCell(){ public XSLFTableCell addCell(){
CTTableCell c = _row.addNewTc(); CTTableCell c = _row.addNewTc();
c.set(XSLFTableCell.prototype()); c.set(XSLFTableCell.prototype());
XSLFTableCell cell = new XSLFTableCell(c, _table.getSheet());
XSLFTableCell cell = new XSLFTableCell(c, _table);
_cells.add(cell); _cells.add(cell);
if(_table.getNumberOfColumns() < _row.sizeOfTcArray()) { if(_table.getNumberOfColumns() < _row.sizeOfTcArray()) {
_table.getCTTable().getTblGrid().addNewGridCol().setW(Units.toEMU(100.0)); _table.getCTTable().getTblGrid().addNewGridCol().setW(Units.toEMU(100.0));
} }
_table.updateRowColIndexes();
return cell; return cell;
} }

+ 41
- 3
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableStyle.java 查看文件

package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTablePartStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle; import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle;
/** /**
* Represents a table in a .pptx presentation
*
* @author Yegor Kozlov
* Represents a table style in a .pptx presentation
*/ */
public class XSLFTableStyle { public class XSLFTableStyle {
private CTTableStyle _tblStyle; private CTTableStyle _tblStyle;
public enum TablePartStyle {
wholeTbl, band1H, band2H, band1V, band2V, firstCol, lastCol, firstRow, lastRow, seCell, swCell, neCell, nwCell;
}
/*package*/ XSLFTableStyle(CTTableStyle style){ /*package*/ XSLFTableStyle(CTTableStyle style){
_tblStyle = style; _tblStyle = style;
} }
public String getStyleId(){ public String getStyleId(){
return _tblStyle.getStyleId(); return _tblStyle.getStyleId();
} }
/**
* @since POI 3.15-beta2
*/
protected CTTablePartStyle getTablePartStyle(TablePartStyle tps) {
switch (tps) {
default:
case wholeTbl:
return _tblStyle.getWholeTbl();
case band1H:
return _tblStyle.getBand1H();
case band2H:
return _tblStyle.getBand2H();
case band1V:
return _tblStyle.getBand1V();
case band2V:
return _tblStyle.getBand2V();
case firstCol:
return _tblStyle.getFirstCol();
case lastCol:
return _tblStyle.getLastCol();
case firstRow:
return _tblStyle.getFirstRow();
case lastRow:
return _tblStyle.getLastRow();
case seCell:
return _tblStyle.getSeCell();
case swCell:
return _tblStyle.getSwCell();
case neCell:
return _tblStyle.getNeCell();
case nwCell:
return _tblStyle.getNwCell();
}
}
} }

+ 6
- 3
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableStyles.java 查看文件

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


import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;

import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle; import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyleList; import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyleList;
import org.openxmlformats.schemas.drawingml.x2006.main.TblStyleLstDocument;


@Beta @Beta
public class XSLFTableStyles extends POIXMLDocumentPart implements Iterable<XSLFTableStyle>{ public class XSLFTableStyles extends POIXMLDocumentPart implements Iterable<XSLFTableStyle>{
public XSLFTableStyles(PackagePart part) throws IOException, XmlException { public XSLFTableStyles(PackagePart part) throws IOException, XmlException {
super(part); super(part);


_tblStyleLst = CTTableStyleList.Factory.parse(getPackagePart().getInputStream(), DEFAULT_XML_OPTIONS);
InputStream is = getPackagePart().getInputStream();
TblStyleLstDocument styleDoc = TblStyleLstDocument.Factory.parse(is);
is.close();
_tblStyleLst = styleDoc.getTblStyleLst();
CTTableStyle[] tblStyleArray = _tblStyleLst.getTblStyleArray(); CTTableStyle[] tblStyleArray = _tblStyleLst.getTblStyleArray();
_styles = new ArrayList<XSLFTableStyle>(tblStyleArray.length); _styles = new ArrayList<XSLFTableStyle>(tblStyleArray.length);
for(CTTableStyle c : tblStyleArray){ for(CTTableStyle c : tblStyleArray){

+ 33
- 17
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java 查看文件

* Represents a paragraph of text within the containing text body. * Represents a paragraph of text within the containing text body.
* The paragraph is the highest level text separation mechanism. * The paragraph is the highest level text separation mechanism.
* *
* @author Yegor Kozlov
* @since POI-3.8 * @since POI-3.8
*/ */
@Beta @Beta
for(XmlObject ch : _p.selectPath("*")){ for(XmlObject ch : _p.selectPath("*")){
if(ch instanceof CTRegularTextRun){ if(ch instanceof CTRegularTextRun){
CTRegularTextRun r = (CTRegularTextRun)ch; CTRegularTextRun r = (CTRegularTextRun)ch;
_runs.add(new XSLFTextRun(r, this));
_runs.add(newTextRun(r));
} else if (ch instanceof CTTextLineBreak){ } else if (ch instanceof CTTextLineBreak){
CTTextLineBreak br = (CTTextLineBreak)ch; CTTextLineBreak br = (CTTextLineBreak)ch;
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance(); CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
r.setRPr(br.getRPr()); r.setRPr(br.getRPr());
r.setT("\n"); r.setT("\n");
_runs.add(new XSLFTextRun(r, this));
_runs.add(newTextRun(r));
} else if (ch instanceof CTTextField){ } else if (ch instanceof CTTextField){
CTTextField f = (CTTextField)ch; CTTextField f = (CTTextField)ch;
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance(); CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
r.setRPr(f.getRPr()); r.setRPr(f.getRPr());
r.setT(f.getT()); r.setT(f.getT());
_runs.add(new XSLFTextRun(r, this));
_runs.add(newTextRun(r));
} }
} }
} }
CTRegularTextRun r = _p.addNewR(); CTRegularTextRun r = _p.addNewR();
CTTextCharacterProperties rPr = r.addNewRPr(); CTTextCharacterProperties rPr = r.addNewRPr();
rPr.setLang("en-US"); rPr.setLang("en-US");
XSLFTextRun run = new XSLFTextRun(r, this);
XSLFTextRun run = newTextRun(r);
_runs.add(run); _runs.add(run);
return run; return run;
} }
int level = getIndentLevel(); int level = getIndentLevel();
// wind up and find the root master sheet which must be slide master // wind up and find the root master sheet which must be slide master
final String nsDecl =
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " +
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' ";
final String xpaths[] = {
nsDecl+".//p:txStyles/p:" + defaultStyleSelector +"/a:lvl" +(level+1)+ "pPr",
nsDecl+".//p:notesStyle/a:lvl" +(level+1)+ "pPr"
};
final String nsPML = "http://schemas.openxmlformats.org/presentationml/2006/main";
final String nsDML = "http://schemas.openxmlformats.org/drawingml/2006/main";
XSLFSheet masterSheet = _shape.getSheet(); XSLFSheet masterSheet = _shape.getSheet();
for (XSLFSheet m = masterSheet; m != null; m = (XSLFSheet)m.getMasterSheet()) { for (XSLFSheet m = masterSheet; m != null; m = (XSLFSheet)m.getMasterSheet()) {
masterSheet = m; masterSheet = m;
XmlObject xo = masterSheet.getXmlObject(); XmlObject xo = masterSheet.getXmlObject();
for (String xpath : xpaths) {
XmlObject[] o = xo.selectPath(xpath);
if (o.length == 1) {
return (CTTextParagraphProperties)o[0];
XmlCursor cur = xo.newCursor();
try {
cur.push();
if ((cur.toChild(nsPML, "txStyles") && cur.toChild(nsPML, defaultStyleSelector)) ||
(cur.pop() && cur.toChild(nsPML, "notesStyle"))) {
if (cur.toChild(nsDML, "lvl" +(level+1)+ "pPr")) {
return (CTTextParagraphProperties)cur.getObject();
}
} }
} finally {
cur.dispose();
} }
} }
List<XSLFTextRun> otherRs = other.getTextRuns(); List<XSLFTextRun> otherRs = other.getTextRuns();
int i=0; int i=0;
for(CTRegularTextRun rtr : thisP.getRArray()) { for(CTRegularTextRun rtr : thisP.getRArray()) {
XSLFTextRun run = new XSLFTextRun(rtr, this);
XSLFTextRun run = newTextRun(rtr);
run.copy(otherRs.get(i++)); run.copy(otherRs.get(i++));
_runs.add(run); _runs.add(run);
} }
@Override @Override
public Double getDefaultFontSize() { public Double getDefaultFontSize() {
CTTextCharacterProperties endPr = _p.getEndParaRPr(); CTTextCharacterProperties endPr = _p.getEndParaRPr();
if (endPr == null || !endPr.isSetSz()) {
endPr = getDefaultMasterStyle().getDefRPr();
}
return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100.); return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100.);
} }
return false; return false;
} }
} }
/**
* Helper method to allow subclasses to provide their own text run
*
* @param r the xml reference
*
* @return a new text paragraph
*
* @since POI 3.15-beta2
*/
protected XSLFTextRun newTextRun(CTRegularTextRun r) {
return new XSLFTextRun(r, this);
}
} }

+ 1
- 3
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java 查看文件

/** /**
* Represents a run of text within the containing text body. The run element is the * Represents a run of text within the containing text body. The run element is the
* lowest level text separation mechanism within a text body. * lowest level text separation mechanism within a text body.
*
* @author Yegor Kozlov
*/ */
@Beta @Beta
public class XSLFTextRun implements TextRun { public class XSLFTextRun implements TextRun {
private final CTRegularTextRun _r; private final CTRegularTextRun _r;
private final XSLFTextParagraph _p; private final XSLFTextParagraph _p;
XSLFTextRun(CTRegularTextRun r, XSLFTextParagraph p){
protected XSLFTextRun(CTRegularTextRun r, XSLFTextParagraph p){
_r = r; _r = r;
_p = p; _p = p;
} }

+ 40
- 29
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java 查看文件

CTTextBody txBody = getTextBody(false); CTTextBody txBody = getTextBody(false);
if (txBody != null) { if (txBody != null) {
for (CTTextParagraph p : txBody.getPArray()) { for (CTTextParagraph p : txBody.getPArray()) {
_paragraphs.add(new XSLFTextParagraph(p, this));
_paragraphs.add(newTextParagraph(p));
} }
} }
} }
txBody.removeP(i-1); txBody.removeP(i-1);
_paragraphs.remove(i-1); _paragraphs.remove(i-1);
} }
_paragraphs.get(0).clearButKeepProperties(); _paragraphs.get(0).clearButKeepProperties();
} }
return appendText(text, false); return appendText(text, false);
} }
@Override @Override
public XSLFTextRun appendText(String text, boolean newParagraph) { public XSLFTextRun appendText(String text, boolean newParagraph) {
if (text == null) return null; if (text == null) return null;
// copy properties from last paragraph / textrun or paragraph end marker // copy properties from last paragraph / textrun or paragraph end marker
CTTextParagraphProperties pPr = null; CTTextParagraphProperties pPr = null;
CTTextCharacterProperties rPr = null; CTTextCharacterProperties rPr = null;
boolean firstPara; boolean firstPara;
XSLFTextParagraph para; XSLFTextParagraph para;
if (_paragraphs.isEmpty()) { if (_paragraphs.isEmpty()) {
rPr = ctp.getEndParaRPr(); rPr = ctp.getEndParaRPr();
} }
} }
XSLFTextRun run = null; XSLFTextRun run = null;
for (String lineTxt : text.split("\\r\\n?|\\n")) { for (String lineTxt : text.split("\\r\\n?|\\n")) {
if (!firstPara) { if (!firstPara) {
} }
firstPara = false; firstPara = false;
} }
assert(run != null); assert(run != null);
return run; return run;
} }
} else { } else {
p = txBody.addNewP(); p = txBody.addNewP();
} }
XSLFTextParagraph paragraph = new XSLFTextParagraph(p, this);
XSLFTextParagraph paragraph = newTextParagraph(p);
_paragraphs.add(paragraph); _paragraphs.add(paragraph);
return paragraph; return paragraph;
} }
fetchShapeProperty(fetcher); fetchShapeProperty(fetcher);
return fetcher.getValue() == null ? false : fetcher.getValue(); return fetcher.getValue() == null ? false : fetcher.getValue();
} }
@Override @Override
public void setTextDirection(TextDirection orientation){ public void setTextDirection(TextDirection orientation){
CTTextBodyProperties bodyPr = getTextBodyPr(true); CTTextBodyProperties bodyPr = getTextBodyPr(true);
if (bodyPr != null && bodyPr.isSetRot()) { if (bodyPr != null && bodyPr.isSetRot()) {
return bodyPr.getRot() / 60000.; return bodyPr.getRot() / 60000.;
} }
return null;
return null;
} }
@Override @Override
public void setTextRotation(Double rotation) { public void setTextRotation(Double rotation) {
CTTextBodyProperties bodyPr = getTextBodyPr(true); CTTextBodyProperties bodyPr = getTextBodyPr(true);
bodyPr.setRot((int)(rotation * 60000.)); bodyPr.setRot((int)(rotation * 60000.));
} }
} }
/** /**
* Returns the distance (in points) between the bottom of the text frame * Returns the distance (in points) between the bottom of the text frame
* and the bottom of the inscribed rectangle of the shape that contains the text. * and the bottom of the inscribed rectangle of the shape that contains the text.
Insets2D insets = new Insets2D(getTopInset(), getLeftInset(), getBottomInset(), getRightInset()); Insets2D insets = new Insets2D(getTopInset(), getLeftInset(), getBottomInset(), getRightInset());
return insets; return insets;
} }
@Override @Override
public void setInsets(Insets2D insets) { public void setInsets(Insets2D insets) {
setTopInset(insets.top); setTopInset(insets.top);
setBottomInset(insets.bottom); setBottomInset(insets.bottom);
setRightInset(insets.right); setRightInset(insets.right);
} }
@Override @Override
public boolean getWordWrap(){ public boolean getWordWrap(){
PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>(){ PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>(){
} }
return textBodyPr; return textBodyPr;
} }
protected abstract CTTextBody getTextBody(boolean create); protected abstract CTTextBody getTextBody(boolean create);


@Override @Override
public void setPlaceholder(Placeholder placeholder) { public void setPlaceholder(Placeholder placeholder) {
super.setPlaceholder(placeholder); super.setPlaceholder(placeholder);
} }
public Placeholder getTextType(){ public Placeholder getTextType(){
CTPlaceholder ph = getCTPlaceholder(); CTPlaceholder ph = getCTPlaceholder();
if (ph == null) return null; if (ph == null) return null;
Rectangle2D anchor = getAnchor(); Rectangle2D anchor = getAnchor();
if(anchor.getWidth() == 0.) throw new POIXMLException( if(anchor.getWidth() == 0.) throw new POIXMLException(
"Anchor of the shape was not set."); "Anchor of the shape was not set.");
double height = getTextHeight();
double height = getTextHeight();
height += 1; // add a pixel to compensate rounding errors height += 1; // add a pixel to compensate rounding errors
anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height); anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height);
setAnchor(anchor); setAnchor(anchor);
return anchor; return anchor;
}
}


@Override @Override
void copy(XSLFShape other){ void copy(XSLFShape other){
if (otherTB == null) { if (otherTB == null) {
return; return;
} }
thisTB.setBodyPr((CTTextBodyProperties)otherTB.getBodyPr().copy()); thisTB.setBodyPr((CTTextBodyProperties)otherTB.getBodyPr().copy());


if (thisTB.isSetLstStyle()) thisTB.unsetLstStyle(); if (thisTB.isSetLstStyle()) thisTB.unsetLstStyle();
if (otherTB.isSetLstStyle()) { if (otherTB.isSetLstStyle()) {
thisTB.setLstStyle((CTTextListStyle)otherTB.getLstStyle().copy()); thisTB.setLstStyle((CTTextListStyle)otherTB.getLstStyle().copy());
} }
boolean srcWordWrap = otherTS.getWordWrap(); boolean srcWordWrap = otherTS.getWordWrap();
if(srcWordWrap != getWordWrap()){ if(srcWordWrap != getWordWrap()){
setWordWrap(srcWordWrap); setWordWrap(srcWordWrap);
} }


clearText(); clearText();
for (XSLFTextParagraph srcP : otherTS.getTextParagraphs()) { for (XSLFTextParagraph srcP : otherTS.getTextParagraphs()) {
XSLFTextParagraph tgtP = addNewTextParagraph(); XSLFTextParagraph tgtP = addNewTextParagraph();
tgtP.copy(srcP); tgtP.copy(srcP);
default: default:
case NOTES: case NOTES:
case HALF_BODY: case HALF_BODY:
case QUARTER_BODY:
case QUARTER_BODY:
case BODY: case BODY:
setPlaceholder(Placeholder.BODY); setPlaceholder(Placeholder.BODY);
break; break;
case CENTERED_TITLE: return TextPlaceholder.CENTER_TITLE; case CENTERED_TITLE: return TextPlaceholder.CENTER_TITLE;
default: default:
case CONTENT: return TextPlaceholder.OTHER; case CONTENT: return TextPlaceholder.OTHER;
}
}
}

/**
* Helper method to allow subclasses to provide their own text paragraph
*
* @param p the xml reference
*
* @return a new text paragraph
*
* @since POI 3.15-beta2
*/
protected XSLFTextParagraph newTextParagraph(CTTextParagraph p) {
return new XSLFTextParagraph(p, this);
} }
} }

+ 5
- 12
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTableStyles.java 查看文件

import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import java.io.IOException;
import org.junit.Test; import org.junit.Test;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle;
/**
* @author Yegor Kozlov
*/
public class TestXSLFTableStyles { public class TestXSLFTableStyles {
@Test @Test
public void testRead(){
public void testRead() throws IOException {
XMLSlideShow ppt = new XMLSlideShow(); XMLSlideShow ppt = new XMLSlideShow();
XSLFTableStyles tblStyles = ppt.getTableStyles(); XSLFTableStyles tblStyles = ppt.getTableStyles();
assertNotNull(tblStyles); assertNotNull(tblStyles);
assertEquals(0, tblStyles.getStyles().size()); assertEquals(0, tblStyles.getStyles().size());
}
@SuppressWarnings("unused")
@Test
public void testStyle(){
CTTableStyle obj = CTTableStyle.Factory.newInstance();
XSLFTableStyle style = new XSLFTableStyle(obj);
ppt.close();
} }
} }

+ 46
- 37
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java 查看文件

package org.apache.poi.hslf.usermodel; package org.apache.poi.hslf.usermodel;


import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;


import org.apache.poi.ddf.AbstractEscherOptRecord; import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherArrayProperty; import org.apache.poi.ddf.EscherArrayProperty;
updateRowHeightsProperty(); updateRowHeightsProperty();
} }


private static class TableCellComparator implements Comparator<HSLFShape>, Serializable {
public int compare( HSLFShape o1, HSLFShape o2 ) {
Rectangle2D anchor1 = o1.getAnchor();
Rectangle2D anchor2 = o2.getAnchor();
double delta = anchor1.getY() - anchor2.getY();
if (delta == 0) {
delta = anchor1.getX() - anchor2.getX();
}
// descending size
if (delta == 0) {
delta = (anchor2.getWidth()*anchor2.getHeight())-(anchor1.getWidth()*anchor1.getHeight());
}
return (int)Math.signum(delta);
}
}

private void cellListToArray() { private void cellListToArray() {
List<HSLFTableCell> htc = new ArrayList<HSLFTableCell>(); List<HSLFTableCell> htc = new ArrayList<HSLFTableCell>();
for (HSLFShape h : getShapes()) { for (HSLFShape h : getShapes()) {
if (htc.isEmpty()) { if (htc.isEmpty()) {
throw new IllegalStateException("HSLFTable without HSLFTableCells"); throw new IllegalStateException("HSLFTable without HSLFTableCells");
} }

Collections.sort(htc, new TableCellComparator());

List<HSLFTableCell[]> lst = new ArrayList<HSLFTableCell[]>();
List<HSLFTableCell> row = new ArrayList<HSLFTableCell>();

double y0 = htc.get(0).getAnchor().getY();
SortedSet<Double> colSet = new TreeSet<Double>();
SortedSet<Double> rowSet = new TreeSet<Double>();
// #1 pass - determine cols and rows
for (HSLFTableCell sh : htc) { for (HSLFTableCell sh : htc) {
Rectangle2D anchor = sh.getAnchor(); Rectangle2D anchor = sh.getAnchor();
boolean isNextRow = (anchor.getY() > y0);
if (isNextRow) {
y0 = anchor.getY();
lst.add(row.toArray(new HSLFTableCell[row.size()]));
row.clear();
}
row.add(sh);
colSet.add(anchor.getX());
rowSet.add(anchor.getY());
} }
lst.add(row.toArray(new HSLFTableCell[row.size()]));

cells = lst.toArray(new HSLFTableCell[lst.size()][]);
cells = new HSLFTableCell[rowSet.size()][colSet.size()];
List<Double> colLst = new ArrayList<Double>(colSet);
List<Double> rowLst = new ArrayList<Double>(rowSet);
// #2 pass - assign shape to table cells
for (HSLFTableCell sh : htc) {
Rectangle2D anchor = sh.getAnchor();
int row = rowLst.indexOf(anchor.getY());
int col = colLst.indexOf(anchor.getX());
assert(row != -1 && col != -1);
cells[row][col] = sh;
// determine gridSpan / rowSpan
int gridSpan = calcSpan(colLst, anchor.getWidth(), col);
int rowSpan = calcSpan(rowLst, anchor.getHeight(), row);
sh.setGridSpan(gridSpan);
sh.setRowSpan(rowSpan);
}
} }


private int calcSpan(List<Double> spaces, double totalSpace, int idx) {
if (idx == spaces.size()-1) {
return 1;
}
int span = 0;
double remainingSpace = totalSpace;
while (idx+1 < spaces.size() && remainingSpace > 0) {
remainingSpace -= spaces.get(idx+1)-spaces.get(idx);
span++;
idx++;
}
return span;
}
static class LineRect { static class LineRect {
final HSLFLine l; final HSLFLine l;
final double lx1, lx2, ly1, ly2; final double lx1, lx2, ly1, ly2;
// TODO: this only works for non-rotated tables // TODO: this only works for non-rotated tables
for (HSLFTableCell[] tca : cells) { for (HSLFTableCell[] tca : cells) {
for (HSLFTableCell tc : tca) { for (HSLFTableCell tc : tca) {
if (tc == null) {
continue;
}
final Rectangle2D cellAnchor = tc.getAnchor(); final Rectangle2D cellAnchor = tc.getAnchor();


/** /**

+ 64
- 17
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java 查看文件



/** /**
* Represents a cell in a ppt table * Represents a cell in a ppt table
*
* @author Yegor Kozlov
*/ */
public final class HSLFTableCell extends HSLFTextBox implements TableCell<HSLFShape,HSLFTextParagraph> { public final class HSLFTableCell extends HSLFTextBox implements TableCell<HSLFShape,HSLFTextParagraph> {
protected static final int DEFAULT_WIDTH = 100; protected static final int DEFAULT_WIDTH = 100;
/* package */ HSLFLine borderTop; /* package */ HSLFLine borderTop;
/* package */ HSLFLine borderBottom; /* package */ HSLFLine borderBottom;


/**
* The number of columns to be spanned/merged
*/
private int gridSpan = 1;

/**
* The number of columns to be spanned/merged
*/
private int rowSpan = 1;

/** /**
* Create a TableCell object and initialize it from the supplied Record container. * Create a TableCell object and initialize it from the supplied Record container.
* *


@Override @Override
public StrokeStyle getBorderStyle(final BorderEdge edge) { public StrokeStyle getBorderStyle(final BorderEdge edge) {
final Double width = getBorderWidth(edge);
final Double width = getBorderWidth(edge);
return (width == null) ? null : new StrokeStyle() { return (width == null) ? null : new StrokeStyle() {
public PaintStyle getPaint() { public PaintStyle getPaint() {
return DrawPaint.createSolidPaint(getBorderColor(edge)); return DrawPaint.createSolidPaint(getBorderColor(edge));
if (style == null) { if (style == null) {
throw new IllegalArgumentException("StrokeStyle needs to be specified."); throw new IllegalArgumentException("StrokeStyle needs to be specified.");
} }
// setting the line cap is not implemented, as the border lines aren't connected // setting the line cap is not implemented, as the border lines aren't connected
LineCompound compound = style.getLineCompound(); LineCompound compound = style.getLineCompound();
if (compound != null) { if (compound != null) {
setBorderCompound(edge, compound); setBorderCompound(edge, compound);
} }
LineDash dash = style.getLineDash(); LineDash dash = style.getLineDash();
if (dash != null) { if (dash != null) {
setBorderDash(edge, dash); setBorderDash(edge, dash);
} }
double width = style.getLineWidth(); double width = style.getLineWidth();
setBorderWidth(edge, width); setBorderWidth(edge, width);
} }


public Double getBorderWidth(BorderEdge edge) { public Double getBorderWidth(BorderEdge edge) {
HSLFLine l; HSLFLine l;
switch (edge) { switch (edge) {
} }
return (l == null) ? null : l.getLineWidth(); return (l == null) ? null : l.getLineWidth();
} }
@Override @Override
public void setBorderWidth(BorderEdge edge, double width) { public void setBorderWidth(BorderEdge edge, double width) {
HSLFLine l = addLine(edge); HSLFLine l = addLine(edge);
if (edge == null || color == null) { if (edge == null || color == null) {
throw new IllegalArgumentException("BorderEdge and/or Color need to be specified."); throw new IllegalArgumentException("BorderEdge and/or Color need to be specified.");
} }
HSLFLine l = addLine(edge); HSLFLine l = addLine(edge);
l.setLineColor(color); l.setLineColor(color);
} }
case left: l = borderLeft; break; case left: l = borderLeft; break;
default: throw new IllegalArgumentException(); default: throw new IllegalArgumentException();
} }
return (l == null) ? null : l.getLineDash();
return (l == null) ? null : l.getLineDash();
} }
@Override @Override
public void setBorderDash(BorderEdge edge, LineDash dash) { public void setBorderDash(BorderEdge edge, LineDash dash) {
if (edge == null || dash == null) { if (edge == null || dash == null) {
throw new IllegalArgumentException("BorderEdge and/or LineDash need to be specified."); throw new IllegalArgumentException("BorderEdge and/or LineDash need to be specified.");
} }
HSLFLine l = addLine(edge); HSLFLine l = addLine(edge);
l.setLineDash(dash); l.setLineDash(dash);
} }
case left: l = borderLeft; break; case left: l = borderLeft; break;
default: throw new IllegalArgumentException(); default: throw new IllegalArgumentException();
} }
return (l == null) ? null : l.getLineCompound();
return (l == null) ? null : l.getLineCompound();
} }
@Override @Override
public void setBorderCompound(BorderEdge edge, LineCompound compound) { public void setBorderCompound(BorderEdge edge, LineCompound compound) {
if (edge == null || compound == null) { if (edge == null || compound == null) {
throw new IllegalArgumentException("BorderEdge and/or LineCompound need to be specified."); throw new IllegalArgumentException("BorderEdge and/or LineCompound need to be specified.");
} }
HSLFLine l = addLine(edge); HSLFLine l = addLine(edge);
l.setLineCompound(compound); l.setLineCompound(compound);
} }
setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE, 0x80000); setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE, 0x80000);


anchorBorder(edge, line); anchorBorder(edge, line);
return line; return line;
} }


public HSLFTable getParent() { public HSLFTable getParent() {
return (HSLFTable)super.getParent(); return (HSLFTable)super.getParent();
} }

/**
* Set the gridSpan (aka col-span)
*
* @param gridSpan the number of columns to be spanned/merged
*
* @since POI 3.15-beta2
*/
protected void setGridSpan(int gridSpan) {
this.gridSpan = gridSpan;
}

/**
* Set the rowSpan
*
* @param rowSpan the number of rows to be spanned/merged
*
* @since POI 3.15-beta2
*/
protected void setRowSpan(int rowSpan) {
this.rowSpan = rowSpan;
}

@Override
public int getGridSpan() {
return gridSpan;
}

@Override
public int getRowSpan() {
return rowSpan;
}

@Override
public boolean isMerged() {
// if a hslf cell is merged, it won't appear in the cell matrix, i.e. it doesn't exist
// therefore this is always false
return false;
}
} }

正在加载...
取消
保存