Return-Path: X-Original-To: apmail-poi-commits-archive@minotaur.apache.org Delivered-To: apmail-poi-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 96A3694AB for ; Thu, 10 Nov 2011 13:59:48 +0000 (UTC) Received: (qmail 8619 invoked by uid 500); 10 Nov 2011 13:59:48 -0000 Delivered-To: apmail-poi-commits-archive@poi.apache.org Received: (qmail 8577 invoked by uid 500); 10 Nov 2011 13:59:48 -0000 Mailing-List: contact commits-help@poi.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@poi.apache.org Delivered-To: mailing list commits@poi.apache.org Received: (qmail 8570 invoked by uid 99); 10 Nov 2011 13:59:48 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 10 Nov 2011 13:59:48 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 10 Nov 2011 13:59:40 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 4BF822388978 for ; Thu, 10 Nov 2011 13:59:18 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1200330 - in /poi/trunk: src/ooxml/java/org/apache/poi/xslf/usermodel/ src/ooxml/testcases/org/apache/poi/xslf/usermodel/ test-data/slideshow/ Date: Thu, 10 Nov 2011 13:59:17 -0000 To: commits@poi.apache.org From: yegor@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111110135918.4BF822388978@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: yegor Date: Thu Nov 10 13:59:16 2011 New Revision: 1200330 URL: http://svn.apache.org/viewvc?rev=1200330&view=rev Log: improved rendering of indented text in XSLF, also improved import content from external slides Added: poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java (with props) Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/LineCap.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/RenderableShape.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java poi/trunk/test-data/slideshow/themes.pptx Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/LineCap.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/LineCap.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/LineCap.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/LineCap.java Thu Nov 10 13:59:16 2011 @@ -17,11 +17,13 @@ package org.apache.poi.xslf.usermodel; /** + * + * * @author Yegor Kozlov */ public enum LineCap { /** - * Rounded ends - the default + * Rounded ends */ ROUND, /** Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/RenderableShape.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/RenderableShape.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/RenderableShape.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/RenderableShape.java Thu Nov 10 13:59:16 2011 @@ -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()); } Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java Thu Nov 10 13:59:16 2011 @@ -331,4 +331,12 @@ public class XSLFConnectorShape extends return lst; } + /** + * YK: dashing of lines is suppressed for now. + * @return + */ + @Override + public XSLFShadow getShadow() { + return null; + } } \ No newline at end of file Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java Thu Nov 10 13:59:16 2011 @@ -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 XS 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 XS 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 XS 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); + + } } Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java Thu Nov 10 13:59:16 2011 @@ -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) { Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java Thu Nov 10 13:59:16 2011 @@ -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. *

- * 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. *

* * @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 *

@@ -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()); + } } \ No newline at end of file Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java Thu Nov 10 13:59:16 2011 @@ -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 /** * 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 tgtShapes = getShapeList(); + List 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 } } + + /** + * 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(); + } } \ No newline at end of file Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java Thu Nov 10 13:59:16 2011 @@ -29,6 +29,11 @@ import org.apache.poi.xslf.model.geom.IA 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.drawin 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 ex 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 ex (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 ex 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 ex } } } - 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 ex 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); + } + + } } Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java Thu Nov 10 13:59:16 2011 @@ -26,11 +26,13 @@ import org.openxmlformats.schemas.drawin 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 XSL } + @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; + } + } Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java Thu Nov 10 13:59:16 2011 @@ -27,6 +27,12 @@ import org.openxmlformats.schemas.drawin 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 implement private final XSLFTextShape _shape; private List _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(); _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 implement 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 implement 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 implement 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 fetcher = new ParagraphPropertyFetcher(getLevel()){ @@ -216,6 +238,13 @@ public class XSLFTextParagraph implement 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 fetcher = new ParagraphPropertyFetcher(getLevel()){ public boolean fetch(CTTextParagraphProperties props){ @@ -234,11 +263,17 @@ public class XSLFTextParagraph implement 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 implement } }; 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 implement /** * - * @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 implement 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 implement } 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 implement void breakText(Graphics2D graphics){ _lines = new ArrayList(); + String text = getRenderableText(); AttributedString at = getAttributedString(graphics); AttributedCharacterIterator it = at.getIterator(); if(it.getBeginIndex() == it.getEndIndex()) { @@ -664,12 +780,17 @@ public class XSLFTextParagraph implement 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 implement 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 implement } - 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 implement 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 srcR = p.getTextRuns(); + List tgtR = getTextRuns(); + for(int i = 0; i < srcR.size(); i++){ + XSLFTextRun r1 = srcR.get(i); + XSLFTextRun r2 = tgtR.get(i); + r2.copy(r1); + } + } } Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java Thu Nov 10 13:59:16 2011 @@ -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); + } } Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java Thu Nov 10 13:59:16 2011 @@ -202,7 +202,8 @@ public abstract class XSLFTextShape exte } }; 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 exte } }; 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 exte } }; 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 exte } }; 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 exte 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 srcP = tsh.getTextParagraphs(); + List tgtP = getTextParagraphs(); + for(int i = 0; i < srcP.size(); i++){ + XSLFTextParagraph p1 = srcP.get(i); + XSLFTextParagraph p2 = tgtP.get(i); + p2.copy(p1); + } + + } } \ No newline at end of file Modified: poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== --- poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java (original) +++ poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java Thu Nov 10 13:59:16 2011 @@ -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 TestC 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())); + } } \ No newline at end of file Added: poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java?rev=1200330&view=auto ============================================================================== --- poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java (added) +++ poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java Thu Nov 10 13:59:16 2011 @@ -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)); + } +} Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java ------------------------------------------------------------------------------ svn:executable = * Modified: poi/trunk/test-data/slideshow/themes.pptx URL: http://svn.apache.org/viewvc/poi/trunk/test-data/slideshow/themes.pptx?rev=1200330&r1=1200329&r2=1200330&view=diff ============================================================================== Binary files - no diff available. --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org For additional commands, e-mail: commits-help@poi.apache.org