git-svn-id: https://svn.apache.org/repos/asf/poi/branches/common_sl@1684773 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_13_FINAL
{"Note"}, | {"Note"}, | ||||
{"This presentation was created programmatically using POI HSLF"} | {"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 i = 0; i < txt1.length; i++) { | ||||
for (int j = 0; j < txt1[i].length; j++) { | 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]); | cell.setText(txt1[i][j]); | ||||
HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0); | HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0); | ||||
rt.setFontSize(10); | rt.setFontSize(10); |
//define position of the drawing in the slide | //define position of the drawing in the slide | ||||
Rectangle bounds = new java.awt.Rectangle(200, 100, 350, 300); | Rectangle bounds = new java.awt.Rectangle(200, 100, 350, 300); | ||||
group.setAnchor(bounds); | 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); | slide.addShape(group); | ||||
Graphics2D graphics = new PPGraphics2D(group); | Graphics2D graphics = new PPGraphics2D(group); | ||||
} | } | ||||
graphics.setColor(Color.black); | graphics.setColor(Color.black); | ||||
graphics.setFont(new Font("Arial", Font.BOLD, 14)); | graphics.setFont(new Font("Arial", Font.BOLD, 14)); | ||||
graphics.draw(group.getCoordinates()); | |||||
graphics.draw(group.getInteriorAnchor()); | |||||
graphics.drawString("Performance", x + 30, y + 10); | graphics.drawString("Performance", x + 30, y + 10); | ||||
FileOutputStream out = new FileOutputStream("hslf-graphics.ppt"); | FileOutputStream out = new FileOutputStream("hslf-graphics.ppt"); |
HSLFSlide slide = ppt.createSlide(); | HSLFSlide slide = ppt.createSlide(); | ||||
//six rows, two columns | //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 i = 0; i < txt1.length; i++) { | ||||
for (int j = 0; j < txt1[i].length; j++) { | 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); | HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0); | ||||
rt.setFontFamily("Arial"); | rt.setFontFamily("Arial"); | ||||
rt.setFontSize(10); | rt.setFontSize(10); | ||||
}; | }; | ||||
//two rows, one column | //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 i = 0; i < txt2.length; i++) { | ||||
for (int j = 0; j < txt2[i].length; j++) { | 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); | HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0); | ||||
rt.setFontSize(10); | rt.setFontSize(10); | ||||
rt.setFontFamily("Arial"); | rt.setFontFamily("Arial"); |
private int field_4_dy2; | private int field_4_dy2; | ||||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | ||||
/*int bytesRemaining =*/ readHeader( data, offset ); | |||||
int bytesRemaining = readHeader( data, offset ); | |||||
int pos = offset + 8; | int pos = offset + 8; | ||||
int size = 0; | 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; | return 8 + size; | ||||
} | } | ||||
LittleEndian.putInt( data, pos, getRecordSize()-8 ); pos += 4; | LittleEndian.putInt( data, pos, getRecordSize()-8 ); pos += 4; | ||||
LittleEndian.putInt( data, pos, field_1_dx1 ); 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_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 ); | listener.afterRecordSerialize( pos, getRecordId(), pos - offset, this ); | ||||
return pos - offset; | return pos - offset; |
addProp(m, SHADOWSTYLE__ORIGINX, "shadowstyle.originx"); | addProp(m, SHADOWSTYLE__ORIGINX, "shadowstyle.originx"); | ||||
addProp(m, SHADOWSTYLE__ORIGINY, "shadowstyle.originy"); | addProp(m, SHADOWSTYLE__ORIGINY, "shadowstyle.originy"); | ||||
addProp(m, SHADOWSTYLE__SHADOW, "shadowstyle.shadow"); | 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__TYPE, "perspective.type"); | ||||
addProp(m, PERSPECTIVE__OFFSETX, "perspective.offsetx"); | addProp(m, PERSPECTIVE__OFFSETX, "perspective.offsetx"); | ||||
addProp(m, PERSPECTIVE__OFFSETY, "perspective.offsety"); | addProp(m, PERSPECTIVE__OFFSETY, "perspective.offsety"); |
package org.apache.poi.ddf; | package org.apache.poi.ddf; | ||||
import org.apache.poi.hslf.record.RecordTypes; | |||||
import org.apache.poi.util.HexDump; | import org.apache.poi.util.HexDump; | ||||
import org.apache.poi.util.LittleEndian; | import org.apache.poi.util.LittleEndian; | ||||
import org.apache.poi.util.RecordFormatException; | import org.apache.poi.util.RecordFormatException; | ||||
*/ | */ | ||||
public class EscherTextboxRecord extends EscherRecord | 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"; | public static final String RECORD_DESCRIPTION = "msofbtClientTextbox"; | ||||
private static final byte[] NO_BYTES = new byte[0]; | private static final byte[] NO_BYTES = new byte[0]; |
import java.awt.image.RenderedImage; | import java.awt.image.RenderedImage; | ||||
import java.awt.image.renderable.RenderableImage; | import java.awt.image.renderable.RenderableImage; | ||||
import java.text.AttributedCharacterIterator; | import java.text.AttributedCharacterIterator; | ||||
import java.util.Arrays; | |||||
import java.util.Map; | import java.util.Map; | ||||
public class DummyGraphics2d | public class DummyGraphics2d | ||||
public void setPaint( Paint paint ) | public void setPaint( Paint paint ) | ||||
{ | { | ||||
System.out.println( "setPain(Paint):" ); | |||||
System.out.println( "setPaint(Paint):" ); | |||||
System.out.println( "paint = " + paint ); | System.out.println( "paint = " + paint ); | ||||
g2D.setPaint( paint ); | g2D.setPaint( paint ); | ||||
} | } | ||||
public void setStroke(Stroke s) | public void setStroke(Stroke s) | ||||
{ | { | ||||
System.out.println( "setStroke(Stoke):" ); | 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 ); | g2D.setStroke( s ); | ||||
} | } | ||||
import java.util.regex.Pattern; | import java.util.regex.Pattern; | ||||
import org.apache.poi.openxml4j.opc.*; | 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.poi.util.*; | ||||
import org.apache.xmlbeans.XmlObject; | import org.apache.xmlbeans.XmlObject; | ||||
import org.openxmlformats.schemas.drawingml.x2006.main.*; | import org.openxmlformats.schemas.drawingml.x2006.main.*; | ||||
* @author Yegor Kozlov | * @author Yegor Kozlov | ||||
*/ | */ | ||||
@Beta | @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 static POILogger _logger = POILogFactory.getLogger(XSLFGroupShape.class); | ||||
private final List<XSLFShape> _shapes; | private final List<XSLFShape> _shapes; | ||||
* used for calculations of grouping, scaling, and rotation | * used for calculations of grouping, scaling, and rotation | ||||
* behavior of shapes placed within a group. | * behavior of shapes placed within a group. | ||||
*/ | */ | ||||
public void setInteriorAnchor(Rectangle2D anchor){ | |||||
public void setInteriorAnchor(Rectangle2D anchor) { | |||||
CTGroupTransform2D xfrm = getSafeXfrm(); | CTGroupTransform2D xfrm = getSafeXfrm(); | ||||
CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff(); | CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff(); | ||||
long x = Units.toEMU(anchor.getX()); | long x = Units.toEMU(anchor.getX()); |
return id; | return id; | ||||
} | } | ||||
@Override | |||||
public Insets getClipping(){ | public Insets getClipping(){ | ||||
CTPicture ct = (CTPicture)getXmlObject(); | CTPicture ct = (CTPicture)getXmlObject(); | ||||
CTRelativeRect r = ct.getBlipFill().getSrcRect(); | CTRelativeRect r = ct.getBlipFill().getSrcRect(); |
* | * | ||||
* @param graphics | * @param graphics | ||||
*/ | */ | ||||
@Override | |||||
public void draw(Graphics2D graphics){ | public void draw(Graphics2D graphics){ | ||||
DrawFactory drawFact = DrawFactory.getInstance(graphics); | DrawFactory drawFact = DrawFactory.getInstance(graphics); | ||||
Drawable draw = drawFact.getDrawable(this); | Drawable draw = drawFact.getDrawable(this); |
import org.apache.poi.POIXMLDocumentPart; | import org.apache.poi.POIXMLDocumentPart; | ||||
import org.apache.poi.openxml4j.opc.PackagePart; | import org.apache.poi.openxml4j.opc.PackagePart; | ||||
import org.apache.poi.openxml4j.opc.PackageRelationship; | import org.apache.poi.openxml4j.opc.PackageRelationship; | ||||
import org.apache.poi.sl.usermodel.Notes; | |||||
import org.apache.poi.sl.usermodel.Slide; | import org.apache.poi.sl.usermodel.Slide; | ||||
import org.apache.poi.util.Beta; | import org.apache.poi.util.Beta; | ||||
import org.apache.xmlbeans.XmlException; | import org.apache.xmlbeans.XmlException; |
/* ==================================================================== | |||||
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); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} |
// Table text | // Table text | ||||
for (HSLFShape shape : slide.getShapes()){ | 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 | // Slide footer, if set | ||||
return ret.toString(); | 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 row = 0; row < table.getNumberOfRows(); row++){ | ||||
for (int col = 0; col < table.getNumberOfColumns(); col++){ | 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 | //defensive null checks; don't know if they're necessary | ||||
if (cell != null){ | if (cell != null){ | ||||
String txt = cell.getText(); | String txt = cell.getText(); |
import org.apache.poi.sl.usermodel.ShapeContainer; | import org.apache.poi.sl.usermodel.ShapeContainer; | ||||
import org.apache.poi.sl.usermodel.ShapeType; | 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 | * Represents a line in a PowerPoint drawing | ||||
Rectangle2D anchor = getLogicalAnchor2D(); | Rectangle2D anchor = getLogicalAnchor2D(); | ||||
return new Line2D.Double(anchor.getX(), anchor.getY(), anchor.getX() + anchor.getWidth(), anchor.getY() + anchor.getHeight()); | 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; | |||||
} | |||||
} | } |
* Clones the given text properties | * Clones the given text properties | ||||
*/ | */ | ||||
public void copy(TextPropCollection other) { | public void copy(TextPropCollection other) { | ||||
if (this == other) return; | |||||
this.charactersCovered = other.charactersCovered; | this.charactersCovered = other.charactersCovered; | ||||
this.indentLevel = other.indentLevel; | this.indentLevel = other.indentLevel; | ||||
this.maskSpecial = other.maskSpecial; | this.maskSpecial = other.maskSpecial; |
// Grab the children's data | // Grab the children's data | ||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | 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(); | byte[] data = baos.toByteArray(); | ||||
// Save in the escher layer | // Save in the escher layer |
findEscherChildren(erf, contents, 8, len-8, escherChildren); | findEscherChildren(erf, contents, 8, len-8, escherChildren); | ||||
this.childRecords = escherChildren.toArray(new EscherRecord[escherChildren.size()]); | 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]); | this.textboxWrappers = findInDgContainer((EscherContainerRecord) this.childRecords[0]); | ||||
} else { | } else { | ||||
// Find and EscherTextboxRecord's, and wrap them up | // Find and EscherTextboxRecord's, and wrap them up | ||||
this.textboxWrappers = textboxes.toArray(new EscherTextboxWrapper[textboxes.size()]); | 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 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); | 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()]); | return found.toArray(new EscherTextboxWrapper[found.size()]); | ||||
} | } | ||||
private StyleTextProp9Atom findInSpContainer(final EscherContainerRecord spContainer) { | 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; } | if (null == escherContainer1388) { return null; } | ||||
final EscherContainerRecord escherContainer138A = findFirstEscherContainerRecordOfType((short)0x138A, escherContainer1388); | final EscherContainerRecord escherContainer138A = findFirstEscherContainerRecordOfType((short)0x138A, escherContainer1388); | ||||
if (null == escherContainer138A) { return null; } | if (null == escherContainer138A) { return null; } |
// Write out our header, less the size | // Write out our header, less the size | ||||
mout.write(new byte[] {headerA,headerB}); | mout.write(new byte[] {headerA,headerB}); | ||||
byte[] typeB = new byte[2]; | byte[] typeB = new byte[2]; | ||||
LittleEndian.putShort(typeB,(short)type); | |||||
LittleEndian.putShort(typeB, 0, (short)type); | |||||
mout.write(typeB); | mout.write(typeB); | ||||
mout.write(new byte[4]); | mout.write(new byte[4]); | ||||
// Write out our header, less the size | // Write out our header, less the size | ||||
baos.write(new byte[] {headerA,headerB}); | baos.write(new byte[] {headerA,headerB}); | ||||
byte[] typeB = new byte[2]; | byte[] typeB = new byte[2]; | ||||
LittleEndian.putShort(typeB,(short)type); | |||||
LittleEndian.putShort(typeB,0,(short)type); | |||||
baos.write(typeB); | baos.write(typeB); | ||||
baos.write(new byte[] {0,0,0,0}); | baos.write(new byte[] {0,0,0,0}); | ||||
} | } | ||||
int clen = endPos - i - 1; | int clen = endPos - i - 1; | ||||
boolean emptySet = false; | |||||
if(clen == 0) { emptySet = true; } | |||||
// Create a SlideAtomsSets, not caring if they're empty | // Create a SlideAtomsSets, not caring if they're empty | ||||
//if(emptySet) { continue; } | //if(emptySet) { continue; } | ||||
} | } | ||||
public void setInstance(int inst){ | public void setInstance(int inst){ | ||||
LittleEndian.putShort(_header, (short)((inst << 4) | 0xF)); | |||||
LittleEndian.putShort(_header, 0, (short)((inst << 4) | 0xF)); | |||||
} | } | ||||
/** | /** |
}; | }; | ||||
} | } | ||||
case FILL_PICTURE: { | case FILL_PICTURE: { | ||||
final HSLFPictureData pd = getPictureData(); | |||||
if (pd == null) break; | |||||
return new TexturePaint() { | return new TexturePaint() { | ||||
final HSLFPictureData pd = getPictureData(); | |||||
public InputStream getImageData() { | public InputStream getImageData() { | ||||
return new ByteArrayInputStream(pd.getData()); | return new ByteArrayInputStream(pd.getData()); | ||||
} | } |
import java.util.*; | import java.util.*; | ||||
import org.apache.poi.ddf.*; | 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.LittleEndian; | ||||
import org.apache.poi.util.POILogger; | import org.apache.poi.util.POILogger; | ||||
* | * | ||||
* @author Yegor Kozlov | * @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. | * Create a new ShapeGroup. This constructor is used when a new shape is created. | ||||
spgr.setRectY2((anchor.y + anchor.height)*MASTER_DPI/POINT_DPI); | 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); | EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID); | ||||
int x1 = (int)Math.round(anchor.getX()*MASTER_DPI/POINT_DPI); | int x1 = (int)Math.round(anchor.getX()*MASTER_DPI/POINT_DPI); | ||||
} | } | ||||
/** | |||||
* 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); | |||||
} | } | ||||
/** | /** | ||||
*/ | */ | ||||
public Rectangle2D getAnchor2D(){ | public Rectangle2D getAnchor2D(){ | ||||
EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID); | EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID); | ||||
Rectangle2D.Float anchor = new Rectangle2D.Float(); | |||||
Rectangle2D anchor; | |||||
if(clientAnchor == null){ | if(clientAnchor == null){ | ||||
logger.log(POILogger.INFO, "EscherClientAnchorRecord was not found for shape group. Searching for EscherChildAnchorRecord."); | logger.log(POILogger.INFO, "EscherClientAnchorRecord was not found for shape group. Searching for EscherChildAnchorRecord."); | ||||
EscherChildAnchorRecord rec = getEscherChild(EscherChildAnchorRecord.RECORD_ID); | 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 { | } 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; | return anchor; |
public final class HSLFNotes extends HSLFSheet implements Notes<HSLFShape, HSLFSlideShow> { | public final class HSLFNotes extends HSLFSheet implements Notes<HSLFShape, HSLFSlideShow> { | ||||
protected static POILogger logger = POILogFactory.getLogger(HSLFNotes.class); | 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. | * Constructs a Notes Sheet from the given Notes record. | ||||
// Now, build up TextRuns from pairs of TextHeaderAtom and | // Now, build up TextRuns from pairs of TextHeaderAtom and | ||||
// one of TextBytesAtom or TextCharsAtom, found inside | // one of TextBytesAtom or TextCharsAtom, found inside | ||||
// EscherTextboxWrapper's in the PPDrawing | // 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"); | logger.log(POILogger.WARN, "No text records found for notes sheet"); | ||||
} | } | ||||
// Set the sheet on each TextRun | // Set the sheet on each TextRun | ||||
for (List<HSLFTextParagraph> ltp : _runs) { | |||||
for (List<HSLFTextParagraph> ltp : _paragraphs) { | |||||
for (HSLFTextParagraph tp : ltp) { | for (HSLFTextParagraph tp : ltp) { | ||||
tp.supplySheet(this); | tp.supplySheet(this); | ||||
} | } | ||||
*/ | */ | ||||
@Override | @Override | ||||
public List<List<HSLFTextParagraph>> getTextParagraphs() { | public List<List<HSLFTextParagraph>> getTextParagraphs() { | ||||
return _runs; | |||||
return _paragraphs; | |||||
} | } | ||||
/** | /** |
package org.apache.poi.hslf.usermodel; | package org.apache.poi.hslf.usermodel; | ||||
import java.awt.Graphics2D; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import java.security.MessageDigest; | 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.CryptoFunctions; | ||||
import org.apache.poi.poifs.crypt.HashAlgorithm; | 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. | * A class that represents image data contained in a slide show. | ||||
* | * | ||||
* @author Yegor Kozlov | * @author Yegor Kozlov | ||||
*/ | */ | ||||
public abstract class HSLFPictureData { | |||||
public abstract class HSLFPictureData implements PictureData { | |||||
protected POILogger logger = POILogFactory.getLogger(this.getClass()); | protected POILogger logger = POILogFactory.getLogger(this.getClass()); | ||||
*/ | */ | ||||
protected abstract int getSignature(); | 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 | * Returns the raw binary data of this Picture excluding the first 8 bytes | ||||
* which hold image signature and size of the image data. | * which hold image signature and size of the image data. | ||||
public int getSize(){ | public int getSize(){ | ||||
return getData().length; | 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]; | |||||
} | |||||
} | } |
import org.apache.poi.ddf.*; | import org.apache.poi.ddf.*; | ||||
import org.apache.poi.hslf.blip.Bitmap; | import org.apache.poi.hslf.blip.Bitmap; | ||||
import org.apache.poi.hslf.record.Document; | 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.*; | import org.apache.poi.util.*; | ||||
* | * | ||||
* @author Yegor Kozlov | * @author Yegor Kozlov | ||||
*/ | */ | ||||
public class HSLFPictureShape extends HSLFSimpleShape { | |||||
public class HSLFPictureShape extends HSLFSimpleShape implements PictureShape { | |||||
/** | /** | ||||
* Windows Enhanced Metafile (EMF) | * Windows Enhanced Metafile (EMF) | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Returns the picture data for this picture. | |||||
* | |||||
* @return the picture data for this picture. | |||||
*/ | |||||
@Override | |||||
public HSLFPictureData getPictureData(){ | public HSLFPictureData getPictureData(){ | ||||
HSLFSlideShow ppt = getSheet().getSlideShow(); | HSLFSlideShow ppt = getSheet().getSlideShow(); | ||||
HSLFPictureData[] pict = ppt.getPictureData(); | HSLFPictureData[] pict = ppt.getPictureData(); | ||||
} | } | ||||
/** | /** | ||||
* Returns the clipping values as percent ratio relatively to the image size. | |||||
* The anchor specified by {@link #getLogicalAnchor2D()} is the displayed size, | * The anchor specified by {@link #getLogicalAnchor2D()} is the displayed size, | ||||
* i.e. the size of the already clipped image | * 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(); | EscherOptRecord opt = getEscherOptRecord(); | ||||
double top = getFractProp(opt, EscherProperties.BLIP__CROPFROMTOP); | double top = getFractProp(opt, EscherProperties.BLIP__CROPFROMTOP); |
public Rectangle2D getAnchor2D(){ | public Rectangle2D getAnchor2D(){ | ||||
EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID); | EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID); | ||||
int flags = spRecord.getFlags(); | int flags = spRecord.getFlags(); | ||||
Rectangle2D anchor=null; | |||||
Rectangle2D anchor; | |||||
if ((flags & EscherSpRecord.FLAG_CHILD) != 0){ | if ((flags & EscherSpRecord.FLAG_CHILD) != 0){ | ||||
EscherChildAnchorRecord rec = getEscherChild(EscherChildAnchorRecord.RECORD_ID); | EscherChildAnchorRecord rec = getEscherChild(EscherChildAnchorRecord.RECORD_ID); | ||||
anchor = new java.awt.Rectangle(); | |||||
if(rec == null){ | if(rec == null){ | ||||
logger.log(POILogger.WARN, "EscherSpRecord.FLAG_CHILD is set but EscherChildAnchorRecord was not found"); | logger.log(POILogger.WARN, "EscherSpRecord.FLAG_CHILD is set but EscherChildAnchorRecord was not found"); | ||||
EscherClientAnchorRecord clrec = getEscherChild(EscherClientAnchorRecord.RECORD_ID); | EscherClientAnchorRecord clrec = getEscherChild(EscherClientAnchorRecord.RECORD_ID); | ||||
anchor = new java.awt.Rectangle(); | |||||
anchor = new Rectangle2D.Float( | anchor = new Rectangle2D.Float( | ||||
(float)clrec.getCol1()*POINT_DPI/MASTER_DPI, | (float)clrec.getCol1()*POINT_DPI/MASTER_DPI, | ||||
(float)clrec.getFlag()*POINT_DPI/MASTER_DPI, | (float)clrec.getFlag()*POINT_DPI/MASTER_DPI, | ||||
(float)(rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI | (float)(rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI | ||||
); | ); | ||||
} | } | ||||
} | |||||
else { | |||||
} else { | |||||
EscherClientAnchorRecord rec = getEscherChild(EscherClientAnchorRecord.RECORD_ID); | EscherClientAnchorRecord rec = getEscherChild(EscherClientAnchorRecord.RECORD_ID); | ||||
anchor = new java.awt.Rectangle(); | |||||
anchor = new Rectangle2D.Float( | anchor = new Rectangle2D.Float( | ||||
(float)rec.getCol1()*POINT_DPI/MASTER_DPI, | (float)rec.getCol1()*POINT_DPI/MASTER_DPI, | ||||
(float)rec.getFlag()*POINT_DPI/MASTER_DPI, | (float)rec.getFlag()*POINT_DPI/MASTER_DPI, | ||||
return anchor; | return anchor; | ||||
} | } | ||||
public Rectangle2D getLogicalAnchor2D(){ | |||||
return getAnchor2D(); | |||||
} | |||||
/** | /** | ||||
* Sets the anchor (the bounding box rectangle) of this shape. | * Sets the anchor (the bounding box rectangle) of this shape. | ||||
* All coordinates should be expressed in points (72 dpi). | * All coordinates should be expressed in points (72 dpi). | ||||
* @return escher property or <code>null</code> if not found. | * @return escher property or <code>null</code> if not found. | ||||
*/ | */ | ||||
public static <T extends EscherProperty> T getEscherProperty(EscherOptRecord opt, int propId){ | 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. | * Set an escher property for this shape. | ||||
logger.log(POILogger.INFO, "Rendering " + getShapeName()); | 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() { | public EscherOptRecord getEscherOptRecord() { | ||||
EscherOptRecord opt = getEscherChild(EscherOptRecord.RECORD_ID); | EscherOptRecord opt = getEscherChild(EscherOptRecord.RECORD_ID); | ||||
if (opt == null) { | if (opt == null) { | ||||
public double getRotation(){ | public double getRotation(){ | ||||
int rot = getEscherProperty(EscherProperties.TRANSFORM__ROTATION); | int rot = getEscherProperty(EscherProperties.TRANSFORM__ROTATION); | ||||
double angle = Units.fixedPointToDouble(rot) % 360.0; | |||||
return angle; | |||||
return Units.fixedPointToDouble(rot); | |||||
} | } | ||||
public void setRotation(double theta){ | public void setRotation(double theta){ |
List<EscherProperty> props = f.createProperties( opt.serialize(), 8, opt.getInstance() ); | List<EscherProperty> props = f.createProperties( opt.serialize(), 8, opt.getInstance() ); | ||||
EscherSimpleProperty p = (EscherSimpleProperty)props.get(0); | EscherSimpleProperty p = (EscherSimpleProperty)props.get(0); | ||||
if(p.getPropertyNumber() == 0x39F && p.getPropertyValue() == 1){ | if(p.getPropertyNumber() == 0x39F && p.getPropertyValue() == 1){ | ||||
group = new Table(spContainer, parent); | |||||
group = new HSLFTable(spContainer, parent); | |||||
} else { | } else { | ||||
group = new HSLFGroupShape(spContainer, parent); | group = new HSLFGroupShape(spContainer, parent); | ||||
} | } |
import org.apache.poi.ddf.*; | import org.apache.poi.ddf.*; | ||||
import org.apache.poi.hslf.record.*; | 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.sl.usermodel.Sheet; | ||||
import org.apache.poi.util.POILogFactory; | import org.apache.poi.util.POILogFactory; | ||||
import org.apache.poi.util.POILogger; | import org.apache.poi.util.POILogger; | ||||
return _background; | 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); | |||||
} | } | ||||
/** | /** |
package org.apache.poi.hslf.usermodel; | package org.apache.poi.hslf.usermodel; | ||||
import java.awt.Color; | import java.awt.Color; | ||||
import java.awt.geom.AffineTransform; | |||||
import java.awt.geom.Rectangle2D; | |||||
import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||
import java.util.ArrayList; | |||||
import org.apache.poi.ddf.*; | import org.apache.poi.ddf.*; | ||||
import org.apache.poi.hslf.exceptions.HSLFException; | import org.apache.poi.hslf.exceptions.HSLFException; | ||||
import org.apache.poi.hslf.record.*; | 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.draw.geom.*; | ||||
import org.apache.poi.sl.usermodel.*; | 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.LineCompound; | ||||
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; | import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; | ||||
import org.apache.poi.util.LittleEndian; | import org.apache.poi.util.LittleEndian; | ||||
public StrokeStyle getStrokeStyle(){ | public StrokeStyle getStrokeStyle(){ | ||||
return new StrokeStyle() { | return new StrokeStyle() { | ||||
public PaintStyle getPaint() { | public PaintStyle getPaint() { | ||||
return null; | |||||
return DrawPaint.createSolidPaint(HSLFSimpleShape.this.getLineColor()); | |||||
} | } | ||||
public LineCap getLineCap() { | public LineCap getLineCap() { | ||||
} | } | ||||
public LineDash getLineDash() { | public LineDash getLineDash() { | ||||
return null; | |||||
return HSLFSimpleShape.this.getLineDashing(); | |||||
} | } | ||||
public LineCompound getLineCompound() { | public LineCompound getLineCompound() { | ||||
return null; | |||||
return HSLFSimpleShape.this.getLineCompound(); | |||||
} | } | ||||
public double getLineWidth() { | public double getLineWidth() { | ||||
return 0; | |||||
return HSLFSimpleShape.this.getLineWidth(); | |||||
} | } | ||||
}; | }; | ||||
getFill().setForegroundColor(color); | 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 | * Find a record in the underlying EscherClientDataRecord | ||||
* | * | ||||
return (adjval == -1) ? null : new Guide(name, "val "+adjval); | return (adjval == -1) ? null : new Guide(name, "val "+adjval); | ||||
} | } | ||||
public LineDecoration getLineDecoration() { | |||||
// TODO Auto-generated method stub | |||||
return null; | |||||
} | |||||
public CustomGeometry getGeometry() { | public CustomGeometry getGeometry() { | ||||
ShapeType st = getShapeType(); | ShapeType st = getShapeType(); | ||||
String name = st.getOoxmlName(); | String name = st.getOoxmlName(); | ||||
return geom; | 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; | |||||
} | |||||
}; | |||||
} | |||||
} | } |
} | } | ||||
// Grab text from slide's PPDrawing | // 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(List<HSLFTextParagraph> ltp : _paragraphs) { | ||||
for (HSLFTextParagraph tp : ltp) { | for (HSLFTextParagraph tp : ltp) { |
* @author Yegor Kozlov | * @author Yegor Kozlov | ||||
*/ | */ | ||||
public final class HSLFSlideMaster extends HSLFMasterSheet { | 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 | * all TxMasterStyleAtoms available in this master | ||||
public HSLFSlideMaster(MainMaster record, int sheetNo) { | public HSLFSlideMaster(MainMaster record, int sheetNo) { | ||||
super(record, 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) { | for (HSLFTextParagraph htp : p) { | ||||
htp.supplySheet(this); | htp.supplySheet(this); | ||||
} | } | ||||
* Returns an array of all the TextRuns found | * Returns an array of all the TextRuns found | ||||
*/ | */ | ||||
public List<List<HSLFTextParagraph>> getTextParagraphs() { | public List<List<HSLFTextParagraph>> getTextParagraphs() { | ||||
return _runs; | |||||
return _paragraphs; | |||||
} | } | ||||
/** | /** | ||||
protected void onAddTextShape(HSLFTextShape shape) { | protected void onAddTextShape(HSLFTextShape shape) { | ||||
List<HSLFTextParagraph> runs = shape.getTextParagraphs(); | List<HSLFTextParagraph> runs = shape.getTextParagraphs(); | ||||
_runs.add(runs); | |||||
_paragraphs.add(runs); | |||||
} | } | ||||
public TxMasterStyleAtom[] getTxMasterStyleAtoms(){ | public TxMasterStyleAtom[] getTxMasterStyleAtoms(){ |
limitations under the License. | 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.ddf.*; | ||||
import org.apache.poi.hslf.model.Line; | |||||
import org.apache.poi.hslf.usermodel.*; | import org.apache.poi.hslf.usermodel.*; | ||||
import org.apache.poi.sl.usermodel.ShapeContainer; | import org.apache.poi.sl.usermodel.ShapeContainer; | ||||
import org.apache.poi.util.LittleEndian; | import org.apache.poi.util.LittleEndian; | ||||
* | * | ||||
* @author Yegor Kozlov | * @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_TOP = 1; | ||||
protected static final int BORDER_RIGHT = 2; | protected static final int BORDER_RIGHT = 2; | ||||
protected static final int BORDERS_NONE = 8; | 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 | * Create a new Table of the given number of rows and columns | ||||
* @param numrows the number of rows | * @param numrows the number of rows | ||||
* @param numcols the number of columns | * @param numcols the number of columns | ||||
*/ | */ | ||||
public Table(int numrows, int numcols) { | |||||
public HSLFTable(int numrows, int numcols) { | |||||
super(); | super(); | ||||
if(numrows < 1) throw new IllegalArgumentException("The number of rows must be greater than 1"); | 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"); | if(numcols < 1) throw new IllegalArgumentException("The number of columns must be greater than 1"); | ||||
int x=0, y=0, tblWidth=0, tblHeight=0; | 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++) { | for (int i = 0; i < cells.length; i++) { | ||||
x = 0; | x = 0; | ||||
for (int j = 0; j < cells[i].length; j++) { | 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); | cells[i][j].setAnchor(anchor); | ||||
x += TableCell.DEFAULT_WIDTH; | |||||
x += HSLFTableCell.DEFAULT_WIDTH; | |||||
} | } | ||||
y += TableCell.DEFAULT_HEIGHT; | |||||
y += HSLFTableCell.DEFAULT_HEIGHT; | |||||
} | } | ||||
tblWidth = x; | tblWidth = x; | ||||
tblHeight = y; | tblHeight = y; | ||||
* @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape | * @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape | ||||
* @param parent the parent of the 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); | super(escherRecord, parent); | ||||
} | } | ||||
* @param col the column index (0-based) | * @param col the column index (0-based) | ||||
* @return the cell | * @return the cell | ||||
*/ | */ | ||||
public TableCell getCell(int row, int col) { | |||||
public HSLFTableCell getCell(int row, int col) { | |||||
return cells[row][col]; | return cells[row][col]; | ||||
} | } | ||||
EscherOptRecord opt = (EscherOptRecord)lst.get(lst.size()-2); | EscherOptRecord opt = (EscherOptRecord)lst.get(lst.size()-2); | ||||
EscherArrayProperty p = opt.lookup(0x3A0); | EscherArrayProperty p = opt.lookup(0x3A0); | ||||
for (int i = 0; i < cells.length; i++) { | 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; | int rowHeight = cell.getAnchor().height*MASTER_DPI/POINT_DPI; | ||||
byte[] val = new byte[4]; | byte[] val = new byte[4]; | ||||
LittleEndian.putInt(val, 0, rowHeight); | LittleEndian.putInt(val, 0, rowHeight); | ||||
p.setElement(i, val); | p.setElement(i, val); | ||||
for (int j = 0; j < cells[i].length; j++) { | for (int j = 0; j < cells[i].length; j++) { | ||||
TableCell c = cells[i][j]; | |||||
HSLFTableCell c = cells[i][j]; | |||||
addShape(c); | addShape(c); | ||||
Line bt = c.getBorderTop(); | Line bt = c.getBorderTop(); | ||||
maxrowlen = Math.max(maxrowlen, row.size()); | 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++) { | for (int i = 0; i < lst.size(); i++) { | ||||
row = lst.get(i); | row = lst.get(i); | ||||
for (int j = 0; j < row.size(); j++) { | for (int j = 0; j < row.size(); j++) { | ||||
HSLFTextShape tx = (HSLFTextShape)row.get(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()); | cells[i][j].setSheet(tx.getSheet()); | ||||
} | } | ||||
} | } | ||||
public void setAllBorders(Line line){ | public void setAllBorders(Line line){ | ||||
for (int i = 0; i < cells.length; i++) { | for (int i = 0; i < cells.length; i++) { | ||||
for (int j = 0; j < cells[i].length; j++) { | for (int j = 0; j < cells[i].length; j++) { | ||||
TableCell cell = cells[i][j]; | |||||
HSLFTableCell cell = cells[i][j]; | |||||
cell.setBorderTop(cloneBorder(line)); | cell.setBorderTop(cloneBorder(line)); | ||||
cell.setBorderLeft(cloneBorder(line)); | cell.setBorderLeft(cloneBorder(line)); | ||||
if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line)); | if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line)); | ||||
public void setOutsideBorders(Line line){ | public void setOutsideBorders(Line line){ | ||||
for (int i = 0; i < cells.length; i++) { | for (int i = 0; i < cells.length; i++) { | ||||
for (int j = 0; j < cells[i].length; j++) { | 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 == 0) cell.setBorderLeft(cloneBorder(line)); | ||||
if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line)); | if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line)); | ||||
public void setInsideBorders(Line line){ | public void setInsideBorders(Line line){ | ||||
for (int i = 0; i < cells.length; i++) { | for (int i = 0; i < cells.length; i++) { | ||||
for (int j = 0; j < cells[i].length; j++) { | 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) | if(j != cells[i].length - 1) | ||||
cell.setBorderRight(cloneBorder(line)); | cell.setBorderRight(cloneBorder(line)); |
limitations under the License. | limitations under the License. | ||||
==================================================================== */ | ==================================================================== */ | ||||
package org.apache.poi.hslf.model; | |||||
package org.apache.poi.hslf.usermodel; | |||||
import java.awt.Rectangle; | import java.awt.Rectangle; | ||||
import org.apache.poi.ddf.EscherContainerRecord; | import org.apache.poi.ddf.EscherContainerRecord; | ||||
import org.apache.poi.ddf.EscherOptRecord; | import org.apache.poi.ddf.EscherOptRecord; | ||||
import org.apache.poi.ddf.EscherProperties; | 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.ShapeContainer; | ||||
import org.apache.poi.sl.usermodel.ShapeType; | import org.apache.poi.sl.usermodel.ShapeType; | ||||
* | * | ||||
* @author Yegor Kozlov | * @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_WIDTH = 100; | ||||
protected static final int DEFAULT_HEIGHT = 40; | protected static final int DEFAULT_HEIGHT = 40; | ||||
* @param escherRecord {@link EscherSpContainer} container which holds information about this shape | * @param escherRecord {@link EscherSpContainer} container which holds information about this shape | ||||
* @param parent the parent of the 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); | super(escherRecord, parent); | ||||
} | } | ||||
* @param parent the parent of this Shape. For example, if this text box is a cell | * @param parent the parent of this Shape. For example, if this text box is a cell | ||||
* in a table then the parent is Table. | * in a table then the parent is Table. | ||||
*/ | */ | ||||
public TableCell(ShapeContainer<HSLFShape> parent){ | |||||
public HSLFTableCell(ShapeContainer<HSLFShape> parent){ | |||||
super(parent); | super(parent); | ||||
setShapeType(ShapeType.RECT); | setShapeType(ShapeType.RECT); | ||||
Rectangle cellAnchor = getAnchor(); | Rectangle cellAnchor = getAnchor(); | ||||
Rectangle lineAnchor = new Rectangle(); | Rectangle lineAnchor = new Rectangle(); | ||||
switch(type){ | switch(type){ | ||||
case Table.BORDER_TOP: | |||||
case HSLFTable.BORDER_TOP: | |||||
lineAnchor.x = cellAnchor.x; | lineAnchor.x = cellAnchor.x; | ||||
lineAnchor.y = cellAnchor.y; | lineAnchor.y = cellAnchor.y; | ||||
lineAnchor.width = cellAnchor.width; | lineAnchor.width = cellAnchor.width; | ||||
lineAnchor.height = 0; | lineAnchor.height = 0; | ||||
break; | break; | ||||
case Table.BORDER_RIGHT: | |||||
case HSLFTable.BORDER_RIGHT: | |||||
lineAnchor.x = cellAnchor.x + cellAnchor.width; | lineAnchor.x = cellAnchor.x + cellAnchor.width; | ||||
lineAnchor.y = cellAnchor.y; | lineAnchor.y = cellAnchor.y; | ||||
lineAnchor.width = 0; | lineAnchor.width = 0; | ||||
lineAnchor.height = cellAnchor.height; | lineAnchor.height = cellAnchor.height; | ||||
break; | break; | ||||
case Table.BORDER_BOTTOM: | |||||
case HSLFTable.BORDER_BOTTOM: | |||||
lineAnchor.x = cellAnchor.x; | lineAnchor.x = cellAnchor.x; | ||||
lineAnchor.y = cellAnchor.y + cellAnchor.height; | lineAnchor.y = cellAnchor.y + cellAnchor.height; | ||||
lineAnchor.width = cellAnchor.width; | lineAnchor.width = cellAnchor.width; | ||||
lineAnchor.height = 0; | lineAnchor.height = 0; | ||||
break; | break; | ||||
case Table.BORDER_LEFT: | |||||
case HSLFTable.BORDER_LEFT: | |||||
lineAnchor.x = cellAnchor.x; | lineAnchor.x = cellAnchor.x; | ||||
lineAnchor.y = cellAnchor.y; | lineAnchor.y = cellAnchor.y; | ||||
lineAnchor.width = 0; | lineAnchor.width = 0; | ||||
} | } | ||||
public void setBorderLeft(Line line) { | public void setBorderLeft(Line line) { | ||||
if(line != null) anchorBorder(Table.BORDER_LEFT, line); | |||||
if(line != null) anchorBorder(HSLFTable.BORDER_LEFT, line); | |||||
this.borderLeft = line; | this.borderLeft = line; | ||||
} | } | ||||
} | } | ||||
public void setBorderRight(Line line) { | public void setBorderRight(Line line) { | ||||
if(line != null) anchorBorder(Table.BORDER_RIGHT, line); | |||||
if(line != null) anchorBorder(HSLFTable.BORDER_RIGHT, line); | |||||
this.borderRight = line; | this.borderRight = line; | ||||
} | } | ||||
} | } | ||||
public void setBorderTop(Line line) { | public void setBorderTop(Line line) { | ||||
if(line != null) anchorBorder(Table.BORDER_TOP, line); | |||||
if(line != null) anchorBorder(HSLFTable.BORDER_TOP, line); | |||||
this.borderTop = line; | this.borderTop = line; | ||||
} | } | ||||
} | } | ||||
public void setBorderBottom(Line line) { | public void setBorderBottom(Line line) { | ||||
if(line != null) anchorBorder(Table.BORDER_BOTTOM, line); | |||||
if(line != null) anchorBorder(HSLFTable.BORDER_BOTTOM, line); | |||||
this.borderBottom = line; | this.borderBottom = line; | ||||
} | } | ||||
public void setAnchor(Rectangle anchor){ | public void setAnchor(Rectangle anchor){ | ||||
super.setAnchor(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); | |||||
} | } | ||||
} | } |
package org.apache.poi.hslf.usermodel; | package org.apache.poi.hslf.usermodel; | ||||
import static org.apache.poi.hslf.record.RecordTypes.OutlineTextRefAtom; | |||||
import java.awt.Color; | import java.awt.Color; | ||||
import java.io.IOException; | |||||
import java.util.*; | import java.util.*; | ||||
import org.apache.poi.hslf.model.PPFont; | import org.apache.poi.hslf.model.PPFont; | ||||
private final TextHeaderAtom _headerAtom; | private final TextHeaderAtom _headerAtom; | ||||
private TextBytesAtom _byteAtom; | private TextBytesAtom _byteAtom; | ||||
private TextCharsAtom _charAtom; | 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 TextRulerAtom _ruler; | ||||
protected List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>(); | protected List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>(); | ||||
private HSLFSheet _sheet; | private HSLFSheet _sheet; | ||||
private int shapeId; | 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 StyleTextPropAtom styleTextPropAtom; | ||||
private StyleTextProp9Atom styleTextProp9Atom; | private StyleTextProp9Atom styleTextProp9Atom; | ||||
* @param tha the TextHeaderAtom that defines what's what | * @param tha the TextHeaderAtom that defines what's what | ||||
* @param tba the TextBytesAtom containing the text or null if {@link TextCharsAtom} is provided | * @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 tca the TextCharsAtom containing the text or null if {@link TextBytesAtom} is provided | ||||
* @param sta the StyleTextPropAtom which defines the character stylings | |||||
*/ | */ | ||||
/* package */ HSLFTextParagraph( | /* package */ HSLFTextParagraph( | ||||
TextHeaderAtom tha, | TextHeaderAtom tha, | ||||
TextBytesAtom tba, | TextBytesAtom tba, | ||||
TextCharsAtom tca, | |||||
StyleTextPropAtom sta | |||||
TextCharsAtom tca | |||||
) { | ) { | ||||
if (tha == null) { | |||||
throw new IllegalArgumentException("TextHeaderAtom must be set."); | |||||
} | |||||
_headerAtom = tha; | _headerAtom = tha; | ||||
_styleAtom = sta; | |||||
_byteAtom = tba; | _byteAtom = tba; | ||||
_charAtom = tca; | _charAtom = tca; | ||||
} | } | ||||
/* package */ HSLFTextParagraph(HSLFTextParagraph other) { | /* 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) { | public void addTextRun(HSLFTextRun run) { | ||||
_runs.add(run); | _runs.add(run); | ||||
} | } | ||||
public void setParagraphStyle(TextPropCollection paragraphStyle) { | public void setParagraphStyle(TextPropCollection paragraphStyle) { | ||||
_paragraphStyle = paragraphStyle; | |||||
_paragraphStyle.copy(paragraphStyle); | |||||
} | } | ||||
/** | /** | ||||
_ruler = getTextRuler(); | _ruler = getTextRuler(); | ||||
if (_ruler == null) { | if (_ruler == null) { | ||||
_ruler = TextRulerAtom.getParagraphInstance(); | _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; | 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 | * @return text run records | ||||
*/ | */ | ||||
public Record[] getRecords(){ | 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 */ | /** Numbered List info */ | ||||
public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) { | public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) { | ||||
this.styleTextProp9Atom = styleTextProp9Atom; | this.styleTextProp9Atom = styleTextProp9Atom; | ||||
return this.styleTextProp9Atom; | return this.styleTextProp9Atom; | ||||
} | } | ||||
/** Characters covered */ | |||||
public StyleTextPropAtom getStyleTextPropAtom() { | |||||
return this._styleAtom; | |||||
} | |||||
/** | /** | ||||
* Fetch the value of the given Paragraph related TextProp. | * Fetch the value of the given Paragraph related TextProp. | ||||
* Returns -1 if that TextProp isn't present. | * Returns -1 if that TextProp isn't present. | ||||
* Master Sheet will apply. | * Master Sheet will apply. | ||||
*/ | */ | ||||
private int getParaTextPropVal(String propName) { | 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){ | if (prop == null && !hardAttribute){ | ||||
HSLFSheet sheet = getSheet(); | HSLFSheet sheet = getSheet(); | ||||
int txtype = getRunType(); | int txtype = getRunType(); | ||||
*/ | */ | ||||
public void setParaTextPropVal(String propName, int val) { | public void setParaTextPropVal(String propName, int val) { | ||||
// Ensure we have the StyleTextProp atom we're going to need | // 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); | assert(_paragraphStyle!=null); | ||||
TextProp tp = fetchOrAddTextProp(_paragraphStyle, propName); | TextProp tp = fetchOrAddTextProp(_paragraphStyle, propName); | ||||
tp.setValue(val); | tp.setValue(val); | ||||
protected void setFlag(int index, boolean value) { | protected void setFlag(int index, boolean value) { | ||||
// Ensure we have the StyleTextProp atom we're going to need | // 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); | BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(_paragraphStyle, ParagraphFlagsTextProp.NAME); | ||||
prop.setSubValue(value,index); | prop.setSubValue(value,index); | ||||
} | } | ||||
boolean afterHeader = false; | boolean afterHeader = false; | ||||
StyleTextPropAtom style = null; | StyleTextPropAtom style = null; | ||||
for (Record record : header.getParentRecord().getChildRecords()) { | 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 | // already on the next header, quit searching | ||||
break; | break; | ||||
} | } | ||||
afterHeader |= (header == record); | afterHeader |= (header == record); | ||||
if (afterHeader && record.getRecordType() == RecordTypes.StyleTextPropAtom.typeID) { | |||||
if (afterHeader && rt == RecordTypes.StyleTextPropAtom.typeID) { | |||||
// found it | // found it | ||||
style = (StyleTextPropAtom)record; | style = (StyleTextPropAtom)record; | ||||
} | } | ||||
* If TextSpecInfoAtom is present, we must update the text size in it, | * If TextSpecInfoAtom is present, we must update the text size in it, | ||||
* otherwise the ppt will be corrupted | * otherwise the ppt will be corrupted | ||||
*/ | */ | ||||
for (Record r : paragraphs.get(0)._records) { | |||||
for (Record r : paragraphs.get(0).getRecords()) { | |||||
if (r instanceof TextSpecInfoAtom) { | if (r instanceof TextSpecInfoAtom) { | ||||
((TextSpecInfoAtom)r).setParentSize(rawText.length()+1); | ((TextSpecInfoAtom)r).setParentSize(rawText.length()+1); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (_txtbox instanceof EscherTextboxWrapper) { | |||||
try { | |||||
((EscherTextboxWrapper)_txtbox).writeOut(null); | |||||
} catch (IOException e) { | |||||
throw new RuntimeException("failed dummy write", e); | |||||
} | |||||
} | |||||
} | } | ||||
/** | /** | ||||
if (!isFirst) { | if (!isFirst) { | ||||
TextPropCollection tpc = htp.getParagraphStyle(); | TextPropCollection tpc = htp.getParagraphStyle(); | ||||
HSLFTextParagraph prevHtp = htp; | 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.getParagraphStyle().copy(tpc); | ||||
htp.setParentShape(prevHtp.getParentShape()); | htp.setParentShape(prevHtp.getParentShape()); | ||||
htp.setShapeId(prevHtp.getShapeId()); | htp.setShapeId(prevHtp.getShapeId()); | ||||
/** | /** | ||||
* For a given PPDrawing, grab all the TextRuns | * 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>>(); | List<List<HSLFTextParagraph>> runsV = new ArrayList<List<HSLFTextParagraph>>(); | ||||
for (EscherTextboxWrapper wrapper : ppdrawing.getTextboxWrappers()) { | for (EscherTextboxWrapper wrapper : ppdrawing.getTextboxWrappers()) { | ||||
runsV.addAll(findTextParagraphs(wrapper)); | |||||
runsV.add(findTextParagraphs(wrapper, sheet)); | |||||
} | } | ||||
return runsV; | 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 | * Scans through the supplied record array, looking for | ||||
* a TextHeaderAtom followed by one of a TextBytesAtom or | * a TextHeaderAtom followed by one of a TextBytesAtom or | ||||
* | * | ||||
* @param wrapper an EscherTextboxWrapper | * @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 | // propagate parents to parent-aware records | ||||
RecordContainer.handleParentAwareRecords(wrapper); | RecordContainer.handleParentAwareRecords(wrapper); | ||||
int shapeId = wrapper.getShapeId(); | 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.setShapeId(shapeId); | ||||
htp.setStyleTextProp9Atom(styleTextProp9Atom); | |||||
} | } | ||||
} | } | ||||
return rv; | return rv; | ||||
* a TextCharsAtom. Builds up TextRuns from these | * a TextCharsAtom. Builds up TextRuns from these | ||||
* | * | ||||
* @param records the records to build from | * @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>>(); | 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; | TextBytesAtom tbytes = null; | ||||
TextCharsAtom tchars = null; | TextCharsAtom tchars = null; | ||||
TextRulerAtom ruler = null; | TextRulerAtom ruler = null; | ||||
MasterTextPropAtom indents = 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(); | 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; | 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) { | if (header.getParentRecord() instanceof SlideListWithText) { | ||||
// runs found in PPDrawing are not linked with SlideListWithTexts | // runs found in PPDrawing are not linked with SlideListWithTexts | ||||
header.setIndex(slwtIndex); | header.setIndex(slwtIndex); | ||||
} | } | ||||
Record otherRecords[] = otherRecordList.toArray(new Record[otherRecordList.size()]); | |||||
if (tbytes == null && tchars == null) { | if (tbytes == null && tchars == null) { | ||||
tbytes = new TextBytesAtom(); | 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."); | 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(); | String rawText = (tchars != null) ? tchars.getText() : tbytes.getText(); | ||||
StyleTextPropAtom styles = findStyleAtomPresent(header, rawText.length()); | StyleTextPropAtom styles = findStyleAtomPresent(header, rawText.length()); | ||||
List<HSLFTextParagraph> paragraphs = new ArrayList<HSLFTextParagraph>(); | |||||
paragraphCollection.add(paragraphs); | |||||
// split, but keep delimiter | // split, but keep delimiter | ||||
for (String para : rawText.split("(?<=\r)")) { | for (String para : rawText.split("(?<=\r)")) { | ||||
HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars, styles); | |||||
HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars); | |||||
paragraphs.add(tpara); | paragraphs.add(tpara); | ||||
tpara.setStyleTextProp9Atom(styleTextProp9Atom); | |||||
tpara._ruler = ruler; | tpara._ruler = ruler; | ||||
tpara._records = otherRecords; | |||||
tpara.getParagraphStyle().updateTextSize(para.length()); | tpara.getParagraphStyle().updateTextSize(para.length()); | ||||
HSLFTextRun trun = new HSLFTextRun(tpara); | HSLFTextRun trun = new HSLFTextRun(tpara); | ||||
} | } | ||||
} | } | ||||
if (paragraphCollection.isEmpty()) { | |||||
logger.log(POILogger.DEBUG, "No text records found."); | |||||
} | |||||
return paragraphCollection; | return paragraphCollection; | ||||
} | } | ||||
TextPropCollection charStyle = sta.addCharacterTextPropCollection(1); | TextPropCollection charStyle = sta.addCharacterTextPropCollection(1); | ||||
wrapper.appendChildRecord(sta); | wrapper.appendChildRecord(sta); | ||||
HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null, sta); | |||||
HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null); | |||||
htp.setParagraphStyle(paraStyle); | htp.setParagraphStyle(paraStyle); | ||||
htp._records = new Record[0]; | |||||
HSLFTextRun htr = new HSLFTextRun(htp); | HSLFTextRun htr = new HSLFTextRun(htp); | ||||
htr.setCharacterStyle(charStyle); | htr.setCharacterStyle(charStyle); |
* Change the text | * Change the text | ||||
*/ | */ | ||||
public void setText(String text) { | public void setText(String text) { | ||||
_runText = text; | |||||
_runText = HSLFTextParagraph.toInternalString(text); | |||||
} | } | ||||
// --------------- Internal helpers on rich text properties ------- | // --------------- Internal helpers on rich text properties ------- |
} | } | ||||
protected EscherTextboxWrapper getEscherTextboxWrapper(){ | 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; | return _txtbox; | ||||
} | } | ||||
_paragraphs.addAll(HSLFTextParagraph.createEmptyParagraph()); | _paragraphs.addAll(HSLFTextParagraph.createEmptyParagraph()); | ||||
_txtbox = _paragraphs.get(0).getTextboxWrapper(); | _txtbox = _paragraphs.get(0).getTextboxWrapper(); | ||||
} else { | } 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) { | for (HSLFTextParagraph p : _paragraphs) { | ||||
} | } | ||||
} | } | ||||
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 | // 0xB acts like cariage return in page titles and like blank in the others | ||||
* Also updates the styles to the correct text length. | * Also updates the styles to the correct text length. | ||||
*/ | */ | ||||
protected void storeText() { | protected void storeText() { | ||||
HSLFTextParagraph.storeText(_paragraphs); | |||||
List<HSLFTextParagraph> paras = getTextParagraphs(); | |||||
HSLFTextParagraph.storeText(paras); | |||||
} | } | ||||
// Accesser methods follow | // Accesser methods follow | ||||
* @author Yegor Kozlov | * @author Yegor Kozlov | ||||
*/ | */ | ||||
public final class HSLFTitleMaster extends HSLFMasterSheet { | 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 | * Constructs a TitleMaster | ||||
public HSLFTitleMaster(org.apache.poi.hslf.record.Slide record, int sheetNo) { | public HSLFTitleMaster(org.apache.poi.hslf.record.Slide record, int sheetNo) { | ||||
super(record, 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 | * Returns an array of all the TextRuns found | ||||
*/ | */ | ||||
public List<List<HSLFTextParagraph>> getTextParagraphs() { | public List<List<HSLFTextParagraph>> getTextParagraphs() { | ||||
return _runs; | |||||
return _paragraphs; | |||||
} | } | ||||
/** | /** |
return getDrawable((FreeformShape<? extends TextParagraph<? extends TextRun>>)shape); | return getDrawable((FreeformShape<? extends TextParagraph<? extends TextRun>>)shape); | ||||
} else if (shape instanceof TextShape) { | } else if (shape instanceof TextShape) { | ||||
return getDrawable((TextShape<? extends TextParagraph<? extends TextRun>>)shape); | 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) { | } else if (shape instanceof PictureShape) { | ||||
return getDrawable((PictureShape)shape); | return getDrawable((PictureShape)shape); | ||||
} else if (shape instanceof Background) { | } else if (shape instanceof Background) { | ||||
return new DrawTextShape<T>(shape); | 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) { | public <T extends PictureShape> DrawPictureShape<T> getDrawable(T shape) { |
import org.apache.poi.sl.usermodel.*; | 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); | super(shape); | ||||
} | } | ||||
tx.translate(-interior.getX(), -interior.getY()); | tx.translate(-interior.getX(), -interior.getY()); | ||||
DrawFactory drawFact = DrawFactory.getInstance(graphics); | DrawFactory drawFact = DrawFactory.getInstance(graphics); | ||||
AffineTransform at2 = graphics.getTransform(); | |||||
for (Shape child : shape) { | for (Shape child : shape) { | ||||
// remember the initial transform and restore it after we are done with the drawing | // remember the initial transform and restore it after we are done with the drawing | ||||
graphics.setRenderingHint(Drawable.GRESTORE, true); | graphics.setRenderingHint(Drawable.GRESTORE, true); | ||||
} | } | ||||
graphics.setTransform(at2); | |||||
graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, tx0); | graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, tx0); | ||||
} | } | ||||
} | } |
if (!(shape instanceof PlaceableShape)) return; | if (!(shape instanceof PlaceableShape)) return; | ||||
PlaceableShape ps = (PlaceableShape)shape; | PlaceableShape ps = (PlaceableShape)shape; | ||||
Rectangle2D anchor = ps.getAnchor(); | |||||
AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM); | 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 | // rotation | ||||
double rotation = ps.getRotation(); | double rotation = ps.getRotation(); | ||||
double centerY = anchor.getCenterY(); | double centerY = anchor.getCenterY(); | ||||
// normalize rotation | // normalize rotation | ||||
rotation = (360.+(rotation%360.))%360.; | |||||
rotation %= 360.; | |||||
if (rotation < 0) rotation += 360.; | |||||
int quadrant = (((int)rotation+45)/90)%4; | int quadrant = (((int)rotation+45)/90)%4; | ||||
double scaleX = 1.0, scaleY = 1.0; | double scaleX = 1.0, scaleY = 1.0; | ||||
// think of it, as if you paint the shape on a canvas. First you rotate the canvas, which might | // 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 | // 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 ... | // 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.translate(centerX, centerY); | ||||
txg.rotate(Math.toRadians(quadrant*90)); | |||||
txg.rotate(Math.toRadians(90)); | |||||
txg.translate(-centerX, -centerY); | 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(); | scaleX = anchor.getWidth() == 0. ? 1.0 : anchor.getWidth() / anchor2.getWidth(); | ||||
scaleY = anchor.getHeight() == 0. ? 1.0 : anchor.getHeight() / anchor2.getHeight(); | 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 ... | // 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 | //flip horizontal |
public boolean isCompatibleValue(Object val) { | public boolean isCompatibleValue(Object val) { | ||||
return true; | 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(); | |||||
} | |||||
} | |||||
} | } | ||||
/** | /** |
/** | /** | ||||
* For now this class renders only images supported by the 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 | * 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> | * <pre> | ||||
* <code> | * <code> | ||||
* public class MyImageRendener extends ImageRendener { | * public class MyImageRendener extends ImageRendener { | ||||
* InputStream data; | |||||
* | * | ||||
* public boolean drawImage(Graphics2D graphics,Rectangle2D anchor,Insets clip) { | * public boolean drawImage(Graphics2D graphics,Rectangle2D anchor,Insets clip) { | ||||
* // draw image | * // 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 { | * public void loadImage(InputStream data, String contentType) throws IOException { | ||||
* if ("image/wmf".equals(contentType)) { | * if ("image/wmf".equals(contentType)) { | ||||
* this.data = data; | |||||
* // use Apache Batik to handle WMF | * // use Apache Batik to handle WMF | ||||
* } else { | * } else { | ||||
* super.loadImage(data,contentType); | * super.loadImage(data,contentType); | ||||
int iw = img.getWidth(); | int iw = img.getWidth(); | ||||
int ih = img.getHeight(); | int ih = img.getHeight(); | ||||
double cw = (100000-clip.left-clip.right) / 100000.0; | double cw = (100000-clip.left-clip.right) / 100000.0; | ||||
double ch = (100000-clip.top-clip.bottom) / 100000.0; | double ch = (100000-clip.top-clip.bottom) / 100000.0; | ||||
double sx = anchor.getWidth()/(iw*cw); | double sx = anchor.getWidth()/(iw*cw); | ||||
double sy = anchor.getHeight()/(ih*ch); | double sy = anchor.getHeight()/(ih*ch); | ||||
double tx = anchor.getX()-(iw*sx*clip.left/100000.0); | double tx = anchor.getX()-(iw*sx*clip.left/100000.0); | ||||
double ty = anchor.getY()-(ih*sy*clip.top/100000.0); | double ty = anchor.getY()-(ih*sy*clip.top/100000.0); | ||||
AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ; | AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ; | ||||
Shape clipOld = graphics.getClip(); | Shape clipOld = graphics.getClip(); |
import java.awt.geom.Rectangle2D; | 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(); | 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); | |||||
} | } |
import java.awt.Insets; | import java.awt.Insets; | ||||
public interface PictureShape extends SimpleShape { | 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 | * @return the clipping rectangle, which is given in percent in relation to the image width/height | ||||
*/ | */ | ||||
Insets getClipping(); | Insets getClipping(); |
package org.apache.poi.sl.usermodel; | package org.apache.poi.sl.usermodel; | ||||
import java.awt.Graphics2D; | |||||
/** | /** | ||||
* Common parent of Slides, Notes and Masters | * Common parent of Slides, Notes and Masters | ||||
MasterSheet<T,SS> getMasterSheet(); | MasterSheet<T,SS> getMasterSheet(); | ||||
Background getBackground(); | Background getBackground(); | ||||
/** | |||||
* Convenience method to draw a sheet to a graphics context | |||||
* | |||||
* @param graphics | |||||
*/ | |||||
void draw(Graphics2D graphics); | |||||
} | } |
TestFreeform.class, | TestFreeform.class, | ||||
TestHeadersFooters.class, | TestHeadersFooters.class, | ||||
TestHyperlink.class, | TestHyperlink.class, | ||||
TestImagePainter.class, | |||||
TestLine.class, | TestLine.class, | ||||
TestMovieShape.class, | TestMovieShape.class, | ||||
TestOleEmbedding.class, | TestOleEmbedding.class, |
/* ==================================================================== | |||||
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); | |||||
} | |||||
} |
HSLFSlide slide = ppt.createSlide(); | HSLFSlide slide = ppt.createSlide(); | ||||
Table tbl = new Table(2, 5); | |||||
HSLFTable tbl = new HSLFTable(2, 5); | |||||
slide.addShape(tbl); | 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 | //table cells have type=TextHeaderAtom.OTHER_TYPE, see bug #46033 | ||||
assertEquals(TextHeaderAtom.OTHER_TYPE, cell.getTextParagraphs().get(0).getRunType()); | 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.getNumberOfColumns(), tbl2.getNumberOfColumns()); | ||||
assertEquals(tbl.getNumberOfRows(), tbl2.getNumberOfRows()); | assertEquals(tbl.getNumberOfRows(), tbl2.getNumberOfRows()); | ||||
ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); | ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); | ||||
slide = ppt.getSlides().get(0); | 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.getNumberOfColumns(), tbl3.getNumberOfColumns()); | ||||
assertEquals(tbl.getNumberOfRows(), tbl3.getNumberOfRows()); | assertEquals(tbl.getNumberOfRows(), tbl3.getNumberOfRows()); | ||||
} | } | ||||
HSLFSlideShow ppt = new HSLFSlideShow(); | HSLFSlideShow ppt = new HSLFSlideShow(); | ||||
HSLFSlide slide = ppt.createSlide(); | HSLFSlide slide = ppt.createSlide(); | ||||
List<HSLFShape> shapes; | List<HSLFShape> shapes; | ||||
Table tbl1 = new Table(1, 5); | |||||
HSLFTable tbl1 = new HSLFTable(1, 5); | |||||
assertEquals(5, tbl1.getNumberOfColumns()); | assertEquals(5, tbl1.getNumberOfColumns()); | ||||
assertEquals(1, tbl1.getNumberOfRows()); | assertEquals(1, tbl1.getNumberOfRows()); | ||||
slide.addShape(tbl1); | slide.addShape(tbl1); | ||||
shapes = slide.getShapes(); | shapes = slide.getShapes(); | ||||
assertEquals(1, shapes.size()); | assertEquals(1, shapes.size()); | ||||
Table tbl2 = (Table)shapes.get(0); | |||||
HSLFTable tbl2 = (HSLFTable)shapes.get(0); | |||||
assertSame(tbl1.getSpContainer(), tbl2.getSpContainer()); | assertSame(tbl1.getSpContainer(), tbl2.getSpContainer()); | ||||
assertEquals(tbl1.getNumberOfColumns(), tbl2.getNumberOfColumns()); | assertEquals(tbl1.getNumberOfColumns(), tbl2.getNumberOfColumns()); | ||||
@Test | @Test | ||||
public void testIllegalCOnstruction(){ | public void testIllegalCOnstruction(){ | ||||
try { | 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"); | fail("Table(rownum, colnum) must throw IllegalArgumentException if any of tghe arguments is less than 1"); | ||||
} catch (IllegalArgumentException e){ | } catch (IllegalArgumentException e){ | ||||
} | } | ||||
try { | 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"); | fail("Table(rownum, colnum) must throw IllegalArgumentException if any of tghe arguments is less than 1"); | ||||
} catch (IllegalArgumentException e){ | } catch (IllegalArgumentException e){ | ||||
assertEquals(14, doc.getNotesSlideListWithText().getSlideAtomsSets().length); | assertEquals(14, doc.getNotesSlideListWithText().getSlideAtomsSets().length); | ||||
//remove all slides, corresponding notes should be removed too | //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); | ppt.removeSlide(0); | ||||
} | } | ||||
assertEquals(0, ppt.getSlides().size()); | assertEquals(0, ppt.getSlides().size()); |
package org.apache.poi.hslf.usermodel; | package org.apache.poi.hslf.usermodel; | ||||
import static org.junit.Assert.*; | 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.ArrayList; | ||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.HashMap; | import java.util.HashMap; | ||||
import org.apache.poi.hslf.HSLFTestDataSamples; | import org.apache.poi.hslf.HSLFTestDataSamples; | ||||
import org.apache.poi.hslf.exceptions.OldPowerPointFormatException; | import org.apache.poi.hslf.exceptions.OldPowerPointFormatException; | ||||
import org.apache.poi.hslf.model.*; | 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.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; | import org.junit.Test; | ||||
/** | /** | ||||
for (List<HSLFTextParagraph> tr : _slides.get(0).getTextParagraphs()) { | for (List<HSLFTextParagraph> tr : _slides.get(0).getTextParagraphs()) { | ||||
if (! tr.get(0).isDrawingBased()) str++; | if (! tr.get(0).isDrawingBased()) str++; | ||||
} | } | ||||
assertEquals(1, str); | |||||
assertEquals(2, str); | |||||
} | } | ||||
@Test | @Test |
package org.apache.poi.hslf.usermodel; | package org.apache.poi.hslf.usermodel; | ||||
import static org.junit.Assert.assertTrue; | |||||
import static org.junit.Assert.*; | |||||
import static org.junit.Assume.assumeTrue; | 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.AffineTransform; | ||||
import java.awt.geom.Rectangle2D; | import java.awt.geom.Rectangle2D; | ||||
import java.awt.image.BufferedImage; | import java.awt.image.BufferedImage; | ||||
import java.awt.image.DataBufferByte; | import java.awt.image.DataBufferByte; | ||||
import java.io.File; | import java.io.File; | ||||
import java.io.InputStream; | import java.io.InputStream; | ||||
import java.util.Arrays; | |||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
import java.util.*; | |||||
import javax.imageio.ImageIO; | import javax.imageio.ImageIO; | ||||
import org.apache.poi.POIDataSamples; | 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.apache.poi.util.TempFile; | ||||
import org.junit.Ignore; | import org.junit.Ignore; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
public class TestFontRendering { | public class TestFontRendering { | ||||
private static POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); | 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 | @Test | ||||
public void bug55902mixedFontWithChineseCharacters() throws Exception { | public void bug55902mixedFontWithChineseCharacters() throws Exception { | ||||
// font files need to be downloaded first via | // font files need to be downloaded first via | ||||
Dimension pgsize = ss.getPageSize(); | Dimension pgsize = ss.getPageSize(); | ||||
HSLFSlide slide = ss.getSlides()[0]; | |||||
HSLFSlide slide = ss.getSlides().get(0); | |||||
// render it | // render it | ||||
double zoom = 1; | double zoom = 1; | ||||
BufferedImage imgActual = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_3BYTE_BGR); | BufferedImage imgActual = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_3BYTE_BGR); | ||||
Graphics2D graphics = imgActual.createGraphics(); | 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_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); | ||||
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); | graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); | ||||
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); | graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); | ||||
if(!Arrays.equals(expectedData, actualData)) { | if(!Arrays.equals(expectedData, actualData)) { | ||||
ImageIO.write(imgActual, "PNG", TempFile.createTempFile("TestFontRendering", ".png")); | 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); | |||||
} | } | ||||
} | } |
assertEquals(Short.valueOf((short)1), autoNumbers[0].getAutoNumberStartNumber());//Default value = 1 will be used | assertEquals(Short.valueOf((short)1), autoNumbers[0].getAutoNumberStartNumber());//Default value = 1 will be used | ||||
assertTrue(TextAutoNumberSchemeEnum.ANM_ArabicPeriod == autoNumbersOfTextBox0[0].getAutoNumberScheme()); | 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()); | assertTrue(textParass.get(0).get(0).isBullet()); | ||||
package org.apache.poi.hslf.usermodel; | 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.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.HashMap; | ||||
import java.util.Map; | import java.util.Map; | ||||
import org.apache.poi.POIDataSamples; | import org.apache.poi.POIDataSamples; | ||||
import org.apache.poi.ddf.EscherBSERecord; | 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.util.JvmBugs; | ||||
import org.apache.poi.xslf.usermodel.XMLSlideShow; | |||||
import org.junit.Ignore; | import org.junit.Ignore; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
} | } | ||||
@Test | @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 { | 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(); | is.close(); | ||||
boolean debugOut = false; | |||||
Dimension pg = ss.getPageSize(); | Dimension pg = ss.getPageSize(); | ||||
int i=1; | 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") | @SuppressWarnings("unchecked") | ||||
private void fixFonts(Graphics2D graphics) { | private void fixFonts(Graphics2D graphics) { | ||||
if (!JvmBugs.hasLineBreakMeasurerBug()) return; | 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>(); | if (fontMap == null) fontMap = new HashMap<String,String>(); | ||||
fontMap.put("Calibri", "Lucida Sans"); | fontMap.put("Calibri", "Lucida Sans"); | ||||
fontMap.put("Cambria", "Lucida Bright"); | fontMap.put("Cambria", "Lucida Bright"); | ||||
graphics.setRenderingHint(TextPainter.KEY_FONTMAP, fontMap); | |||||
graphics.setRenderingHint(Drawable.FONT_MAP, fontMap); | |||||
} | } | ||||
} | } |
import java.io.ByteArrayInputStream; | import java.io.ByteArrayInputStream; | ||||
import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||
import java.net.URL; | import java.net.URL; | ||||
import java.util.List; | |||||
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
import org.apache.poi.POIDataSamples; | 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 | * Test adding/reading pictures | ||||
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); | 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 | //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()); | assertEquals(idx, pict.getPictureIndex()); | ||||
//check picture data | //check picture data | ||||
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); | 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 | //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()); | assertEquals(idx, pict.getPictureIndex()); | ||||
//check picture data | //check picture data | ||||
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); | 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 | //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()); | assertEquals(idx, pict.getPictureIndex()); | ||||
//check picture data | //check picture data | ||||
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); | 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 | //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()); | assertEquals(idx, pict.getPictureIndex()); | ||||
//check picture data | //check picture data | ||||
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); | 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 | //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()); | assertEquals(idx, pict.getPictureIndex()); | ||||
//check picture data | //check picture data | ||||
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); | 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 | //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()); | assertEquals(idx, pict.getPictureIndex()); | ||||
//check picture data | //check picture data | ||||
HSLFPictureData pdata; | HSLFPictureData pdata; | ||||
HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("pictures.ppt")); | HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("pictures.ppt")); | ||||
HSLFSlide[] slides = ppt.getSlides(); | |||||
List<HSLFSlide> slides = ppt.getSlides(); | |||||
HSLFPictureData[] pictures = ppt.getPictureData(); | HSLFPictureData[] pictures = ppt.getPictureData(); | ||||
assertEquals(5, pictures.length); | 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(); | pdata = pict.getPictureData(); | ||||
assertTrue(pdata instanceof JPEG); | assertTrue(pdata instanceof JPEG); | ||||
assertEquals(HSLFPictureShape.JPEG, pdata.getType()); | assertEquals(HSLFPictureShape.JPEG, pdata.getType()); | ||||
ppt_bytes = slTests.readFile("clock.jpg"); | ppt_bytes = slTests.readFile("clock.jpg"); | ||||
assertArrayEquals(src_bytes, ppt_bytes); | 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(); | pdata = pict.getPictureData(); | ||||
assertTrue(pdata instanceof PNG); | assertTrue(pdata instanceof PNG); | ||||
assertEquals(HSLFPictureShape.PNG, pdata.getType()); | assertEquals(HSLFPictureShape.PNG, pdata.getType()); | ||||
ppt_bytes = slTests.readFile("tomcat.png"); | ppt_bytes = slTests.readFile("tomcat.png"); | ||||
assertArrayEquals(src_bytes, ppt_bytes); | 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(); | pdata = pict.getPictureData(); | ||||
assertTrue(pdata instanceof WMF); | assertTrue(pdata instanceof WMF); | ||||
assertEquals(HSLFPictureShape.WMF, pdata.getType()); | assertEquals(HSLFPictureShape.WMF, pdata.getType()); | ||||
System.arraycopy(ppt_bytes, 22, b2, 0, b2.length); | System.arraycopy(ppt_bytes, 22, b2, 0, b2.length); | ||||
assertArrayEquals(b1, b2); | 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(); | pdata = pict.getPictureData(); | ||||
assertTrue(pdata instanceof PICT); | assertTrue(pdata instanceof PICT); | ||||
assertEquals(HSLFPictureShape.PICT, pdata.getType()); | assertEquals(HSLFPictureShape.PICT, pdata.getType()); | ||||
System.arraycopy(ppt_bytes, 512, b2, 0, b2.length); | System.arraycopy(ppt_bytes, 512, b2, 0, b2.length); | ||||
assertArrayEquals(b1, b2); | 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(); | pdata = pict.getPictureData(); | ||||
assertTrue(pdata instanceof EMF); | assertTrue(pdata instanceof EMF); | ||||
assertEquals(HSLFPictureShape.EMF, pdata.getType()); | assertEquals(HSLFPictureShape.EMF, pdata.getType()); | ||||
// Now test what happens when we use the SlideShow interface | // Now test what happens when we use the SlideShow interface | ||||
HSLFSlideShow ppt = new HSLFSlideShow(hslf); | HSLFSlideShow ppt = new HSLFSlideShow(hslf); | ||||
HSLFSlide[] slides = ppt.getSlides(); | |||||
List<HSLFSlide> slides = ppt.getSlides(); | |||||
HSLFPictureData[] pictures = ppt.getPictureData(); | HSLFPictureData[] pictures = ppt.getPictureData(); | ||||
assertEquals(12, slides.length); | |||||
assertEquals(12, slides.size()); | |||||
assertEquals(2, pictures.length); | assertEquals(2, pictures.length); | ||||
HSLFPictureShape pict; | HSLFPictureShape pict; | ||||
HSLFPictureData pdata; | 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(); | pdata = pict.getPictureData(); | ||||
assertTrue(pdata instanceof WMF); | assertTrue(pdata instanceof WMF); | ||||
assertEquals(HSLFPictureShape.WMF, pdata.getType()); | 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(); | pdata = pict.getPictureData(); | ||||
assertTrue(pdata instanceof WMF); | assertTrue(pdata instanceof WMF); | ||||
assertEquals(HSLFPictureShape.WMF, pdata.getType()); | assertEquals(HSLFPictureShape.WMF, pdata.getType()); | ||||
// Now test what happens when we use the SlideShow interface | // Now test what happens when we use the SlideShow interface | ||||
HSLFSlideShow ppt = new HSLFSlideShow(hslf); | HSLFSlideShow ppt = new HSLFSlideShow(hslf); | ||||
HSLFSlide[] slides = ppt.getSlides(); | |||||
List<HSLFSlide> slides = ppt.getSlides(); | |||||
HSLFPictureData[] pictures = ppt.getPictureData(); | HSLFPictureData[] pictures = ppt.getPictureData(); | ||||
assertEquals(27, slides.length); | |||||
assertEquals(27, slides.size()); | |||||
assertEquals(2, pictures.length); | assertEquals(2, pictures.length); | ||||
HSLFPictureShape pict; | HSLFPictureShape pict; | ||||
HSLFPictureData pdata; | HSLFPictureData pdata; | ||||
pict = (HSLFPictureShape)slides[6].getShapes()[13]; | |||||
pict = (HSLFPictureShape)slides.get(6).getShapes().get(13); | |||||
pdata = pict.getPictureData(); | pdata = pict.getPictureData(); | ||||
assertTrue(pdata instanceof WMF); | assertTrue(pdata instanceof WMF); | ||||
assertEquals(HSLFPictureShape.WMF, pdata.getType()); | assertEquals(HSLFPictureShape.WMF, pdata.getType()); | ||||
pict = (HSLFPictureShape)slides[7].getShapes()[13]; | |||||
pict = (HSLFPictureShape)slides.get(7).getShapes().get(13); | |||||
pdata = pict.getPictureData(); | pdata = pict.getPictureData(); | ||||
assertTrue(pdata instanceof WMF); | assertTrue(pdata instanceof WMF); | ||||
assertEquals(HSLFPictureShape.WMF, pdata.getType()); | assertEquals(HSLFPictureShape.WMF, pdata.getType()); | ||||
public void testGetPictureName() throws Exception { | public void testGetPictureName() throws Exception { | ||||
HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("ppt_with_png.ppt")); | 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()); | assertEquals("test", p.getPictureName()); | ||||
} | } | ||||
ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); | 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()); | assertEquals("tomcat.png", p.getPictureName()); | ||||
} | } | ||||
} | } |
package org.apache.poi.hslf.usermodel; | 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.apache.poi.POIDataSamples; | ||||
import org.junit.Test; | |||||
/** | /** | ||||
* | * | ||||
* @author Alex Nikiforov [mailto:anikif@gmail.com] | * @author Alex Nikiforov [mailto:anikif@gmail.com] | ||||
*/ | */ | ||||
public final class TestTable extends TestCase { | |||||
public class TestTable { | |||||
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); | 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")); | HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("54111.ppt")); | ||||
assertTrue("No Exceptions while reading file", true); | 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) { | 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("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); | 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(4, table.getNumberOfColumns()); | ||||
assertEquals(6, table.getNumberOfRows()); | assertEquals(6, table.getNumberOfRows()); | ||||
for (int x = 0; x < 4; x ++) { | 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++) { | for (int y = 1; y < 6; y++) { | ||||
assertEquals("Row " + y + ", Cell " + (x + 1), table.getCell(y, x).getText()); | assertEquals("Row " + y + ", Cell " + (x + 1), table.getCell(y, x).getText()); | ||||
} | } |
import static org.junit.Assert.*; | import static org.junit.Assert.*; | ||||
import java.io.IOException; | |||||
import java.awt.Color; | |||||
import java.io.*; | |||||
import java.util.List; | import java.util.List; | ||||
import org.apache.poi.POIDataSamples; | import org.apache.poi.POIDataSamples; | ||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection; | |||||
import org.apache.poi.hslf.record.*; | import org.apache.poi.hslf.record.*; | ||||
import org.junit.Before; | import org.junit.Before; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
// Ensure trailing \n's are NOT stripped, it is legal to set a text with a trailing '\r' | // Ensure trailing \n's are NOT stripped, it is legal to set a text with a trailing '\r' | ||||
tr.setText(changeTo + "\n"); | tr.setText(changeTo + "\n"); | ||||
assertEquals(changeTo + "\n", tr.getRawText()); | |||||
assertEquals(changeTo + "\r", tr.getRawText()); | |||||
} | } | ||||
/** | /** | ||||
else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r; | else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r; | ||||
else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r; | else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r; | ||||
} | } | ||||
// Bytes -> Bytes | // Bytes -> Bytes | ||||
assertNull(tca); | assertNull(tca); | ||||
List<HSLFTextParagraph> trB = textParass.get(1); | List<HSLFTextParagraph> trB = textParass.get(1); | ||||
assertEquals(1, trA.size()); | assertEquals(1, trA.size()); | ||||
assertEquals(1, trB.size()); | |||||
assertEquals(2, trB.size()); | |||||
HSLFTextRun rtrA = trA.get(0).getTextRuns().get(0); | HSLFTextRun rtrA = trA.get(0).getTextRuns().get(0); | ||||
HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); | HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); | ||||
assertEquals(HSLFTextParagraph.getRawText(trA), rtrA.getRawText()); | 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()); | |||||
} | } | ||||
/** | /** | ||||
HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); | HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); | ||||
HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0); | HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0); | ||||
HSLFTextRun rtrD = trB.get(2).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()); | // 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 | // Change text via normal | ||||
// trB.setText("Test Foo Test"); | |||||
HSLFTextParagraph.setText(trB, "Test Foo Test"); | |||||
// Ensure now have first style | // 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() ); | |||||
} | } | ||||
/** | /** | ||||
HSLFSlide slideOne = ss.getSlides().get(0); | HSLFSlide slideOne = ss.getSlides().get(0); | ||||
List<List<HSLFTextParagraph>> textRuns = slideOne.getTextParagraphs(); | List<List<HSLFTextParagraph>> textRuns = slideOne.getTextParagraphs(); | ||||
List<HSLFTextParagraph> trB = textRuns.get(1); | 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 | // 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 | // Will now have dummy props | ||||
// assertNotNull(rtrB._getRawCharacterStyle()); | |||||
// assertNotNull(rtrB._getRawParagraphStyle()); | |||||
assertNotNull(rtrB.getCharacterStyle()); | |||||
assertNotNull(rtrB.getTextParagraph().getParagraphStyle()); | |||||
} | } | ||||
/** | /** | ||||
assertEquals(3, trB.size()); | assertEquals(3, trB.size()); | ||||
// We start with 3 text runs, each with their own set of styles, | // 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 rtrB = trB.get(0).getTextRuns().get(0); | ||||
HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0); | HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0); | ||||
HSLFTextRun rtrD = trB.get(2).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 | // 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 | // Check text in the rich runs | ||||
assertEquals("This is the subtitle, in bold\r", rtrB.getRawText()); | assertEquals("This is the subtitle, in bold\r", rtrB.getRawText()); | ||||
rtrB.setText(newBText); | rtrB.setText(newBText); | ||||
rtrC.setText(newCText); | rtrC.setText(newCText); | ||||
rtrD.setText(newDText); | 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 | // 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()); | |||||
} | } | ||||
assertEquals(0, slide.getTextParagraphs().size()); | assertEquals(0, slide.getTextParagraphs().size()); | ||||
HSLFTextBox shape1 = new HSLFTextBox(); | 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); | slide.addShape(shape1); | ||||
//The array of Slide's text runs must be updated when new text shapes are added. | //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 | @Test | ||||
public void test48916() throws IOException { | 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); | |||||
} | |||||
} | |||||
} | |||||
} | } | ||||