mirror of https://github.com/apache/poi.git
improved rendering of indented text in XSLF, also improved import content from external slides
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1200330 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b0a7faba08
commit
dd654d9870
|
@ -17,11 +17,13 @@
|
|||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public enum LineCap {
|
||||
/**
|
||||
* Rounded ends - the default
|
||||
* Rounded ends
|
||||
*/
|
||||
ROUND,
|
||||
/**
|
||||
|
|
|
@ -469,10 +469,19 @@ class RenderableShape {
|
|||
|
||||
// first fill
|
||||
Paint fill = getFillPaint(graphics);
|
||||
Paint line = getLinePaint(graphics);
|
||||
applyStroke(graphics); // the stroke applies both to the shadow and the shape
|
||||
|
||||
// first paint the shadow
|
||||
if(shadow != null) for(Outline o : elems){
|
||||
if(o.getPath().isFilled()){
|
||||
if(fill != null) shadow.fill(graphics, o.getOutline());
|
||||
if(line != null) shadow.draw(graphics, o.getOutline());
|
||||
}
|
||||
}
|
||||
// then fill the shape interior
|
||||
if(fill != null) for(Outline o : elems){
|
||||
if(o.getPath().isFilled()){
|
||||
if(shadow != null) shadow.fill(graphics, o.getOutline());
|
||||
|
||||
graphics.setPaint(fill);
|
||||
graphics.fill(o.getOutline());
|
||||
}
|
||||
|
@ -482,13 +491,8 @@ class RenderableShape {
|
|||
_shape.drawContent(graphics);
|
||||
|
||||
// then stroke the shape outline
|
||||
Paint line = getLinePaint(graphics);
|
||||
if(line != null) for(Outline o : elems){
|
||||
if(o.getPath().isStroked()){
|
||||
applyStroke(graphics); // the stroke applies both to the shadow and the shape
|
||||
|
||||
if(shadow != null) shadow.draw(graphics, o.getOutline());
|
||||
|
||||
graphics.setPaint(line);
|
||||
graphics.draw(o.getOutline());
|
||||
}
|
||||
|
|
|
@ -331,4 +331,12 @@ public class XSLFConnectorShape extends XSLFSimpleShape {
|
|||
return lst;
|
||||
}
|
||||
|
||||
/**
|
||||
* YK: dashing of lines is suppressed for now.
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public XSLFShadow getShadow() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ package org.apache.poi.xslf.usermodel;
|
|||
import org.apache.poi.POIXMLException;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||
import org.apache.poi.openxml4j.opc.TargetMode;
|
||||
import org.apache.poi.util.Beta;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
|
||||
|
@ -97,8 +98,7 @@ public class XSLFPictureShape extends XSLFSimpleShape {
|
|||
|
||||
public XSLFPictureData getPictureData() {
|
||||
if(_data == null){
|
||||
CTPicture ct = (CTPicture)getXmlObject();
|
||||
String blipId = ct.getBlipFill().getBlip().getEmbed();
|
||||
String blipId = getBlipId();
|
||||
|
||||
PackagePart p = getSheet().getPackagePart();
|
||||
PackageRelationship rel = p.getRelationship(blipId);
|
||||
|
@ -115,6 +115,11 @@ public class XSLFPictureShape extends XSLFSimpleShape {
|
|||
return _data;
|
||||
}
|
||||
|
||||
private String getBlipId(){
|
||||
CTPicture ct = (CTPicture)getXmlObject();
|
||||
return ct.getBlipFill().getBlip().getEmbed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawContent(Graphics2D graphics) {
|
||||
|
||||
|
@ -126,4 +131,19 @@ public class XSLFPictureShape extends XSLFSimpleShape {
|
|||
|
||||
renderer.drawImage(graphics, data, getAnchor());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
void copy(XSLFShape sh){
|
||||
super.copy(sh);
|
||||
|
||||
XSLFPictureShape p = (XSLFPictureShape)sh;
|
||||
String blipId = p.getBlipId();
|
||||
String relId = getSheet().importBlip(blipId, p.getSheet().getPackagePart());
|
||||
|
||||
CTPicture ct = (CTPicture)getXmlObject();
|
||||
CTBlip blip = ct.getBlipFill().getBlip();
|
||||
blip.setEmbed(relId);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.awt.geom.Rectangle2D;
|
|||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class XSLFShadow extends XSLFSimpleShape {
|
||||
|
||||
private XSLFSimpleShape _parent;
|
||||
|
||||
/* package */XSLFShadow(CTOuterShadowEffect shape, XSLFSimpleShape parentShape) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import org.apache.poi.util.Beta;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
|
@ -34,27 +35,23 @@ import java.awt.geom.Rectangle2D;
|
|||
public abstract class XSLFShape {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the position of this shape within the drawing canvas.
|
||||
* The coordinates are expressed in points
|
||||
* The coordinates are expressed in points
|
||||
*/
|
||||
public abstract Rectangle2D getAnchor();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param anchor the position of this shape within the drawing canvas.
|
||||
* The coordinates are expressed in points
|
||||
* The coordinates are expressed in points
|
||||
*/
|
||||
public abstract void setAnchor(Rectangle2D anchor);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the xml bean holding this shape's data
|
||||
*/
|
||||
public abstract XmlObject getXmlObject();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return human-readable name of this shape, e.g. "Rectange 3"
|
||||
*/
|
||||
public abstract String getShapeName();
|
||||
|
@ -64,8 +61,8 @@ public abstract class XSLFShape {
|
|||
* This ID may be used to assist in uniquely identifying this object so that it can
|
||||
* be referred to by other parts of the document.
|
||||
* <p>
|
||||
* If multiple objects within the same document share the same id attribute value,
|
||||
* then the document shall be considered non-conformant.
|
||||
* If multiple objects within the same document share the same id attribute value,
|
||||
* then the document shall be considered non-conformant.
|
||||
* </p>
|
||||
*
|
||||
* @return unique id of this shape
|
||||
|
@ -82,7 +79,7 @@ public abstract class XSLFShape {
|
|||
* @param theta the rotation angle in degrees.
|
||||
*/
|
||||
public abstract void setRotation(double theta);
|
||||
|
||||
|
||||
/**
|
||||
* Rotation angle in degrees
|
||||
* <p>
|
||||
|
@ -105,7 +102,7 @@ public abstract class XSLFShape {
|
|||
* @param flip whether the shape is vertically flipped
|
||||
*/
|
||||
public abstract void setFlipVertical(boolean flip);
|
||||
|
||||
|
||||
/**
|
||||
* Whether the shape is horizontally flipped
|
||||
*
|
||||
|
@ -132,15 +129,15 @@ public abstract class XSLFShape {
|
|||
*
|
||||
* @param graphics the graphics whos transform matrix will be modified
|
||||
*/
|
||||
protected void applyTransform(Graphics2D graphics){
|
||||
protected void applyTransform(Graphics2D graphics) {
|
||||
Rectangle2D anchor = getAnchor();
|
||||
|
||||
// rotation
|
||||
double rotation = getRotation();
|
||||
if(rotation != 0.) {
|
||||
// PowerPoint rotates shapes relative to the geometric center
|
||||
double centerX = anchor.getX() + anchor.getWidth()/2;
|
||||
double centerY = anchor.getY() + anchor.getHeight()/2;
|
||||
if (rotation != 0.) {
|
||||
// PowerPoint rotates shapes relative to the geometric center
|
||||
double centerX = anchor.getX() + anchor.getWidth() / 2;
|
||||
double centerY = anchor.getY() + anchor.getHeight() / 2;
|
||||
|
||||
graphics.translate(centerX, centerY);
|
||||
graphics.rotate(Math.toRadians(rotation));
|
||||
|
@ -148,18 +145,34 @@ public abstract class XSLFShape {
|
|||
}
|
||||
|
||||
//flip horizontal
|
||||
if(getFlipHorizontal()){
|
||||
if (getFlipHorizontal()) {
|
||||
graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
|
||||
graphics.scale(-1, 1);
|
||||
graphics.translate(-anchor.getX() , -anchor.getY());
|
||||
graphics.translate(-anchor.getX(), -anchor.getY());
|
||||
}
|
||||
|
||||
//flip vertical
|
||||
if(getFlipVertical()){
|
||||
if (getFlipVertical()) {
|
||||
graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
|
||||
graphics.scale(1, -1);
|
||||
graphics.translate(-anchor.getX(), -anchor.getY());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the contents of this shape to be a copy of the source shape.
|
||||
* This method is called recursively for each shape when merging slides
|
||||
*
|
||||
* @param sh the source shape
|
||||
* @see org.apache.poi.xslf.usermodel.XSLFSlide#importContent(XSLFSheet)
|
||||
*/
|
||||
@Internal
|
||||
void copy(XSLFShape sh) {
|
||||
if (!getClass().isInstance(sh)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't copy " + sh.getClass().getSimpleName() + " into " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
setAnchor(sh.getAnchor());
|
||||
}
|
||||
}
|
|
@ -17,9 +17,11 @@
|
|||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import org.apache.poi.POIXMLDocumentPart;
|
||||
import org.apache.poi.POIXMLException;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||
import org.apache.poi.openxml4j.opc.TargetMode;
|
||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||
import org.apache.poi.util.Beta;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
|
@ -270,14 +272,29 @@ public abstract class XSLFSheet extends POIXMLDocumentPart implements Iterable<X
|
|||
|
||||
/**
|
||||
* Set the contents of this sheet to be a copy of the source sheet.
|
||||
* This method erases any existing shapes and replaces them with
|
||||
* object from the source sheet.
|
||||
*
|
||||
* @param src the source sheet to copy data from
|
||||
* @return modified 'this'
|
||||
*/
|
||||
public void copy(XSLFSheet src){
|
||||
public XSLFSheet importContent(XSLFSheet src){
|
||||
_shapes = null;
|
||||
_spTree = null;
|
||||
_drawing = null;
|
||||
// first copy the source xml
|
||||
getXmlObject().set(src.getXmlObject());
|
||||
|
||||
// recursively update each shape
|
||||
List<XSLFShape> tgtShapes = getShapeList();
|
||||
List<XSLFShape> srcShapes = src.getShapeList();
|
||||
for(int i = 0; i < tgtShapes.size(); i++){
|
||||
XSLFShape s1 = srcShapes.get(i);
|
||||
XSLFShape s2 = tgtShapes.get(i);
|
||||
|
||||
s2.copy(s1);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -423,4 +440,32 @@ public abstract class XSLFSheet extends POIXMLDocumentPart implements Iterable<X
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a picture data from another document.
|
||||
*
|
||||
* @param blipId ID of the package relationship to retrieve.
|
||||
* @param packagePart package part containing the data to import
|
||||
* @return ID of the created relationship
|
||||
*/
|
||||
String importBlip(String blipId, PackagePart packagePart) {
|
||||
PackageRelationship blipRel = packagePart.getRelationship(blipId);
|
||||
PackagePart blipPart;
|
||||
try {
|
||||
blipPart = packagePart.getRelatedPart(blipRel);
|
||||
} catch (InvalidFormatException e){
|
||||
throw new POIXMLException(e);
|
||||
}
|
||||
XSLFPictureData data = new XSLFPictureData(blipPart, null);
|
||||
|
||||
XMLSlideShow ppt = getSlideShow();
|
||||
int pictureIdx = ppt.addPicture(data.getData(), data.getPictureType());
|
||||
PackagePart pic = ppt.getAllPictures().get(pictureIdx).getPackagePart();
|
||||
|
||||
PackageRelationship rel = getPackagePart().addRelationship(
|
||||
pic.getPartName(), TargetMode.INTERNAL, blipRel.getRelationshipType());
|
||||
addRelation(rel.getId(), new XSLFPictureData(pic, rel));
|
||||
|
||||
return rel.getId();
|
||||
}
|
||||
}
|
|
@ -29,6 +29,11 @@ import org.apache.poi.xslf.model.geom.IAdjustableShape;
|
|||
import org.apache.poi.xslf.model.geom.Outline;
|
||||
import org.apache.poi.xslf.model.geom.Path;
|
||||
import org.apache.poi.xslf.model.geom.PresetGeometries;
|
||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
import org.apache.poi.openxml4j.opc.TargetMode;
|
||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||
import org.apache.poi.POIXMLException;
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide;
|
||||
|
@ -48,8 +53,10 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
|
|||
import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
|
@ -69,6 +76,7 @@ import java.util.List;
|
|||
*/
|
||||
@Beta
|
||||
public abstract class XSLFSimpleShape extends XSLFShape {
|
||||
private static CTOuterShadowEffect NO_SHADOW = CTOuterShadowEffect.Factory.newInstance();
|
||||
|
||||
private final XmlObject _shape;
|
||||
private final XSLFSheet _sheet;
|
||||
|
@ -285,6 +293,11 @@ public abstract class XSLFSimpleShape extends XSLFShape {
|
|||
CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln
|
||||
.getSolidFill() : ln.addNewSolidFill();
|
||||
fill.setSrgbClr(rgb);
|
||||
if(fill.isSetHslClr()) fill.unsetHslClr();
|
||||
if(fill.isSetPrstClr()) fill.unsetPrstClr();
|
||||
if(fill.isSetSchemeClr()) fill.unsetSchemeClr();
|
||||
if(fill.isSetScrgbClr()) fill.unsetScrgbClr();
|
||||
if(fill.isSetSysClr()) fill.unsetSysClr();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -483,6 +496,11 @@ public abstract class XSLFSimpleShape extends XSLFShape {
|
|||
(byte) color.getGreen(), (byte) color.getBlue()});
|
||||
|
||||
fill.setSrgbClr(rgb);
|
||||
if(fill.isSetHslClr()) fill.unsetHslClr();
|
||||
if(fill.isSetPrstClr()) fill.unsetPrstClr();
|
||||
if(fill.isSetSchemeClr()) fill.unsetSchemeClr();
|
||||
if(fill.isSetScrgbClr()) fill.unsetScrgbClr();
|
||||
if(fill.isSetSysClr()) fill.unsetSysClr();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -508,7 +526,7 @@ public abstract class XSLFSimpleShape extends XSLFShape {
|
|||
CTShapeProperties spPr = shape.getSpPr();
|
||||
if (spPr.isSetEffectLst()) {
|
||||
CTOuterShadowEffect obj = spPr.getEffectLst().getOuterShdw();
|
||||
setValue(obj);
|
||||
setValue(obj == null ? NO_SHADOW : obj);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -530,7 +548,7 @@ public abstract class XSLFSimpleShape extends XSLFShape {
|
|||
}
|
||||
}
|
||||
}
|
||||
return obj == null ? null : new XSLFShadow(obj, this);
|
||||
return (obj == null || obj == NO_SHADOW) ? null : new XSLFShadow(obj, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -640,4 +658,50 @@ public abstract class XSLFSimpleShape extends XSLFShape {
|
|||
public void drawContent(Graphics2D graphics){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
void copy(XSLFShape sh){
|
||||
super.copy(sh);
|
||||
|
||||
XSLFSimpleShape s = (XSLFSimpleShape)sh;
|
||||
|
||||
Color srsSolidFill = s.getFillColor();
|
||||
Color tgtSoliFill = getFillColor();
|
||||
if(srsSolidFill != null && !srsSolidFill.equals(tgtSoliFill)){
|
||||
setFillColor(srsSolidFill);
|
||||
}
|
||||
|
||||
if(getSpPr().isSetBlipFill()){
|
||||
CTBlip blip = getSpPr().getBlipFill().getBlip();
|
||||
String blipId = blip.getEmbed();
|
||||
|
||||
String relId = getSheet().importBlip(blipId, s.getSheet().getPackagePart());
|
||||
blip.setEmbed(relId);
|
||||
}
|
||||
|
||||
Color srcLineColor = s.getLineColor();
|
||||
Color tgtLineColor = getLineColor();
|
||||
if(srcLineColor != null && !srcLineColor.equals(tgtLineColor)) {
|
||||
setLineColor(srcLineColor);
|
||||
}
|
||||
|
||||
double srcLineWidth = s.getLineWidth();
|
||||
double tgtLineWidth = getLineWidth();
|
||||
if(srcLineWidth != tgtLineWidth) {
|
||||
setLineWidth(srcLineWidth);
|
||||
}
|
||||
|
||||
LineDash srcLineDash = s.getLineDash();
|
||||
LineDash tgtLineDash = getLineDash();
|
||||
if(srcLineDash != null && srcLineDash != tgtLineDash) {
|
||||
setLineDash(srcLineDash);
|
||||
}
|
||||
|
||||
LineCap srcLineCap = s.getLineCap();
|
||||
LineCap tgtLineCap = getLineCap();
|
||||
if(srcLineCap != null && srcLineCap != tgtLineCap) {
|
||||
setLineCap(srcLineCap);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,11 +26,13 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D;
|
|||
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTCommonSlideData;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.SldDocument;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.io.IOException;
|
||||
|
@ -228,4 +230,21 @@ public final class XSLFSlide extends XSLFSheet {
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public XSLFSlide importContent(XSLFSheet src){
|
||||
super.importContent(src);
|
||||
|
||||
CTBackground bg = ((CTSlide)src.getXmlObject()).getCSld().getBg();
|
||||
if(bg != null) {
|
||||
if(bg.isSetBgPr() && bg.getBgPr().isSetBlipFill()){
|
||||
CTBlip blip = bg.getBgPr().getBlipFill().getBlip();
|
||||
String blipId = blip.getEmbed();
|
||||
|
||||
String relId = importBlip(blipId, src.getPackagePart());
|
||||
blip.setEmbed(relId);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,12 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
|
|||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharBullet;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePoint;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
||||
|
||||
|
@ -56,20 +62,33 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
private final XSLFTextShape _shape;
|
||||
private List<TextFragment> _lines;
|
||||
private TextFragment _bullet;
|
||||
/**
|
||||
* the highest line in this paragraph. Used for line spacing.
|
||||
*/
|
||||
private double _maxLineHeight;
|
||||
|
||||
XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){
|
||||
_p = p;
|
||||
_runs = new ArrayList<XSLFTextRun>();
|
||||
_shape = shape;
|
||||
|
||||
for (CTRegularTextRun r : _p.getRList()) {
|
||||
_runs.add(new XSLFTextRun(r, this));
|
||||
}
|
||||
|
||||
for (CTTextField f : _p.getFldList()) {
|
||||
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
|
||||
r.setT(f.getT());
|
||||
_runs.add(new XSLFTextRun(r, this));
|
||||
for(XmlObject ch : _p.selectPath("*")){
|
||||
if(ch instanceof CTRegularTextRun){
|
||||
CTRegularTextRun r = (CTRegularTextRun)ch;
|
||||
_runs.add(new XSLFTextRun(r, this));
|
||||
} else if (ch instanceof CTTextLineBreak){
|
||||
CTTextLineBreak br = (CTTextLineBreak)ch;
|
||||
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
|
||||
r.setRPr(br.getRPr());
|
||||
r.setT("\n");
|
||||
_runs.add(new XSLFTextRun(r, this));
|
||||
} else if (ch instanceof CTTextField){
|
||||
CTTextField f = (CTTextField)ch;
|
||||
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
|
||||
r.setRPr(f.getRPr());
|
||||
r.setT(f.getT());
|
||||
_runs.add(new XSLFTextRun(r, this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,19 +100,10 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
return out.toString();
|
||||
}
|
||||
|
||||
private String getVisibleText(){
|
||||
String getRenderableText(){
|
||||
StringBuilder out = new StringBuilder();
|
||||
for (XSLFTextRun r : _runs) {
|
||||
String txt = r.getText();
|
||||
switch (r.getTextCap()){
|
||||
case ALL:
|
||||
txt = txt.toUpperCase();
|
||||
break;
|
||||
case SMALL:
|
||||
txt = txt.toLowerCase();
|
||||
break;
|
||||
}
|
||||
out.append(txt);
|
||||
out.append(r.getRenderableText());
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
@ -183,6 +193,12 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
return fetcher.getValue();
|
||||
}
|
||||
|
||||
public void setBulletFont(String typeface){
|
||||
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
|
||||
CTTextFont font = pr.isSetBuFont() ? pr.getBuFont() : pr.addNewBuFont();
|
||||
font.setTypeface(typeface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the character to be used in place of the standard bullet point
|
||||
*/
|
||||
|
@ -200,6 +216,12 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
return fetcher.getValue();
|
||||
}
|
||||
|
||||
public void setBulletCharacter(String str){
|
||||
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
|
||||
CTTextCharBullet c = pr.isSetBuChar() ? pr.getBuChar() : pr.addNewBuChar();
|
||||
c.setChar(str);
|
||||
}
|
||||
|
||||
public Color getBulletFontColor(){
|
||||
final XSLFTheme theme = getParentShape().getSheet().getTheme();
|
||||
ParagraphPropertyFetcher<Color> fetcher = new ParagraphPropertyFetcher<Color>(getLevel()){
|
||||
|
@ -216,6 +238,13 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
return fetcher.getValue();
|
||||
}
|
||||
|
||||
public void setBulletFontColor(Color color){
|
||||
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
|
||||
CTColor c = pr.isSetBuClr() ? pr.getBuClr() : pr.addNewBuClr();
|
||||
CTSRgbColor clr = c.isSetSrgbClr() ? c.getSrgbClr() : c.addNewSrgbClr();
|
||||
clr.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});
|
||||
}
|
||||
|
||||
public double getBulletFontSize(){
|
||||
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
|
||||
public boolean fetch(CTTextParagraphProperties props){
|
||||
|
@ -234,11 +263,17 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
return fetcher.getValue() == null ? 100 : fetcher.getValue();
|
||||
}
|
||||
|
||||
public void setBulletFontSize(double size){
|
||||
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
|
||||
CTTextBulletSizePoint pt = pr.isSetBuSzPts() ? pr.getBuSzPts() : pr.addNewBuSzPts();
|
||||
pt.setVal((int)(size*1000));
|
||||
if(pr.isSetBuSzPct()) pr.unsetBuSzPct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the indent size that will be applied to the first line of text in the paragraph.
|
||||
*
|
||||
* @param value the indent in points. The value of -1 unsets the indent attribute
|
||||
* from the underlying xml bean.
|
||||
* @param value the indent in points.
|
||||
*/
|
||||
public void setIndent(double value){
|
||||
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
|
||||
|
@ -297,7 +332,8 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
}
|
||||
};
|
||||
fetchParagraphProperty(fetcher);
|
||||
return fetcher.getValue() == null ? 0 : fetcher.getValue();
|
||||
// if the marL attribute is omitted, then a value of 347663 is implied
|
||||
return fetcher.getValue() == null ? Units.toPoints(347663) : fetcher.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -512,7 +548,7 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
|
||||
/**
|
||||
*
|
||||
* @param isBullet whether text in this paragraph has bullets
|
||||
* @param flag whether text in this paragraph has bullets
|
||||
*/
|
||||
public void setBullet(boolean flag) {
|
||||
if(isBullet() == flag) return;
|
||||
|
@ -535,38 +571,117 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
return _lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns wrapping width to break lines in this paragraph
|
||||
*
|
||||
* @param firstLine whether the first line is breaking
|
||||
*
|
||||
* @return wrapping width in points
|
||||
*/
|
||||
double getWrappingWidth(boolean firstLine){
|
||||
// internal margins for the text box
|
||||
double leftInset = _shape.getLeftInset();
|
||||
double rightInset = _shape.getRightInset();
|
||||
|
||||
Rectangle2D anchor = _shape.getAnchor();
|
||||
|
||||
double leftMargin = getLeftMargin();
|
||||
double indent = getIndent();
|
||||
|
||||
double width;
|
||||
if(!_shape.getWordWrap()) {
|
||||
// if wordWrap == false then we return the advance to the right border of the sheet
|
||||
width = _shape.getSheet().getSlideShow().getPageSize().getWidth() - anchor.getX();
|
||||
} else {
|
||||
width = anchor.getWidth() - leftInset - rightInset - leftMargin;
|
||||
if(firstLine) {
|
||||
if(isBullet()){
|
||||
width -= Math.abs(indent);
|
||||
} else {
|
||||
if(indent > 0) width -= indent; // first line indentation
|
||||
else if (indent < 0) { // hanging indentation: the first line start at the left margin
|
||||
width += leftMargin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
public double draw(Graphics2D graphics, double x, double y){
|
||||
double marginLeft = _shape.getLeftInset();
|
||||
double marginRight = _shape.getRightInset();
|
||||
double leftInset = _shape.getLeftInset();
|
||||
double rightInset = _shape.getRightInset();
|
||||
Rectangle2D anchor = _shape.getAnchor();
|
||||
double penY = y;
|
||||
|
||||
double textOffset = getLeftMargin();
|
||||
double leftMargin = getLeftMargin();
|
||||
boolean firstLine = true;
|
||||
double indent = getIndent();
|
||||
for(TextFragment line : _lines){
|
||||
double penX = x;
|
||||
|
||||
if(firstLine) {
|
||||
|
||||
if(_bullet != null){
|
||||
if(indent < 0) {
|
||||
// a negative value means "Hanging" indentation and
|
||||
// indicates the position of the actual bullet character.
|
||||
// (the bullet is shifted to right relative to the text)
|
||||
_bullet.draw(graphics, penX, penY);
|
||||
penX -= indent;
|
||||
} else if(indent > 0){
|
||||
penX += leftMargin;
|
||||
// a positive value means the "First Line" indentation:
|
||||
// the first line is indented and other lines start at the bullet ofset
|
||||
_bullet.draw(graphics, penX, penY);
|
||||
penX += indent;
|
||||
} else {
|
||||
// no special indent. The first line behaves like all others
|
||||
penX += leftMargin;
|
||||
|
||||
// a zero indent means that the bullet and text have the same offset
|
||||
_bullet.draw(graphics, penX, penY);
|
||||
|
||||
// don't let text overlay the bullet and advance by the bullet width
|
||||
penX += _bullet._layout.getAdvance() + 1;
|
||||
}
|
||||
} else {
|
||||
if(indent < 0) {
|
||||
// if bullet=false and indentation=hanging then the first line
|
||||
// starts at the left offset (penX is not incremented)
|
||||
} else if(indent > 0) {
|
||||
// first line indent shifts penX
|
||||
penX += indent + leftMargin;
|
||||
} else {
|
||||
// no special indent. The first line behaves like all others
|
||||
penX += leftMargin;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
penX += leftMargin;
|
||||
}
|
||||
|
||||
|
||||
switch (getTextAlign()) {
|
||||
case CENTER:
|
||||
penX += textOffset + (anchor.getWidth() - textOffset - line.getWidth() - marginLeft - marginRight) / 2;
|
||||
penX += (anchor.getWidth() - leftMargin - line.getWidth() - leftInset - rightInset) / 2;
|
||||
break;
|
||||
case RIGHT:
|
||||
penX += (anchor.getWidth() - line.getWidth() - marginLeft - marginRight);
|
||||
penX += (anchor.getWidth() - line.getWidth() - leftInset - rightInset);
|
||||
break;
|
||||
default:
|
||||
penX = x + textOffset;
|
||||
//penX += leftInset;
|
||||
break;
|
||||
}
|
||||
|
||||
if(_bullet != null && firstLine){
|
||||
_bullet.draw(graphics, penX + getIndent(), penY);
|
||||
}
|
||||
line.draw(graphics, penX, penY);
|
||||
|
||||
//The vertical line spacing
|
||||
double spacing = getLineSpacing();
|
||||
if(spacing > 0) {
|
||||
// If linespacing >= 0, then linespacing is a percentage of normal line height.
|
||||
penY += spacing*0.01*line.getHeight();
|
||||
penY += spacing*0.01* _maxLineHeight;
|
||||
} else {
|
||||
// positive value means absolute spacing in points
|
||||
penY += -spacing;
|
||||
|
@ -607,13 +722,13 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
}
|
||||
|
||||
AttributedString getAttributedString(Graphics2D graphics){
|
||||
String text = getVisibleText();
|
||||
String text = getRenderableText();
|
||||
|
||||
AttributedString string = new AttributedString(text);
|
||||
|
||||
int startIndex = 0;
|
||||
for (XSLFTextRun run : _runs){
|
||||
int length = run.getText().length();
|
||||
int length = run.getRenderableText().length();
|
||||
if(length == 0) {
|
||||
// skip empty runs
|
||||
continue;
|
||||
|
@ -656,6 +771,7 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
void breakText(Graphics2D graphics){
|
||||
_lines = new ArrayList<TextFragment>();
|
||||
|
||||
String text = getRenderableText();
|
||||
AttributedString at = getAttributedString(graphics);
|
||||
AttributedCharacterIterator it = at.getIterator();
|
||||
if(it.getBeginIndex() == it.getEndIndex()) {
|
||||
|
@ -664,12 +780,17 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
LineBreakMeasurer measurer = new LineBreakMeasurer(it, graphics.getFontRenderContext());
|
||||
for (;;) {
|
||||
int startIndex = measurer.getPosition();
|
||||
double wrappingWidth = getWrappingWidth() + 1; // add a pixel to compensate rounding errors
|
||||
TextLayout layout = measurer.nextLayout((float)wrappingWidth, it.getEndIndex(), true);
|
||||
double wrappingWidth = getWrappingWidth(_lines.size() == 0) + 1; // add a pixel to compensate rounding errors
|
||||
|
||||
|
||||
int nextBreak = text.indexOf('\n', startIndex + 1);
|
||||
if(nextBreak == -1) nextBreak = it.getEndIndex();
|
||||
|
||||
TextLayout layout = measurer.nextLayout((float)wrappingWidth, nextBreak, true);
|
||||
if (layout == null) {
|
||||
// layout can be null if the entire word at the current position
|
||||
// does not fit within the wrapping width. Try with requireNextWord=false.
|
||||
layout = measurer.nextLayout((float)wrappingWidth, it.getEndIndex(), false);
|
||||
layout = measurer.nextLayout((float)wrappingWidth, nextBreak, false);
|
||||
}
|
||||
|
||||
int endIndex = measurer.getPosition();
|
||||
|
@ -683,6 +804,8 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
TextFragment line = new TextFragment(layout, str);
|
||||
_lines.add(line);
|
||||
|
||||
_maxLineHeight = Math.max(_maxLineHeight, line.getHeight());
|
||||
|
||||
if(endIndex == it.getEndIndex()) break;
|
||||
}
|
||||
|
||||
|
@ -714,17 +837,6 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
|
||||
}
|
||||
|
||||
double getWrappingWidth(){
|
||||
double width;
|
||||
if(!_shape.getWordWrap()) {
|
||||
width = _shape.getSheet().getSlideShow().getPageSize().getWidth();
|
||||
} else {
|
||||
width = _shape.getAnchor().getWidth() -
|
||||
_shape.getLeftInset() - _shape.getRightInset() - getLeftMargin();
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
CTTextParagraphProperties getDefaultStyle(){
|
||||
CTPlaceholder ph = _shape.getCTPlaceholder();
|
||||
String defaultStyleSelector;
|
||||
|
@ -782,4 +894,64 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||
return ok;
|
||||
}
|
||||
|
||||
void copy(XSLFTextParagraph p){
|
||||
TextAlign srcAlign = p.getTextAlign();
|
||||
if(srcAlign != getTextAlign()){
|
||||
setTextAlign(srcAlign);
|
||||
}
|
||||
|
||||
boolean isBullet = p.isBullet();
|
||||
if(isBullet != isBullet()){
|
||||
setBullet(isBullet);
|
||||
if(isBullet) {
|
||||
String buFont = p.getBulletFont();
|
||||
if(buFont != null && !buFont.equals(getBulletFont())){
|
||||
setBulletFont(buFont);
|
||||
}
|
||||
String buChar = p.getBulletCharacter();
|
||||
if(buChar != null && !buChar.equals(getBulletCharacter())){
|
||||
setBulletCharacter(buChar);
|
||||
}
|
||||
Color buColor = p.getBulletFontColor();
|
||||
if(buColor != null && !buColor.equals(getBulletFontColor())){
|
||||
setBulletFontColor(buColor);
|
||||
}
|
||||
double buSize = p.getBulletFontSize();
|
||||
if(buSize != getBulletFontSize()){
|
||||
setBulletFontSize(buSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double leftMargin = p.getLeftMargin();
|
||||
if(leftMargin != getLeftMargin()){
|
||||
setLeftMargin(leftMargin);
|
||||
}
|
||||
|
||||
double indent = p.getIndent();
|
||||
if(indent != getIndent()){
|
||||
setIndent(indent);
|
||||
}
|
||||
|
||||
double spaceAfter = p.getSpaceAfter();
|
||||
if(spaceAfter != getSpaceAfter()){
|
||||
setSpaceAfter(spaceAfter);
|
||||
}
|
||||
double spaceBefore = p.getSpaceBefore();
|
||||
if(spaceBefore != getSpaceBefore()){
|
||||
setSpaceBefore(spaceBefore);
|
||||
}
|
||||
double lineSpacing = p.getLineSpacing();
|
||||
if(lineSpacing != getLineSpacing()){
|
||||
setLineSpacing(lineSpacing);
|
||||
}
|
||||
|
||||
List<XSLFTextRun> srcR = p.getTextRuns();
|
||||
List<XSLFTextRun> tgtR = getTextRuns();
|
||||
for(int i = 0; i < srcR.size(); i++){
|
||||
XSLFTextRun r1 = srcR.get(i);
|
||||
XSLFTextRun r2 = tgtR.get(i);
|
||||
r2.copy(r1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,23 @@ public class XSLFTextRun {
|
|||
return _r.getT();
|
||||
}
|
||||
|
||||
String getRenderableText(){
|
||||
String txt = _r.getT();
|
||||
switch (getTextCap()){
|
||||
case ALL:
|
||||
txt = txt.toUpperCase();
|
||||
break;
|
||||
case SMALL:
|
||||
txt = txt.toLowerCase();
|
||||
break;
|
||||
}
|
||||
// TODO-1 is is the place to convert wingdings to unicode
|
||||
|
||||
// TODO-2 this is a temporary hack. Rendering text with tabs is not yet supported.
|
||||
// for now tabs are replaced with some number of spaces.
|
||||
return txt.replace("\t", " ");
|
||||
}
|
||||
|
||||
public void setText(String text){
|
||||
_r.setT(text);
|
||||
}
|
||||
|
@ -69,6 +86,13 @@ public class XSLFTextRun {
|
|||
CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill();
|
||||
CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr();
|
||||
clr.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});
|
||||
|
||||
if(fill.isSetHslClr()) fill.unsetHslClr();
|
||||
if(fill.isSetPrstClr()) fill.unsetPrstClr();
|
||||
if(fill.isSetSchemeClr()) fill.unsetSchemeClr();
|
||||
if(fill.isSetScrgbClr()) fill.unsetScrgbClr();
|
||||
if(fill.isSetSysClr()) fill.unsetSysClr();
|
||||
|
||||
}
|
||||
|
||||
public Color getFontColor(){
|
||||
|
@ -393,4 +417,32 @@ public class XSLFTextRun {
|
|||
return ok;
|
||||
}
|
||||
|
||||
void copy(XSLFTextRun r){
|
||||
String srcFontFamily = r.getFontFamily();
|
||||
if(srcFontFamily != null && !srcFontFamily.equals(getFontFamily())){
|
||||
setFontFamily(srcFontFamily);
|
||||
}
|
||||
|
||||
Color srcFontColor = r.getFontColor();
|
||||
if(srcFontColor != null && !srcFontColor.equals(getFontColor())){
|
||||
setFontColor(srcFontColor);
|
||||
}
|
||||
|
||||
double srcFontSize = r.getFontSize();
|
||||
if(srcFontSize != getFontSize()){
|
||||
setFontSize(srcFontSize);
|
||||
}
|
||||
|
||||
boolean bold = r.isBold();
|
||||
if(bold != isBold()) setBold(bold);
|
||||
|
||||
boolean italic = r.isItalic();
|
||||
if(italic != isItalic()) setItalic(italic);
|
||||
|
||||
boolean underline = r.isUnderline();
|
||||
if(underline != isUnderline()) setUnderline(underline);
|
||||
|
||||
boolean strike = r.isStrikethrough();
|
||||
if(strike != isStrikethrough()) setStrikethrough(strike);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,7 +202,8 @@ public abstract class XSLFTextShape extends XSLFSimpleShape implements Iterable<
|
|||
}
|
||||
};
|
||||
fetchShapeProperty(fetcher);
|
||||
return fetcher.getValue() == null ? 0 : fetcher.getValue();
|
||||
// If this attribute is omitted, then a value of 0.05 inches is implied
|
||||
return fetcher.getValue() == null ? 3.6 : fetcher.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -224,7 +225,8 @@ public abstract class XSLFTextShape extends XSLFSimpleShape implements Iterable<
|
|||
}
|
||||
};
|
||||
fetchShapeProperty(fetcher);
|
||||
return fetcher.getValue() == null ? 0 : fetcher.getValue();
|
||||
// If this attribute is omitted, then a value of 0.1 inches is implied
|
||||
return fetcher.getValue() == null ? 7.2 : fetcher.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -246,7 +248,8 @@ public abstract class XSLFTextShape extends XSLFSimpleShape implements Iterable<
|
|||
}
|
||||
};
|
||||
fetchShapeProperty(fetcher);
|
||||
return fetcher.getValue() == null ? 0 : fetcher.getValue();
|
||||
// If this attribute is omitted, then a value of 0.1 inches is implied
|
||||
return fetcher.getValue() == null ? 7.2 : fetcher.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -267,7 +270,8 @@ public abstract class XSLFTextShape extends XSLFSimpleShape implements Iterable<
|
|||
}
|
||||
};
|
||||
fetchShapeProperty(fetcher);
|
||||
return fetcher.getValue() == null ? 0 : fetcher.getValue();
|
||||
// If this attribute is omitted, then a value of 0.05 inches is implied
|
||||
return fetcher.getValue() == null ? 3.6 : fetcher.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -521,4 +525,46 @@ public abstract class XSLFTextShape extends XSLFSimpleShape implements Iterable<
|
|||
return y - y0;
|
||||
}
|
||||
|
||||
@Override
|
||||
void copy(XSLFShape sh){
|
||||
super.copy(sh);
|
||||
|
||||
XSLFTextShape tsh = (XSLFTextShape)sh;
|
||||
|
||||
boolean srcWordWrap = tsh.getWordWrap();
|
||||
if(srcWordWrap != getWordWrap()){
|
||||
setWordWrap(srcWordWrap);
|
||||
}
|
||||
|
||||
double leftInset = tsh.getLeftInset();
|
||||
if(leftInset != getLeftInset()) {
|
||||
setLeftInset(leftInset);
|
||||
}
|
||||
double rightInset = tsh.getRightInset();
|
||||
if(rightInset != getRightInset()) {
|
||||
setRightInset(rightInset);
|
||||
}
|
||||
double topInset = tsh.getTopInset();
|
||||
if(topInset != getTopInset()) {
|
||||
setTopInset(topInset);
|
||||
}
|
||||
double bottomInset = tsh.getBottomInset();
|
||||
if(bottomInset != getBottomInset()) {
|
||||
setBottomInset(bottomInset);
|
||||
}
|
||||
|
||||
VerticalAlignment vAlign = tsh.getVerticalAlignment();
|
||||
if(vAlign != getVerticalAlignment()) {
|
||||
setVerticalAlignment(vAlign);
|
||||
}
|
||||
|
||||
List<XSLFTextParagraph> srcP = tsh.getTextParagraphs();
|
||||
List<XSLFTextParagraph> tgtP = getTextParagraphs();
|
||||
for(int i = 0; i < srcP.size(); i++){
|
||||
XSLFTextParagraph p1 = srcP.get(i);
|
||||
XSLFTextParagraph p2 = tgtP.get(i);
|
||||
p2.copy(p1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -19,6 +19,12 @@ package org.apache.poi.xslf.usermodel;
|
|||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.xslf.XSLFTestDataSamples;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Yegor Kozlov
|
||||
|
@ -103,4 +109,58 @@ public class TestXSLFSlide extends TestCase {
|
|||
assertTrue(slide.getFollowMasterGraphics());
|
||||
}
|
||||
|
||||
public void testImportContent(){
|
||||
XMLSlideShow ppt = new XMLSlideShow();
|
||||
|
||||
XMLSlideShow src = XSLFTestDataSamples.openSampleDocument("themes.pptx");
|
||||
|
||||
// create a blank slide and import content from the 4th slide of themes.pptx
|
||||
XSLFSlide slide1 = ppt.createSlide().importContent(src.getSlides()[3]);
|
||||
XSLFShape[] shapes1 = slide1.getShapes();
|
||||
assertEquals(2, shapes1.length);
|
||||
|
||||
XSLFTextShape sh1 = (XSLFTextShape)shapes1[0];
|
||||
assertEquals("Austin Theme", sh1.getText());
|
||||
XSLFTextRun r1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);
|
||||
assertEquals("Century Gothic", r1.getFontFamily());
|
||||
assertEquals(40.0, r1.getFontSize());
|
||||
assertTrue(r1.isBold());
|
||||
assertTrue(r1.isItalic());
|
||||
assertEquals(new Color(148, 198, 0), r1.getFontColor());
|
||||
assertNull(sh1.getFillColor());
|
||||
assertNull(sh1.getLineColor());
|
||||
|
||||
XSLFTextShape sh2 = (XSLFTextShape)shapes1[1];
|
||||
assertEquals(
|
||||
"Text in a autoshape is white\n" +
|
||||
"Fill: RGB(148, 198,0)", sh2.getText());
|
||||
XSLFTextRun r2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0);
|
||||
assertEquals("Century Gothic", r2.getFontFamily());
|
||||
assertEquals(18.0, r2.getFontSize());
|
||||
assertFalse(r2.isBold());
|
||||
assertFalse(r2.isItalic());
|
||||
assertEquals(Color.white, r2.getFontColor());
|
||||
assertEquals(new Color(148, 198, 0), sh2.getFillColor());
|
||||
assertEquals(new Color(74, 99, 0), sh2.getLineColor()); // slightly different from PowerPoint!
|
||||
|
||||
// the 5th slide has a picture and a texture fill
|
||||
XSLFSlide slide2 = ppt.createSlide().importContent(src.getSlides()[4]);
|
||||
XSLFShape[] shapes2 = slide2.getShapes();
|
||||
assertEquals(2, shapes2.length);
|
||||
|
||||
XSLFTextShape sh3 = (XSLFTextShape)shapes2[0];
|
||||
assertEquals("This slide overrides master background with a texture fill", sh3.getText());
|
||||
XSLFTextRun r3 = sh3.getTextParagraphs().get(0).getTextRuns().get(0);
|
||||
assertEquals("Century Gothic", r3.getFontFamily());
|
||||
//assertEquals(32.4.0, r3.getFontSize());
|
||||
assertTrue(r3.isBold());
|
||||
assertTrue(r3.isItalic());
|
||||
assertEquals(new Color(148, 198, 0), r3.getFontColor());
|
||||
assertNull(sh3.getFillColor());
|
||||
assertNull(sh3.getLineColor());
|
||||
|
||||
XSLFPictureShape sh4 = (XSLFPictureShape)shapes2[1];
|
||||
XSLFPictureShape srcPic = (XSLFPictureShape)src.getSlides()[4].getShapes()[1];
|
||||
assertTrue(Arrays.equals(sh4.getPictureData().getData(), srcPic.getPictureData().getData()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Color;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import org.apache.poi.xssf.dev.XSSFDump;
|
||||
import org.apache.poi.xslf.util.PPTX2PNG;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: yegor
|
||||
* Date: Nov 10, 2011
|
||||
* Time: 1:43:25 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public class TestXSLFTextParagraph extends TestCase {
|
||||
|
||||
public void testWrappingWidth() throws Exception {
|
||||
XMLSlideShow ppt = new XMLSlideShow();
|
||||
XSLFSlide slide = ppt.createSlide();
|
||||
XSLFTextShape sh = slide.createAutoShape();
|
||||
sh.setLineColor(Color.black);
|
||||
|
||||
XSLFTextParagraph p = sh.addNewTextParagraph();
|
||||
p.addNewTextRun().setText(
|
||||
"Paragraph formatting allows for more granular control " +
|
||||
"of text within a shape. Properties here apply to all text " +
|
||||
"residing within the corresponding paragraph.");
|
||||
|
||||
Rectangle2D anchor = new Rectangle(50, 50, 300, 200);
|
||||
sh.setAnchor(anchor);
|
||||
|
||||
double leftInset = sh.getLeftInset();
|
||||
double rightInset = sh.getRightInset();
|
||||
assertEquals(7.2, leftInset);
|
||||
assertEquals(7.2, rightInset);
|
||||
|
||||
double leftMargin = p.getLeftMargin();
|
||||
assertEquals(0.0, leftMargin);
|
||||
|
||||
double indent = p.getIndent();
|
||||
assertEquals(0.0, indent); // default
|
||||
|
||||
double expectedWidth;
|
||||
|
||||
// Case 1: bullet=false, leftMargin=0, indent=0.
|
||||
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;
|
||||
assertEquals(285.6, expectedWidth); // 300 - 7.2 - 7.2 - 0
|
||||
assertEquals(expectedWidth, p.getWrappingWidth(true));
|
||||
assertEquals(expectedWidth, p.getWrappingWidth(false));
|
||||
|
||||
p.setLeftMargin(36); // 0.5"
|
||||
leftMargin = p.getLeftMargin();
|
||||
assertEquals(36.0, leftMargin);
|
||||
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;
|
||||
assertEquals(249.6, expectedWidth, 1E-5); // 300 - 7.2 - 7.2 - 36
|
||||
assertEquals(expectedWidth, p.getWrappingWidth(true));
|
||||
assertEquals(expectedWidth, p.getWrappingWidth(false));
|
||||
|
||||
// increase insets, the wrapping width should get smaller
|
||||
sh.setLeftInset(10);
|
||||
sh.setRightInset(10);
|
||||
leftInset = sh.getLeftInset();
|
||||
rightInset = sh.getRightInset();
|
||||
assertEquals(10.0, leftInset);
|
||||
assertEquals(10.0, rightInset);
|
||||
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;
|
||||
assertEquals(244.0, expectedWidth); // 300 - 10 - 10 - 36
|
||||
assertEquals(expectedWidth, p.getWrappingWidth(true));
|
||||
assertEquals(expectedWidth, p.getWrappingWidth(false));
|
||||
|
||||
// set a positive indent of a 0.5 inch. This means "First Line" indentation:
|
||||
// |<--- indent -->|Here goes first line of the text
|
||||
// Here go other lines (second and subsequent)
|
||||
|
||||
p.setIndent(36.0); // 0.5"
|
||||
indent = p.getIndent();
|
||||
assertEquals(36.0, indent);
|
||||
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin - indent;
|
||||
assertEquals(208.0, expectedWidth); // 300 - 10 - 10 - 36 - 6.4
|
||||
assertEquals(expectedWidth, p.getWrappingWidth(true)); // first line is indented
|
||||
// other lines are not indented
|
||||
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;
|
||||
assertEquals(244.0, expectedWidth); // 300 - 10 - 10 - 36
|
||||
assertEquals(expectedWidth, p.getWrappingWidth(false));
|
||||
|
||||
// set a negative indent of a 1 inch. This means "Hanging" indentation:
|
||||
// Here goes first line of the text
|
||||
// |<--- indent -->|Here go other lines (second and subsequent)
|
||||
p.setIndent(-72.0); // 1"
|
||||
indent = p.getIndent();
|
||||
assertEquals(-72.0, indent);
|
||||
expectedWidth = anchor.getWidth() - leftInset - rightInset;
|
||||
assertEquals(280.0, expectedWidth); // 300 - 10 - 10
|
||||
assertEquals(expectedWidth, p.getWrappingWidth(true)); // first line is NOT indented
|
||||
// other lines are indented by leftMargin (the value of indent is not used)
|
||||
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;
|
||||
assertEquals(244.0, expectedWidth); // 300 - 10 - 10 - 36
|
||||
assertEquals(expectedWidth, p.getWrappingWidth(false));
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue