git-svn-id: https://svn.apache.org/repos/asf/poi/branches/common_sl@1684773 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_13_FINAL
@@ -146,10 +146,10 @@ public final class ApacheconEU08 { | |||
{"Note"}, | |||
{"This presentation was created programmatically using POI HSLF"} | |||
}; | |||
Table table1 = new Table(2, 1); | |||
HSLFTable table1 = new HSLFTable(2, 1); | |||
for (int i = 0; i < txt1.length; i++) { | |||
for (int j = 0; j < txt1[i].length; j++) { | |||
TableCell cell = table1.getCell(i, j); | |||
HSLFTableCell cell = table1.getCell(i, j); | |||
cell.setText(txt1[i][j]); | |||
HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0); | |||
rt.setFontSize(10); |
@@ -50,7 +50,7 @@ public final class Graphics2DDemo { | |||
//define position of the drawing in the slide | |||
Rectangle bounds = new java.awt.Rectangle(200, 100, 350, 300); | |||
group.setAnchor(bounds); | |||
group.setCoordinates(new java.awt.Rectangle(0, 0, 100, 100)); | |||
group.setInteriorAnchor(new java.awt.Rectangle(0, 0, 100, 100)); | |||
slide.addShape(group); | |||
Graphics2D graphics = new PPGraphics2D(group); | |||
@@ -68,7 +68,7 @@ public final class Graphics2DDemo { | |||
} | |||
graphics.setColor(Color.black); | |||
graphics.setFont(new Font("Arial", Font.BOLD, 14)); | |||
graphics.draw(group.getCoordinates()); | |||
graphics.draw(group.getInteriorAnchor()); | |||
graphics.drawString("Performance", x + 30, y + 10); | |||
FileOutputStream out = new FileOutputStream("hslf-graphics.ppt"); |
@@ -49,10 +49,10 @@ public final class TableDemo { | |||
HSLFSlide slide = ppt.createSlide(); | |||
//six rows, two columns | |||
Table table1 = new Table(6, 2); | |||
HSLFTable table1 = new HSLFTable(6, 2); | |||
for (int i = 0; i < txt1.length; i++) { | |||
for (int j = 0; j < txt1[i].length; j++) { | |||
TableCell cell = table1.getCell(i, j); | |||
HSLFTableCell cell = table1.getCell(i, j); | |||
HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0); | |||
rt.setFontFamily("Arial"); | |||
rt.setFontSize(10); | |||
@@ -88,10 +88,10 @@ public final class TableDemo { | |||
}; | |||
//two rows, one column | |||
Table table2 = new Table(2, 1); | |||
HSLFTable table2 = new HSLFTable(2, 1); | |||
for (int i = 0; i < txt2.length; i++) { | |||
for (int j = 0; j < txt2[i].length; j++) { | |||
TableCell cell = table2.getCell(i, j); | |||
HSLFTableCell cell = table2.getCell(i, j); | |||
HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0); | |||
rt.setFontSize(10); | |||
rt.setFontFamily("Arial"); |
@@ -40,13 +40,26 @@ public class EscherChildAnchorRecord | |||
private int field_4_dy2; | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
/*int bytesRemaining =*/ readHeader( data, offset ); | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
int size = 0; | |||
field_1_dx1 = LittleEndian.getInt( data, pos + size );size+=4; | |||
field_2_dy1 = LittleEndian.getInt( data, pos + size );size+=4; | |||
field_3_dx2 = LittleEndian.getInt( data, pos + size );size+=4; | |||
field_4_dy2 = LittleEndian.getInt( data, pos + size );size+=4; | |||
switch (bytesRemaining) { | |||
case 16: // RectStruct | |||
field_1_dx1 = LittleEndian.getInt( data, pos + size );size+=4; | |||
field_2_dy1 = LittleEndian.getInt( data, pos + size );size+=4; | |||
field_3_dx2 = LittleEndian.getInt( data, pos + size );size+=4; | |||
field_4_dy2 = LittleEndian.getInt( data, pos + size );size+=4; | |||
break; | |||
case 8: // SmallRectStruct | |||
field_1_dx1 = LittleEndian.getShort( data, pos + size );size+=2; | |||
field_2_dy1 = LittleEndian.getShort( data, pos + size );size+=2; | |||
field_3_dx2 = LittleEndian.getShort( data, pos + size );size+=2; | |||
field_4_dy2 = LittleEndian.getShort( data, pos + size );size+=2; | |||
break; | |||
default: | |||
throw new RuntimeException("Invalid EscherChildAnchorRecord - neither 8 nor 16 bytes."); | |||
} | |||
return 8 + size; | |||
} | |||
@@ -58,8 +71,8 @@ public class EscherChildAnchorRecord | |||
LittleEndian.putInt( data, pos, getRecordSize()-8 ); pos += 4; | |||
LittleEndian.putInt( data, pos, field_1_dx1 ); pos += 4; | |||
LittleEndian.putInt( data, pos, field_2_dy1 ); pos += 4; | |||
LittleEndian.putInt( data, pos, field_3_dx2 ); pos += 4; | |||
LittleEndian.putInt( data, pos, field_4_dy2 ); pos += 4; | |||
LittleEndian.putInt( data, pos, field_3_dx2 ); pos += 4; | |||
LittleEndian.putInt( data, pos, field_4_dy2 ); pos += 4; | |||
listener.afterRecordSerialize( pos, getRecordId(), pos - offset, this ); | |||
return pos - offset; |
@@ -507,7 +507,7 @@ public final class EscherProperties { | |||
addProp(m, SHADOWSTYLE__ORIGINX, "shadowstyle.originx"); | |||
addProp(m, SHADOWSTYLE__ORIGINY, "shadowstyle.originy"); | |||
addProp(m, SHADOWSTYLE__SHADOW, "shadowstyle.shadow"); | |||
addProp(m, SHADOWSTYLE__SHADOWOBSURED, "shadowstyle.shadowobsured"); | |||
addProp(m, SHADOWSTYLE__SHADOWOBSURED, "shadowstyle.shadowobscured"); | |||
addProp(m, PERSPECTIVE__TYPE, "perspective.type"); | |||
addProp(m, PERSPECTIVE__OFFSETX, "perspective.offsetx"); | |||
addProp(m, PERSPECTIVE__OFFSETY, "perspective.offsety"); |
@@ -17,6 +17,7 @@ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.hslf.record.RecordTypes; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.RecordFormatException; | |||
@@ -32,7 +33,7 @@ import org.apache.poi.util.RecordFormatException; | |||
*/ | |||
public class EscherTextboxRecord extends EscherRecord | |||
{ | |||
public static final short RECORD_ID = (short)0xF00D; | |||
public static final short RECORD_ID = (short)RecordTypes.EscherClientTextbox; | |||
public static final String RECORD_DESCRIPTION = "msofbtClientTextbox"; | |||
private static final byte[] NO_BYTES = new byte[0]; |
@@ -28,6 +28,7 @@ import java.awt.image.ImageObserver; | |||
import java.awt.image.RenderedImage; | |||
import java.awt.image.renderable.RenderableImage; | |||
import java.text.AttributedCharacterIterator; | |||
import java.util.Arrays; | |||
import java.util.Map; | |||
public class DummyGraphics2d | |||
@@ -262,7 +263,7 @@ public class DummyGraphics2d | |||
public void setPaint( Paint paint ) | |||
{ | |||
System.out.println( "setPain(Paint):" ); | |||
System.out.println( "setPaint(Paint):" ); | |||
System.out.println( "paint = " + paint ); | |||
g2D.setPaint( paint ); | |||
} | |||
@@ -285,7 +286,19 @@ public class DummyGraphics2d | |||
public void setStroke(Stroke s) | |||
{ | |||
System.out.println( "setStroke(Stoke):" ); | |||
System.out.println( "s = " + s ); | |||
if (s instanceof BasicStroke) { | |||
BasicStroke bs = (BasicStroke)s; | |||
StringBuilder str = new StringBuilder("s = BasicStroke("); | |||
str.append("dash[]: "+Arrays.toString(bs.getDashArray())+", "); | |||
str.append("dashPhase: "+bs.getDashPhase()+", "); | |||
str.append("endCap: "+bs.getEndCap()+", "); | |||
str.append("lineJoin: "+bs.getLineJoin()+", "); | |||
str.append("width: "+bs.getLineWidth()+", "); | |||
str.append("miterLimit: "+bs.getMiterLimit()+")"); | |||
System.out.println(str.toString()); | |||
} else { | |||
System.out.println( "s = " + s ); | |||
} | |||
g2D.setStroke( s ); | |||
} | |||
@@ -25,8 +25,7 @@ import java.util.List; | |||
import java.util.regex.Pattern; | |||
import org.apache.poi.openxml4j.opc.*; | |||
import org.apache.poi.sl.usermodel.PlaceableShape; | |||
import org.apache.poi.sl.usermodel.ShapeGroup; | |||
import org.apache.poi.sl.usermodel.GroupShape; | |||
import org.apache.poi.util.*; | |||
import org.apache.xmlbeans.XmlObject; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.*; | |||
@@ -38,7 +37,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.*; | |||
* @author Yegor Kozlov | |||
*/ | |||
@Beta | |||
public class XSLFGroupShape extends XSLFShape implements XSLFShapeContainer, ShapeGroup<XSLFShape> { | |||
public class XSLFGroupShape extends XSLFShape implements XSLFShapeContainer, GroupShape<XSLFShape> { | |||
private static POILogger _logger = POILogFactory.getLogger(XSLFGroupShape.class); | |||
private final List<XSLFShape> _shapes; | |||
@@ -118,7 +117,7 @@ public class XSLFGroupShape extends XSLFShape implements XSLFShapeContainer, Sha | |||
* used for calculations of grouping, scaling, and rotation | |||
* behavior of shapes placed within a group. | |||
*/ | |||
public void setInteriorAnchor(Rectangle2D anchor){ | |||
public void setInteriorAnchor(Rectangle2D anchor) { | |||
CTGroupTransform2D xfrm = getSafeXfrm(); | |||
CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff(); | |||
long x = Units.toEMU(anchor.getX()); |
@@ -169,6 +169,7 @@ public class XSLFPictureShape extends XSLFSimpleShape implements PictureShape { | |||
return id; | |||
} | |||
@Override | |||
public Insets getClipping(){ | |||
CTPicture ct = (CTPicture)getXmlObject(); | |||
CTRelativeRect r = ct.getBlipFill().getSrcRect(); |
@@ -481,6 +481,7 @@ public abstract class XSLFSheet extends POIXMLDocumentPart implements XSLFShapeC | |||
* | |||
* @param graphics | |||
*/ | |||
@Override | |||
public void draw(Graphics2D graphics){ | |||
DrawFactory drawFact = DrawFactory.getInstance(graphics); | |||
Drawable draw = drawFact.getDrawable(this); |
@@ -21,7 +21,6 @@ import java.io.IOException; | |||
import org.apache.poi.POIXMLDocumentPart; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.sl.usermodel.Notes; | |||
import org.apache.poi.sl.usermodel.Slide; | |||
import org.apache.poi.util.Beta; | |||
import org.apache.xmlbeans.XmlException; |
@@ -1,95 +0,0 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hslf.blip; | |||
import org.apache.poi.hslf.usermodel.HSLFPictureData; | |||
import org.apache.poi.hslf.usermodel.HSLFPictureShape; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.POILogFactory; | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
import javax.imageio.ImageIO; | |||
import java.awt.*; | |||
import java.awt.geom.AffineTransform; | |||
import java.awt.image.BufferedImage; | |||
import java.io.ByteArrayInputStream; | |||
/** | |||
* Creates BufferedImage using javax.imageio.ImageIO and draws it in the specified graphics. | |||
* | |||
* @author Yegor Kozlov. | |||
*/ | |||
public final class BitmapPainter implements ImagePainter { | |||
protected POILogger logger = POILogFactory.getLogger(this.getClass()); | |||
public void paint(Graphics2D graphics, HSLFPictureData pict, HSLFPictureShape parent) { | |||
BufferedImage img; | |||
try { | |||
img = ImageIO.read(new ByteArrayInputStream(pict.getData())); | |||
} catch (Exception e) { | |||
logger.log(POILogger.WARN, "ImageIO failed to create image. image.type: " + pict.getType()); | |||
return; | |||
} | |||
boolean isClipped = true; | |||
Insets clip = parent.getBlipClip(); | |||
if (clip == null) { | |||
isClipped = false; | |||
clip = new Insets(0,0,0,0); | |||
} | |||
int iw = img.getWidth(); | |||
int ih = img.getHeight(); | |||
Rectangle anchor = parent.getLogicalAnchor2D().getBounds(); | |||
double cw = (100000-clip.left-clip.right) / 100000.0; | |||
double ch = (100000-clip.top-clip.bottom) / 100000.0; | |||
double sx = anchor.getWidth()/(iw*cw); | |||
double sy = anchor.getHeight()/(ih*ch); | |||
double tx = anchor.getX()-(iw*sx*clip.left/100000.0); | |||
double ty = anchor.getY()-(ih*sy*clip.top/100000.0); | |||
AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ; | |||
Shape clipOld = graphics.getClip(); | |||
if (isClipped) graphics.clip(anchor.getBounds2D()); | |||
graphics.drawRenderedImage(img, at); | |||
graphics.setClip(clipOld); | |||
} | |||
} |
@@ -1,72 +0,0 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hslf.blip; | |||
import org.apache.poi.hslf.usermodel.HSLFPictureData; | |||
import org.apache.poi.hslf.usermodel.HSLFPictureShape; | |||
import java.awt.*; | |||
/** | |||
* A common interface for objects that can render ppt picture data. | |||
* <p> | |||
* Subclasses can redefine it and use third-party libraries for actual rendering, | |||
* for example, Bitmaps can be rendered using javax.imageio.* , WMF can be rendered using Apache Batik, | |||
* PICT can be rendered using Apple QuickTime API for Java, etc. | |||
* </p> | |||
* | |||
* A typical usage is as follows: | |||
* <code> | |||
* public WMFPaiter implements ImagePainter{ | |||
* public void paint(Graphics2D graphics, PictureData pict, Picture parent){ | |||
* DataInputStream is = new DataInputStream(new ByteArrayInputStream(pict.getData())); | |||
* org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore wmfStore = | |||
* new org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore(); | |||
* try { | |||
* wmfStore.read(is); | |||
* } catch (IOException e){ | |||
* return; | |||
* } | |||
* | |||
* Rectangle anchor = parent.getAnchor(); | |||
* float scale = (float)anchor.width/wmfStore.getWidthPixels(); | |||
* | |||
* org.apache.batik.transcoder.wmf.tosvg.WMFPainter painter = | |||
* new org.apache.batik.transcoder.wmf.tosvg.WMFPainter(wmfStore, 0, 0, scale); | |||
* graphics.translate(anchor.x, anchor.y); | |||
* painter.paint(graphics); | |||
* } | |||
* } | |||
* PictureData.setImagePainter(Picture.WMF, new WMFPaiter()); | |||
* ... | |||
* </code> | |||
* Subsequent calls of Slide.draw(Graphics gr) will use WMFPaiter for WMF images. | |||
* | |||
* @author Yegor Kozlov. | |||
*/ | |||
public interface ImagePainter { | |||
/** | |||
* Paints the specified picture data | |||
* | |||
* @param graphics the graphics to paintb into | |||
* @param pict the data to paint | |||
* @param parent the shapes that owns the picture data | |||
*/ | |||
public void paint(Graphics2D graphics, HSLFPictureData pict, HSLFPictureShape parent); | |||
} |
@@ -247,8 +247,8 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor { | |||
// Table text | |||
for (HSLFShape shape : slide.getShapes()){ | |||
if (shape instanceof Table){ | |||
extractTableText(ret, (Table)shape); | |||
if (shape instanceof HSLFTable){ | |||
extractTableText(ret, (HSLFTable)shape); | |||
} | |||
} | |||
// Slide footer, if set | |||
@@ -305,10 +305,10 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor { | |||
return ret.toString(); | |||
} | |||
private void extractTableText(StringBuffer ret, Table table) { | |||
private void extractTableText(StringBuffer ret, HSLFTable table) { | |||
for (int row = 0; row < table.getNumberOfRows(); row++){ | |||
for (int col = 0; col < table.getNumberOfColumns(); col++){ | |||
TableCell cell = table.getCell(row, col); | |||
HSLFTableCell cell = table.getCell(row, col); | |||
//defensive null checks; don't know if they're necessary | |||
if (cell != null){ | |||
String txt = cell.getText(); |
@@ -22,8 +22,8 @@ import org.apache.poi.hslf.usermodel.*; | |||
import org.apache.poi.sl.usermodel.ShapeContainer; | |||
import org.apache.poi.sl.usermodel.ShapeType; | |||
import java.awt.geom.Rectangle2D; | |||
import java.awt.geom.Line2D; | |||
import java.awt.geom.*; | |||
import java.util.ArrayList; | |||
/** | |||
* Represents a line in a PowerPoint drawing | |||
@@ -69,4 +69,63 @@ public final class Line extends HSLFSimpleShape { | |||
Rectangle2D anchor = getLogicalAnchor2D(); | |||
return new Line2D.Double(anchor.getX(), anchor.getY(), anchor.getX() + anchor.getWidth(), anchor.getY() + anchor.getHeight()); | |||
} | |||
/** | |||
* | |||
* @return 'absolute' anchor of this shape relative to the parent sheet | |||
* | |||
* @deprecated TODO: remove the whole class, should work with preset geometries instead | |||
*/ | |||
public Rectangle2D getLogicalAnchor2D(){ | |||
Rectangle2D anchor = getAnchor2D(); | |||
//if it is a groupped shape see if we need to transform the coordinates | |||
if (getParent() != null){ | |||
ArrayList<HSLFGroupShape> lst = new ArrayList<HSLFGroupShape>(); | |||
for (ShapeContainer<HSLFShape> parent=this.getParent(); | |||
parent instanceof HSLFGroupShape; | |||
parent = ((HSLFGroupShape)parent).getParent()) { | |||
lst.add(0, (HSLFGroupShape)parent); | |||
} | |||
AffineTransform tx = new AffineTransform(); | |||
for(HSLFGroupShape prnt : lst) { | |||
Rectangle2D exterior = prnt.getAnchor2D(); | |||
Rectangle2D interior = prnt.getInteriorAnchor(); | |||
double scaleX = exterior.getWidth() / interior.getWidth(); | |||
double scaleY = exterior.getHeight() / interior.getHeight(); | |||
tx.translate(exterior.getX(), exterior.getY()); | |||
tx.scale(scaleX, scaleY); | |||
tx.translate(-interior.getX(), -interior.getY()); | |||
} | |||
anchor = tx.createTransformedShape(anchor).getBounds2D(); | |||
} | |||
double 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; | |||
} | |||
} |
@@ -285,6 +285,7 @@ public class TextPropCollection { | |||
* Clones the given text properties | |||
*/ | |||
public void copy(TextPropCollection other) { | |||
if (this == other) return; | |||
this.charactersCovered = other.charactersCovered; | |||
this.indentLevel = other.indentLevel; | |||
this.maskSpecial = other.maskSpecial; |
@@ -87,9 +87,7 @@ public final class EscherTextboxWrapper extends RecordContainer { | |||
// Grab the children's data | |||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||
for(int i=0; i<_children.length; i++) { | |||
_children[i].writeOut(baos); | |||
} | |||
for (Record r : _children) r.writeOut(baos); | |||
byte[] data = baos.toByteArray(); | |||
// Save in the escher layer |
@@ -97,7 +97,7 @@ public final class PPDrawing extends RecordAtom { | |||
findEscherChildren(erf, contents, 8, len-8, escherChildren); | |||
this.childRecords = escherChildren.toArray(new EscherRecord[escherChildren.size()]); | |||
if (1 == this.childRecords.length && (short)0xf002 == this.childRecords[0].getRecordId() && this.childRecords[0] instanceof EscherContainerRecord) { | |||
if (1 == this.childRecords.length && (short)RecordTypes.EscherDgContainer == this.childRecords[0].getRecordId() && this.childRecords[0] instanceof EscherContainerRecord) { | |||
this.textboxWrappers = findInDgContainer((EscherContainerRecord) this.childRecords[0]); | |||
} else { | |||
// Find and EscherTextboxRecord's, and wrap them up | |||
@@ -106,37 +106,30 @@ public final class PPDrawing extends RecordAtom { | |||
this.textboxWrappers = textboxes.toArray(new EscherTextboxWrapper[textboxes.size()]); | |||
} | |||
} | |||
private EscherTextboxWrapper[] findInDgContainer(final EscherContainerRecord escherContainerF002) { | |||
private EscherTextboxWrapper[] findInDgContainer(final EscherContainerRecord dgContainer) { | |||
final List<EscherTextboxWrapper> found = new LinkedList<EscherTextboxWrapper>(); | |||
final EscherContainerRecord SpgrContainer = findFirstEscherContainerRecordOfType((short)0xf003, escherContainerF002); | |||
final EscherContainerRecord[] escherContainersF004 = findAllEscherContainerRecordOfType((short)0xf004, SpgrContainer); | |||
for (EscherContainerRecord spContainer : escherContainersF004) { | |||
final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherSpgrContainer, dgContainer); | |||
final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType((short)RecordTypes.EscherSpContainer, spgrContainer); | |||
for (EscherContainerRecord spContainer : spContainers) { | |||
StyleTextProp9Atom nineAtom = findInSpContainer(spContainer); | |||
EscherSpRecord sp = null; | |||
final EscherRecord escherContainerF00A = findFirstEscherRecordOfType((short)0xf00a, spContainer); | |||
if (null != escherContainerF00A) { | |||
if (escherContainerF00A instanceof EscherSpRecord) { | |||
sp = (EscherSpRecord) escherContainerF00A; | |||
} | |||
} | |||
final EscherRecord escherContainerF00D = findFirstEscherRecordOfType((short)0xf00d, spContainer); | |||
if (null == escherContainerF00D) { continue; } | |||
if (escherContainerF00D instanceof EscherTextboxRecord) { | |||
EscherTextboxRecord tbr = (EscherTextboxRecord) escherContainerF00D; | |||
EscherTextboxWrapper w = new EscherTextboxWrapper(tbr); | |||
w.setStyleTextProp9Atom(nineAtom); | |||
if (null != sp) { | |||
w.setShapeId(sp.getShapeId()); | |||
} | |||
found.add(w); | |||
EscherSpRecord sp = (EscherSpRecord)findFirstEscherRecordOfType((short)RecordTypes.EscherSp, spContainer); | |||
EscherTextboxRecord clientTextbox = (EscherTextboxRecord)findFirstEscherRecordOfType((short)RecordTypes.EscherClientTextbox, spContainer); | |||
if (null == clientTextbox) { continue; } | |||
EscherTextboxWrapper w = new EscherTextboxWrapper(clientTextbox); | |||
w.setStyleTextProp9Atom(nineAtom); | |||
if (null != sp) { | |||
w.setShapeId(sp.getShapeId()); | |||
} | |||
found.add(w); | |||
} | |||
return found.toArray(new EscherTextboxWrapper[found.size()]); | |||
} | |||
private StyleTextProp9Atom findInSpContainer(final EscherContainerRecord spContainer) { | |||
final EscherContainerRecord escherContainerF011 = findFirstEscherContainerRecordOfType((short)0xf011, spContainer); | |||
if (null == escherContainerF011) { return null; } | |||
final EscherContainerRecord escherContainer1388 = findFirstEscherContainerRecordOfType((short)0x1388, escherContainerF011); | |||
EscherContainerRecord clientData = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherClientData, spContainer); | |||
if (null == clientData) { return null; } | |||
final EscherContainerRecord escherContainer1388 = findFirstEscherContainerRecordOfType((short)0x1388, clientData); | |||
if (null == escherContainer1388) { return null; } | |||
final EscherContainerRecord escherContainer138A = findFirstEscherContainerRecordOfType((short)0x138A, escherContainer1388); | |||
if (null == escherContainer138A) { return null; } |
@@ -294,7 +294,7 @@ public abstract class RecordContainer extends Record | |||
// Write out our header, less the size | |||
mout.write(new byte[] {headerA,headerB}); | |||
byte[] typeB = new byte[2]; | |||
LittleEndian.putShort(typeB,(short)type); | |||
LittleEndian.putShort(typeB, 0, (short)type); | |||
mout.write(typeB); | |||
mout.write(new byte[4]); | |||
@@ -320,7 +320,7 @@ public abstract class RecordContainer extends Record | |||
// Write out our header, less the size | |||
baos.write(new byte[] {headerA,headerB}); | |||
byte[] typeB = new byte[2]; | |||
LittleEndian.putShort(typeB,(short)type); | |||
LittleEndian.putShort(typeB,0,(short)type); | |||
baos.write(typeB); | |||
baos.write(new byte[] {0,0,0,0}); | |||
@@ -93,8 +93,6 @@ public final class SlideListWithText extends RecordContainer { | |||
} | |||
int clen = endPos - i - 1; | |||
boolean emptySet = false; | |||
if(clen == 0) { emptySet = true; } | |||
// Create a SlideAtomsSets, not caring if they're empty | |||
//if(emptySet) { continue; } | |||
@@ -149,7 +147,7 @@ public final class SlideListWithText extends RecordContainer { | |||
} | |||
public void setInstance(int inst){ | |||
LittleEndian.putShort(_header, (short)((inst << 4) | 0xF)); | |||
LittleEndian.putShort(_header, 0, (short)((inst << 4) | 0xF)); | |||
} | |||
/** |
@@ -128,9 +128,10 @@ public final class HSLFFill { | |||
}; | |||
} | |||
case FILL_PICTURE: { | |||
final HSLFPictureData pd = getPictureData(); | |||
if (pd == null) break; | |||
return new TexturePaint() { | |||
final HSLFPictureData pd = getPictureData(); | |||
public InputStream getImageData() { | |||
return new ByteArrayInputStream(pd.getData()); | |||
} |
@@ -21,8 +21,7 @@ import java.awt.geom.Rectangle2D; | |||
import java.util.*; | |||
import org.apache.poi.ddf.*; | |||
import org.apache.poi.sl.usermodel.ShapeContainer; | |||
import org.apache.poi.sl.usermodel.ShapeType; | |||
import org.apache.poi.sl.usermodel.*; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.POILogger; | |||
@@ -31,7 +30,7 @@ import org.apache.poi.util.POILogger; | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public class HSLFGroupShape extends HSLFShape implements ShapeContainer<HSLFShape> { | |||
public class HSLFGroupShape extends HSLFShape implements GroupShape<HSLFShape> { | |||
/** | |||
* Create a new ShapeGroup. This constructor is used when a new shape is created. | |||
@@ -87,13 +86,8 @@ public class HSLFGroupShape extends HSLFShape implements ShapeContainer<HSLFShap | |||
spgr.setRectY2((anchor.y + anchor.height)*MASTER_DPI/POINT_DPI); | |||
} | |||
/** | |||
* Sets the coordinate space of this group. All children are constrained | |||
* to these coordinates. | |||
* | |||
* @param anchor the coordinate space of this group | |||
*/ | |||
public void setCoordinates(Rectangle2D anchor){ | |||
@Override | |||
public void setInteriorAnchor(Rectangle2D anchor){ | |||
EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID); | |||
int x1 = (int)Math.round(anchor.getX()*MASTER_DPI/POINT_DPI); | |||
@@ -108,22 +102,14 @@ public class HSLFGroupShape extends HSLFShape implements ShapeContainer<HSLFShap | |||
} | |||
/** | |||
* Gets the coordinate space of this group. All children are constrained | |||
* to these coordinates. | |||
* | |||
* @return the coordinate space of this group | |||
*/ | |||
public Rectangle2D getCoordinates(){ | |||
EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID); | |||
Rectangle2D.Float anchor = new Rectangle2D.Float(); | |||
anchor.x = (float)spgr.getRectX1()*POINT_DPI/MASTER_DPI; | |||
anchor.y = (float)spgr.getRectY1()*POINT_DPI/MASTER_DPI; | |||
anchor.width = (float)(spgr.getRectX2() - spgr.getRectX1())*POINT_DPI/MASTER_DPI; | |||
anchor.height = (float)(spgr.getRectY2() - spgr.getRectY1())*POINT_DPI/MASTER_DPI; | |||
return anchor; | |||
@Override | |||
public Rectangle2D getInteriorAnchor(){ | |||
EscherSpgrRecord rec = getEscherChild(EscherSpgrRecord.RECORD_ID); | |||
double x = rec.getRectX1()*POINT_DPI/MASTER_DPI; | |||
double y = rec.getRectY1()*POINT_DPI/MASTER_DPI; | |||
double width = (rec.getRectX2()-rec.getRectX1())*POINT_DPI/MASTER_DPI; | |||
double height = (rec.getRectY2()-rec.getRectY1())*POINT_DPI/MASTER_DPI; | |||
return new Rectangle2D.Double(x,y,width,height); | |||
} | |||
/** | |||
@@ -199,21 +185,21 @@ public class HSLFGroupShape extends HSLFShape implements ShapeContainer<HSLFShap | |||
*/ | |||
public Rectangle2D getAnchor2D(){ | |||
EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID); | |||
Rectangle2D.Float anchor = new Rectangle2D.Float(); | |||
Rectangle2D anchor; | |||
if(clientAnchor == null){ | |||
logger.log(POILogger.INFO, "EscherClientAnchorRecord was not found for shape group. Searching for EscherChildAnchorRecord."); | |||
EscherChildAnchorRecord rec = getEscherChild(EscherChildAnchorRecord.RECORD_ID); | |||
anchor = new Rectangle2D.Float( | |||
(float)rec.getDx1()*POINT_DPI/MASTER_DPI, | |||
(float)rec.getDy1()*POINT_DPI/MASTER_DPI, | |||
(float)(rec.getDx2()-rec.getDx1())*POINT_DPI/MASTER_DPI, | |||
(float)(rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI | |||
); | |||
double x = rec.getDx1()*POINT_DPI/MASTER_DPI; | |||
double y = rec.getDy1()*POINT_DPI/MASTER_DPI; | |||
double width = (rec.getDx2()-rec.getDx1())*POINT_DPI/MASTER_DPI; | |||
double height = (rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI; | |||
anchor = new Rectangle2D.Double(x,y,width,height); | |||
} else { | |||
anchor.x = (float)clientAnchor.getCol1()*POINT_DPI/MASTER_DPI; | |||
anchor.y = (float)clientAnchor.getFlag()*POINT_DPI/MASTER_DPI; | |||
anchor.width = (float)(clientAnchor.getDx1() - clientAnchor.getCol1())*POINT_DPI/MASTER_DPI ; | |||
anchor.height = (float)(clientAnchor.getRow1() - clientAnchor.getFlag())*POINT_DPI/MASTER_DPI; | |||
double x = clientAnchor.getCol1()*POINT_DPI/MASTER_DPI; | |||
double y = clientAnchor.getFlag()*POINT_DPI/MASTER_DPI; | |||
double width = (clientAnchor.getDx1() - clientAnchor.getCol1())*POINT_DPI/MASTER_DPI ; | |||
double height = (clientAnchor.getRow1() - clientAnchor.getFlag())*POINT_DPI/MASTER_DPI; | |||
anchor = new Rectangle2D.Double(x,y,width,height); | |||
} | |||
return anchor; |
@@ -35,7 +35,7 @@ import org.apache.poi.util.POILogger; | |||
public final class HSLFNotes extends HSLFSheet implements Notes<HSLFShape, HSLFSlideShow> { | |||
protected static POILogger logger = POILogFactory.getLogger(HSLFNotes.class); | |||
private List<List<HSLFTextParagraph>> _runs; | |||
private List<List<HSLFTextParagraph>> _paragraphs = new ArrayList<List<HSLFTextParagraph>>(); | |||
/** | |||
* Constructs a Notes Sheet from the given Notes record. | |||
@@ -49,13 +49,16 @@ public final class HSLFNotes extends HSLFSheet implements Notes<HSLFShape, HSLFS | |||
// Now, build up TextRuns from pairs of TextHeaderAtom and | |||
// one of TextBytesAtom or TextCharsAtom, found inside | |||
// EscherTextboxWrapper's in the PPDrawing | |||
_runs = HSLFTextParagraph.findTextParagraphs(getPPDrawing()); | |||
if (_runs.isEmpty()) { | |||
for (List<HSLFTextParagraph> l : HSLFTextParagraph.findTextParagraphs(getPPDrawing(), this)) { | |||
if (!_paragraphs.contains(l)) _paragraphs.add(l); | |||
} | |||
if (_paragraphs.isEmpty()) { | |||
logger.log(POILogger.WARN, "No text records found for notes sheet"); | |||
} | |||
// Set the sheet on each TextRun | |||
for (List<HSLFTextParagraph> ltp : _runs) { | |||
for (List<HSLFTextParagraph> ltp : _paragraphs) { | |||
for (HSLFTextParagraph tp : ltp) { | |||
tp.supplySheet(this); | |||
} | |||
@@ -67,7 +70,7 @@ public final class HSLFNotes extends HSLFSheet implements Notes<HSLFShape, HSLFS | |||
*/ | |||
@Override | |||
public List<List<HSLFTextParagraph>> getTextParagraphs() { | |||
return _runs; | |||
return _paragraphs; | |||
} | |||
/** |
@@ -17,31 +17,22 @@ | |||
package org.apache.poi.hslf.usermodel; | |||
import java.awt.Graphics2D; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.security.MessageDigest; | |||
import org.apache.poi.hslf.blip.BitmapPainter; | |||
import org.apache.poi.hslf.blip.DIB; | |||
import org.apache.poi.hslf.blip.EMF; | |||
import org.apache.poi.hslf.blip.ImagePainter; | |||
import org.apache.poi.hslf.blip.JPEG; | |||
import org.apache.poi.hslf.blip.PICT; | |||
import org.apache.poi.hslf.blip.PNG; | |||
import org.apache.poi.hslf.blip.WMF; | |||
import org.apache.poi.hslf.blip.*; | |||
import org.apache.poi.poifs.crypt.CryptoFunctions; | |||
import org.apache.poi.poifs.crypt.HashAlgorithm; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.sl.usermodel.PictureData; | |||
import org.apache.poi.util.*; | |||
/** | |||
* A class that represents image data contained in a slide show. | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public abstract class HSLFPictureData { | |||
public abstract class HSLFPictureData implements PictureData { | |||
protected POILogger logger = POILogFactory.getLogger(this.getClass()); | |||
@@ -91,13 +82,6 @@ public abstract class HSLFPictureData { | |||
*/ | |||
protected abstract int getSignature(); | |||
protected static final ImagePainter[] painters = new ImagePainter[8]; | |||
static { | |||
HSLFPictureData.setImagePainter(HSLFPictureShape.PNG, new BitmapPainter()); | |||
HSLFPictureData.setImagePainter(HSLFPictureShape.JPEG, new BitmapPainter()); | |||
HSLFPictureData.setImagePainter(HSLFPictureShape.DIB, new BitmapPainter()); | |||
} | |||
/** | |||
* Returns the raw binary data of this Picture excluding the first 8 bytes | |||
* which hold image signature and size of the image data. | |||
@@ -233,31 +217,4 @@ public abstract class HSLFPictureData { | |||
public int getSize(){ | |||
return getData().length; | |||
} | |||
public void draw(Graphics2D graphics, HSLFPictureShape parent){ | |||
ImagePainter painter = painters[getType()]; | |||
if(painter != null) painter.paint(graphics, this, parent); | |||
else logger.log(POILogger.WARN, "Rendering is not supported: " + getClass().getName()); | |||
} | |||
/** | |||
* Register ImagePainter for the specified image type | |||
* | |||
* @param type image type, must be one of the static constants defined in the <code>Picture<code> class. | |||
* @param painter | |||
*/ | |||
public static void setImagePainter(int type, ImagePainter painter){ | |||
painters[type] = painter; | |||
} | |||
/** | |||
* Return ImagePainter for the specified image type | |||
* | |||
* @param type blip type, must be one of the static constants defined in the <code>Picture<code> class. | |||
* @return ImagePainter for the specified image type | |||
*/ | |||
public static ImagePainter getImagePainter(int type){ | |||
return painters[type]; | |||
} | |||
} |
@@ -28,8 +28,7 @@ import javax.imageio.ImageIO; | |||
import org.apache.poi.ddf.*; | |||
import org.apache.poi.hslf.blip.Bitmap; | |||
import org.apache.poi.hslf.record.Document; | |||
import org.apache.poi.sl.usermodel.ShapeContainer; | |||
import org.apache.poi.sl.usermodel.ShapeType; | |||
import org.apache.poi.sl.usermodel.*; | |||
import org.apache.poi.util.*; | |||
@@ -38,7 +37,7 @@ import org.apache.poi.util.*; | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public class HSLFPictureShape extends HSLFSimpleShape { | |||
public class HSLFPictureShape extends HSLFSimpleShape implements PictureShape { | |||
/** | |||
* Windows Enhanced Metafile (EMF) | |||
@@ -165,11 +164,7 @@ public class HSLFPictureShape extends HSLFSimpleShape { | |||
} | |||
} | |||
/** | |||
* Returns the picture data for this picture. | |||
* | |||
* @return the picture data for this picture. | |||
*/ | |||
@Override | |||
public HSLFPictureData getPictureData(){ | |||
HSLFSlideShow ppt = getSheet().getSlideShow(); | |||
HSLFPictureData[] pict = ppt.getPictureData(); | |||
@@ -247,13 +242,11 @@ public class HSLFPictureShape extends HSLFSimpleShape { | |||
} | |||
/** | |||
* Returns the clipping values as percent ratio relatively to the image size. | |||
* The anchor specified by {@link #getLogicalAnchor2D()} is the displayed size, | |||
* i.e. the size of the already clipped image | |||
* | |||
* @return the clipping as insets converted/scaled to 100000 (=100%) | |||
*/ | |||
public Insets getBlipClip() { | |||
@Override | |||
public Insets getClipping() { | |||
EscherOptRecord opt = getEscherOptRecord(); | |||
double top = getFractProp(opt, EscherProperties.BLIP__CROPFROMTOP); |
@@ -165,14 +165,12 @@ public abstract class HSLFShape implements Shape { | |||
public Rectangle2D getAnchor2D(){ | |||
EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID); | |||
int flags = spRecord.getFlags(); | |||
Rectangle2D anchor=null; | |||
Rectangle2D anchor; | |||
if ((flags & EscherSpRecord.FLAG_CHILD) != 0){ | |||
EscherChildAnchorRecord rec = getEscherChild(EscherChildAnchorRecord.RECORD_ID); | |||
anchor = new java.awt.Rectangle(); | |||
if(rec == null){ | |||
logger.log(POILogger.WARN, "EscherSpRecord.FLAG_CHILD is set but EscherChildAnchorRecord was not found"); | |||
EscherClientAnchorRecord clrec = getEscherChild(EscherClientAnchorRecord.RECORD_ID); | |||
anchor = new java.awt.Rectangle(); | |||
anchor = new Rectangle2D.Float( | |||
(float)clrec.getCol1()*POINT_DPI/MASTER_DPI, | |||
(float)clrec.getFlag()*POINT_DPI/MASTER_DPI, | |||
@@ -187,10 +185,8 @@ public abstract class HSLFShape implements Shape { | |||
(float)(rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI | |||
); | |||
} | |||
} | |||
else { | |||
} else { | |||
EscherClientAnchorRecord rec = getEscherChild(EscherClientAnchorRecord.RECORD_ID); | |||
anchor = new java.awt.Rectangle(); | |||
anchor = new Rectangle2D.Float( | |||
(float)rec.getCol1()*POINT_DPI/MASTER_DPI, | |||
(float)rec.getFlag()*POINT_DPI/MASTER_DPI, | |||
@@ -201,10 +197,6 @@ public abstract class HSLFShape implements 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). | |||
@@ -262,8 +254,9 @@ public abstract class HSLFShape implements Shape { | |||
* @return escher property or <code>null</code> if not found. | |||
*/ | |||
public static <T extends EscherProperty> T getEscherProperty(EscherOptRecord opt, int propId){ | |||
return opt.lookup(propId); | |||
} | |||
if (opt == null) return null; | |||
return opt.lookup(propId); | |||
} | |||
/** | |||
* Set an escher property for this shape. | |||
@@ -475,15 +468,6 @@ public abstract class HSLFShape implements Shape { | |||
logger.log(POILogger.INFO, "Rendering " + getShapeName()); | |||
} | |||
/** | |||
* Return shape outline as a java.awt.Shape object | |||
* | |||
* @return the shape outline | |||
*/ | |||
public java.awt.Shape getOutline(){ | |||
return getLogicalAnchor2D(); | |||
} | |||
public EscherOptRecord getEscherOptRecord() { | |||
EscherOptRecord opt = getEscherChild(EscherOptRecord.RECORD_ID); | |||
if (opt == null) { | |||
@@ -516,8 +500,7 @@ public abstract class HSLFShape implements Shape { | |||
public double getRotation(){ | |||
int rot = getEscherProperty(EscherProperties.TRANSFORM__ROTATION); | |||
double angle = Units.fixedPointToDouble(rot) % 360.0; | |||
return angle; | |||
return Units.fixedPointToDouble(rot); | |||
} | |||
public void setRotation(double theta){ |
@@ -69,7 +69,7 @@ public final class HSLFShapeFactory { | |||
List<EscherProperty> props = f.createProperties( opt.serialize(), 8, opt.getInstance() ); | |||
EscherSimpleProperty p = (EscherSimpleProperty)props.get(0); | |||
if(p.getPropertyNumber() == 0x39F && p.getPropertyValue() == 1){ | |||
group = new Table(spContainer, parent); | |||
group = new HSLFTable(spContainer, parent); | |||
} else { | |||
group = new HSLFGroupShape(spContainer, parent); | |||
} |
@@ -22,6 +22,8 @@ import java.util.*; | |||
import org.apache.poi.ddf.*; | |||
import org.apache.poi.hslf.record.*; | |||
import org.apache.poi.sl.draw.DrawFactory; | |||
import org.apache.poi.sl.draw.Drawable; | |||
import org.apache.poi.sl.usermodel.Sheet; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
@@ -288,8 +290,11 @@ public abstract class HSLFSheet implements Sheet<HSLFShape,HSLFSlideShow> { | |||
return _background; | |||
} | |||
public void draw(Graphics2D graphics){ | |||
@Override | |||
public void draw(Graphics2D graphics) { | |||
DrawFactory drawFact = DrawFactory.getInstance(graphics); | |||
Drawable draw = drawFact.getDrawable(this); | |||
draw.draw(graphics); | |||
} | |||
/** |
@@ -18,16 +18,15 @@ | |||
package org.apache.poi.hslf.usermodel; | |||
import java.awt.Color; | |||
import java.awt.geom.AffineTransform; | |||
import java.awt.geom.Rectangle2D; | |||
import java.io.ByteArrayOutputStream; | |||
import java.util.ArrayList; | |||
import org.apache.poi.ddf.*; | |||
import org.apache.poi.hslf.exceptions.HSLFException; | |||
import org.apache.poi.hslf.record.*; | |||
import org.apache.poi.sl.draw.DrawPaint; | |||
import org.apache.poi.sl.draw.geom.*; | |||
import org.apache.poi.sl.usermodel.*; | |||
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; | |||
import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound; | |||
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; | |||
import org.apache.poi.util.LittleEndian; | |||
@@ -196,7 +195,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape { | |||
public StrokeStyle getStrokeStyle(){ | |||
return new StrokeStyle() { | |||
public PaintStyle getPaint() { | |||
return null; | |||
return DrawPaint.createSolidPaint(HSLFSimpleShape.this.getLineColor()); | |||
} | |||
public LineCap getLineCap() { | |||
@@ -204,15 +203,15 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape { | |||
} | |||
public LineDash getLineDash() { | |||
return null; | |||
return HSLFSimpleShape.this.getLineDashing(); | |||
} | |||
public LineCompound getLineCompound() { | |||
return null; | |||
return HSLFSimpleShape.this.getLineCompound(); | |||
} | |||
public double getLineWidth() { | |||
return 0; | |||
return HSLFSimpleShape.this.getLineWidth(); | |||
} | |||
}; | |||
@@ -234,61 +233,6 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape { | |||
getFill().setForegroundColor(color); | |||
} | |||
/** | |||
* | |||
* @return 'absolute' anchor of this shape relative to the parent sheet | |||
*/ | |||
public Rectangle2D getLogicalAnchor2D(){ | |||
Rectangle2D anchor = getAnchor2D(); | |||
//if it is a groupped shape see if we need to transform the coordinates | |||
if (getParent() != null){ | |||
ArrayList<HSLFGroupShape> lst = new ArrayList<HSLFGroupShape>(); | |||
for (ShapeContainer<HSLFShape> parent=this.getParent(); | |||
parent instanceof HSLFGroupShape; | |||
parent = ((HSLFGroupShape)parent).getParent()) { | |||
lst.add(0, (HSLFGroupShape)parent); | |||
} | |||
AffineTransform tx = new AffineTransform(); | |||
for(HSLFGroupShape prnt : lst) { | |||
Rectangle2D exterior = prnt.getAnchor2D(); | |||
Rectangle2D interior = prnt.getCoordinates(); | |||
double scaleX = exterior.getWidth() / interior.getWidth(); | |||
double scaleY = exterior.getHeight() / interior.getHeight(); | |||
tx.translate(exterior.getX(), exterior.getY()); | |||
tx.scale(scaleX, scaleY); | |||
tx.translate(-interior.getX(), -interior.getY()); | |||
} | |||
anchor = tx.createTransformedShape(anchor).getBounds2D(); | |||
} | |||
double 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; | |||
} | |||
/** | |||
* Find a record in the underlying EscherClientDataRecord | |||
* | |||
@@ -424,11 +368,6 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape { | |||
return (adjval == -1) ? null : new Guide(name, "val "+adjval); | |||
} | |||
public LineDecoration getLineDecoration() { | |||
// TODO Auto-generated method stub | |||
return null; | |||
} | |||
public CustomGeometry getGeometry() { | |||
ShapeType st = getShapeType(); | |||
String name = st.getOoxmlName(); | |||
@@ -442,11 +381,89 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape { | |||
return geom; | |||
} | |||
public Shadow getShadow() { | |||
// TODO Auto-generated method stub | |||
return null; | |||
} | |||
public double getShadowAngle() { | |||
EscherOptRecord opt = getEscherOptRecord(); | |||
EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.SHADOWSTYLE__OFFSETX); | |||
int offX = (prop == null) ? 0 : prop.getPropertyValue(); | |||
prop = getEscherProperty(opt, EscherProperties.SHADOWSTYLE__OFFSETY); | |||
int offY = (prop == null) ? 0 : prop.getPropertyValue(); | |||
return Math.toDegrees(Math.atan2(offY, offX)); | |||
} | |||
public double getShadowDistance() { | |||
EscherOptRecord opt = getEscherOptRecord(); | |||
EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.SHADOWSTYLE__OFFSETX); | |||
int offX = (prop == null) ? 0 : prop.getPropertyValue(); | |||
prop = getEscherProperty(opt, EscherProperties.SHADOWSTYLE__OFFSETY); | |||
int offY = (prop == null) ? 0 : prop.getPropertyValue(); | |||
return Units.toPoints((long)Math.hypot(offX, offY)); | |||
} | |||
/** | |||
* @return color of the line. If color is not set returns <code>java.awt.Color.black</code> | |||
*/ | |||
public Color getShadowColor(){ | |||
Color clr = getColor(EscherProperties.SHADOWSTYLE__COLOR, EscherProperties.SHADOWSTYLE__OPACITY, -1); | |||
return clr == null ? Color.black : clr; | |||
} | |||
public Shadow getShadow() { | |||
EscherOptRecord opt = getEscherOptRecord(); | |||
EscherProperty shadowType = opt.lookup(EscherProperties.SHADOWSTYLE__TYPE); | |||
if (shadowType == null) return null; | |||
return new Shadow(){ | |||
public SimpleShape getShadowParent() { | |||
return HSLFSimpleShape.this; | |||
} | |||
public double getDistance() { | |||
return getShadowDistance(); | |||
} | |||
public double getAngle() { | |||
return getShadowAngle(); | |||
} | |||
public double getBlur() { | |||
// TODO Auto-generated method stub | |||
return 0; | |||
} | |||
public SolidPaint getFillStyle() { | |||
return DrawPaint.createSolidPaint(getShadowColor()); | |||
} | |||
}; | |||
} | |||
public LineDecoration getLineDecoration() { | |||
return new LineDecoration() { | |||
public DecorationShape getHeadShape() { | |||
return DecorationShape.NONE; | |||
} | |||
public DecorationSize getHeadWidth() { | |||
return DecorationSize.MEDIUM; | |||
} | |||
public DecorationSize getHeadLength() { | |||
return DecorationSize.MEDIUM; | |||
} | |||
public DecorationShape getTailShape() { | |||
return DecorationShape.NONE; | |||
} | |||
public DecorationSize getTailWidth() { | |||
return DecorationSize.MEDIUM; | |||
} | |||
public DecorationSize getTailLength() { | |||
return DecorationSize.MEDIUM; | |||
} | |||
}; | |||
} | |||
} |
@@ -72,7 +72,9 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFSl | |||
} | |||
// Grab text from slide's PPDrawing | |||
_paragraphs.addAll(HSLFTextParagraph.findTextParagraphs(getPPDrawing())); | |||
for (List<HSLFTextParagraph> l : HSLFTextParagraph.findTextParagraphs(getPPDrawing(), this)) { | |||
if (!_paragraphs.contains(l)) _paragraphs.add(l); | |||
} | |||
for(List<HSLFTextParagraph> ltp : _paragraphs) { | |||
for (HSLFTextParagraph tp : ltp) { |
@@ -32,7 +32,7 @@ import org.apache.poi.hslf.record.*; | |||
* @author Yegor Kozlov | |||
*/ | |||
public final class HSLFSlideMaster extends HSLFMasterSheet { | |||
private final List<List<HSLFTextParagraph>> _runs = new ArrayList<List<HSLFTextParagraph>>(); | |||
private final List<List<HSLFTextParagraph>> _paragraphs = new ArrayList<List<HSLFTextParagraph>>(); | |||
/** | |||
* all TxMasterStyleAtoms available in this master | |||
@@ -46,8 +46,11 @@ public final class HSLFSlideMaster extends HSLFMasterSheet { | |||
public HSLFSlideMaster(MainMaster record, int sheetNo) { | |||
super(record, sheetNo); | |||
_runs.addAll(HSLFTextParagraph.findTextParagraphs(getPPDrawing())); | |||
for (List<HSLFTextParagraph> p : _runs) { | |||
for (List<HSLFTextParagraph> l : HSLFTextParagraph.findTextParagraphs(getPPDrawing(), this)) { | |||
if (!_paragraphs.contains(l)) _paragraphs.add(l); | |||
} | |||
for (List<HSLFTextParagraph> p : _paragraphs) { | |||
for (HSLFTextParagraph htp : p) { | |||
htp.supplySheet(this); | |||
} | |||
@@ -58,7 +61,7 @@ public final class HSLFSlideMaster extends HSLFMasterSheet { | |||
* Returns an array of all the TextRuns found | |||
*/ | |||
public List<List<HSLFTextParagraph>> getTextParagraphs() { | |||
return _runs; | |||
return _paragraphs; | |||
} | |||
/** | |||
@@ -138,7 +141,7 @@ public final class HSLFSlideMaster extends HSLFMasterSheet { | |||
protected void onAddTextShape(HSLFTextShape shape) { | |||
List<HSLFTextParagraph> runs = shape.getTextParagraphs(); | |||
_runs.add(runs); | |||
_paragraphs.add(runs); | |||
} | |||
public TxMasterStyleAtom[] getTxMasterStyleAtoms(){ |
@@ -15,9 +15,10 @@ | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hslf.model; | |||
package org.apache.poi.hslf.usermodel; | |||
import org.apache.poi.ddf.*; | |||
import org.apache.poi.hslf.model.Line; | |||
import org.apache.poi.hslf.usermodel.*; | |||
import org.apache.poi.sl.usermodel.ShapeContainer; | |||
import org.apache.poi.util.LittleEndian; | |||
@@ -31,7 +32,7 @@ import java.awt.*; | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public final class Table extends HSLFGroupShape { | |||
public final class HSLFTable extends HSLFGroupShape { | |||
protected static final int BORDER_TOP = 1; | |||
protected static final int BORDER_RIGHT = 2; | |||
@@ -44,7 +45,7 @@ public final class Table extends HSLFGroupShape { | |||
protected static final int BORDERS_NONE = 8; | |||
protected TableCell[][] cells; | |||
protected HSLFTableCell[][] cells; | |||
/** | |||
* Create a new Table of the given number of rows and columns | |||
@@ -52,23 +53,23 @@ public final class Table extends HSLFGroupShape { | |||
* @param numrows the number of rows | |||
* @param numcols the number of columns | |||
*/ | |||
public Table(int numrows, int numcols) { | |||
public HSLFTable(int numrows, int numcols) { | |||
super(); | |||
if(numrows < 1) throw new IllegalArgumentException("The number of rows must be greater than 1"); | |||
if(numcols < 1) throw new IllegalArgumentException("The number of columns must be greater than 1"); | |||
int x=0, y=0, tblWidth=0, tblHeight=0; | |||
cells = new TableCell[numrows][numcols]; | |||
cells = new HSLFTableCell[numrows][numcols]; | |||
for (int i = 0; i < cells.length; i++) { | |||
x = 0; | |||
for (int j = 0; j < cells[i].length; j++) { | |||
cells[i][j] = new TableCell(this); | |||
Rectangle anchor = new Rectangle(x, y, TableCell.DEFAULT_WIDTH, TableCell.DEFAULT_HEIGHT); | |||
cells[i][j] = new HSLFTableCell(this); | |||
Rectangle anchor = new Rectangle(x, y, HSLFTableCell.DEFAULT_WIDTH, HSLFTableCell.DEFAULT_HEIGHT); | |||
cells[i][j].setAnchor(anchor); | |||
x += TableCell.DEFAULT_WIDTH; | |||
x += HSLFTableCell.DEFAULT_WIDTH; | |||
} | |||
y += TableCell.DEFAULT_HEIGHT; | |||
y += HSLFTableCell.DEFAULT_HEIGHT; | |||
} | |||
tblWidth = x; | |||
tblHeight = y; | |||
@@ -94,7 +95,7 @@ public final class Table extends HSLFGroupShape { | |||
* @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape | |||
* @param parent the parent of the shape | |||
*/ | |||
public Table(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent) { | |||
public HSLFTable(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent) { | |||
super(escherRecord, parent); | |||
} | |||
@@ -105,7 +106,7 @@ public final class Table extends HSLFGroupShape { | |||
* @param col the column index (0-based) | |||
* @return the cell | |||
*/ | |||
public TableCell getCell(int row, int col) { | |||
public HSLFTableCell getCell(int row, int col) { | |||
return cells[row][col]; | |||
} | |||
@@ -124,13 +125,13 @@ public final class Table extends HSLFGroupShape { | |||
EscherOptRecord opt = (EscherOptRecord)lst.get(lst.size()-2); | |||
EscherArrayProperty p = opt.lookup(0x3A0); | |||
for (int i = 0; i < cells.length; i++) { | |||
TableCell cell = cells[i][0]; | |||
HSLFTableCell cell = cells[i][0]; | |||
int rowHeight = cell.getAnchor().height*MASTER_DPI/POINT_DPI; | |||
byte[] val = new byte[4]; | |||
LittleEndian.putInt(val, 0, rowHeight); | |||
p.setElement(i, val); | |||
for (int j = 0; j < cells[i].length; j++) { | |||
TableCell c = cells[i][j]; | |||
HSLFTableCell c = cells[i][j]; | |||
addShape(c); | |||
Line bt = c.getBorderTop(); | |||
@@ -177,12 +178,12 @@ public final class Table extends HSLFGroupShape { | |||
maxrowlen = Math.max(maxrowlen, row.size()); | |||
} | |||
} | |||
cells = new TableCell[lst.size()][maxrowlen]; | |||
cells = new HSLFTableCell[lst.size()][maxrowlen]; | |||
for (int i = 0; i < lst.size(); i++) { | |||
row = lst.get(i); | |||
for (int j = 0; j < row.size(); j++) { | |||
HSLFTextShape tx = (HSLFTextShape)row.get(j); | |||
cells[i][j] = new TableCell(tx.getSpContainer(), getParent()); | |||
cells[i][j] = new HSLFTableCell(tx.getSpContainer(), getParent()); | |||
cells[i][j].setSheet(tx.getSheet()); | |||
} | |||
} | |||
@@ -256,7 +257,7 @@ public final class Table extends HSLFGroupShape { | |||
public void setAllBorders(Line line){ | |||
for (int i = 0; i < cells.length; i++) { | |||
for (int j = 0; j < cells[i].length; j++) { | |||
TableCell cell = cells[i][j]; | |||
HSLFTableCell cell = cells[i][j]; | |||
cell.setBorderTop(cloneBorder(line)); | |||
cell.setBorderLeft(cloneBorder(line)); | |||
if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line)); | |||
@@ -273,7 +274,7 @@ public final class Table extends HSLFGroupShape { | |||
public void setOutsideBorders(Line line){ | |||
for (int i = 0; i < cells.length; i++) { | |||
for (int j = 0; j < cells[i].length; j++) { | |||
TableCell cell = cells[i][j]; | |||
HSLFTableCell cell = cells[i][j]; | |||
if(j == 0) cell.setBorderLeft(cloneBorder(line)); | |||
if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line)); | |||
@@ -300,7 +301,7 @@ public final class Table extends HSLFGroupShape { | |||
public void setInsideBorders(Line line){ | |||
for (int i = 0; i < cells.length; i++) { | |||
for (int j = 0; j < cells[i].length; j++) { | |||
TableCell cell = cells[i][j]; | |||
HSLFTableCell cell = cells[i][j]; | |||
if(j != cells[i].length - 1) | |||
cell.setBorderRight(cloneBorder(line)); |
@@ -15,15 +15,14 @@ | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hslf.model; | |||
package org.apache.poi.hslf.usermodel; | |||
import java.awt.Rectangle; | |||
import org.apache.poi.ddf.EscherContainerRecord; | |||
import org.apache.poi.ddf.EscherOptRecord; | |||
import org.apache.poi.ddf.EscherProperties; | |||
import org.apache.poi.hslf.usermodel.HSLFShape; | |||
import org.apache.poi.hslf.usermodel.HSLFTextBox; | |||
import org.apache.poi.hslf.model.Line; | |||
import org.apache.poi.sl.usermodel.ShapeContainer; | |||
import org.apache.poi.sl.usermodel.ShapeType; | |||
@@ -32,7 +31,7 @@ import org.apache.poi.sl.usermodel.ShapeType; | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public final class TableCell extends HSLFTextBox { | |||
public final class HSLFTableCell extends HSLFTextBox { | |||
protected static final int DEFAULT_WIDTH = 100; | |||
protected static final int DEFAULT_HEIGHT = 40; | |||
@@ -47,7 +46,7 @@ public final class TableCell extends HSLFTextBox { | |||
* @param escherRecord {@link EscherSpContainer} container which holds information about this shape | |||
* @param parent the parent of the shape | |||
*/ | |||
protected TableCell(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){ | |||
protected HSLFTableCell(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){ | |||
super(escherRecord, parent); | |||
} | |||
@@ -57,7 +56,7 @@ public final class TableCell extends HSLFTextBox { | |||
* @param parent the parent of this Shape. For example, if this text box is a cell | |||
* in a table then the parent is Table. | |||
*/ | |||
public TableCell(ShapeContainer<HSLFShape> parent){ | |||
public HSLFTableCell(ShapeContainer<HSLFShape> parent){ | |||
super(parent); | |||
setShapeType(ShapeType.RECT); | |||
@@ -81,25 +80,25 @@ public final class TableCell extends HSLFTextBox { | |||
Rectangle cellAnchor = getAnchor(); | |||
Rectangle lineAnchor = new Rectangle(); | |||
switch(type){ | |||
case Table.BORDER_TOP: | |||
case HSLFTable.BORDER_TOP: | |||
lineAnchor.x = cellAnchor.x; | |||
lineAnchor.y = cellAnchor.y; | |||
lineAnchor.width = cellAnchor.width; | |||
lineAnchor.height = 0; | |||
break; | |||
case Table.BORDER_RIGHT: | |||
case HSLFTable.BORDER_RIGHT: | |||
lineAnchor.x = cellAnchor.x + cellAnchor.width; | |||
lineAnchor.y = cellAnchor.y; | |||
lineAnchor.width = 0; | |||
lineAnchor.height = cellAnchor.height; | |||
break; | |||
case Table.BORDER_BOTTOM: | |||
case HSLFTable.BORDER_BOTTOM: | |||
lineAnchor.x = cellAnchor.x; | |||
lineAnchor.y = cellAnchor.y + cellAnchor.height; | |||
lineAnchor.width = cellAnchor.width; | |||
lineAnchor.height = 0; | |||
break; | |||
case Table.BORDER_LEFT: | |||
case HSLFTable.BORDER_LEFT: | |||
lineAnchor.x = cellAnchor.x; | |||
lineAnchor.y = cellAnchor.y; | |||
lineAnchor.width = 0; | |||
@@ -116,7 +115,7 @@ public final class TableCell extends HSLFTextBox { | |||
} | |||
public void setBorderLeft(Line line) { | |||
if(line != null) anchorBorder(Table.BORDER_LEFT, line); | |||
if(line != null) anchorBorder(HSLFTable.BORDER_LEFT, line); | |||
this.borderLeft = line; | |||
} | |||
@@ -125,7 +124,7 @@ public final class TableCell extends HSLFTextBox { | |||
} | |||
public void setBorderRight(Line line) { | |||
if(line != null) anchorBorder(Table.BORDER_RIGHT, line); | |||
if(line != null) anchorBorder(HSLFTable.BORDER_RIGHT, line); | |||
this.borderRight = line; | |||
} | |||
@@ -134,7 +133,7 @@ public final class TableCell extends HSLFTextBox { | |||
} | |||
public void setBorderTop(Line line) { | |||
if(line != null) anchorBorder(Table.BORDER_TOP, line); | |||
if(line != null) anchorBorder(HSLFTable.BORDER_TOP, line); | |||
this.borderTop = line; | |||
} | |||
@@ -143,16 +142,16 @@ public final class TableCell extends HSLFTextBox { | |||
} | |||
public void setBorderBottom(Line line) { | |||
if(line != null) anchorBorder(Table.BORDER_BOTTOM, line); | |||
if(line != null) anchorBorder(HSLFTable.BORDER_BOTTOM, line); | |||
this.borderBottom = line; | |||
} | |||
public void setAnchor(Rectangle anchor){ | |||
super.setAnchor(anchor); | |||
if(borderTop != null) anchorBorder(Table.BORDER_TOP, borderTop); | |||
if(borderRight != null) anchorBorder(Table.BORDER_RIGHT, borderRight); | |||
if(borderBottom != null) anchorBorder(Table.BORDER_BOTTOM, borderBottom); | |||
if(borderLeft != null) anchorBorder(Table.BORDER_LEFT, borderLeft); | |||
if(borderTop != null) anchorBorder(HSLFTable.BORDER_TOP, borderTop); | |||
if(borderRight != null) anchorBorder(HSLFTable.BORDER_RIGHT, borderRight); | |||
if(borderBottom != null) anchorBorder(HSLFTable.BORDER_BOTTOM, borderBottom); | |||
if(borderLeft != null) anchorBorder(HSLFTable.BORDER_LEFT, borderLeft); | |||
} | |||
} |
@@ -17,7 +17,10 @@ | |||
package org.apache.poi.hslf.usermodel; | |||
import static org.apache.poi.hslf.record.RecordTypes.OutlineTextRefAtom; | |||
import java.awt.Color; | |||
import java.io.IOException; | |||
import java.util.*; | |||
import org.apache.poi.hslf.model.PPFont; | |||
@@ -52,8 +55,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
private final TextHeaderAtom _headerAtom; | |||
private TextBytesAtom _byteAtom; | |||
private TextCharsAtom _charAtom; | |||
private StyleTextPropAtom _styleAtom; | |||
private TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph); | |||
private final TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph); | |||
protected TextRulerAtom _ruler; | |||
protected List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>(); | |||
@@ -61,11 +63,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
private HSLFSheet _sheet; | |||
private int shapeId; | |||
/** | |||
* all text run records that follow TextHeaderAtom. | |||
* (there can be misc InteractiveInfo, TxInteractiveInfo and other records) | |||
*/ | |||
private Record[] _records; | |||
// private StyleTextPropAtom styleTextPropAtom; | |||
private StyleTextProp9Atom styleTextProp9Atom; | |||
@@ -76,32 +73,30 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
* @param tha the TextHeaderAtom that defines what's what | |||
* @param tba the TextBytesAtom containing the text or null if {@link TextCharsAtom} is provided | |||
* @param tca the TextCharsAtom containing the text or null if {@link TextBytesAtom} is provided | |||
* @param sta the StyleTextPropAtom which defines the character stylings | |||
*/ | |||
/* package */ HSLFTextParagraph( | |||
TextHeaderAtom tha, | |||
TextBytesAtom tba, | |||
TextCharsAtom tca, | |||
StyleTextPropAtom sta | |||
TextCharsAtom tca | |||
) { | |||
if (tha == null) { | |||
throw new IllegalArgumentException("TextHeaderAtom must be set."); | |||
} | |||
_headerAtom = tha; | |||
_styleAtom = sta; | |||
_byteAtom = tba; | |||
_charAtom = tca; | |||
} | |||
/* package */ HSLFTextParagraph(HSLFTextParagraph other) { | |||
_headerAtom = other._headerAtom; | |||
_styleAtom = other._styleAtom; | |||
_byteAtom = other._byteAtom; | |||
_charAtom = other._charAtom; | |||
_paragraphStyle = other._paragraphStyle; | |||
_parentShape = other._parentShape; | |||
_sheet = other._sheet; | |||
_ruler = other._ruler; // ???? | |||
shapeId = other.shapeId; | |||
_records = other._records; | |||
} | |||
_headerAtom = other._headerAtom; | |||
_byteAtom = other._byteAtom; | |||
_charAtom = other._charAtom; | |||
_parentShape = other._parentShape; | |||
_sheet = other._sheet; | |||
_ruler = other._ruler; | |||
shapeId = other.shapeId; | |||
_paragraphStyle.copy(other._paragraphStyle); | |||
} | |||
public void addTextRun(HSLFTextRun run) { | |||
_runs.add(run); | |||
@@ -120,7 +115,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
} | |||
public void setParagraphStyle(TextPropCollection paragraphStyle) { | |||
_paragraphStyle = paragraphStyle; | |||
_paragraphStyle.copy(paragraphStyle); | |||
} | |||
/** | |||
@@ -196,20 +191,52 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
_ruler = getTextRuler(); | |||
if (_ruler == null) { | |||
_ruler = TextRulerAtom.getParagraphInstance(); | |||
_headerAtom.getParentRecord().appendChildRecord(_ruler); | |||
Record childAfter = _byteAtom; | |||
if (childAfter == null) childAfter = _charAtom; | |||
if (childAfter == null) childAfter = _headerAtom; | |||
_headerAtom.getParentRecord().addChildAfter(_ruler, childAfter); | |||
} | |||
return _ruler; | |||
} | |||
/** | |||
* Returns records that make up this text run | |||
* Returns records that make up the list of text paragraphs | |||
* (there can be misc InteractiveInfo, TxInteractiveInfo and other records) | |||
* | |||
* @return text run records | |||
*/ | |||
public Record[] getRecords(){ | |||
return _records; | |||
Record r[] = _headerAtom.getParentRecord().getChildRecords(); | |||
return getRecords(r, new int[]{0}, _headerAtom); | |||
} | |||
private static Record[] getRecords(Record[] records, int[] startIdx, TextHeaderAtom headerAtom) { | |||
if (records == null) { | |||
throw new NullPointerException("records need to be set."); | |||
} | |||
for (; startIdx[0] < records.length; startIdx[0]++) { | |||
Record r = records[startIdx[0]]; | |||
if (r instanceof TextHeaderAtom && (headerAtom == null || r == headerAtom)) break; | |||
} | |||
if (startIdx[0] >= records.length) { | |||
logger.log(POILogger.INFO, "header atom wasn't found - container might contain only an OutlineTextRefAtom"); | |||
return new Record[0]; | |||
} | |||
int length; | |||
for (length = 1; startIdx[0]+length < records.length; length++) { | |||
if (records[startIdx[0]+length] instanceof TextHeaderAtom) break; | |||
} | |||
Record result[] = new Record[length]; | |||
System.arraycopy(records, startIdx[0], result, 0, length); | |||
startIdx[0] += length; | |||
return result; | |||
} | |||
/** Numbered List info */ | |||
public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) { | |||
this.styleTextProp9Atom = styleTextProp9Atom; | |||
@@ -220,11 +247,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
return this.styleTextProp9Atom; | |||
} | |||
/** Characters covered */ | |||
public StyleTextPropAtom getStyleTextPropAtom() { | |||
return this._styleAtom; | |||
} | |||
/** | |||
* Fetch the value of the given Paragraph related TextProp. | |||
* Returns -1 if that TextProp isn't present. | |||
@@ -232,14 +254,9 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
* Master Sheet will apply. | |||
*/ | |||
private int getParaTextPropVal(String propName) { | |||
TextProp prop = null; | |||
boolean hardAttribute = false; | |||
if (_paragraphStyle != null){ | |||
prop = _paragraphStyle.findByName(propName); | |||
BitMaskTextProp maskProp = (BitMaskTextProp)_paragraphStyle.findByName(ParagraphFlagsTextProp.NAME); | |||
hardAttribute = maskProp != null && maskProp.getValue() == 0; | |||
} | |||
TextProp prop = _paragraphStyle.findByName(propName); | |||
BitMaskTextProp maskProp = (BitMaskTextProp)_paragraphStyle.findByName(ParagraphFlagsTextProp.NAME); | |||
boolean hardAttribute = (maskProp != null && maskProp.getValue() == 0); | |||
if (prop == null && !hardAttribute){ | |||
HSLFSheet sheet = getSheet(); | |||
int txtype = getRunType(); | |||
@@ -258,11 +275,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
*/ | |||
public void setParaTextPropVal(String propName, int val) { | |||
// Ensure we have the StyleTextProp atom we're going to need | |||
if(_paragraphStyle == null) { | |||
_styleAtom = findStyleAtomPresent(_headerAtom, -1); | |||
_paragraphStyle = _styleAtom.getParagraphStyles().get(0); | |||
} | |||
assert(_paragraphStyle!=null); | |||
TextProp tp = fetchOrAddTextProp(_paragraphStyle, propName); | |||
tp.setValue(val); | |||
@@ -615,10 +627,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
protected void setFlag(int index, boolean value) { | |||
// Ensure we have the StyleTextProp atom we're going to need | |||
if(_paragraphStyle == null) { | |||
_paragraphStyle = new TextPropCollection(1, TextPropType.paragraph); | |||
} | |||
assert(_paragraphStyle!=null); | |||
BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(_paragraphStyle, ParagraphFlagsTextProp.NAME); | |||
prop.setSubValue(value,index); | |||
} | |||
@@ -653,12 +662,13 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
boolean afterHeader = false; | |||
StyleTextPropAtom style = null; | |||
for (Record record : header.getParentRecord().getChildRecords()) { | |||
if (afterHeader && record.getRecordType() == RecordTypes.TextHeaderAtom.typeID) { | |||
long rt = record.getRecordType(); | |||
if (afterHeader && rt == RecordTypes.TextHeaderAtom.typeID) { | |||
// already on the next header, quit searching | |||
break; | |||
} | |||
afterHeader |= (header == record); | |||
if (afterHeader && record.getRecordType() == RecordTypes.StyleTextPropAtom.typeID) { | |||
if (afterHeader && rt == RecordTypes.StyleTextPropAtom.typeID) { | |||
// found it | |||
style = (StyleTextPropAtom)record; | |||
} | |||
@@ -789,12 +799,20 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
* If TextSpecInfoAtom is present, we must update the text size in it, | |||
* otherwise the ppt will be corrupted | |||
*/ | |||
for (Record r : paragraphs.get(0)._records) { | |||
for (Record r : paragraphs.get(0).getRecords()) { | |||
if (r instanceof TextSpecInfoAtom) { | |||
((TextSpecInfoAtom)r).setParentSize(rawText.length()+1); | |||
break; | |||
} | |||
} | |||
if (_txtbox instanceof EscherTextboxWrapper) { | |||
try { | |||
((EscherTextboxWrapper)_txtbox).writeOut(null); | |||
} catch (IOException e) { | |||
throw new RuntimeException("failed dummy write", e); | |||
} | |||
} | |||
} | |||
/** | |||
@@ -817,7 +835,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
if (!isFirst) { | |||
TextPropCollection tpc = htp.getParagraphStyle(); | |||
HSLFTextParagraph prevHtp = htp; | |||
htp = new HSLFTextParagraph(htp._headerAtom, htp._byteAtom, htp._charAtom, htp._styleAtom); | |||
htp = new HSLFTextParagraph(htp._headerAtom, htp._byteAtom, htp._charAtom); | |||
htp.getParagraphStyle().copy(tpc); | |||
htp.setParentShape(prevHtp.getParentShape()); | |||
htp.setShapeId(prevHtp.getShapeId()); | |||
@@ -930,24 +948,14 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
/** | |||
* For a given PPDrawing, grab all the TextRuns | |||
*/ | |||
public static List<List<HSLFTextParagraph>> findTextParagraphs(PPDrawing ppdrawing) { | |||
public static List<List<HSLFTextParagraph>> findTextParagraphs(PPDrawing ppdrawing, HSLFSheet sheet) { | |||
List<List<HSLFTextParagraph>> runsV = new ArrayList<List<HSLFTextParagraph>>(); | |||
for (EscherTextboxWrapper wrapper : ppdrawing.getTextboxWrappers()) { | |||
runsV.addAll(findTextParagraphs(wrapper)); | |||
runsV.add(findTextParagraphs(wrapper, sheet)); | |||
} | |||
return runsV; | |||
} | |||
/** | |||
* Scans through the supplied record array, looking for | |||
* a TextHeaderAtom followed by one of a TextBytesAtom or | |||
* a TextCharsAtom. Builds up TextRuns from these | |||
* | |||
* @param records the records to build from | |||
* @param found vector to add any found to | |||
*/ | |||
protected static List<List<HSLFTextParagraph>> findTextParagraphs(final Record[] records) { | |||
return findTextParagraphs(records, null); | |||
} | |||
/** | |||
* Scans through the supplied record array, looking for | |||
* a TextHeaderAtom followed by one of a TextBytesAtom or | |||
@@ -955,14 +963,73 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
* | |||
* @param wrapper an EscherTextboxWrapper | |||
*/ | |||
protected static List<List<HSLFTextParagraph>> findTextParagraphs(EscherTextboxWrapper wrapper) { | |||
protected static List<HSLFTextParagraph> findTextParagraphs(EscherTextboxWrapper wrapper, HSLFSheet sheet) { | |||
// propagate parents to parent-aware records | |||
RecordContainer.handleParentAwareRecords(wrapper); | |||
int shapeId = wrapper.getShapeId(); | |||
List<List<HSLFTextParagraph>> rv = findTextParagraphs(wrapper.getChildRecords(), wrapper.getStyleTextProp9Atom()); | |||
for (List<HSLFTextParagraph> htpList : rv) { | |||
for (HSLFTextParagraph htp : htpList) { | |||
List<HSLFTextParagraph> rv = null; | |||
OutlineTextRefAtom ota = (OutlineTextRefAtom)wrapper.findFirstOfType(OutlineTextRefAtom.typeID); | |||
if (ota != null) { | |||
// if we are based on an outline, there are no further records to be parsed from the wrapper | |||
if (sheet == null) { | |||
throw new RuntimeException("Outline atom reference can't be solved without a sheet record"); | |||
} | |||
List<List<HSLFTextParagraph>> sheetRuns = sheet.getTextParagraphs(); | |||
assert(sheetRuns != null); | |||
int idx = ota.getTextIndex(); | |||
for (List<HSLFTextParagraph> r : sheetRuns) { | |||
if (r.isEmpty()) continue; | |||
int ridx = r.get(0).getIndex(); | |||
if (ridx > idx) break; | |||
if (ridx == idx) { | |||
if (rv == null) { | |||
rv = r; | |||
} else { | |||
// create a new container | |||
// TODO: ... is this case really happening? | |||
rv = new ArrayList<HSLFTextParagraph>(rv); | |||
rv.addAll(r); | |||
} | |||
} | |||
} | |||
if(rv == null || rv.isEmpty()) { | |||
logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx); | |||
} | |||
} else { | |||
if (sheet != null) { | |||
// check sheet runs first, so we get exactly the same paragraph list | |||
List<List<HSLFTextParagraph>> sheetRuns = sheet.getTextParagraphs(); | |||
assert(sheetRuns != null); | |||
for (List<HSLFTextParagraph> paras : sheetRuns) { | |||
if (!paras.isEmpty() && paras.get(0)._headerAtom.getParentRecord() == wrapper) { | |||
rv = paras; | |||
break; | |||
} | |||
} | |||
} | |||
if (rv == null) { | |||
// if we haven't found the wrapper in the sheet runs, create a new paragraph list from its record | |||
List<List<HSLFTextParagraph>> rvl = findTextParagraphs(wrapper.getChildRecords()); | |||
switch (rvl.size()) { | |||
case 0: break; // nothing found | |||
case 1: rv = rvl.get(0); break; // normal case | |||
default: | |||
throw new RuntimeException("TextBox contains more than one list of paragraphs."); | |||
} | |||
} | |||
} | |||
if (rv != null) { | |||
StyleTextProp9Atom styleTextProp9Atom = wrapper.getStyleTextProp9Atom(); | |||
for (HSLFTextParagraph htp : rv) { | |||
htp.setShapeId(shapeId); | |||
htp.setStyleTextProp9Atom(styleTextProp9Atom); | |||
} | |||
} | |||
return rv; | |||
@@ -974,77 +1041,59 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
* a TextCharsAtom. Builds up TextRuns from these | |||
* | |||
* @param records the records to build from | |||
* @param styleTextProp9Atom an optional StyleTextProp9Atom with numbered lists info | |||
*/ | |||
protected static List<List<HSLFTextParagraph>> findTextParagraphs(Record[] records, StyleTextProp9Atom styleTextProp9Atom) { | |||
protected static List<List<HSLFTextParagraph>> findTextParagraphs(Record[] records) { | |||
List<List<HSLFTextParagraph>> paragraphCollection = new ArrayList<List<HSLFTextParagraph>>(); | |||
if (records == null) { | |||
throw new NullPointerException("records need to be filled."); | |||
} | |||
int recordIdx; | |||
for (recordIdx = 0; recordIdx < records.length; recordIdx++) { | |||
if (records[recordIdx] instanceof TextHeaderAtom) break; | |||
} | |||
if (recordIdx == records.length) { | |||
logger.log(POILogger.INFO, "No text records found."); | |||
return paragraphCollection; | |||
} | |||
for (int slwtIndex = 0; recordIdx < records.length; slwtIndex++) { | |||
List<HSLFTextParagraph> paragraphs = new ArrayList<HSLFTextParagraph>(); | |||
paragraphCollection.add(paragraphs); | |||
TextHeaderAtom header = (TextHeaderAtom)records[recordIdx++]; | |||
int[] recordIdx = {0}; | |||
for (int slwtIndex = 0; recordIdx[0] < records.length; slwtIndex++) { | |||
TextHeaderAtom header = null; | |||
TextBytesAtom tbytes = null; | |||
TextCharsAtom tchars = null; | |||
TextRulerAtom ruler = null; | |||
MasterTextPropAtom indents = null; | |||
List<Record> otherRecordList = new ArrayList<Record>(); | |||
for (; recordIdx < records.length; recordIdx++) { | |||
Record r = records[recordIdx]; | |||
for (Record r : getRecords(records, recordIdx, null)) { | |||
long rt = r.getRecordType(); | |||
if (RecordTypes.TextHeaderAtom.typeID == rt) break; | |||
else if (RecordTypes.TextBytesAtom.typeID == rt) tbytes = (TextBytesAtom)r; | |||
else if (RecordTypes.TextCharsAtom.typeID == rt) tchars = (TextCharsAtom)r; | |||
// don't search for RecordTypes.StyleTextPropAtom.typeID here ... see findStyleAtomPresent below | |||
else if (RecordTypes.TextRulerAtom.typeID == rt) ruler = (TextRulerAtom)r; | |||
else if (RecordTypes.MasterTextPropAtom.typeID == rt) { | |||
if (RecordTypes.TextHeaderAtom.typeID == rt) { | |||
header = (TextHeaderAtom)r; | |||
} else if (RecordTypes.TextBytesAtom.typeID == rt) { | |||
tbytes = (TextBytesAtom)r; | |||
} else if (RecordTypes.TextCharsAtom.typeID == rt) { | |||
tchars = (TextCharsAtom)r; | |||
} else if (RecordTypes.TextRulerAtom.typeID == rt) { | |||
ruler = (TextRulerAtom)r; | |||
} else if (RecordTypes.MasterTextPropAtom.typeID == rt) { | |||
indents = (MasterTextPropAtom)r; | |||
otherRecordList.add(indents); | |||
} else { | |||
otherRecordList.add(r); | |||
} | |||
// don't search for RecordTypes.StyleTextPropAtom.typeID here ... see findStyleAtomPresent below | |||
} | |||
assert(header != null); | |||
if (header == null) break; | |||
if (header.getParentRecord() instanceof SlideListWithText) { | |||
// runs found in PPDrawing are not linked with SlideListWithTexts | |||
header.setIndex(slwtIndex); | |||
} | |||
Record otherRecords[] = otherRecordList.toArray(new Record[otherRecordList.size()]); | |||
if (tbytes == null && tchars == null) { | |||
tbytes = new TextBytesAtom(); | |||
// header.getParentRecord().addChildAfter(tbytes, header); | |||
// don't add record yet - set it in storeText | |||
logger.log(POILogger.INFO, "bytes nor chars atom doesn't exist. Creating dummy record for later saving."); | |||
} | |||
String rawText = (tchars != null) ? tchars.getText() : tbytes.getText(); | |||
StyleTextPropAtom styles = findStyleAtomPresent(header, rawText.length()); | |||
List<HSLFTextParagraph> paragraphs = new ArrayList<HSLFTextParagraph>(); | |||
paragraphCollection.add(paragraphs); | |||
// split, but keep delimiter | |||
for (String para : rawText.split("(?<=\r)")) { | |||
HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars, styles); | |||
HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars); | |||
paragraphs.add(tpara); | |||
tpara.setStyleTextProp9Atom(styleTextProp9Atom); | |||
tpara._ruler = ruler; | |||
tpara._records = otherRecords; | |||
tpara.getParagraphStyle().updateTextSize(para.length()); | |||
HSLFTextRun trun = new HSLFTextRun(tpara); | |||
@@ -1059,6 +1108,10 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
} | |||
} | |||
if (paragraphCollection.isEmpty()) { | |||
logger.log(POILogger.DEBUG, "No text records found."); | |||
} | |||
return paragraphCollection; | |||
} | |||
@@ -1166,9 +1219,8 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> { | |||
TextPropCollection charStyle = sta.addCharacterTextPropCollection(1); | |||
wrapper.appendChildRecord(sta); | |||
HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null, sta); | |||
HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null); | |||
htp.setParagraphStyle(paraStyle); | |||
htp._records = new Record[0]; | |||
HSLFTextRun htr = new HSLFTextRun(htp); | |||
htr.setCharacterStyle(charStyle); |
@@ -92,7 +92,7 @@ public final class HSLFTextRun implements TextRun { | |||
* Change the text | |||
*/ | |||
public void setText(String text) { | |||
_runText = text; | |||
_runText = HSLFTextParagraph.toInternalString(text); | |||
} | |||
// --------------- Internal helpers on rich text properties ------- |
@@ -159,10 +159,29 @@ public abstract class HSLFTextShape extends HSLFSimpleShape implements TextShape | |||
} | |||
protected EscherTextboxWrapper getEscherTextboxWrapper(){ | |||
if(_txtbox == null){ | |||
EscherTextboxRecord textRecord = getEscherChild(EscherTextboxRecord.RECORD_ID); | |||
if(textRecord != null) _txtbox = new EscherTextboxWrapper(textRecord); | |||
if(_txtbox != null) return _txtbox; | |||
EscherTextboxRecord textRecord = getEscherChild(EscherTextboxRecord.RECORD_ID); | |||
if (textRecord == null) return null; | |||
HSLFSheet sheet = getSheet(); | |||
if (sheet != null) { | |||
PPDrawing drawing = sheet.getPPDrawing(); | |||
if (drawing != null) { | |||
EscherTextboxWrapper wrappers[] = drawing.getTextboxWrappers(); | |||
if (wrappers != null) { | |||
for (EscherTextboxWrapper w : wrappers) { | |||
// check for object identity | |||
if (textRecord == w.getEscherRecord()) { | |||
_txtbox = w; | |||
return _txtbox; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
_txtbox = new EscherTextboxWrapper(textRecord); | |||
return _txtbox; | |||
} | |||
@@ -507,13 +526,17 @@ public abstract class HSLFTextShape extends HSLFSimpleShape implements TextShape | |||
_paragraphs.addAll(HSLFTextParagraph.createEmptyParagraph()); | |||
_txtbox = _paragraphs.get(0).getTextboxWrapper(); | |||
} else { | |||
initParagraphsFromSheetRecords(); | |||
if (_paragraphs.isEmpty()) { | |||
List<List<HSLFTextParagraph>> llhtp = HSLFTextParagraph.findTextParagraphs(_txtbox); | |||
if (!llhtp.isEmpty()) { | |||
_paragraphs.addAll(llhtp.get(0)); | |||
} | |||
_paragraphs = HSLFTextParagraph.findTextParagraphs(_txtbox, getSheet()); | |||
if (_paragraphs == null || _paragraphs.isEmpty()) { | |||
throw new RuntimeException("TextRecord didn't contained any text lines"); | |||
} | |||
// initParagraphsFromSheetRecords(); | |||
// if (_paragraphs.isEmpty()) { | |||
// List<List<HSLFTextParagraph>> llhtp = HSLFTextParagraph.findTextParagraphs(_txtbox); | |||
// if (!llhtp.isEmpty()) { | |||
// _paragraphs.addAll(llhtp.get(0)); | |||
// } | |||
// } | |||
} | |||
for (HSLFTextParagraph p : _paragraphs) { | |||
@@ -536,57 +559,47 @@ public abstract class HSLFTextShape extends HSLFSimpleShape implements TextShape | |||
} | |||
} | |||
protected void initParagraphsFromSheetRecords(){ | |||
EscherTextboxWrapper txtbox = getEscherTextboxWrapper(); | |||
HSLFSheet sheet = getSheet(); | |||
if(sheet == null || txtbox == null) return; | |||
OutlineTextRefAtom ota = null; | |||
Record[] child = txtbox.getChildRecords(); | |||
for (int i = 0; i < child.length; i++) { | |||
if (child[i] instanceof OutlineTextRefAtom) { | |||
ota = (OutlineTextRefAtom)child[i]; | |||
break; | |||
} | |||
} | |||
List<List<HSLFTextParagraph>> sheetRuns = _sheet.getTextParagraphs(); | |||
_paragraphs.clear(); | |||
if (sheetRuns != null) { | |||
if (ota != null) { | |||
int idx = ota.getTextIndex(); | |||
for (List<HSLFTextParagraph> r : sheetRuns) { | |||
if (r.isEmpty()) continue; | |||
int ridx = r.get(0).getIndex(); | |||
if (ridx > idx) break; | |||
if (ridx == idx) _paragraphs.addAll(r); | |||
} | |||
if(_paragraphs.isEmpty()) { | |||
logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx); | |||
} | |||
} else { | |||
int shapeId = getShapeId(); | |||
for (List<HSLFTextParagraph> r : sheetRuns) { | |||
if (r.isEmpty()) continue; | |||
if (r.get(0).getShapeId() == shapeId) _paragraphs.addAll(r); | |||
} | |||
} | |||
} | |||
// ensure the same references child records of TextRun | |||
// TODO: check the purpose of this ... | |||
// if(_txtrun != null) { | |||
// for (int i = 0; i < child.length; i++) { | |||
// for (Record r : _txtrun.getRecords()) { | |||
// if (child[i].getRecordType() == r.getRecordType()) { | |||
// child[i] = r; | |||
// } | |||
// } | |||
// protected void initParagraphsFromSheetRecords(){ | |||
// EscherTextboxWrapper txtbox = getEscherTextboxWrapper(); | |||
// HSLFSheet sheet = getSheet(); | |||
// | |||
// if (sheet == null || txtbox == null) return; | |||
// List<List<HSLFTextParagraph>> sheetRuns = _sheet.getTextParagraphs(); | |||
// if (sheetRuns == null) return; | |||
// | |||
// _paragraphs.clear(); | |||
// OutlineTextRefAtom ota = (OutlineTextRefAtom)txtbox.findFirstOfType(OutlineTextRefAtom.typeID); | |||
// | |||
// if (ota != null) { | |||
// int idx = ota.getTextIndex(); | |||
// for (List<HSLFTextParagraph> r : sheetRuns) { | |||
// if (r.isEmpty()) continue; | |||
// int ridx = r.get(0).getIndex(); | |||
// if (ridx > idx) break; | |||
// if (ridx == idx) _paragraphs.addAll(r); | |||
// } | |||
// if(_paragraphs.isEmpty()) { | |||
// logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx); | |||
// } | |||
// } else { | |||
// int shapeId = getShapeId(); | |||
// for (List<HSLFTextParagraph> r : sheetRuns) { | |||
// if (r.isEmpty()) continue; | |||
// if (r.get(0).getShapeId() == shapeId) _paragraphs.addAll(r); | |||
// } | |||
// } | |||
} | |||
// | |||
// // ensure the same references child records of TextRun - see #48916 | |||
//// if(_txtrun != null) { | |||
//// for (int i = 0; i < child.length; i++) { | |||
//// for (Record r : _txtrun.getRecords()) { | |||
//// if (child[i].getRecordType() == r.getRecordType()) { | |||
//// child[i] = r; | |||
//// } | |||
//// } | |||
//// } | |||
//// } | |||
// } | |||
/* | |||
// 0xB acts like cariage return in page titles and like blank in the others | |||
@@ -740,7 +753,8 @@ public abstract class HSLFTextShape extends HSLFSimpleShape implements TextShape | |||
* Also updates the styles to the correct text length. | |||
*/ | |||
protected void storeText() { | |||
HSLFTextParagraph.storeText(_paragraphs); | |||
List<HSLFTextParagraph> paras = getTextParagraphs(); | |||
HSLFTextParagraph.storeText(paras); | |||
} | |||
// Accesser methods follow | |||
@@ -29,7 +29,7 @@ import org.apache.poi.hslf.record.SlideAtom; | |||
* @author Yegor Kozlov | |||
*/ | |||
public final class HSLFTitleMaster extends HSLFMasterSheet { | |||
private final List<List<HSLFTextParagraph>> _runs = new ArrayList<List<HSLFTextParagraph>>(); | |||
private final List<List<HSLFTextParagraph>> _paragraphs = new ArrayList<List<HSLFTextParagraph>>(); | |||
/** | |||
* Constructs a TitleMaster | |||
@@ -38,14 +38,16 @@ public final class HSLFTitleMaster extends HSLFMasterSheet { | |||
public HSLFTitleMaster(org.apache.poi.hslf.record.Slide record, int sheetNo) { | |||
super(record, sheetNo); | |||
_runs.addAll(HSLFTextParagraph.findTextParagraphs(getPPDrawing())); | |||
for (List<HSLFTextParagraph> l : HSLFTextParagraph.findTextParagraphs(getPPDrawing(), this)) { | |||
if (!_paragraphs.contains(l)) _paragraphs.add(l); | |||
} | |||
} | |||
/** | |||
* Returns an array of all the TextRuns found | |||
*/ | |||
public List<List<HSLFTextParagraph>> getTextParagraphs() { | |||
return _runs; | |||
return _paragraphs; | |||
} | |||
/** |
@@ -69,8 +69,8 @@ public class DrawFactory { | |||
return getDrawable((FreeformShape<? extends TextParagraph<? extends TextRun>>)shape); | |||
} else if (shape instanceof TextShape) { | |||
return getDrawable((TextShape<? extends TextParagraph<? extends TextRun>>)shape); | |||
} else if (shape instanceof ShapeGroup) { | |||
return getDrawable((ShapeGroup<? extends Shape>)shape); | |||
} else if (shape instanceof GroupShape) { | |||
return getDrawable((GroupShape<? extends Shape>)shape); | |||
} else if (shape instanceof PictureShape) { | |||
return getDrawable((PictureShape)shape); | |||
} else if (shape instanceof Background) { | |||
@@ -110,8 +110,8 @@ public class DrawFactory { | |||
return new DrawTextShape<T>(shape); | |||
} | |||
public <T extends ShapeGroup<? extends Shape>> DrawShapeGroup<T> getDrawable(T shape) { | |||
return new DrawShapeGroup<T>(shape); | |||
public <T extends GroupShape<? extends Shape>> DrawGroupShape<T> getDrawable(T shape) { | |||
return new DrawGroupShape<T>(shape); | |||
} | |||
public <T extends PictureShape> DrawPictureShape<T> getDrawable(T shape) { |
@@ -7,9 +7,9 @@ import java.awt.geom.Rectangle2D; | |||
import org.apache.poi.sl.usermodel.*; | |||
public class DrawShapeGroup<T extends ShapeGroup<? extends Shape>> extends DrawShape<T> implements Drawable { | |||
public class DrawGroupShape<T extends GroupShape<? extends Shape>> extends DrawShape<T> implements Drawable { | |||
public DrawShapeGroup(T shape) { | |||
public DrawGroupShape(T shape) { | |||
super(shape); | |||
} | |||
@@ -31,6 +31,7 @@ public class DrawShapeGroup<T extends ShapeGroup<? extends Shape>> extends DrawS | |||
tx.translate(-interior.getX(), -interior.getY()); | |||
DrawFactory drawFact = DrawFactory.getInstance(graphics); | |||
AffineTransform at2 = graphics.getTransform(); | |||
for (Shape child : shape) { | |||
// remember the initial transform and restore it after we are done with the drawing | |||
@@ -46,7 +47,7 @@ public class DrawShapeGroup<T extends ShapeGroup<? extends Shape>> extends DrawS | |||
graphics.setRenderingHint(Drawable.GRESTORE, true); | |||
} | |||
graphics.setTransform(at2); | |||
graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, tx0); | |||
} | |||
} |
@@ -25,11 +25,10 @@ public class DrawShape<T extends Shape> implements Drawable { | |||
if (!(shape instanceof PlaceableShape)) return; | |||
PlaceableShape ps = (PlaceableShape)shape; | |||
Rectangle2D anchor = ps.getAnchor(); | |||
AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM); | |||
if(tx != null) { | |||
anchor = tx.createTransformedShape(anchor).getBounds2D(); | |||
} | |||
final Rectangle2D anchor = (tx != null) | |||
? tx.createTransformedShape(ps.getAnchor()).getBounds2D() | |||
: ps.getAnchor(); | |||
// rotation | |||
double rotation = ps.getRotation(); | |||
@@ -39,7 +38,8 @@ public class DrawShape<T extends Shape> implements Drawable { | |||
double centerY = anchor.getCenterY(); | |||
// normalize rotation | |||
rotation = (360.+(rotation%360.))%360.; | |||
rotation %= 360.; | |||
if (rotation < 0) rotation += 360.; | |||
int quadrant = (((int)rotation+45)/90)%4; | |||
double scaleX = 1.0, scaleY = 1.0; | |||
@@ -53,26 +53,43 @@ public class DrawShape<T extends Shape> implements Drawable { | |||
// think of it, as if you paint the shape on a canvas. First you rotate the canvas, which might | |||
// be already (differently) scaled, so you can paint the shape in its default orientation | |||
// and later on, turn it around again to compare it with its original size ... | |||
AffineTransform txg = new AffineTransform(); // graphics coordinate space | |||
AffineTransform txs = new AffineTransform(tx); // shape coordinate space | |||
// graphics coordinate space | |||
AffineTransform txg = new AffineTransform(); | |||
txg.translate(centerX, centerY); | |||
txg.rotate(Math.toRadians(quadrant*90)); | |||
txg.rotate(Math.toRadians(90)); | |||
txg.translate(-centerX, -centerY); | |||
txs.translate(centerX, centerY); | |||
txs.rotate(Math.toRadians(-quadrant*90)); | |||
txs.translate(-centerX, -centerY); | |||
txg.concatenate(txs); | |||
Rectangle2D anchor2 = txg.createTransformedShape(ps.getAnchor()).getBounds2D(); | |||
boolean oldVariant = true; | |||
Rectangle2D anchor2; | |||
if (oldVariant) { | |||
// shape coordinate space | |||
AffineTransform txs = new AffineTransform(tx); | |||
txs.translate(centerX, centerY); | |||
txs.rotate(Math.toRadians(90)); | |||
txs.translate(-centerX, -centerY); | |||
txg.concatenate(txs); | |||
anchor2 = txg.createTransformedShape(ps.getAnchor()).getBounds2D(); | |||
} else { | |||
anchor2 = txg.createTransformedShape(anchor).getBounds2D(); | |||
} | |||
scaleX = anchor.getWidth() == 0. ? 1.0 : anchor.getWidth() / anchor2.getWidth(); | |||
scaleY = anchor.getHeight() == 0. ? 1.0 : anchor.getHeight() / anchor2.getHeight(); | |||
graphics.translate(centerX, centerY); | |||
graphics.rotate(Math.toRadians(rotation-quadrant*90.)); | |||
graphics.scale(scaleX, scaleY); | |||
graphics.rotate(Math.toRadians(quadrant*90)); | |||
graphics.translate(-centerX, -centerY); | |||
} else { | |||
graphics.translate(centerX, centerY); | |||
graphics.rotate(Math.toRadians(rotation)); | |||
graphics.scale(scaleX, scaleY); | |||
graphics.translate(-centerX, -centerY); | |||
} | |||
// transformation is applied reversed ... | |||
graphics.translate(centerX, centerY); | |||
graphics.rotate(Math.toRadians(rotation-quadrant*90.)); | |||
graphics.scale(scaleX, scaleY); | |||
graphics.rotate(Math.toRadians(quadrant*90)); | |||
graphics.translate(-centerX, -centerY); | |||
} | |||
//flip horizontal |
@@ -32,6 +32,23 @@ public interface Drawable { | |||
public boolean isCompatibleValue(Object val) { | |||
return true; | |||
} | |||
public String toString() { | |||
switch (intKey()) { | |||
case 1: return "DRAW_FACTORY"; | |||
case 2: return "GROUP_TRANSFORM"; | |||
case 3: return "IMAGE_RENDERER"; | |||
case 4: return "TEXT_RENDERING_MODE"; | |||
case 5: return "GRADIENT_SHAPE"; | |||
case 6: return "PRESET_GEOMETRY_CACHE"; | |||
case 7: return "FONT_HANDLER"; | |||
case 8: return "FONT_FALLBACK"; | |||
case 9: return "FONT_MAP"; | |||
case 10: return "GSAVE"; | |||
case 11: return "GRESTORE"; | |||
default: return "UNKNOWN_ID "+intKey(); | |||
} | |||
} | |||
} | |||
/** |
@@ -30,18 +30,35 @@ import javax.imageio.ImageIO; | |||
/** | |||
* For now this class renders only images supported by the javax.imageio.ImageIO | |||
* framework. Subclasses can override this class to support other formats, for | |||
* example, Use Apache batik to render WMF: | |||
* example, use Apache Batik to render WMF, PICT can be rendered using Apple QuickTime API for Java: | |||
* | |||
* <pre> | |||
* <code> | |||
* public class MyImageRendener extends ImageRendener { | |||
* InputStream data; | |||
* | |||
* public boolean drawImage(Graphics2D graphics,Rectangle2D anchor,Insets clip) { | |||
* // draw image | |||
* DataInputStream is = new DataInputStream(data); | |||
* org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore wmfStore = | |||
* new org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore(); | |||
* try { | |||
* wmfStore.read(is); | |||
* } catch (IOException e){ | |||
* return; | |||
* } | |||
* | |||
* float scale = (float)anchor.width/wmfStore.getWidthPixels(); | |||
* | |||
* org.apache.batik.transcoder.wmf.tosvg.WMFPainter painter = | |||
* new org.apache.batik.transcoder.wmf.tosvg.WMFPainter(wmfStore, 0, 0, scale); | |||
* graphics.translate(anchor.x, anchor.y); | |||
* painter.paint(graphics); | |||
* } | |||
* | |||
* public void loadImage(InputStream data, String contentType) throws IOException { | |||
* if ("image/wmf".equals(contentType)) { | |||
* this.data = data; | |||
* // use Apache Batik to handle WMF | |||
* } else { | |||
* super.loadImage(data,contentType); | |||
@@ -147,12 +164,14 @@ public class ImageRenderer { | |||
int iw = img.getWidth(); | |||
int ih = img.getHeight(); | |||
double cw = (100000-clip.left-clip.right) / 100000.0; | |||
double ch = (100000-clip.top-clip.bottom) / 100000.0; | |||
double sx = anchor.getWidth()/(iw*cw); | |||
double sy = anchor.getHeight()/(ih*ch); | |||
double tx = anchor.getX()-(iw*sx*clip.left/100000.0); | |||
double ty = anchor.getY()-(ih*sy*clip.top/100000.0); | |||
AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ; | |||
Shape clipOld = graphics.getClip(); |
@@ -19,6 +19,21 @@ package org.apache.poi.sl.usermodel; | |||
import java.awt.geom.Rectangle2D; | |||
public interface ShapeGroup<T extends Shape> extends Shape, ShapeContainer<T>, PlaceableShape { | |||
public interface GroupShape<T extends Shape> extends Shape, ShapeContainer<T>, PlaceableShape { | |||
/** | |||
* Gets the coordinate space of this group. All children are constrained | |||
* to these coordinates. | |||
* | |||
* @param anchor the coordinate space of this group | |||
*/ | |||
Rectangle2D getInteriorAnchor(); | |||
/** | |||
* Sets the coordinate space of this group. All children are constrained | |||
* to these coordinates. | |||
* | |||
* @param anchor the coordinate space of this group | |||
*/ | |||
void setInteriorAnchor(Rectangle2D anchor); | |||
} |
@@ -20,9 +20,17 @@ package org.apache.poi.sl.usermodel; | |||
import java.awt.Insets; | |||
public interface PictureShape extends SimpleShape { | |||
PictureData getPictureData(); | |||
/** | |||
* Returns the picture data for this picture. | |||
* | |||
* @return the picture data for this picture. | |||
*/ | |||
PictureData getPictureData(); | |||
/** | |||
* Returns the clipping values as percent ratio relatively to the image size. | |||
* The clipping are returned as insets converted/scaled to 100000 (=100%). | |||
* | |||
* @return the clipping rectangle, which is given in percent in relation to the image width/height | |||
*/ | |||
Insets getClipping(); |
@@ -17,6 +17,8 @@ | |||
package org.apache.poi.sl.usermodel; | |||
import java.awt.Graphics2D; | |||
/** | |||
* Common parent of Slides, Notes and Masters | |||
@@ -34,4 +36,11 @@ public interface Sheet<T extends Shape, SS extends SlideShow> extends ShapeConta | |||
MasterSheet<T,SS> getMasterSheet(); | |||
Background getBackground(); | |||
/** | |||
* Convenience method to draw a sheet to a graphics context | |||
* | |||
* @param graphics | |||
*/ | |||
void draw(Graphics2D graphics); | |||
} |
@@ -29,7 +29,6 @@ import org.junit.runners.Suite; | |||
TestFreeform.class, | |||
TestHeadersFooters.class, | |||
TestHyperlink.class, | |||
TestImagePainter.class, | |||
TestLine.class, | |||
TestMovieShape.class, | |||
TestOleEmbedding.class, |
@@ -1,55 +0,0 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hslf.model; | |||
import java.awt.Graphics2D; | |||
import junit.framework.TestCase; | |||
import org.apache.poi.hslf.blip.BitmapPainter; | |||
import org.apache.poi.hslf.blip.ImagePainter; | |||
import org.apache.poi.hslf.usermodel.HSLFPictureData; | |||
import org.apache.poi.hslf.usermodel.HSLFPictureShape; | |||
/** | |||
* Test Picture shape. | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public final class TestImagePainter extends TestCase { | |||
private static class CustomImagePainter implements ImagePainter { | |||
public CustomImagePainter() { | |||
// no fields to initialise | |||
} | |||
public void paint(Graphics2D graphics, HSLFPictureData pict, HSLFPictureShape parent){ | |||
//do noting | |||
} | |||
} | |||
public void testImagePainter() { | |||
ImagePainter pntr = HSLFPictureData.getImagePainter(HSLFPictureShape.PNG); | |||
assertTrue(HSLFPictureData.getImagePainter(HSLFPictureShape.PNG) instanceof BitmapPainter); | |||
assertTrue(HSLFPictureData.getImagePainter(HSLFPictureShape.JPEG) instanceof BitmapPainter); | |||
assertTrue(HSLFPictureData.getImagePainter(HSLFPictureShape.DIB) instanceof BitmapPainter); | |||
HSLFPictureData.setImagePainter(HSLFPictureShape.WMF, new CustomImagePainter()); | |||
assertTrue(HSLFPictureData.getImagePainter(HSLFPictureShape.WMF) instanceof CustomImagePainter); | |||
} | |||
} |
@@ -43,15 +43,15 @@ public final class TestTable { | |||
HSLFSlide slide = ppt.createSlide(); | |||
Table tbl = new Table(2, 5); | |||
HSLFTable tbl = new HSLFTable(2, 5); | |||
slide.addShape(tbl); | |||
TableCell cell = tbl.getCell(0, 0); | |||
HSLFTableCell cell = tbl.getCell(0, 0); | |||
//table cells have type=TextHeaderAtom.OTHER_TYPE, see bug #46033 | |||
assertEquals(TextHeaderAtom.OTHER_TYPE, cell.getTextParagraphs().get(0).getRunType()); | |||
assertTrue(slide.getShapes().get(0) instanceof Table); | |||
Table tbl2 = (Table)slide.getShapes().get(0); | |||
assertTrue(slide.getShapes().get(0) instanceof HSLFTable); | |||
HSLFTable tbl2 = (HSLFTable)slide.getShapes().get(0); | |||
assertEquals(tbl.getNumberOfColumns(), tbl2.getNumberOfColumns()); | |||
assertEquals(tbl.getNumberOfRows(), tbl2.getNumberOfRows()); | |||
@@ -61,8 +61,8 @@ public final class TestTable { | |||
ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); | |||
slide = ppt.getSlides().get(0); | |||
assertTrue(slide.getShapes().get(0) instanceof Table); | |||
Table tbl3 = (Table)slide.getShapes().get(0); | |||
assertTrue(slide.getShapes().get(0) instanceof HSLFTable); | |||
HSLFTable tbl3 = (HSLFTable)slide.getShapes().get(0); | |||
assertEquals(tbl.getNumberOfColumns(), tbl3.getNumberOfColumns()); | |||
assertEquals(tbl.getNumberOfRows(), tbl3.getNumberOfRows()); | |||
} | |||
@@ -75,7 +75,7 @@ public final class TestTable { | |||
HSLFSlideShow ppt = new HSLFSlideShow(); | |||
HSLFSlide slide = ppt.createSlide(); | |||
List<HSLFShape> shapes; | |||
Table tbl1 = new Table(1, 5); | |||
HSLFTable tbl1 = new HSLFTable(1, 5); | |||
assertEquals(5, tbl1.getNumberOfColumns()); | |||
assertEquals(1, tbl1.getNumberOfRows()); | |||
slide.addShape(tbl1); | |||
@@ -83,7 +83,7 @@ public final class TestTable { | |||
shapes = slide.getShapes(); | |||
assertEquals(1, shapes.size()); | |||
Table tbl2 = (Table)shapes.get(0); | |||
HSLFTable tbl2 = (HSLFTable)shapes.get(0); | |||
assertSame(tbl1.getSpContainer(), tbl2.getSpContainer()); | |||
assertEquals(tbl1.getNumberOfColumns(), tbl2.getNumberOfColumns()); | |||
@@ -93,13 +93,13 @@ public final class TestTable { | |||
@Test | |||
public void testIllegalCOnstruction(){ | |||
try { | |||
new Table(0, 5); | |||
new HSLFTable(0, 5); | |||
fail("Table(rownum, colnum) must throw IllegalArgumentException if any of tghe arguments is less than 1"); | |||
} catch (IllegalArgumentException e){ | |||
} | |||
try { | |||
new Table(5, 0); | |||
new HSLFTable(5, 0); | |||
fail("Table(rownum, colnum) must throw IllegalArgumentException if any of tghe arguments is less than 1"); | |||
} catch (IllegalArgumentException e){ | |||
@@ -281,7 +281,7 @@ public final class TestAddingSlides extends TestCase { | |||
assertEquals(14, doc.getNotesSlideListWithText().getSlideAtomsSets().length); | |||
//remove all slides, corresponding notes should be removed too | |||
for (int i = 0; i < slides.size(); i++) { | |||
for (int i = slides.size(); i > 0; i--) { | |||
ppt.removeSlide(0); | |||
} | |||
assertEquals(0, ppt.getSlides().size()); |
@@ -18,14 +18,10 @@ | |||
package org.apache.poi.hslf.usermodel; | |||
import static org.junit.Assert.*; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertTrue; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.awt.Color; | |||
import java.awt.Rectangle; | |||
import java.io.*; | |||
import java.util.ArrayList; | |||
import java.util.Date; | |||
import java.util.HashMap; | |||
@@ -44,14 +40,14 @@ import org.apache.poi.ddf.EscherProperties; | |||
import org.apache.poi.hslf.HSLFTestDataSamples; | |||
import org.apache.poi.hslf.exceptions.OldPowerPointFormatException; | |||
import org.apache.poi.hslf.model.*; | |||
import org.apache.poi.hslf.record.Document; | |||
import org.apache.poi.hslf.record.Record; | |||
import org.apache.poi.hslf.record.SlideListWithText; | |||
import org.apache.poi.hslf.model.textproperties.TextPropCollection; | |||
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType; | |||
import org.apache.poi.hslf.record.*; | |||
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet; | |||
import org.apache.poi.hslf.record.TextHeaderAtom; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.StringUtil; | |||
import org.apache.poi.util.Units; | |||
import org.apache.poi.poifs.filesystem.DocumentEntry; | |||
import org.apache.poi.poifs.filesystem.POIFSFileSystem; | |||
import org.apache.poi.util.*; | |||
import org.junit.Ignore; | |||
import org.junit.Test; | |||
/** | |||
@@ -527,7 +523,7 @@ public final class TestBugs { | |||
for (List<HSLFTextParagraph> tr : _slides.get(0).getTextParagraphs()) { | |||
if (! tr.get(0).isDrawingBased()) str++; | |||
} | |||
assertEquals(1, str); | |||
assertEquals(2, str); | |||
} | |||
@Test |
@@ -17,29 +17,22 @@ | |||
package org.apache.poi.hslf.usermodel; | |||
import static org.junit.Assert.assertTrue; | |||
import static org.junit.Assert.*; | |||
import static org.junit.Assume.assumeTrue; | |||
import java.awt.Color; | |||
import java.awt.Dimension; | |||
import java.awt.Font; | |||
import java.awt.Graphics2D; | |||
import java.awt.GraphicsEnvironment; | |||
import java.awt.RenderingHints; | |||
import java.awt.*; | |||
import java.awt.geom.AffineTransform; | |||
import java.awt.geom.Rectangle2D; | |||
import java.awt.image.BufferedImage; | |||
import java.awt.image.DataBufferByte; | |||
import java.io.File; | |||
import java.io.InputStream; | |||
import java.util.Arrays; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import java.util.*; | |||
import javax.imageio.ImageIO; | |||
import org.apache.poi.POIDataSamples; | |||
import org.apache.poi.hslf.model.TextPainter; | |||
import org.apache.poi.sl.draw.Drawable; | |||
import org.apache.poi.util.TempFile; | |||
import org.junit.Ignore; | |||
import org.junit.Test; | |||
@@ -50,7 +43,7 @@ import org.junit.Test; | |||
public class TestFontRendering { | |||
private static POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); | |||
@Ignore("This fails on some systems because fonts are rendered slightly different") | |||
// @Ignore2("This fails on some systems because fonts are rendered slightly different") | |||
@Test | |||
public void bug55902mixedFontWithChineseCharacters() throws Exception { | |||
// font files need to be downloaded first via | |||
@@ -86,7 +79,7 @@ public class TestFontRendering { | |||
Dimension pgsize = ss.getPageSize(); | |||
HSLFSlide slide = ss.getSlides()[0]; | |||
HSLFSlide slide = ss.getSlides().get(0); | |||
// render it | |||
double zoom = 1; | |||
@@ -95,8 +88,8 @@ public class TestFontRendering { | |||
BufferedImage imgActual = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_3BYTE_BGR); | |||
Graphics2D graphics = imgActual.createGraphics(); | |||
graphics.setRenderingHint(TextPainter.KEY_FONTFALLBACK, fallbackMap); | |||
graphics.setRenderingHint(TextPainter.KEY_FONTMAP, fontMap); | |||
graphics.setRenderingHint(Drawable.FONT_FALLBACK, fallbackMap); | |||
graphics.setRenderingHint(Drawable.FONT_MAP, fontMap); | |||
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); | |||
@@ -116,7 +109,7 @@ public class TestFontRendering { | |||
if(!Arrays.equals(expectedData, actualData)) { | |||
ImageIO.write(imgActual, "PNG", TempFile.createTempFile("TestFontRendering", ".png")); | |||
} | |||
assertTrue("Expected to have matching raster-arrays, but found differences, size " + expectedData.length + " and " + actualData.length, | |||
Arrays.equals(expectedData, actualData)); | |||
assertArrayEquals("Expected to have matching raster-arrays, but found differences", expectedData, actualData); | |||
} | |||
} |
@@ -79,10 +79,14 @@ public final class TestNumberedList3 { | |||
assertEquals(Short.valueOf((short)1), autoNumbers[0].getAutoNumberStartNumber());//Default value = 1 will be used | |||
assertTrue(TextAutoNumberSchemeEnum.ANM_ArabicPeriod == autoNumbersOfTextBox0[0].getAutoNumberScheme()); | |||
final List<TextPropCollection> textProps = textParass.get(1).get(0).getStyleTextPropAtom().getCharacterStyles(); | |||
assertEquals(1, textProps.size()); | |||
final TextPropCollection textProp = textProps.get(0); | |||
assertEquals(67, textProp.getCharactersCovered()); | |||
int chCovered = 0; | |||
for (HSLFTextParagraph htp : textParass.get(1)) { | |||
for (HSLFTextRun htr : htp.getTextRuns()) { | |||
TextPropCollection textProp = htr.getCharacterStyle(); | |||
chCovered += textProp.getCharactersCovered(); | |||
} | |||
} | |||
assertEquals(67, chCovered); | |||
assertTrue(textParass.get(0).get(0).isBullet()); | |||
@@ -17,18 +17,11 @@ | |||
package org.apache.poi.hslf.usermodel; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertNull; | |||
import static org.junit.Assert.assertSame; | |||
import java.awt.Dimension; | |||
import java.awt.Graphics2D; | |||
import java.awt.Rectangle; | |||
import static org.junit.Assert.*; | |||
import java.awt.*; | |||
import java.awt.image.BufferedImage; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.File; | |||
import java.io.InputStream; | |||
import java.io.*; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
@@ -36,8 +29,12 @@ import javax.imageio.ImageIO; | |||
import org.apache.poi.POIDataSamples; | |||
import org.apache.poi.ddf.EscherBSERecord; | |||
import org.apache.poi.hslf.usermodel.*; | |||
import org.apache.poi.hssf.usermodel.DummyGraphics2d; | |||
import org.apache.poi.sl.draw.Drawable; | |||
import org.apache.poi.sl.usermodel.Slide; | |||
import org.apache.poi.sl.usermodel.SlideShow; | |||
import org.apache.poi.util.JvmBugs; | |||
import org.apache.poi.xslf.usermodel.XMLSlideShow; | |||
import org.junit.Ignore; | |||
import org.junit.Test; | |||
@@ -143,45 +140,42 @@ public final class TestPicture { | |||
} | |||
@Test | |||
@Ignore("Just for visual validation - antialiasing is different on various systems") | |||
// @Ignore("Just for visual validation - antialiasing is different on various systems") | |||
public void bug54541() throws Exception { | |||
// InputStream xis = _slTests.openResourceAsStream("54542_cropped_bitmap.pptx"); | |||
// XMLSlideShow xss = new XMLSlideShow(xis); | |||
// xis.close(); | |||
// | |||
// Dimension xpg = xss.getPageSize(); | |||
// for(XSLFSlide slide : xss.getSlides()) { | |||
// BufferedImage img = new BufferedImage(xpg.width, xpg.height, BufferedImage.TYPE_INT_RGB); | |||
// Graphics2D graphics = img.createGraphics(); | |||
// fixFonts(graphics); | |||
// slide.draw(graphics); | |||
// ImageIO.write(img, "PNG", new File("testx.png")); | |||
// } | |||
// | |||
// System.out.println("########################"); | |||
InputStream is = _slTests.openResourceAsStream("54541_cropped_bitmap.ppt"); | |||
HSLFSlideShow ss = new HSLFSlideShow(is); | |||
String file = new String[]{ | |||
"54542_cropped_bitmap.pptx", | |||
"54541_cropped_bitmap.ppt", | |||
"54541_cropped_bitmap2.ppt", | |||
"sample_pptx_grouping_issues.pptx" | |||
}[3]; | |||
InputStream is = _slTests.openResourceAsStream(file); | |||
SlideShow ss = file.endsWith("pptx") ? new XMLSlideShow(is) : new HSLFSlideShow(is); | |||
is.close(); | |||
boolean debugOut = false; | |||
Dimension pg = ss.getPageSize(); | |||
int i=1; | |||
for(HSLFSlide slide : ss.getSlides()) { | |||
BufferedImage img = new BufferedImage(pg.width, pg.height, BufferedImage.TYPE_INT_RGB); | |||
Graphics2D graphics = img.createGraphics(); | |||
fixFonts(graphics); | |||
slide.draw(graphics); | |||
ImageIO.write(img, "PNG", new File("test"+(i++)+".png")); | |||
for(Slide<?,?,?> slide : ss.getSlides()) { | |||
if (debugOut) { | |||
DummyGraphics2d graphics = new DummyGraphics2d(); | |||
slide.draw(graphics); | |||
} else { | |||
BufferedImage img = new BufferedImage(pg.width, pg.height, BufferedImage.TYPE_INT_RGB); | |||
Graphics2D graphics = img.createGraphics(); | |||
fixFonts(graphics); | |||
slide.draw(graphics); | |||
ImageIO.write(img, "PNG", new File("test"+(i++)+"hslf.png")); | |||
} | |||
} | |||
} | |||
@SuppressWarnings("unchecked") | |||
private void fixFonts(Graphics2D graphics) { | |||
if (!JvmBugs.hasLineBreakMeasurerBug()) return; | |||
Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(TextPainter.KEY_FONTMAP); | |||
Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_MAP); | |||
if (fontMap == null) fontMap = new HashMap<String,String>(); | |||
fontMap.put("Calibri", "Lucida Sans"); | |||
fontMap.put("Cambria", "Lucida Bright"); | |||
graphics.setRenderingHint(TextPainter.KEY_FONTMAP, fontMap); | |||
graphics.setRenderingHint(Drawable.FONT_MAP, fontMap); | |||
} | |||
} |
@@ -22,17 +22,12 @@ import static org.junit.Assert.assertArrayEquals; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.net.URL; | |||
import java.util.List; | |||
import junit.framework.TestCase; | |||
import org.apache.poi.POIDataSamples; | |||
import org.apache.poi.hslf.blip.DIB; | |||
import org.apache.poi.hslf.blip.EMF; | |||
import org.apache.poi.hslf.blip.JPEG; | |||
import org.apache.poi.hslf.blip.PICT; | |||
import org.apache.poi.hslf.blip.PNG; | |||
import org.apache.poi.hslf.blip.WMF; | |||
import org.apache.poi.hslf.model.*; | |||
import org.apache.poi.hslf.blip.*; | |||
/** | |||
* Test adding/reading pictures | |||
@@ -65,9 +60,9 @@ public final class TestPictures extends TestCase{ | |||
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); | |||
//make sure we can read this picture shape and it refers to the correct picture data | |||
HSLFShape[] sh = ppt.getSlides()[0].getShapes(); | |||
assertEquals(1, sh.length); | |||
pict = (HSLFPictureShape)sh[0]; | |||
List<HSLFShape> sh = ppt.getSlides().get(0).getShapes(); | |||
assertEquals(1, sh.size()); | |||
pict = (HSLFPictureShape)sh.get(0); | |||
assertEquals(idx, pict.getPictureIndex()); | |||
//check picture data | |||
@@ -110,9 +105,9 @@ public final class TestPictures extends TestCase{ | |||
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); | |||
//make sure we can read this picture shape and it refers to the correct picture data | |||
HSLFShape[] sh = ppt.getSlides()[0].getShapes(); | |||
assertEquals(1, sh.length); | |||
pict = (HSLFPictureShape)sh[0]; | |||
List<HSLFShape> sh = ppt.getSlides().get(0).getShapes(); | |||
assertEquals(1, sh.size()); | |||
pict = (HSLFPictureShape)sh.get(0); | |||
assertEquals(idx, pict.getPictureIndex()); | |||
//check picture data | |||
@@ -156,9 +151,9 @@ public final class TestPictures extends TestCase{ | |||
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); | |||
//make sure we can get this picture shape and it refers to the correct picture data | |||
HSLFShape[] sh = ppt.getSlides()[0].getShapes(); | |||
assertEquals(1, sh.length); | |||
pict = (HSLFPictureShape)sh[0]; | |||
List<HSLFShape> sh = ppt.getSlides().get(0).getShapes(); | |||
assertEquals(1, sh.size()); | |||
pict = (HSLFPictureShape)sh.get(0); | |||
assertEquals(idx, pict.getPictureIndex()); | |||
//check picture data | |||
@@ -195,9 +190,9 @@ public final class TestPictures extends TestCase{ | |||
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); | |||
//make sure we can read this picture shape and it refers to the correct picture data | |||
HSLFShape[] sh = ppt.getSlides()[0].getShapes(); | |||
assertEquals(1, sh.length); | |||
pict = (HSLFPictureShape)sh[0]; | |||
List<HSLFShape> sh = ppt.getSlides().get(0).getShapes(); | |||
assertEquals(1, sh.size()); | |||
pict = (HSLFPictureShape)sh.get(0); | |||
assertEquals(idx, pict.getPictureIndex()); | |||
//check picture data | |||
@@ -235,9 +230,9 @@ public final class TestPictures extends TestCase{ | |||
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); | |||
//make sure we can read this picture shape and it refers to the correct picture data | |||
HSLFShape[] sh = ppt.getSlides()[0].getShapes(); | |||
assertEquals(1, sh.length); | |||
pict = (HSLFPictureShape)sh[0]; | |||
List<HSLFShape> sh = ppt.getSlides().get(0).getShapes(); | |||
assertEquals(1, sh.size()); | |||
pict = (HSLFPictureShape)sh.get(0); | |||
assertEquals(idx, pict.getPictureIndex()); | |||
//check picture data | |||
@@ -274,9 +269,9 @@ public final class TestPictures extends TestCase{ | |||
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); | |||
//make sure we can read this picture shape and it refers to the correct picture data | |||
HSLFShape[] sh = ppt.getSlides()[0].getShapes(); | |||
assertEquals(1, sh.length); | |||
pict = (HSLFPictureShape)sh[0]; | |||
List<HSLFShape> sh = ppt.getSlides().get(0).getShapes(); | |||
assertEquals(1, sh.size()); | |||
pict = (HSLFPictureShape)sh.get(0); | |||
assertEquals(idx, pict.getPictureIndex()); | |||
//check picture data | |||
@@ -302,11 +297,11 @@ public final class TestPictures extends TestCase{ | |||
HSLFPictureData pdata; | |||
HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("pictures.ppt")); | |||
HSLFSlide[] slides = ppt.getSlides(); | |||
List<HSLFSlide> slides = ppt.getSlides(); | |||
HSLFPictureData[] pictures = ppt.getPictureData(); | |||
assertEquals(5, pictures.length); | |||
pict = (HSLFPictureShape)slides[0].getShapes()[0]; //the first slide contains JPEG | |||
pict = (HSLFPictureShape)slides.get(0).getShapes().get(0); //the first slide contains JPEG | |||
pdata = pict.getPictureData(); | |||
assertTrue(pdata instanceof JPEG); | |||
assertEquals(HSLFPictureShape.JPEG, pdata.getType()); | |||
@@ -314,7 +309,7 @@ public final class TestPictures extends TestCase{ | |||
ppt_bytes = slTests.readFile("clock.jpg"); | |||
assertArrayEquals(src_bytes, ppt_bytes); | |||
pict = (HSLFPictureShape)slides[1].getShapes()[0]; //the second slide contains PNG | |||
pict = (HSLFPictureShape)slides.get(1).getShapes().get(0); //the second slide contains PNG | |||
pdata = pict.getPictureData(); | |||
assertTrue(pdata instanceof PNG); | |||
assertEquals(HSLFPictureShape.PNG, pdata.getType()); | |||
@@ -322,7 +317,7 @@ public final class TestPictures extends TestCase{ | |||
ppt_bytes = slTests.readFile("tomcat.png"); | |||
assertArrayEquals(src_bytes, ppt_bytes); | |||
pict = (HSLFPictureShape)slides[2].getShapes()[0]; //the third slide contains WMF | |||
pict = (HSLFPictureShape)slides.get(2).getShapes().get(0); //the third slide contains WMF | |||
pdata = pict.getPictureData(); | |||
assertTrue(pdata instanceof WMF); | |||
assertEquals(HSLFPictureShape.WMF, pdata.getType()); | |||
@@ -336,7 +331,7 @@ public final class TestPictures extends TestCase{ | |||
System.arraycopy(ppt_bytes, 22, b2, 0, b2.length); | |||
assertArrayEquals(b1, b2); | |||
pict = (HSLFPictureShape)slides[3].getShapes()[0]; //the forth slide contains PICT | |||
pict = (HSLFPictureShape)slides.get(3).getShapes().get(0); //the forth slide contains PICT | |||
pdata = pict.getPictureData(); | |||
assertTrue(pdata instanceof PICT); | |||
assertEquals(HSLFPictureShape.PICT, pdata.getType()); | |||
@@ -350,7 +345,7 @@ public final class TestPictures extends TestCase{ | |||
System.arraycopy(ppt_bytes, 512, b2, 0, b2.length); | |||
assertArrayEquals(b1, b2); | |||
pict = (HSLFPictureShape)slides[4].getShapes()[0]; //the fifth slide contains EMF | |||
pict = (HSLFPictureShape)slides.get(4).getShapes().get(0); //the fifth slide contains EMF | |||
pdata = pict.getPictureData(); | |||
assertTrue(pdata instanceof EMF); | |||
assertEquals(HSLFPictureShape.EMF, pdata.getType()); | |||
@@ -375,20 +370,20 @@ public final class TestPictures extends TestCase{ | |||
// Now test what happens when we use the SlideShow interface | |||
HSLFSlideShow ppt = new HSLFSlideShow(hslf); | |||
HSLFSlide[] slides = ppt.getSlides(); | |||
List<HSLFSlide> slides = ppt.getSlides(); | |||
HSLFPictureData[] pictures = ppt.getPictureData(); | |||
assertEquals(12, slides.length); | |||
assertEquals(12, slides.size()); | |||
assertEquals(2, pictures.length); | |||
HSLFPictureShape pict; | |||
HSLFPictureData pdata; | |||
pict = (HSLFPictureShape)slides[0].getShapes()[1]; // 2nd object on 1st slide | |||
pict = (HSLFPictureShape)slides.get(0).getShapes().get(1); // 2nd object on 1st slide | |||
pdata = pict.getPictureData(); | |||
assertTrue(pdata instanceof WMF); | |||
assertEquals(HSLFPictureShape.WMF, pdata.getType()); | |||
pict = (HSLFPictureShape)slides[0].getShapes()[2]; // 3rd object on 1st slide | |||
pict = (HSLFPictureShape)slides.get(0).getShapes().get(2); // 3rd object on 1st slide | |||
pdata = pict.getPictureData(); | |||
assertTrue(pdata instanceof WMF); | |||
assertEquals(HSLFPictureShape.WMF, pdata.getType()); | |||
@@ -411,20 +406,20 @@ public final class TestPictures extends TestCase{ | |||
// Now test what happens when we use the SlideShow interface | |||
HSLFSlideShow ppt = new HSLFSlideShow(hslf); | |||
HSLFSlide[] slides = ppt.getSlides(); | |||
List<HSLFSlide> slides = ppt.getSlides(); | |||
HSLFPictureData[] pictures = ppt.getPictureData(); | |||
assertEquals(27, slides.length); | |||
assertEquals(27, slides.size()); | |||
assertEquals(2, pictures.length); | |||
HSLFPictureShape pict; | |||
HSLFPictureData pdata; | |||
pict = (HSLFPictureShape)slides[6].getShapes()[13]; | |||
pict = (HSLFPictureShape)slides.get(6).getShapes().get(13); | |||
pdata = pict.getPictureData(); | |||
assertTrue(pdata instanceof WMF); | |||
assertEquals(HSLFPictureShape.WMF, pdata.getType()); | |||
pict = (HSLFPictureShape)slides[7].getShapes()[13]; | |||
pict = (HSLFPictureShape)slides.get(7).getShapes().get(13); | |||
pdata = pict.getPictureData(); | |||
assertTrue(pdata instanceof WMF); | |||
assertEquals(HSLFPictureShape.WMF, pdata.getType()); | |||
@@ -446,9 +441,9 @@ public final class TestPictures extends TestCase{ | |||
public void testGetPictureName() throws Exception { | |||
HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("ppt_with_png.ppt")); | |||
HSLFSlide slide = ppt.getSlides()[0]; | |||
HSLFSlide slide = ppt.getSlides().get(0); | |||
HSLFPictureShape p = (HSLFPictureShape)slide.getShapes()[0]; //the first slide contains JPEG | |||
HSLFPictureShape p = (HSLFPictureShape)slide.getShapes().get(0); //the first slide contains JPEG | |||
assertEquals("test", p.getPictureName()); | |||
} | |||
@@ -469,7 +464,7 @@ public final class TestPictures extends TestCase{ | |||
ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); | |||
HSLFPictureShape p = (HSLFPictureShape)ppt.getSlides()[0].getShapes()[0]; | |||
HSLFPictureShape p = (HSLFPictureShape)ppt.getSlides().get(0).getShapes().get(0); | |||
assertEquals("tomcat.png", p.getPictureName()); | |||
} | |||
} |
@@ -19,10 +19,12 @@ | |||
package org.apache.poi.hslf.usermodel; | |||
import junit.framework.TestCase; | |||
import static org.junit.Assert.*; | |||
import java.util.List; | |||
import org.apache.poi.hslf.model.Table; | |||
import org.apache.poi.POIDataSamples; | |||
import org.junit.Test; | |||
/** | |||
@@ -30,40 +32,39 @@ import org.apache.poi.POIDataSamples; | |||
* | |||
* @author Alex Nikiforov [mailto:anikif@gmail.com] | |||
*/ | |||
public final class TestTable extends TestCase { | |||
public class TestTable { | |||
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); | |||
protected void setUp() throws Exception { | |||
} | |||
public void testTable() throws Exception { | |||
@Test | |||
public void testTable() throws Exception { | |||
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("54111.ppt")); | |||
assertTrue("No Exceptions while reading file", true); | |||
final HSLFSlide[] slides = ppt.getSlides(); | |||
assertEquals(1, slides.length); | |||
checkSlide(slides[0]); | |||
List<HSLFSlide> slides = ppt.getSlides(); | |||
assertEquals(1, slides.size()); | |||
checkSlide(slides.get(0)); | |||
} | |||
private void checkSlide(final HSLFSlide s) { | |||
HSLFTextParagraph[] textRuns = s.getTextParagraphs(); | |||
assertEquals(2, textRuns.length); | |||
List<List<HSLFTextParagraph>> textRuns = s.getTextParagraphs(); | |||
assertEquals(2, textRuns.size()); | |||
HSLFTextRun textRun = textRuns[0].getTextRuns()[0]; | |||
HSLFTextRun textRun = textRuns.get(0).get(0).getTextRuns().get(0); | |||
assertEquals("Table sample", textRun.getRawText().trim()); | |||
assertEquals(1, textRuns[0].getTextRuns().length); | |||
assertFalse(textRun.isBullet()); | |||
assertEquals(1, textRuns.get(0).get(0).getTextRuns().size()); | |||
assertFalse(textRun.getTextParagraph().isBullet()); | |||
assertEquals("Dummy text", textRuns[1].getRawText()); | |||
assertEquals("Dummy text", HSLFTextParagraph.getRawText(textRuns.get(1))); | |||
final HSLFShape[] shapes = s.getShapes(); | |||
List<HSLFShape> shapes = s.getShapes(); | |||
assertNotNull(shapes); | |||
assertEquals(3, shapes.length); | |||
assertTrue(shapes[2] instanceof Table); | |||
final Table table = (Table) shapes[2]; | |||
assertEquals(3, shapes.size()); | |||
assertTrue(shapes.get(2) instanceof HSLFTable); | |||
final HSLFTable table = (HSLFTable) shapes.get(2); | |||
assertEquals(4, table.getNumberOfColumns()); | |||
assertEquals(6, table.getNumberOfRows()); | |||
for (int x = 0; x < 4; x ++) { | |||
assertEquals("TH Cell " + (x + 1), table.getCell(0, x).getTextParagraphs().getRawText()); | |||
assertEquals("TH Cell " + (x + 1), HSLFTextParagraph.getRawText(table.getCell(0, x).getTextParagraphs())); | |||
for (int y = 1; y < 6; y++) { | |||
assertEquals("Row " + y + ", Cell " + (x + 1), table.getCell(y, x).getText()); | |||
} |
@@ -19,10 +19,12 @@ package org.apache.poi.hslf.usermodel; | |||
import static org.junit.Assert.*; | |||
import java.io.IOException; | |||
import java.awt.Color; | |||
import java.io.*; | |||
import java.util.List; | |||
import org.apache.poi.POIDataSamples; | |||
import org.apache.poi.hslf.model.textproperties.TextPropCollection; | |||
import org.apache.poi.hslf.record.*; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
@@ -99,7 +101,7 @@ public final class TestTextRun { | |||
// Ensure trailing \n's are NOT stripped, it is legal to set a text with a trailing '\r' | |||
tr.setText(changeTo + "\n"); | |||
assertEquals(changeTo + "\n", tr.getRawText()); | |||
assertEquals(changeTo + "\r", tr.getRawText()); | |||
} | |||
/** | |||
@@ -121,7 +123,6 @@ public final class TestTextRun { | |||
else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r; | |||
else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r; | |||
} | |||
// Bytes -> Bytes | |||
assertNull(tca); | |||
@@ -197,18 +198,13 @@ public final class TestTextRun { | |||
List<HSLFTextParagraph> trB = textParass.get(1); | |||
assertEquals(1, trA.size()); | |||
assertEquals(1, trB.size()); | |||
assertEquals(2, trB.size()); | |||
HSLFTextRun rtrA = trA.get(0).getTextRuns().get(0); | |||
HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); | |||
assertEquals(HSLFTextParagraph.getRawText(trA), rtrA.getRawText()); | |||
assertEquals(HSLFTextParagraph.getRawText(trB), rtrB.getRawText()); | |||
// assertNull(rtrA._getRawCharacterStyle()); | |||
// assertNull(rtrA._getRawParagraphStyle()); | |||
// assertNull(rtrB._getRawCharacterStyle()); | |||
// assertNull(rtrB._getRawParagraphStyle()); | |||
assertEquals(HSLFTextParagraph.getRawText(trB.subList(0, 1)), rtrB.getRawText()); | |||
} | |||
/** | |||
@@ -284,39 +280,39 @@ public final class TestTextRun { | |||
HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); | |||
HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0); | |||
HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0); | |||
// TextPropCollection tpBP = rtrB._getRawParagraphStyle(); | |||
// TextPropCollection tpBC = rtrB._getRawCharacterStyle(); | |||
// TextPropCollection tpCP = rtrC._getRawParagraphStyle(); | |||
// TextPropCollection tpCC = rtrC._getRawCharacterStyle(); | |||
// TextPropCollection tpDP = rtrD._getRawParagraphStyle(); | |||
// TextPropCollection tpDC = rtrD._getRawCharacterStyle(); | |||
TextPropCollection tpBP = rtrB.getTextParagraph().getParagraphStyle(); | |||
TextPropCollection tpBC = rtrB.getCharacterStyle(); | |||
TextPropCollection tpCP = rtrC.getTextParagraph().getParagraphStyle(); | |||
TextPropCollection tpCC = rtrC.getCharacterStyle(); | |||
TextPropCollection tpDP = rtrD.getTextParagraph().getParagraphStyle(); | |||
TextPropCollection tpDC = rtrD.getCharacterStyle(); | |||
// assertEquals(trB.getRawText().substring(0, 30), rtrB.getRawText()); | |||
// assertNotNull(tpBP); | |||
// assertNotNull(tpBC); | |||
// assertNotNull(tpCP); | |||
// assertNotNull(tpCC); | |||
// assertNotNull(tpDP); | |||
// assertNotNull(tpDC); | |||
// assertTrue(tpBP.equals(tpCP)); | |||
// assertTrue(tpBP.equals(tpDP)); | |||
// assertTrue(tpCP.equals(tpDP)); | |||
// assertFalse(tpBC.equals(tpCC)); | |||
// assertFalse(tpBC.equals(tpDC)); | |||
// assertFalse(tpCC.equals(tpDC)); | |||
assertNotNull(tpBP); | |||
assertNotNull(tpBC); | |||
assertNotNull(tpCP); | |||
assertNotNull(tpCC); | |||
assertNotNull(tpDP); | |||
assertNotNull(tpDC); | |||
assertEquals(tpBP,tpCP); | |||
assertEquals(tpBP,tpDP); | |||
assertEquals(tpCP,tpDP); | |||
assertNotEquals(tpBC,tpCC); | |||
assertNotEquals(tpBC,tpDC); | |||
assertNotEquals(tpCC,tpDC); | |||
// Change text via normal | |||
// trB.setText("Test Foo Test"); | |||
HSLFTextParagraph.setText(trB, "Test Foo Test"); | |||
// Ensure now have first style | |||
// assertEquals(1, trB.getTextRuns().length); | |||
// rtrB = trB.getTextRuns().get(0); | |||
// assertEquals("Test Foo Test", trB.getRawText()); | |||
// assertEquals("Test Foo Test", rtrB.getRawText()); | |||
// assertNotNull(rtrB._getRawCharacterStyle()); | |||
// assertNotNull(rtrB._getRawParagraphStyle()); | |||
// assertEquals( tpBP, rtrB._getRawParagraphStyle() ); | |||
// assertEquals( tpBC, rtrB._getRawCharacterStyle() ); | |||
assertEquals(1, trB.get(0).getTextRuns().size()); | |||
rtrB = trB.get(0).getTextRuns().get(0); | |||
assertEquals("Test Foo Test", HSLFTextParagraph.getRawText(trB)); | |||
assertEquals("Test Foo Test", rtrB.getRawText()); | |||
assertNotNull(rtrB.getCharacterStyle()); | |||
assertNotNull(rtrB.getTextParagraph().getParagraphStyle()); | |||
assertEquals( tpBP, rtrB.getTextParagraph().getParagraphStyle() ); | |||
assertEquals( tpBC, rtrB.getCharacterStyle() ); | |||
} | |||
/** | |||
@@ -328,21 +324,21 @@ public final class TestTextRun { | |||
HSLFSlide slideOne = ss.getSlides().get(0); | |||
List<List<HSLFTextParagraph>> textRuns = slideOne.getTextParagraphs(); | |||
List<HSLFTextParagraph> trB = textRuns.get(1); | |||
// assertEquals(1, trB.getTextRuns().length); | |||
// | |||
// HSLFTextRun rtrB = trB.getTextRuns().get(0); | |||
// assertEquals(trB.getRawText(), rtrB.getRawText()); | |||
// assertNull(rtrB._getRawCharacterStyle()); | |||
// assertNull(rtrB._getRawParagraphStyle()); | |||
assertEquals(1, trB.get(0).getTextRuns().size()); | |||
HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); | |||
assertEquals(HSLFTextParagraph.getRawText(trB.subList(0, 1)), rtrB.getRawText()); | |||
assertNotNull(rtrB.getCharacterStyle()); | |||
assertNotNull(rtrB.getTextParagraph().getParagraphStyle()); | |||
// Change text via rich | |||
// rtrB.setText("Test Test Test"); | |||
// assertEquals("Test Test Test", trB.getRawText()); | |||
// assertEquals("Test Test Test", rtrB.getRawText()); | |||
rtrB.setText("Test Test Test"); | |||
assertEquals("Test Test Test", HSLFTextParagraph.getRawText(trB.subList(0, 1))); | |||
assertEquals("Test Test Test", rtrB.getRawText()); | |||
// Will now have dummy props | |||
// assertNotNull(rtrB._getRawCharacterStyle()); | |||
// assertNotNull(rtrB._getRawParagraphStyle()); | |||
assertNotNull(rtrB.getCharacterStyle()); | |||
assertNotNull(rtrB.getTextParagraph().getParagraphStyle()); | |||
} | |||
/** | |||
@@ -357,31 +353,31 @@ public final class TestTextRun { | |||
assertEquals(3, trB.size()); | |||
// We start with 3 text runs, each with their own set of styles, | |||
// but all sharing the same paragraph styles | |||
// but all sharing the same paragraph styles | |||
HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); | |||
HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0); | |||
HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0); | |||
// TextPropCollection tpBP = rtrB._getRawParagraphStyle(); | |||
// TextPropCollection tpBC = rtrB._getRawCharacterStyle(); | |||
// TextPropCollection tpCP = rtrC._getRawParagraphStyle(); | |||
// TextPropCollection tpCC = rtrC._getRawCharacterStyle(); | |||
// TextPropCollection tpDP = rtrD._getRawParagraphStyle(); | |||
// TextPropCollection tpDC = rtrD._getRawCharacterStyle(); | |||
TextPropCollection tpBP = rtrB.getTextParagraph().getParagraphStyle(); | |||
TextPropCollection tpBC = rtrB.getCharacterStyle(); | |||
TextPropCollection tpCP = rtrC.getTextParagraph().getParagraphStyle(); | |||
TextPropCollection tpCC = rtrC.getCharacterStyle(); | |||
TextPropCollection tpDP = rtrD.getTextParagraph().getParagraphStyle(); | |||
TextPropCollection tpDC = rtrD.getCharacterStyle(); | |||
// Check text and stylings | |||
// assertEquals(trB.getRawText().substring(0, 30), rtrB.getRawText()); | |||
// assertNotNull(tpBP); | |||
// assertNotNull(tpBC); | |||
// assertNotNull(tpCP); | |||
// assertNotNull(tpCC); | |||
// assertNotNull(tpDP); | |||
// assertNotNull(tpDC); | |||
// assertTrue(tpBP.equals(tpCP)); | |||
// assertTrue(tpBP.equals(tpDP)); | |||
// assertTrue(tpCP.equals(tpDP)); | |||
// assertFalse(tpBC.equals(tpCC)); | |||
// assertFalse(tpBC.equals(tpDC)); | |||
// assertFalse(tpCC.equals(tpDC)); | |||
assertEquals(HSLFTextParagraph.getRawText(trB).substring(0, 30), rtrB.getRawText()); | |||
assertNotNull(tpBP); | |||
assertNotNull(tpBC); | |||
assertNotNull(tpCP); | |||
assertNotNull(tpCC); | |||
assertNotNull(tpDP); | |||
assertNotNull(tpDC); | |||
assertEquals(tpBP, tpCP); | |||
assertEquals(tpBP, tpDP); | |||
assertEquals(tpCP, tpDP); | |||
assertNotEquals(tpBC, tpCC); | |||
assertNotEquals(tpBC, tpDC); | |||
assertNotEquals(tpCC, tpDC); | |||
// Check text in the rich runs | |||
assertEquals("This is the subtitle, in bold\r", rtrB.getRawText()); | |||
@@ -394,32 +390,32 @@ public final class TestTextRun { | |||
rtrB.setText(newBText); | |||
rtrC.setText(newCText); | |||
rtrD.setText(newDText); | |||
assertEquals(newBText, rtrB.getRawText()); | |||
assertEquals(newCText, rtrC.getRawText()); | |||
assertEquals(newDText, rtrD.getRawText()); | |||
HSLFTextParagraph.storeText(trB); | |||
// assertEquals(newBText + newCText + newDText, trB.getRawText()); | |||
assertEquals(newBText.replace('\n','\r'), rtrB.getRawText()); | |||
assertEquals(newCText.replace('\n','\r'), rtrC.getRawText()); | |||
assertEquals(newDText.replace('\n','\r'), rtrD.getRawText()); | |||
// The styles should have been updated for the new sizes | |||
// assertEquals(newBText.length(), tpBC.getCharactersCovered()); | |||
// assertEquals(newCText.length(), tpCC.getCharactersCovered()); | |||
// assertEquals(newDText.length()+1, tpDC.getCharactersCovered()); // Last one is always one larger | |||
assertEquals(newBText.replace('\n','\r') + newCText.replace('\n','\r') + newDText.replace('\n','\r'), HSLFTextParagraph.getRawText(trB)); | |||
// assertEquals( | |||
// newBText.length() + newCText.length() + newDText.length(), | |||
// tpBP.getCharactersCovered() | |||
// ); | |||
// The styles should have been updated for the new sizes | |||
assertEquals(newBText.length(), tpBC.getCharactersCovered()); | |||
assertEquals(newCText.length(), tpCC.getCharactersCovered()); | |||
assertEquals(newDText.length()+1, tpDC.getCharactersCovered()); // Last one is always one larger | |||
// Paragraph style should be sum of text length | |||
// assertEquals(newBText.length() + newCText.length() + newDText.length(), tpBP.getCharactersCovered()); | |||
// Paragraph style should be sum of text length | |||
assertEquals( | |||
newBText.length() + newCText.length() + newDText.length() +1, | |||
tpBP.getCharactersCovered() + tpCP.getCharactersCovered() + tpDP.getCharactersCovered() | |||
); | |||
// Check stylings still as expected | |||
// TextPropCollection ntpBC = rtrB._getRawCharacterStyle(); | |||
// TextPropCollection ntpCC = rtrC._getRawCharacterStyle(); | |||
// TextPropCollection ntpDC = rtrD._getRawCharacterStyle(); | |||
// assertEquals(tpBC.getTextPropList(), ntpBC.getTextPropList()); | |||
// assertEquals(tpCC.getTextPropList(), ntpCC.getTextPropList()); | |||
// assertEquals(tpDC.getTextPropList(), ntpDC.getTextPropList()); | |||
TextPropCollection ntpBC = rtrB.getCharacterStyle(); | |||
TextPropCollection ntpCC = rtrC.getCharacterStyle(); | |||
TextPropCollection ntpDC = rtrD.getCharacterStyle(); | |||
assertEquals(tpBC.getTextPropList(), ntpBC.getTextPropList()); | |||
assertEquals(tpCC.getTextPropList(), ntpCC.getTextPropList()); | |||
assertEquals(tpDC.getTextPropList(), ntpDC.getTextPropList()); | |||
} | |||
@@ -467,82 +463,86 @@ public final class TestTextRun { | |||
assertEquals(0, slide.getTextParagraphs().size()); | |||
HSLFTextBox shape1 = new HSLFTextBox(); | |||
// HSLFTextParagraph run1 = shape1.getTextParagraphs(); | |||
// assertSame(run1, shape1.createTextRun()); | |||
// run1.setText("Text 1"); | |||
List<HSLFTextParagraph> run1 = shape1.getTextParagraphs(); | |||
shape1.setText("Text 1"); | |||
slide.addShape(shape1); | |||
//The array of Slide's text runs must be updated when new text shapes are added. | |||
// HSLFTextParagraph[] runs = slide.getTextParagraphs(); | |||
// assertNotNull(runs); | |||
// assertSame(run1, runs.get(0)); | |||
// | |||
// HSLFTextBox shape2 = new HSLFTextBox(); | |||
// HSLFTextParagraph run2 = shape2.getTextParagraphs(); | |||
// assertSame(run2, shape2.createTextRun()); | |||
// run2.setText("Text 2"); | |||
// slide.addShape(shape2); | |||
// | |||
// runs = slide.getTextParagraphs(); | |||
// assertEquals(2, runs.length); | |||
// | |||
// assertSame(run1, runs.get(0)); | |||
// assertSame(run2, runs.get(1)); | |||
// | |||
// //as getShapes() | |||
// HSLFShape[] sh = slide.getShapes(); | |||
// assertEquals(2, sh.length); | |||
// assertTrue(sh.get(0) instanceof HSLFTextBox); | |||
// HSLFTextBox box1 = (HSLFTextBox)sh.get(0); | |||
// assertSame(run1, box1.getTextParagraphs()); | |||
// HSLFTextBox box2 = (HSLFTextBox)sh.get(1); | |||
// assertSame(run2, box2.getTextParagraphs()); | |||
// | |||
// //test Table - a complex group of shapes containing text objects | |||
// HSLFSlide slide2 = ppt.createSlide(); | |||
// assertNull(slide2.getTextParagraphs()); | |||
// Table table = new Table(2, 2); | |||
// slide2.addShape(table); | |||
// runs = slide2.getTextParagraphs(); | |||
// assertNotNull(runs); | |||
// assertEquals(4, runs.length); | |||
List<List<HSLFTextParagraph>> runs = slide.getTextParagraphs(); | |||
assertNotNull(runs); | |||
assertSame(run1, runs.get(0)); | |||
HSLFTextBox shape2 = new HSLFTextBox(); | |||
List<HSLFTextParagraph> run2 = shape2.getTextParagraphs(); | |||
shape2.setText("Text 2"); | |||
slide.addShape(shape2); | |||
runs = slide.getTextParagraphs(); | |||
assertEquals(2, runs.size()); | |||
assertSame(run1, runs.get(0)); | |||
assertSame(run2, runs.get(1)); | |||
// as getShapes() | |||
List<HSLFShape> sh = slide.getShapes(); | |||
assertEquals(2, sh.size()); | |||
assertTrue(sh.get(0) instanceof HSLFTextBox); | |||
HSLFTextBox box1 = (HSLFTextBox)sh.get(0); | |||
assertSame(run1, box1.getTextParagraphs()); | |||
HSLFTextBox box2 = (HSLFTextBox)sh.get(1); | |||
assertSame(run2, box2.getTextParagraphs()); | |||
// test Table - a complex group of shapes containing text objects | |||
HSLFSlide slide2 = ppt.createSlide(); | |||
assertTrue(slide2.getTextParagraphs().isEmpty()); | |||
HSLFTable table = new HSLFTable(2, 2); | |||
slide2.addShape(table); | |||
runs = slide2.getTextParagraphs(); | |||
assertNotNull(runs); | |||
assertEquals(4, runs.size()); | |||
} | |||
@Test | |||
public void test48916() throws IOException { | |||
// HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("SampleShow.ppt")); | |||
// for(HSLFSlide slide : ppt.getSlides()){ | |||
// for(HSLFShape sh : slide.getShapes()){ | |||
// if(sh instanceof HSLFTextShape){ | |||
// HSLFTextShape tx = (HSLFTextShape)sh; | |||
// HSLFTextParagraph run = tx.getTextParagraphs(); | |||
// //verify that records cached in TextRun and EscherTextboxWrapper are the same | |||
// Record[] runChildren = run.getRecords(); | |||
// Record[] txboxChildren = tx.getEscherTextboxWrapper().getChildRecords(); | |||
// assertEquals(runChildren.length, txboxChildren.length); | |||
// for(int i=0; i < txboxChildren.length; i++){ | |||
// assertSame(txboxChildren.get(i), runChildren.get(i)); | |||
// } | |||
// //caused NPE prior to fix of Bugzilla #48916 | |||
// run.getTextRuns().get(0).setBold(true); | |||
// run.getTextRuns().get(0).setFontColor(Color.RED); | |||
// } | |||
// } | |||
// } | |||
// ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
// ppt.write(out); | |||
// ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); | |||
// for(HSLFSlide slide : ppt.getSlides()){ | |||
// for(HSLFShape sh : slide.getShapes()){ | |||
// if(sh instanceof HSLFTextShape){ | |||
// HSLFTextShape tx = (HSLFTextShape)sh; | |||
// HSLFTextParagraph run = tx.getTextParagraphs(); | |||
// HSLFTextRun rt = run.getTextRuns().get(0); | |||
// assertTrue(rt.isBold()); | |||
// assertEquals(rt.getFontColor(), Color.RED); | |||
// } | |||
// } | |||
// } | |||
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("SampleShow.ppt")); | |||
List<HSLFSlide> slides = ppt.getSlides(); | |||
for(HSLFSlide slide : slides){ | |||
for(HSLFShape sh : slide.getShapes()){ | |||
if (!(sh instanceof HSLFTextShape)) continue; | |||
HSLFTextShape tx = (HSLFTextShape)sh; | |||
List<HSLFTextParagraph> paras = tx.getTextParagraphs(); | |||
//verify that records cached in TextRun and EscherTextboxWrapper are the same | |||
Record[] runChildren = paras.get(0).getRecords(); | |||
Record[] txboxChildren = tx.getEscherTextboxWrapper().getChildRecords(); | |||
assertEquals(runChildren.length, txboxChildren.length); | |||
for(int i=0; i < txboxChildren.length; i++){ | |||
assertSame(txboxChildren[i], runChildren[i]); | |||
} | |||
// caused NPE prior to fix of Bugzilla #48916 | |||
for (HSLFTextParagraph p : paras) { | |||
for (HSLFTextRun rt : p.getTextRuns()) { | |||
rt.setBold(true); | |||
rt.setFontColor(Color.RED); | |||
} | |||
} | |||
tx.storeText(); | |||
} | |||
} | |||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
ppt.write(out); | |||
ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); | |||
for(HSLFSlide slide : ppt.getSlides()){ | |||
for(HSLFShape sh : slide.getShapes()){ | |||
if(sh instanceof HSLFTextShape){ | |||
HSLFTextShape tx = (HSLFTextShape)sh; | |||
List<HSLFTextParagraph> run = tx.getTextParagraphs(); | |||
HSLFTextRun rt = run.get(0).getTextRuns().get(0); | |||
assertTrue(rt.isBold()); | |||
assertEquals(rt.getFontColor(), Color.RED); | |||
} | |||
} | |||
} | |||
} | |||