diff --git a/src/scratchpad/examples/src/org/apache/poi/hslf/examples/PPT2PNG.java b/src/scratchpad/examples/src/org/apache/poi/hslf/examples/PPT2PNG.java index aa8145051..8a7529712 100755 --- a/src/scratchpad/examples/src/org/apache/poi/hslf/examples/PPT2PNG.java +++ b/src/scratchpad/examples/src/org/apache/poi/hslf/examples/PPT2PNG.java @@ -83,6 +83,11 @@ public class PPT2PNG { BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = img.createGraphics(); + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + graphics.setPaint(Color.white); graphics.fill(new Rectangle2D.Float(0, 0, width, height)); diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java index dc5f798cd..299fe5522 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java @@ -108,9 +108,9 @@ public class AutoShape extends TextShape { public java.awt.Shape getOutline(){ ShapeOutline outline = AutoShapes.getShapeOutline(getShapeType()); - Rectangle2D anchor = getAnchor2D(); + Rectangle2D anchor = getLogicalAnchor2D(); if(outline == null){ - logger.log(POILogger.WARN, "getOutline() is not implemented for " + ShapeTypes.typeName(getShapeType())); + logger.log(POILogger.WARN, "Outline not found for " + ShapeTypes.typeName(getShapeType())); return anchor; } else { java.awt.Shape shape = outline.getOutline(this); diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/AutoShapes.java b/src/scratchpad/src/org/apache/poi/hslf/model/AutoShapes.java index 9d9f5e204..5d345e6de 100755 --- a/src/scratchpad/src/org/apache/poi/hslf/model/AutoShapes.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/AutoShapes.java @@ -288,6 +288,86 @@ public class AutoShapes { return path; } }; - } + shapes[ShapeTypes.Can] = new ShapeOutline(){ + public java.awt.Shape getOutline(Shape shape){ + //m10800,qx0@1l0@2qy10800,21600,21600@2l21600@1qy10800,xem0@1qy10800@0,21600@1nfe + int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 5400); + + GeneralPath path = new GeneralPath(); + + path.append(new Arc2D.Float(0, 0, 21600, adjval, 0, 180, Arc2D.OPEN), false); + path.moveTo(0, adjval/2); + + path.lineTo(0, 21600 - adjval/2); + path.closePath(); + + path.append(new Arc2D.Float(0, 21600 - adjval, 21600, adjval, 180, 180, Arc2D.OPEN), false); + path.moveTo(21600, 21600 - adjval/2); + + path.lineTo(21600, adjval/2); + path.append(new Arc2D.Float(0, 0, 21600, adjval, 180, 180, Arc2D.OPEN), false); + path.moveTo(0, adjval/2); + path.closePath(); + return path; + } + }; + + shapes[ShapeTypes.LeftBrace] = new ShapeOutline(){ + public java.awt.Shape getOutline(Shape shape){ + //m21600,qx10800@0l10800@2qy0@11,10800@3l10800@1qy21600,21600e + int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 1800); + int adjval2 = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUST2VALUE, 10800); + + GeneralPath path = new GeneralPath(); + path.moveTo(21600, 0); + + path.append(new Arc2D.Float(10800, 0, 21600, adjval*2, 90, 90, Arc2D.OPEN), false); + path.moveTo(10800, adjval); + + path.lineTo(10800, adjval2 - adjval); + + path.append(new Arc2D.Float(-10800, adjval2 - 2*adjval, 21600, adjval*2, 270, 90, Arc2D.OPEN), false); + path.moveTo(0, adjval2); + + path.append(new Arc2D.Float(-10800, adjval2, 21600, adjval*2, 0, 90, Arc2D.OPEN), false); + path.moveTo(10800, adjval2 + adjval); + + path.lineTo(10800, 21600 - adjval); + + path.append(new Arc2D.Float(10800, 21600 - 2*adjval, 21600, adjval*2, 180, 90, Arc2D.OPEN), false); + + return path; + } + }; + + shapes[ShapeTypes.RightBrace] = new ShapeOutline(){ + public java.awt.Shape getOutline(Shape shape){ + //m,qx10800@0 l10800@2qy21600@11,10800@3l10800@1qy,21600e + int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 1800); + int adjval2 = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUST2VALUE, 10800); + + GeneralPath path = new GeneralPath(); + path.moveTo(0, 0); + + path.append(new Arc2D.Float(-10800, 0, 21600, adjval*2, 0, 90, Arc2D.OPEN), false); + path.moveTo(10800, adjval); + + path.lineTo(10800, adjval2 - adjval); + + path.append(new Arc2D.Float(10800, adjval2 - 2*adjval, 21600, adjval*2, 180, 90, Arc2D.OPEN), false); + path.moveTo(21600, adjval2); + + path.append(new Arc2D.Float(10800, adjval2, 21600, adjval*2, 90, 90, Arc2D.OPEN), false); + path.moveTo(10800, adjval2 + adjval); + + path.lineTo(10800, 21600 - adjval); + + path.append(new Arc2D.Float(-10800, 21600 - 2*adjval, 21600, adjval*2, 270, 90, Arc2D.OPEN), false); + + return path; + } + }; + + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Line.java b/src/scratchpad/src/org/apache/poi/hslf/model/Line.java index 073efa395..370da96d6 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Line.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Line.java @@ -130,7 +130,7 @@ public class Line extends SimpleShape { } public java.awt.Shape getOutline(){ - Rectangle2D anchor = getAnchor2D(); + Rectangle2D anchor = getLogicalAnchor2D(); return new Line2D.Double(anchor.getX(), anchor.getY(), anchor.getX() + anchor.getWidth(), anchor.getY() + anchor.getHeight()); } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java b/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java index d4975df42..e96e34900 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java @@ -198,6 +198,10 @@ public abstract class Shape { return anchor; } + public Rectangle2D getLogicalAnchor2D(){ + return getAnchor2D(); + } + /** * Sets the anchor (the bounding box rectangle) of this shape. * All coordinates should be expressed in points (72 dpi). @@ -466,6 +470,6 @@ public abstract class Shape { * @return the shape outline */ public java.awt.Shape getOutline(){ - return getAnchor2D(); + return getLogicalAnchor2D(); } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java index a0fbb114d..b57a6e233 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java @@ -237,7 +237,7 @@ public class ShapeGroup extends Shape{ EscherClientAnchorRecord clientAnchor = (EscherClientAnchorRecord)getEscherChild(spContainer, EscherClientAnchorRecord.RECORD_ID); Rectangle2D.Float anchor = new Rectangle2D.Float(); if(clientAnchor == null){ - logger.log(POILogger.WARN, "EscherClientAnchorRecord was not found for the shape group"); + logger.log(POILogger.INFO, "EscherClientAnchorRecord was not found for shape group. Searching for EscherChildAnchorRecord."); EscherChildAnchorRecord rec = (EscherChildAnchorRecord)getEscherChild(spContainer, EscherChildAnchorRecord.RECORD_ID); anchor = new Rectangle2D.Float( (float)rec.getDx1()*POINT_DPI/MASTER_DPI, @@ -282,7 +282,7 @@ public class ShapeGroup extends Shape{ //transform coordinates AffineTransform at = graphics.getTransform(); - + /* if(!anchor.equals(coords)){ graphics.scale(anchor.getWidth()/coords.getWidth(), anchor.getHeight()/coords.getHeight()); @@ -290,7 +290,7 @@ public class ShapeGroup extends Shape{ anchor.getX()*coords.getWidth()/anchor.getWidth() - coords.getX(), anchor.getY()*coords.getHeight()/anchor.getHeight() - coords.getY()); } - + */ Shape[] sh = getShapes(); for (int i = 0; i < sh.length; i++) { sh[i].draw(graphics); diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ShapePainter.java b/src/scratchpad/src/org/apache/poi/hslf/model/ShapePainter.java index b50b4f7ca..fa947ddfe 100755 --- a/src/scratchpad/src/org/apache/poi/hslf/model/ShapePainter.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/ShapePainter.java @@ -32,7 +32,7 @@ public class ShapePainter { protected static POILogger logger = POILogFactory.getLogger(ShapePainter.class); public static void paint(SimpleShape shape, Graphics2D graphics){ - Rectangle2D anchor = shape.getAnchor2D(); + Rectangle2D anchor = shape.getLogicalAnchor2D(); java.awt.Shape outline = shape.getOutline(); //flip vertical diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java index 0155ca3f5..ea0719a7f 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java @@ -23,6 +23,7 @@ import org.apache.poi.hslf.record.ColorSchemeAtom; import java.awt.*; import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; /** * An abstract simple (non-group) shape. @@ -232,6 +233,52 @@ public class SimpleShape extends Shape { return angle; } + public Rectangle2D getLogicalAnchor2D(){ + Rectangle2D anchor = getAnchor2D(); + + //if it is a groupped shape see if we need to transform the coordinates + if (_parent != null){ + Shape top = _parent; + while(top.getParent() != null) top = top.getParent(); + + Rectangle2D clientAnchor = top.getAnchor2D(); + Rectangle2D spgrAnchor = ((ShapeGroup)top).getCoordinates(); + + double scalex = (double)spgrAnchor.getWidth()/clientAnchor.getWidth(); + double scaley = (double)spgrAnchor.getHeight()/clientAnchor.getHeight(); + + double x = clientAnchor.getX() + (anchor.getX() - spgrAnchor.getX())/scalex; + double y = clientAnchor.getY() + (anchor.getY() - spgrAnchor.getY())/scaley; + double width = anchor.getWidth()/scalex; + double height = anchor.getHeight()/scaley; + + anchor = new Rectangle2D.Double(x, y, width, height); + + } + + int angle = getRotation(); + if(angle != 0){ + double centerX = anchor.getX() + anchor.getWidth()/2; + double centerY = anchor.getY() + anchor.getHeight()/2; + + AffineTransform trans = new AffineTransform(); + trans.translate(centerX, centerY); + trans.rotate(Math.toRadians(angle)); + trans.translate(-centerX, -centerY); + + Rectangle2D rect = trans.createTransformedShape(anchor).getBounds2D(); + if((anchor.getWidth() < anchor.getHeight() && rect.getWidth() > rect.getHeight()) || + (anchor.getWidth() > anchor.getHeight() && rect.getWidth() < rect.getHeight()) ){ + trans = new AffineTransform(); + trans.translate(centerX, centerY); + trans.rotate(Math.PI/2); + trans.translate(-centerX, -centerY); + anchor = trans.createTransformedShape(anchor).getBounds2D(); + } + } + return anchor; + } + public void draw(Graphics2D graphics){ AffineTransform at = graphics.getTransform(); ShapePainter.paint(this, graphics); diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextPainter.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextPainter.java index 7d23c7cfb..c1eadc336 100755 --- a/src/scratchpad/src/org/apache/poi/hslf/model/TextPainter.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextPainter.java @@ -54,7 +54,10 @@ public class TextPainter { for (int i = 0; i < rt.length; i++) { int start = rt[i].getStartIndex(); int end = rt[i].getEndIndex(); - if(start == end) continue; + if(start == end) { + logger.log(POILogger.INFO, "Skipping RichTextRun with zero length"); + continue; + } at.addAttribute(TextAttribute.FAMILY, rt[i].getFontName(), start, end); at.addAttribute(TextAttribute.SIZE, new Float(rt[i].getFontSize()), start, end); @@ -86,7 +89,7 @@ public class TextPainter { int paragraphStart = it.getBeginIndex(); int paragraphEnd = it.getEndIndex(); - Rectangle2D anchor = _shape.getAnchor2D(); + Rectangle2D anchor = _shape.getLogicalAnchor2D(); float textHeight = 0; ArrayList lines = new ArrayList(); @@ -115,7 +118,7 @@ public class TextPainter { TextLayout textLayout = measurer.nextLayout(wrappingWidth + 1, nextBreak == -1 ? paragraphEnd : nextBreak, true); if (textLayout == null) { - textLayout = measurer.nextLayout(wrappingWidth, + textLayout = measurer.nextLayout((float)anchor.getWidth(), nextBreak == -1 ? paragraphEnd : nextBreak, false); } if(textLayout == null){ @@ -175,9 +178,12 @@ public class TextPainter { if(rt.isBullet() && (prStart || startIndex == 0)){ it.setIndex(startIndex); - AttributedString bat = new AttributedString(Character.toString(rt.getBulletChar()), it.getAttributes()); + AttributedString bat = new AttributedString(Character.toString(rt.getBulletChar())); Color clr = rt.getBulletColor(); if (clr != null) bat.addAttribute(TextAttribute.FOREGROUND, clr); + else bat.addAttribute(TextAttribute.FOREGROUND, it.getAttribute(TextAttribute.FOREGROUND)); + bat.addAttribute(TextAttribute.FAMILY, it.getAttribute(TextAttribute.FAMILY)); + bat.addAttribute(TextAttribute.SIZE, it.getAttribute(TextAttribute.SIZE)); TextLayout bulletLayout = new TextLayout(bat.getIterator(), graphics.getFontRenderContext()); if(text.substring(startIndex, endIndex).length() > 1){