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
afecad3532
commit
abccf7f303
@ -17,11 +17,13 @@
|
|||||||
package org.apache.poi.xslf.usermodel;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
* @author Yegor Kozlov
|
* @author Yegor Kozlov
|
||||||
*/
|
*/
|
||||||
public enum LineCap {
|
public enum LineCap {
|
||||||
/**
|
/**
|
||||||
* Rounded ends - the default
|
* Rounded ends
|
||||||
*/
|
*/
|
||||||
ROUND,
|
ROUND,
|
||||||
/**
|
/**
|
||||||
|
@ -469,10 +469,19 @@ class RenderableShape {
|
|||||||
|
|
||||||
// first fill
|
// first fill
|
||||||
Paint fill = getFillPaint(graphics);
|
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(fill != null) for(Outline o : elems){
|
||||||
if(o.getPath().isFilled()){
|
if(o.getPath().isFilled()){
|
||||||
if(shadow != null) shadow.fill(graphics, o.getOutline());
|
|
||||||
|
|
||||||
graphics.setPaint(fill);
|
graphics.setPaint(fill);
|
||||||
graphics.fill(o.getOutline());
|
graphics.fill(o.getOutline());
|
||||||
}
|
}
|
||||||
@ -482,13 +491,8 @@ class RenderableShape {
|
|||||||
_shape.drawContent(graphics);
|
_shape.drawContent(graphics);
|
||||||
|
|
||||||
// then stroke the shape outline
|
// then stroke the shape outline
|
||||||
Paint line = getLinePaint(graphics);
|
|
||||||
if(line != null) for(Outline o : elems){
|
if(line != null) for(Outline o : elems){
|
||||||
if(o.getPath().isStroked()){
|
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.setPaint(line);
|
||||||
graphics.draw(o.getOutline());
|
graphics.draw(o.getOutline());
|
||||||
}
|
}
|
||||||
|
@ -331,4 +331,12 @@ public class XSLFConnectorShape extends XSLFSimpleShape {
|
|||||||
return lst;
|
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.POIXMLException;
|
||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||||
|
import org.apache.poi.openxml4j.opc.TargetMode;
|
||||||
import org.apache.poi.util.Beta;
|
import org.apache.poi.util.Beta;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
|
||||||
@ -97,8 +98,7 @@ public class XSLFPictureShape extends XSLFSimpleShape {
|
|||||||
|
|
||||||
public XSLFPictureData getPictureData() {
|
public XSLFPictureData getPictureData() {
|
||||||
if(_data == null){
|
if(_data == null){
|
||||||
CTPicture ct = (CTPicture)getXmlObject();
|
String blipId = getBlipId();
|
||||||
String blipId = ct.getBlipFill().getBlip().getEmbed();
|
|
||||||
|
|
||||||
PackagePart p = getSheet().getPackagePart();
|
PackagePart p = getSheet().getPackagePart();
|
||||||
PackageRelationship rel = p.getRelationship(blipId);
|
PackageRelationship rel = p.getRelationship(blipId);
|
||||||
@ -115,6 +115,11 @@ public class XSLFPictureShape extends XSLFSimpleShape {
|
|||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getBlipId(){
|
||||||
|
CTPicture ct = (CTPicture)getXmlObject();
|
||||||
|
return ct.getBlipFill().getBlip().getEmbed();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawContent(Graphics2D graphics) {
|
public void drawContent(Graphics2D graphics) {
|
||||||
|
|
||||||
@ -126,4 +131,19 @@ public class XSLFPictureShape extends XSLFSimpleShape {
|
|||||||
|
|
||||||
renderer.drawImage(graphics, data, getAnchor());
|
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
|
* @author Yegor Kozlov
|
||||||
*/
|
*/
|
||||||
public class XSLFShadow extends XSLFSimpleShape {
|
public class XSLFShadow extends XSLFSimpleShape {
|
||||||
|
|
||||||
private XSLFSimpleShape _parent;
|
private XSLFSimpleShape _parent;
|
||||||
|
|
||||||
/* package */XSLFShadow(CTOuterShadowEffect shape, XSLFSimpleShape parentShape) {
|
/* package */XSLFShadow(CTOuterShadowEffect shape, XSLFSimpleShape parentShape) {
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
package org.apache.poi.xslf.usermodel;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
import org.apache.poi.util.Beta;
|
import org.apache.poi.util.Beta;
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
import org.apache.xmlbeans.XmlObject;
|
import org.apache.xmlbeans.XmlObject;
|
||||||
|
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
@ -34,27 +35,23 @@ import java.awt.geom.Rectangle2D;
|
|||||||
public abstract class XSLFShape {
|
public abstract class XSLFShape {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @return the position of this shape within the drawing canvas.
|
* @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();
|
public abstract Rectangle2D getAnchor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param anchor the position of this shape within the drawing canvas.
|
* @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);
|
public abstract void setAnchor(Rectangle2D anchor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @return the xml bean holding this shape's data
|
* @return the xml bean holding this shape's data
|
||||||
*/
|
*/
|
||||||
public abstract XmlObject getXmlObject();
|
public abstract XmlObject getXmlObject();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @return human-readable name of this shape, e.g. "Rectange 3"
|
* @return human-readable name of this shape, e.g. "Rectange 3"
|
||||||
*/
|
*/
|
||||||
public abstract String getShapeName();
|
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
|
* 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.
|
* be referred to by other parts of the document.
|
||||||
* <p>
|
* <p>
|
||||||
* If multiple objects within the same document share the same id attribute value,
|
* If multiple objects within the same document share the same id attribute value,
|
||||||
* then the document shall be considered non-conformant.
|
* then the document shall be considered non-conformant.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @return unique id of this shape
|
* @return unique id of this shape
|
||||||
@ -82,7 +79,7 @@ public abstract class XSLFShape {
|
|||||||
* @param theta the rotation angle in degrees.
|
* @param theta the rotation angle in degrees.
|
||||||
*/
|
*/
|
||||||
public abstract void setRotation(double theta);
|
public abstract void setRotation(double theta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotation angle in degrees
|
* Rotation angle in degrees
|
||||||
* <p>
|
* <p>
|
||||||
@ -105,7 +102,7 @@ public abstract class XSLFShape {
|
|||||||
* @param flip whether the shape is vertically flipped
|
* @param flip whether the shape is vertically flipped
|
||||||
*/
|
*/
|
||||||
public abstract void setFlipVertical(boolean flip);
|
public abstract void setFlipVertical(boolean flip);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the shape is horizontally flipped
|
* Whether the shape is horizontally flipped
|
||||||
*
|
*
|
||||||
@ -132,15 +129,15 @@ public abstract class XSLFShape {
|
|||||||
*
|
*
|
||||||
* @param graphics the graphics whos transform matrix will be modified
|
* @param graphics the graphics whos transform matrix will be modified
|
||||||
*/
|
*/
|
||||||
protected void applyTransform(Graphics2D graphics){
|
protected void applyTransform(Graphics2D graphics) {
|
||||||
Rectangle2D anchor = getAnchor();
|
Rectangle2D anchor = getAnchor();
|
||||||
|
|
||||||
// rotation
|
// rotation
|
||||||
double rotation = getRotation();
|
double rotation = getRotation();
|
||||||
if(rotation != 0.) {
|
if (rotation != 0.) {
|
||||||
// PowerPoint rotates shapes relative to the geometric center
|
// PowerPoint rotates shapes relative to the geometric center
|
||||||
double centerX = anchor.getX() + anchor.getWidth()/2;
|
double centerX = anchor.getX() + anchor.getWidth() / 2;
|
||||||
double centerY = anchor.getY() + anchor.getHeight()/2;
|
double centerY = anchor.getY() + anchor.getHeight() / 2;
|
||||||
|
|
||||||
graphics.translate(centerX, centerY);
|
graphics.translate(centerX, centerY);
|
||||||
graphics.rotate(Math.toRadians(rotation));
|
graphics.rotate(Math.toRadians(rotation));
|
||||||
@ -148,18 +145,34 @@ public abstract class XSLFShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//flip horizontal
|
//flip horizontal
|
||||||
if(getFlipHorizontal()){
|
if (getFlipHorizontal()) {
|
||||||
graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
|
graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
|
||||||
graphics.scale(-1, 1);
|
graphics.scale(-1, 1);
|
||||||
graphics.translate(-anchor.getX() , -anchor.getY());
|
graphics.translate(-anchor.getX(), -anchor.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
//flip vertical
|
//flip vertical
|
||||||
if(getFlipVertical()){
|
if (getFlipVertical()) {
|
||||||
graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
|
graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
|
||||||
graphics.scale(1, -1);
|
graphics.scale(1, -1);
|
||||||
graphics.translate(-anchor.getX(), -anchor.getY());
|
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;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
import org.apache.poi.POIXMLDocumentPart;
|
import org.apache.poi.POIXMLDocumentPart;
|
||||||
|
import org.apache.poi.POIXMLException;
|
||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||||
import org.apache.poi.openxml4j.opc.TargetMode;
|
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.Beta;
|
||||||
import org.apache.poi.util.Internal;
|
import org.apache.poi.util.Internal;
|
||||||
import org.apache.xmlbeans.XmlObject;
|
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.
|
* 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
|
* @param src the source sheet to copy data from
|
||||||
|
* @return modified 'this'
|
||||||
*/
|
*/
|
||||||
public void copy(XSLFSheet src){
|
public XSLFSheet importContent(XSLFSheet src){
|
||||||
_shapes = null;
|
_shapes = null;
|
||||||
_spTree = null;
|
_spTree = null;
|
||||||
_drawing = null;
|
_drawing = null;
|
||||||
|
// first copy the source xml
|
||||||
getXmlObject().set(src.getXmlObject());
|
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.Outline;
|
||||||
import org.apache.poi.xslf.model.geom.Path;
|
import org.apache.poi.xslf.model.geom.Path;
|
||||||
import org.apache.poi.xslf.model.geom.PresetGeometries;
|
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.apache.xmlbeans.XmlObject;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide;
|
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.STLineCap;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
|
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
|
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.CTPlaceholder;
|
||||||
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
||||||
|
import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
@ -69,6 +76,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@Beta
|
@Beta
|
||||||
public abstract class XSLFSimpleShape extends XSLFShape {
|
public abstract class XSLFSimpleShape extends XSLFShape {
|
||||||
|
private static CTOuterShadowEffect NO_SHADOW = CTOuterShadowEffect.Factory.newInstance();
|
||||||
|
|
||||||
private final XmlObject _shape;
|
private final XmlObject _shape;
|
||||||
private final XSLFSheet _sheet;
|
private final XSLFSheet _sheet;
|
||||||
@ -285,6 +293,11 @@ public abstract class XSLFSimpleShape extends XSLFShape {
|
|||||||
CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln
|
CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln
|
||||||
.getSolidFill() : ln.addNewSolidFill();
|
.getSolidFill() : ln.addNewSolidFill();
|
||||||
fill.setSrgbClr(rgb);
|
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()});
|
(byte) color.getGreen(), (byte) color.getBlue()});
|
||||||
|
|
||||||
fill.setSrgbClr(rgb);
|
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();
|
CTShapeProperties spPr = shape.getSpPr();
|
||||||
if (spPr.isSetEffectLst()) {
|
if (spPr.isSetEffectLst()) {
|
||||||
CTOuterShadowEffect obj = spPr.getEffectLst().getOuterShdw();
|
CTOuterShadowEffect obj = spPr.getEffectLst().getOuterShdw();
|
||||||
setValue(obj);
|
setValue(obj == null ? NO_SHADOW : obj);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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
|
@Override
|
||||||
@ -640,4 +658,50 @@ public abstract class XSLFSimpleShape extends XSLFShape {
|
|||||||
public void drawContent(Graphics2D graphics){
|
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.CTNonVisualDrawingProps;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
|
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.CTCommonSlideData;
|
||||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
|
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
|
||||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual;
|
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual;
|
||||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;
|
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;
|
||||||
import org.openxmlformats.schemas.presentationml.x2006.main.SldDocument;
|
import org.openxmlformats.schemas.presentationml.x2006.main.SldDocument;
|
||||||
|
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;
|
||||||
|
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.io.IOException;
|
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.CTTextParagraphProperties;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;
|
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.CTPlaceholder;
|
||||||
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
||||||
|
|
||||||
@ -56,20 +62,33 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||||||
private final XSLFTextShape _shape;
|
private final XSLFTextShape _shape;
|
||||||
private List<TextFragment> _lines;
|
private List<TextFragment> _lines;
|
||||||
private TextFragment _bullet;
|
private TextFragment _bullet;
|
||||||
|
/**
|
||||||
|
* the highest line in this paragraph. Used for line spacing.
|
||||||
|
*/
|
||||||
|
private double _maxLineHeight;
|
||||||
|
|
||||||
XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){
|
XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){
|
||||||
_p = p;
|
_p = p;
|
||||||
_runs = new ArrayList<XSLFTextRun>();
|
_runs = new ArrayList<XSLFTextRun>();
|
||||||
_shape = shape;
|
_shape = shape;
|
||||||
|
|
||||||
for (CTRegularTextRun r : _p.getRList()) {
|
for(XmlObject ch : _p.selectPath("*")){
|
||||||
_runs.add(new XSLFTextRun(r, this));
|
if(ch instanceof CTRegularTextRun){
|
||||||
}
|
CTRegularTextRun r = (CTRegularTextRun)ch;
|
||||||
|
_runs.add(new XSLFTextRun(r, this));
|
||||||
for (CTTextField f : _p.getFldList()) {
|
} else if (ch instanceof CTTextLineBreak){
|
||||||
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
|
CTTextLineBreak br = (CTTextLineBreak)ch;
|
||||||
r.setT(f.getT());
|
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
|
||||||
_runs.add(new XSLFTextRun(r, this));
|
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();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getVisibleText(){
|
String getRenderableText(){
|
||||||
StringBuilder out = new StringBuilder();
|
StringBuilder out = new StringBuilder();
|
||||||
for (XSLFTextRun r : _runs) {
|
for (XSLFTextRun r : _runs) {
|
||||||
String txt = r.getText();
|
out.append(r.getRenderableText());
|
||||||
switch (r.getTextCap()){
|
|
||||||
case ALL:
|
|
||||||
txt = txt.toUpperCase();
|
|
||||||
break;
|
|
||||||
case SMALL:
|
|
||||||
txt = txt.toLowerCase();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
out.append(txt);
|
|
||||||
}
|
}
|
||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
@ -183,6 +193,12 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||||||
return fetcher.getValue();
|
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
|
* @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();
|
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(){
|
public Color getBulletFontColor(){
|
||||||
final XSLFTheme theme = getParentShape().getSheet().getTheme();
|
final XSLFTheme theme = getParentShape().getSheet().getTheme();
|
||||||
ParagraphPropertyFetcher<Color> fetcher = new ParagraphPropertyFetcher<Color>(getLevel()){
|
ParagraphPropertyFetcher<Color> fetcher = new ParagraphPropertyFetcher<Color>(getLevel()){
|
||||||
@ -216,6 +238,13 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||||||
return fetcher.getValue();
|
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(){
|
public double getBulletFontSize(){
|
||||||
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
|
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
|
||||||
public boolean fetch(CTTextParagraphProperties props){
|
public boolean fetch(CTTextParagraphProperties props){
|
||||||
@ -234,11 +263,17 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||||||
return fetcher.getValue() == null ? 100 : fetcher.getValue();
|
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.
|
* 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
|
* @param value the indent in points.
|
||||||
* from the underlying xml bean.
|
|
||||||
*/
|
*/
|
||||||
public void setIndent(double value){
|
public void setIndent(double value){
|
||||||
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
|
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
|
||||||
@ -297,7 +332,8 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetchParagraphProperty(fetcher);
|
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) {
|
public void setBullet(boolean flag) {
|
||||||
if(isBullet() == flag) return;
|
if(isBullet() == flag) return;
|
||||||
@ -535,38 +571,117 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||||||
return _lines;
|
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){
|
public double draw(Graphics2D graphics, double x, double y){
|
||||||
double marginLeft = _shape.getLeftInset();
|
double leftInset = _shape.getLeftInset();
|
||||||
double marginRight = _shape.getRightInset();
|
double rightInset = _shape.getRightInset();
|
||||||
Rectangle2D anchor = _shape.getAnchor();
|
Rectangle2D anchor = _shape.getAnchor();
|
||||||
double penY = y;
|
double penY = y;
|
||||||
|
|
||||||
double textOffset = getLeftMargin();
|
double leftMargin = getLeftMargin();
|
||||||
boolean firstLine = true;
|
boolean firstLine = true;
|
||||||
|
double indent = getIndent();
|
||||||
for(TextFragment line : _lines){
|
for(TextFragment line : _lines){
|
||||||
double penX = x;
|
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()) {
|
switch (getTextAlign()) {
|
||||||
case CENTER:
|
case CENTER:
|
||||||
penX += textOffset + (anchor.getWidth() - textOffset - line.getWidth() - marginLeft - marginRight) / 2;
|
penX += (anchor.getWidth() - leftMargin - line.getWidth() - leftInset - rightInset) / 2;
|
||||||
break;
|
break;
|
||||||
case RIGHT:
|
case RIGHT:
|
||||||
penX += (anchor.getWidth() - line.getWidth() - marginLeft - marginRight);
|
penX += (anchor.getWidth() - line.getWidth() - leftInset - rightInset);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
penX = x + textOffset;
|
//penX += leftInset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_bullet != null && firstLine){
|
|
||||||
_bullet.draw(graphics, penX + getIndent(), penY);
|
|
||||||
}
|
|
||||||
line.draw(graphics, penX, penY);
|
line.draw(graphics, penX, penY);
|
||||||
|
|
||||||
//The vertical line spacing
|
//The vertical line spacing
|
||||||
double spacing = getLineSpacing();
|
double spacing = getLineSpacing();
|
||||||
if(spacing > 0) {
|
if(spacing > 0) {
|
||||||
// If linespacing >= 0, then linespacing is a percentage of normal line height.
|
// If linespacing >= 0, then linespacing is a percentage of normal line height.
|
||||||
penY += spacing*0.01*line.getHeight();
|
penY += spacing*0.01* _maxLineHeight;
|
||||||
} else {
|
} else {
|
||||||
// positive value means absolute spacing in points
|
// positive value means absolute spacing in points
|
||||||
penY += -spacing;
|
penY += -spacing;
|
||||||
@ -607,13 +722,13 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
AttributedString getAttributedString(Graphics2D graphics){
|
AttributedString getAttributedString(Graphics2D graphics){
|
||||||
String text = getVisibleText();
|
String text = getRenderableText();
|
||||||
|
|
||||||
AttributedString string = new AttributedString(text);
|
AttributedString string = new AttributedString(text);
|
||||||
|
|
||||||
int startIndex = 0;
|
int startIndex = 0;
|
||||||
for (XSLFTextRun run : _runs){
|
for (XSLFTextRun run : _runs){
|
||||||
int length = run.getText().length();
|
int length = run.getRenderableText().length();
|
||||||
if(length == 0) {
|
if(length == 0) {
|
||||||
// skip empty runs
|
// skip empty runs
|
||||||
continue;
|
continue;
|
||||||
@ -656,6 +771,7 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||||||
void breakText(Graphics2D graphics){
|
void breakText(Graphics2D graphics){
|
||||||
_lines = new ArrayList<TextFragment>();
|
_lines = new ArrayList<TextFragment>();
|
||||||
|
|
||||||
|
String text = getRenderableText();
|
||||||
AttributedString at = getAttributedString(graphics);
|
AttributedString at = getAttributedString(graphics);
|
||||||
AttributedCharacterIterator it = at.getIterator();
|
AttributedCharacterIterator it = at.getIterator();
|
||||||
if(it.getBeginIndex() == it.getEndIndex()) {
|
if(it.getBeginIndex() == it.getEndIndex()) {
|
||||||
@ -664,12 +780,17 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||||||
LineBreakMeasurer measurer = new LineBreakMeasurer(it, graphics.getFontRenderContext());
|
LineBreakMeasurer measurer = new LineBreakMeasurer(it, graphics.getFontRenderContext());
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int startIndex = measurer.getPosition();
|
int startIndex = measurer.getPosition();
|
||||||
double wrappingWidth = getWrappingWidth() + 1; // add a pixel to compensate rounding errors
|
double wrappingWidth = getWrappingWidth(_lines.size() == 0) + 1; // add a pixel to compensate rounding errors
|
||||||
TextLayout layout = measurer.nextLayout((float)wrappingWidth, it.getEndIndex(), true);
|
|
||||||
|
|
||||||
|
int nextBreak = text.indexOf('\n', startIndex + 1);
|
||||||
|
if(nextBreak == -1) nextBreak = it.getEndIndex();
|
||||||
|
|
||||||
|
TextLayout layout = measurer.nextLayout((float)wrappingWidth, nextBreak, true);
|
||||||
if (layout == null) {
|
if (layout == null) {
|
||||||
// layout can be null if the entire word at the current position
|
// layout can be null if the entire word at the current position
|
||||||
// does not fit within the wrapping width. Try with requireNextWord=false.
|
// 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();
|
int endIndex = measurer.getPosition();
|
||||||
@ -683,6 +804,8 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||||||
TextFragment line = new TextFragment(layout, str);
|
TextFragment line = new TextFragment(layout, str);
|
||||||
_lines.add(line);
|
_lines.add(line);
|
||||||
|
|
||||||
|
_maxLineHeight = Math.max(_maxLineHeight, line.getHeight());
|
||||||
|
|
||||||
if(endIndex == it.getEndIndex()) break;
|
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(){
|
CTTextParagraphProperties getDefaultStyle(){
|
||||||
CTPlaceholder ph = _shape.getCTPlaceholder();
|
CTPlaceholder ph = _shape.getCTPlaceholder();
|
||||||
String defaultStyleSelector;
|
String defaultStyleSelector;
|
||||||
@ -782,4 +894,64 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
|||||||
return ok;
|
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();
|
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){
|
public void setText(String text){
|
||||||
_r.setT(text);
|
_r.setT(text);
|
||||||
}
|
}
|
||||||
@ -69,6 +86,13 @@ public class XSLFTextRun {
|
|||||||
CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill();
|
CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill();
|
||||||
CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr();
|
CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr();
|
||||||
clr.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});
|
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(){
|
public Color getFontColor(){
|
||||||
@ -393,4 +417,32 @@ public class XSLFTextRun {
|
|||||||
return ok;
|
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);
|
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);
|
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);
|
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);
|
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;
|
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 junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.poi.xslf.XSLFTestDataSamples;
|
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
|
* @author Yegor Kozlov
|
||||||
@ -103,4 +109,58 @@ public class TestXSLFSlide extends TestCase {
|
|||||||
assertTrue(slide.getFollowMasterGraphics());
|
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()));
|
||||||
|
}
|
||||||
}
|
}
|
105
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java
Executable file
105
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java
Executable file
@ -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
Block a user