git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@387008 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_0_ALPHA3
@@ -262,6 +262,7 @@ public class HSLFSlideShow | |||
int oldPos = pdr.getLastOnDiskOffset(); | |||
int newPos = baos.size(); | |||
pdr.setLastOnDiskOffset(newPos); | |||
//System.out.println(i + " " + oldPos + " " + newPos); | |||
oldToNewPositions.put(new Integer(oldPos),new Integer(newPos)); | |||
pdr.updateOtherRecordReferences(oldToNewPositions); | |||
} | |||
@@ -317,6 +318,31 @@ public class HSLFSlideShow | |||
* Returns an array of all the records found in the slideshow | |||
*/ | |||
public Record[] getRecords() { return _records; } | |||
/** | |||
* Adds a new root level record, at the end, but before the last | |||
* PersistPtrIncrementalBlock. | |||
*/ | |||
public synchronized int appendRootLevelRecord(Record newRecord) { | |||
int addedAt = -1; | |||
Record[] r = new Record[_records.length+1]; | |||
boolean added = false; | |||
for(int i=(_records.length-1); i>=0; i--) { | |||
if(added) { | |||
// Just copy over | |||
r[i] = _records[i]; | |||
} else { | |||
r[(i+1)] = _records[i]; | |||
if(_records[i] instanceof PersistPtrHolder) { | |||
r[i] = newRecord; | |||
added = true; | |||
addedAt = i; | |||
} | |||
} | |||
} | |||
_records = r; | |||
return addedAt; | |||
} | |||
/** | |||
* Returns an array of the bytes of the file. Only correct after a |
@@ -0,0 +1,60 @@ | |||
/* ==================================================================== | |||
Copyright 2002-2004 Apache Software Foundation | |||
Licensed 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 org.apache.poi.ddf.*; | |||
import java.awt.*; | |||
/** | |||
* Represents a ellipse in a PowerPoint drawing | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public class Ellipse extends SimpleShape { | |||
protected Ellipse(EscherContainerRecord escherRecord, Shape parent){ | |||
super(escherRecord, parent); | |||
} | |||
public Ellipse(Shape parent){ | |||
super(null, parent); | |||
_escherContainer = create(parent instanceof ShapeGroup); | |||
} | |||
public Ellipse(){ | |||
this(null); | |||
} | |||
protected EscherContainerRecord create(boolean isChild){ | |||
EscherContainerRecord spcont = super.create(isChild); | |||
spcont.setOptions((short)15); | |||
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID); | |||
short type = (ShapeTypes.Ellipse << 4) + 2; | |||
spRecord.setOptions(type); | |||
//set default properties for a line | |||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID); | |||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__SHAPEPATH, 4)); | |||
opt.sortProperties(); | |||
return spcont; | |||
} | |||
} |
@@ -0,0 +1,123 @@ | |||
/* ==================================================================== | |||
Copyright 2002-2004 Apache Software Foundation | |||
Licensed 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 org.apache.poi.ddf.*; | |||
import java.awt.*; | |||
/** | |||
* Represents a line in a PowerPoint drawing | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public class Line extends SimpleShape { | |||
/** | |||
* Solid (continuous) pen | |||
*/ | |||
public static final int LineSolid = 1; | |||
/** | |||
* PS_DASH system dash style | |||
*/ | |||
public static final int LineDashSys = 2; | |||
/** | |||
* PS_DOT system dash style | |||
*/ | |||
public static final int LineDotSys = 3; | |||
/** | |||
* PS_DASHDOT system dash style | |||
*/ | |||
public static final int LineDashDotSys = 4; | |||
/** | |||
* PS_DASHDOTDOT system dash style | |||
*/ | |||
public static final int LineDashDotDotSys = 5; | |||
/** | |||
* square dot style | |||
*/ | |||
public static final int LineDotGEL = 6; | |||
/** | |||
* dash style | |||
*/ | |||
public static final int LineDashGEL = 7; | |||
/** | |||
* long dash style | |||
*/ | |||
public static final int LineLongDashGEL = 8; | |||
/** | |||
* dash short dash | |||
*/ | |||
public static final int LineDashDotGEL = 9; | |||
/** | |||
* long dash short dash | |||
*/ | |||
public static final int LineLongDashDotGEL = 10; | |||
/** | |||
* long dash short dash short dash | |||
*/ | |||
public static final int LineLongDashDotDotGEL = 11; | |||
/** | |||
* Decoration of the end of line, | |||
* reserved in API but not supported. | |||
*/ | |||
/** | |||
* Line ends at end point | |||
*/ | |||
public static final int EndCapFlat = 0; | |||
/** | |||
* Rounded ends - the default | |||
*/ | |||
public static final int EndCapRound = 1; | |||
/** | |||
* Square protrudes by half line width | |||
*/ | |||
public static final int EndCapSquare = 2; | |||
protected Line(EscherContainerRecord escherRecord, Shape parent){ | |||
super(escherRecord, parent); | |||
} | |||
public Line(Shape parent){ | |||
super(null, parent); | |||
_escherContainer = create(parent instanceof ShapeGroup); | |||
} | |||
public Line(){ | |||
this(null); | |||
} | |||
protected EscherContainerRecord create(boolean isChild){ | |||
EscherContainerRecord spcont = super.create(isChild); | |||
spcont.setOptions((short)15); | |||
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID); | |||
short type = (ShapeTypes.Line << 4) + 2; | |||
spRecord.setOptions(type); | |||
//set default properties for a line | |||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID); | |||
//opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__SHAPEPATH, 4)); | |||
opt.sortProperties(); | |||
return spcont; | |||
} | |||
} |
@@ -70,4 +70,5 @@ public class Notes extends Sheet | |||
* Returns the sheet number | |||
*/ | |||
public int getSheetNumber() { return _sheetNo; } | |||
} | |||
protected PPDrawing getPPDrawing() { return _notes.getPPDrawing(); }} |
@@ -0,0 +1,434 @@ | |||
/* ==================================================================== | |||
Copyright 2002-2004 Apache Software Foundation | |||
Licensed 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.*; | |||
import java.awt.Shape; | |||
import java.awt.font.FontRenderContext; | |||
import java.awt.font.GlyphVector; | |||
import java.awt.image.*; | |||
import java.awt.image.renderable.RenderableImage; | |||
import java.awt.geom.AffineTransform; | |||
import java.awt.geom.PathIterator; | |||
import java.text.AttributedCharacterIterator; | |||
import java.util.Map; | |||
import org.apache.poi.ddf.EscherProperties; | |||
/** | |||
* Translates Graphics2D calls into PowerPoint. | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public class PPGraphics2D extends Graphics2D { | |||
//The group to write the graphics calls into. | |||
private ShapeGroup group; | |||
private AffineTransform transform; | |||
private Stroke stroke; | |||
private Paint paint; | |||
private Font font; | |||
private Color foreground; | |||
private Color background = Color.white; | |||
private Shape clip; | |||
/** | |||
* Construct an powerpoint Graphics object. | |||
* | |||
* @param group The shape group to write the graphics calls into. | |||
*/ | |||
public PPGraphics2D(ShapeGroup group){ | |||
this.group = group; | |||
transform = new AffineTransform(); | |||
} | |||
/** | |||
* @return the shape group being used for drawing | |||
*/ | |||
public ShapeGroup getShapeGroup(){ | |||
return group; | |||
} | |||
public Font getFont(){ | |||
return font; | |||
} | |||
public void setFont(Font font){ | |||
this.font = font; | |||
} | |||
public Color getColor(){ | |||
return foreground; | |||
} | |||
public void setColor(Color color) { | |||
this.foreground = color; | |||
} | |||
public Stroke getStroke(){ | |||
return stroke; | |||
} | |||
public void setStroke(Stroke s){ | |||
this.stroke = s; | |||
} | |||
public Paint getPaint(){ | |||
return paint; | |||
} | |||
public void setPaint(Paint paint){ | |||
this.paint = paint; | |||
if (paint instanceof Color) setColor((Color)paint); | |||
} | |||
public AffineTransform getTransform(){ | |||
return (AffineTransform)transform.clone(); | |||
} | |||
public void setTransform(AffineTransform trans) { | |||
transform = (AffineTransform)trans.clone(); | |||
} | |||
public void draw(Shape shape){ | |||
if(clip != null) { | |||
if (!clip.getBounds().contains(transform.createTransformedShape(shape).getBounds())) { | |||
//return; | |||
} | |||
} | |||
PathIterator it = shape.getPathIterator(transform); | |||
double[] prev = null; | |||
double[] coords = new double[6]; | |||
double[] first = new double[6]; | |||
if(!it.isDone()) it.currentSegment(first); //first point | |||
while(!it.isDone()){ | |||
int type = it.currentSegment(coords); | |||
if (prev != null ){ | |||
Line line = new Line(group); | |||
if (stroke instanceof BasicStroke){ | |||
BasicStroke bs = (BasicStroke)stroke; | |||
line.setLineWidth(bs.getLineWidth()); | |||
} | |||
if(getColor() != null) line.setLineColor(getColor()); | |||
if (type == PathIterator.SEG_LINETO) { | |||
line.setAnchor(new java.awt.Rectangle((int)prev[0], (int)prev[1], (int)(coords[0] - prev[0]), (int)(coords[1] - prev[1]))); | |||
} else if (type == PathIterator.SEG_CLOSE){ | |||
line.setAnchor(new java.awt.Rectangle((int)coords[0], (int)coords[1], (int)(first[0] - coords[0]), (int)(first[1] - coords[1]))); | |||
} | |||
group.addShape(line); | |||
} | |||
prev = new double[]{coords[0], coords[1]}; | |||
it.next(); | |||
} | |||
} | |||
public void drawString(String string, float x, float y){ | |||
} | |||
public void fill(Shape shape){ | |||
if (paint instanceof Color){ | |||
Color color = (Color)paint; | |||
} | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void translate(int x, int y) { | |||
AffineTransform at = new AffineTransform(); | |||
at.translate(x, y); | |||
transform.concatenate(at); | |||
} | |||
public void clip(Shape shape) { | |||
this.clip = transform.createTransformedShape(shape); | |||
//update size of the escher group which holds the drawing | |||
group.setAnchor(clip.getBounds()); | |||
} | |||
public Shape getClip() { | |||
return clip; | |||
} | |||
public void scale(double sx, double sy) { | |||
AffineTransform at = new AffineTransform(); | |||
at.scale(sx, sy); | |||
transform.concatenate(at); | |||
} | |||
//=============================================== | |||
public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void drawString(String str, int x, int y) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void fillOval(int x, int y, int width, int height) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void fillArc(int x, int y, int width, int height, | |||
int startAngle, int arcAngle) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void setPaintMode() { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void drawArc(int x, int y, int width, int height, | |||
int startAngle, int arcAngle) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void drawPolyline(int xPoints[], int yPoints[], | |||
int nPoints) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public Graphics create() { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void drawOval(int x, int y, int width, int height) { | |||
Ellipse ellipse = new Ellipse(); | |||
ellipse.setAnchor(new java.awt.Rectangle(x-width/2, y-height/2, width, height)); | |||
if (stroke instanceof BasicStroke){ | |||
BasicStroke bs = (BasicStroke)stroke; | |||
ellipse.setLineWidth(bs.getLineWidth()); | |||
} | |||
if(getColor() != null) ellipse.setLineColor(getColor()); | |||
if (paint instanceof Color){ | |||
Color color = (Color)paint; | |||
ellipse.setFillColor(color); | |||
} | |||
group.addShape(ellipse); | |||
} | |||
public void setXORMode(Color color1) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public boolean drawImage(Image img, int x, int y, | |||
Color bgcolor, | |||
ImageObserver observer) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public boolean drawImage(Image img, int x, int y, | |||
int width, int height, | |||
Color bgcolor, | |||
ImageObserver observer) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public boolean drawImage(Image img, | |||
int dx1, int dy1, int dx2, int dy2, | |||
int sx1, int sy1, int sx2, int sy2, | |||
ImageObserver observer) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public boolean drawImage(Image img, | |||
int dx1, int dy1, int dx2, int dy2, | |||
int sx1, int sy1, int sx2, int sy2, | |||
Color bgcolor, | |||
ImageObserver observer) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public boolean drawImage(Image img, int x, int y, | |||
ImageObserver observer) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public boolean drawImage(Image img, int x, int y, | |||
int width, int height, | |||
ImageObserver observer) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void dispose() { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void drawLine(int x1, int y1, int x2, int y2) { | |||
Line line = new Line(); | |||
line.setAnchor(new java.awt.Rectangle(x1, y1, x2-x1, y2-y1)); | |||
if (stroke instanceof BasicStroke){ | |||
BasicStroke bs = (BasicStroke)stroke; | |||
line.setLineWidth(bs.getLineWidth()); | |||
} | |||
if(getColor() != null) line.setLineColor(getColor()); | |||
group.addShape(line); | |||
} | |||
public void fillPolygon(int xPoints[], int yPoints[], | |||
int nPoints) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public FontMetrics getFontMetrics(Font f) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void fillRect(int x, int y, int width, int height) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void drawPolygon(int xPoints[], int yPoints[], | |||
int nPoints) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void clipRect(int x, int y, int width, int height) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void setClip(Shape clip) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public java.awt.Rectangle getClipBounds() { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void drawString(AttributedCharacterIterator iterator, int x, int y) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void clearRect(int x, int y, int width, int height) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void copyArea(int x, int y, int width, int height, int dx, int dy) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void setClip(int x, int y, int width, int height) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void rotate(double d) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void rotate(double d, double d1, double d2) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void shear(double d, double d1) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public FontRenderContext getFontRenderContext() { | |||
return new FontRenderContext(transform, true, true); | |||
} | |||
public void transform(AffineTransform affinetransform) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void drawImage(BufferedImage bufferedimage, BufferedImageOp op, int x, int y) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void setBackground(Color c) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void drawRenderedImage(RenderedImage renderedimage, AffineTransform affinetransform) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public Color getBackground() { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void setComposite(Composite composite) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public Composite getComposite() { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public Object getRenderingHint(java.awt.RenderingHints.Key key) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public boolean drawImage(Image image, AffineTransform affinetransform, ImageObserver imageobserver) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void setRenderingHint(java.awt.RenderingHints.Key key, Object obj) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void drawGlyphVector(GlyphVector g, float x, float y) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public GraphicsConfiguration getDeviceConfiguration() { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void addRenderingHints(Map map) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void translate(double d, double d1) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void drawString(AttributedCharacterIterator attributedcharacteriterator, float x, float y) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public boolean hit(java.awt.Rectangle rectangle, Shape shape, boolean flag) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public RenderingHints getRenderingHints() { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void setRenderingHints(Map map) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
public void drawRenderableImage(RenderableImage renderableimage, AffineTransform affinetransform) { | |||
throw new RuntimeException("Not implemented"); | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
/* ==================================================================== | |||
Copyright 2002-2004 Apache Software Foundation | |||
Licensed 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 org.apache.poi.ddf.*; | |||
import java.awt.*; | |||
/** | |||
* Represents a line in a PowerPoint drawing | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public class Rectangle extends SimpleShape { | |||
protected Rectangle(EscherContainerRecord escherRecord, Shape parent){ | |||
super(escherRecord, parent); | |||
} | |||
public Rectangle(Shape parent){ | |||
super(null, parent); | |||
_escherContainer = create(parent instanceof ShapeGroup); | |||
} | |||
public Rectangle(){ | |||
this(null); | |||
} | |||
protected EscherContainerRecord create(boolean isChild){ | |||
EscherContainerRecord spcont = super.create(isChild); | |||
spcont.setOptions((short)15); | |||
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID); | |||
short type = (ShapeTypes.Rectangle << 4) + 2; | |||
spRecord.setOptions(type); | |||
//set default properties for a rectangle | |||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID); | |||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__SHAPEPATH, 4)); | |||
opt.sortProperties(); | |||
return spcont; | |||
} | |||
} |
@@ -0,0 +1,172 @@ | |||
/* ==================================================================== | |||
Copyright 2002-2004 Apache Software Foundation | |||
Licensed 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 org.apache.poi.ddf.*; | |||
import org.apache.poi.hslf.model.ShapeTypes; | |||
import java.awt.*; | |||
import java.util.Iterator; | |||
/** | |||
* Represents a Shape which is the elemental object that composes a drawing. | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public class Shape { | |||
public static final int EMU_PER_POINT = 12700; | |||
/** | |||
* The parent of the shape | |||
*/ | |||
protected Shape _parent; | |||
/** | |||
* Either EscherSpContainer or EscheSpgrContainer record | |||
* which holds information about this shape. | |||
*/ | |||
protected EscherContainerRecord _escherContainer; | |||
protected Shape(EscherContainerRecord escherRecord, Shape parent){ | |||
_escherContainer = escherRecord; | |||
_parent = parent; | |||
} | |||
/** | |||
* @return the parent of this shape | |||
*/ | |||
public Shape getParent(){ | |||
return _parent; | |||
} | |||
/** | |||
* @return name of the shape. | |||
*/ | |||
public String getShapeName(){ | |||
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); | |||
return ShapeTypes.typeName(spRecord.getOptions() >> 4); | |||
} | |||
/** | |||
* Returns the anchor (the bounding box rectangle) of this shape. | |||
* All coordinates are expressed in Master units (576 dpi). | |||
* | |||
* @return the anchor of this shape | |||
*/ | |||
public java.awt.Rectangle getAnchor(){ | |||
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); | |||
int flags = spRecord.getFlags(); | |||
java.awt.Rectangle anchor=null; | |||
if ((flags & EscherSpRecord.FLAG_CHILD) != 0){ | |||
EscherChildAnchorRecord rec = (EscherChildAnchorRecord)getEscherChild(_escherContainer, EscherChildAnchorRecord.RECORD_ID); | |||
anchor = new java.awt.Rectangle(); | |||
anchor.x = rec.getDx1(); | |||
anchor.y = rec.getDy1(); | |||
anchor.width = rec.getDx2() - anchor.x; | |||
anchor.height = rec.getDy2() - anchor.y; | |||
} | |||
else { | |||
EscherClientAnchorRecord rec = (EscherClientAnchorRecord)getEscherChild(_escherContainer, EscherClientAnchorRecord.RECORD_ID); | |||
anchor = new java.awt.Rectangle(); | |||
anchor.y = rec.getFlag(); | |||
anchor.x = rec.getCol1(); | |||
anchor.width = rec.getDx1() - anchor.x; | |||
anchor.height = rec.getRow1() - anchor.y; | |||
} | |||
return anchor; | |||
} | |||
/** | |||
* Sets the anchor (the bounding box rectangle) of this shape. | |||
* All coordinates should be expressed in Master units (576 dpi). | |||
* | |||
* @param anchor new anchor | |||
*/ | |||
public void setAnchor(java.awt.Rectangle anchor){ | |||
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); | |||
int flags = spRecord.getFlags(); | |||
if ((flags & EscherSpRecord.FLAG_CHILD) != 0){ | |||
EscherChildAnchorRecord rec = (EscherChildAnchorRecord)getEscherChild(_escherContainer, EscherChildAnchorRecord.RECORD_ID); | |||
rec.setDx1(anchor.x); | |||
rec.setDy1(anchor.y); | |||
rec.setDx2(anchor.width + anchor.x); | |||
rec.setDy2(anchor.height + anchor.y); | |||
} | |||
else { | |||
EscherClientAnchorRecord rec = (EscherClientAnchorRecord)getEscherChild(_escherContainer, EscherClientAnchorRecord.RECORD_ID); | |||
rec.setFlag((short)anchor.y); | |||
rec.setCol1((short)anchor.x); | |||
rec.setDx1((short)(anchor.width + anchor.x)); | |||
rec.setRow1((short)(anchor.height + anchor.y)); | |||
} | |||
} | |||
/** | |||
* Moves the top left corner of the shape to the specified point. | |||
* | |||
* @param x the x coordinate of the top left corner of the shape | |||
* @param y the y coordinate of the top left corner of the shape | |||
*/ | |||
public void moveTo(int x, int y){ | |||
java.awt.Rectangle anchor = getAnchor(); | |||
anchor.setLocation(x, y); | |||
setAnchor(anchor); | |||
} | |||
protected static EscherRecord getEscherChild(EscherContainerRecord owner, int recordId){ | |||
for ( Iterator iterator = owner.getChildRecords().iterator(); iterator.hasNext(); ) | |||
{ | |||
EscherRecord escherRecord = (EscherRecord) iterator.next(); | |||
if (escherRecord.getRecordId() == recordId) | |||
return (EscherRecord) escherRecord; | |||
} | |||
return null; | |||
} | |||
protected static EscherProperty getEscherProperty(EscherOptRecord opt, int propId){ | |||
for ( Iterator iterator = opt.getEscherProperties().iterator(); iterator.hasNext(); ) | |||
{ | |||
EscherProperty prop = (EscherProperty) iterator.next(); | |||
if (prop.getId() == propId) | |||
return prop; | |||
} | |||
return null; | |||
} | |||
protected static void setEscherProperty(EscherOptRecord opt, short propId, int value){ | |||
java.util.List props = opt.getEscherProperties(); | |||
for ( Iterator iterator = props.iterator(); iterator.hasNext(); ) { | |||
EscherProperty prop = (EscherProperty) iterator.next(); | |||
if (prop.getId() == propId){ | |||
iterator.remove(); | |||
} | |||
} | |||
if (value != -1) { | |||
opt.addEscherProperty(new EscherSimpleProperty(propId, value)); | |||
opt.sortProperties(); | |||
} | |||
} | |||
/** | |||
* | |||
* @return escher container which holds information about this shape | |||
*/ | |||
public EscherContainerRecord getShapeRecord(){ | |||
return _escherContainer; | |||
} | |||
} |
@@ -0,0 +1,61 @@ | |||
/* ==================================================================== | |||
Copyright 2002-2004 Apache Software Foundation | |||
Licensed 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 org.apache.poi.ddf.EscherSpRecord; | |||
import org.apache.poi.ddf.EscherContainerRecord; | |||
/** | |||
* Create a <code>Shape</code> object depending on its type | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public class ShapeFactory { | |||
public static Shape createShape(EscherContainerRecord spContainer, Shape parent){ | |||
if (spContainer.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){ | |||
return new ShapeGroup(spContainer, parent); | |||
} | |||
Shape shape; | |||
EscherSpRecord spRecord = spContainer.getChildById(EscherSpRecord.RECORD_ID); | |||
int type = spRecord.getOptions() >> 4; | |||
switch (type){ | |||
case ShapeTypes.TextBox: | |||
case ShapeTypes.Rectangle: | |||
shape = new Shape(spContainer, parent); | |||
break; | |||
case ShapeTypes.PictureFrame: | |||
shape = new Shape(spContainer, parent); | |||
break; | |||
case ShapeTypes.Line: | |||
shape = new Line(spContainer, parent); | |||
break; | |||
case ShapeTypes.Ellipse: | |||
shape = new Ellipse(spContainer, parent); | |||
break; | |||
case ShapeTypes.NotPrimitive: | |||
shape = new ShapeGroup(spContainer, parent); | |||
break; | |||
default: | |||
shape = new Shape(spContainer, parent); | |||
break; | |||
} | |||
return shape; | |||
} | |||
} |
@@ -0,0 +1,151 @@ | |||
/* ==================================================================== | |||
Copyright 2002-2004 Apache Software Foundation | |||
Licensed 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 org.apache.poi.ddf.*; | |||
import org.apache.poi.util.LittleEndian; | |||
import java.util.List; | |||
/** | |||
* Represents a group of shapes. | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public class ShapeGroup extends Shape{ | |||
public ShapeGroup(Shape parent){ | |||
super(null, parent); | |||
_escherContainer = create(); | |||
} | |||
public ShapeGroup(){ | |||
this(null); | |||
} | |||
protected ShapeGroup(EscherContainerRecord escherRecord, Shape parent){ | |||
super(escherRecord, parent); | |||
} | |||
/** | |||
* @return the shapes contained in this group container | |||
*/ | |||
public Shape[] getShapes() { | |||
//several SpContainers, the first of which is the group shape itself | |||
List lst = _escherContainer.getChildRecords(); | |||
//don't include the first SpContainer, it is always NotPrimitive | |||
Shape[] shapes = new Shape[lst.size() - 1]; | |||
for (int i = 1; i < lst.size(); i++){ | |||
EscherContainerRecord container = (EscherContainerRecord)lst.get(i); | |||
shapes[i-1] = ShapeFactory.createShape(container, this); | |||
} | |||
return shapes; | |||
} | |||
/** | |||
* Sets the anchor (the bounding box rectangle) of this shape. | |||
* All coordinates should be expressed in Master units (576 dpi). | |||
* | |||
* @param anchor new anchor | |||
*/ | |||
public void setAnchor(java.awt.Rectangle anchor){ | |||
EscherContainerRecord spContainer = (EscherContainerRecord)_escherContainer.getChildRecords().get(0); | |||
EscherClientAnchorRecord clientAnchor = (EscherClientAnchorRecord)getEscherChild(spContainer, EscherClientAnchorRecord.RECORD_ID); | |||
//hack. internal variable EscherClientAnchorRecord.shortRecord can be | |||
//initialized only in fillFields(). We need to set shortRecord=false; | |||
byte[] header = new byte[16]; | |||
LittleEndian.putUShort(header, 0, 0); | |||
LittleEndian.putUShort(header, 2, 0); | |||
LittleEndian.putInt(header, 4, 8); | |||
clientAnchor.fillFields(header, 0, null); | |||
clientAnchor.setFlag((short)anchor.y); | |||
clientAnchor.setCol1((short)anchor.x); | |||
clientAnchor.setDx1((short)(anchor.width + anchor.x)); | |||
clientAnchor.setRow1((short)(anchor.height + anchor.y)); | |||
EscherSpgrRecord spgr = (EscherSpgrRecord)getEscherChild(spContainer, EscherSpgrRecord.RECORD_ID); | |||
spgr.setRectX1(anchor.x); | |||
spgr.setRectY1(anchor.y); | |||
spgr.setRectX2(anchor.x + anchor.width); | |||
spgr.setRectY2(anchor.y + anchor.height); | |||
} | |||
/** | |||
* Create a new ShapeGroup and create an instance of <code>EscherSpgrContainer</code> which represents a group of shapes | |||
*/ | |||
protected EscherContainerRecord create() { | |||
EscherContainerRecord spgr = new EscherContainerRecord(); | |||
spgr.setRecordId(EscherContainerRecord.SPGR_CONTAINER); | |||
spgr.setOptions((short)15); | |||
//The group itself is a shape, and always appears as the first EscherSpContainer in the group container. | |||
EscherContainerRecord spcont = new EscherContainerRecord(); | |||
spcont.setRecordId(EscherContainerRecord.SP_CONTAINER); | |||
spcont.setOptions((short)15); | |||
EscherSpgrRecord spg = new EscherSpgrRecord(); | |||
spg.setOptions((short)1); | |||
spcont.addChildRecord(spg); | |||
EscherSpRecord sp = new EscherSpRecord(); | |||
short type = (ShapeTypes.NotPrimitive << 4) + 2; | |||
sp.setOptions(type); | |||
sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_GROUP); | |||
spcont.addChildRecord(sp); | |||
EscherClientAnchorRecord anchor = new EscherClientAnchorRecord(); | |||
spcont.addChildRecord(anchor); | |||
spgr.addChildRecord(spcont); | |||
return spgr; | |||
} | |||
/** | |||
* Add a shape to this group. | |||
* | |||
* @param shape - the Shape to add | |||
*/ | |||
public void addShape(Shape shape){ | |||
_escherContainer.addChildRecord(shape.getShapeRecord()); | |||
} | |||
/** | |||
* Moves this <code>ShapeGroup</code> to the specified location. | |||
* <p> | |||
* @param x the x coordinate of the top left corner of the shape in new location | |||
* @param y the y coordinate of the top left corner of the shape in new location | |||
*/ | |||
public void moveTo(int x, int y){ | |||
java.awt.Rectangle anchor = getAnchor(); | |||
int dx = x - anchor.x; | |||
int dy = y - anchor.y; | |||
anchor.translate(dx, dy); | |||
setAnchor(anchor); | |||
Shape[] shape = getShapes(); | |||
for (int i = 0; i < shape.length; i++) { | |||
java.awt.Rectangle chanchor = shape[i].getAnchor(); | |||
chanchor.translate(dx, dy); | |||
shape[i].setAnchor(chanchor); | |||
} | |||
} | |||
} |
@@ -0,0 +1,257 @@ | |||
/* ==================================================================== | |||
Copyright 2002-2004 Apache Software Foundation | |||
Licensed 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.util.HashMap; | |||
import java.lang.reflect.Field; | |||
/** | |||
* Contains all known shape types in PowerPoint | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public class ShapeTypes { | |||
public static final int NotPrimitive = 0; | |||
public static final int Rectangle = 1; | |||
public static final int RoundRectangle = 2; | |||
public static final int Ellipse = 3; | |||
public static final int Diamond = 4; | |||
public static final int IsocelesTriangle = 5; | |||
public static final int RightTriangle = 6; | |||
public static final int Parallelogram = 7; | |||
public static final int Trapezoid = 8; | |||
public static final int Hexagon = 9; | |||
public static final int Octagon = 10; | |||
public static final int Plus = 11; | |||
public static final int Star = 12; | |||
public static final int Arrow = 13; | |||
public static final int ThickArrow = 14; | |||
public static final int HomePlate = 15; | |||
public static final int Cube = 16; | |||
public static final int Balloon = 17; | |||
public static final int Seal = 18; | |||
public static final int Arc = 19; | |||
public static final int Line = 20; | |||
public static final int Plaque = 21; | |||
public static final int Can = 22; | |||
public static final int Donut = 23; | |||
public static final int TextSimple = 24; | |||
public static final int TextOctagon = 25; | |||
public static final int TextHexagon = 26; | |||
public static final int TextCurve = 27; | |||
public static final int TextWave = 28; | |||
public static final int TextRing = 29; | |||
public static final int TextOnCurve = 30; | |||
public static final int TextOnRing = 31; | |||
public static final int StraightConnector1 = 32; | |||
public static final int BentConnector2 = 33; | |||
public static final int BentConnector3 = 34; | |||
public static final int BentConnector4 = 35; | |||
public static final int BentConnector5 = 36; | |||
public static final int CurvedConnector2 = 37; | |||
public static final int CurvedConnector3 = 38; | |||
public static final int CurvedConnector4 = 39; | |||
public static final int CurvedConnector5 = 40; | |||
public static final int Callout1 = 41; | |||
public static final int Callout2 = 42; | |||
public static final int Callout3 = 43; | |||
public static final int AccentCallout1 = 44; | |||
public static final int AccentCallout2 = 45; | |||
public static final int AccentCallout3 = 46; | |||
public static final int BorderCallout1 = 47; | |||
public static final int BorderCallout2 = 48; | |||
public static final int BorderCallout3 = 49; | |||
public static final int AccentBorderCallout1 = 50; | |||
public static final int AccentBorderCallout2 = 51; | |||
public static final int AccentBorderCallout3 = 52; | |||
public static final int Ribbon = 53; | |||
public static final int Ribbon2 = 54; | |||
public static final int Chevron = 55; | |||
public static final int Pentagon = 56; | |||
public static final int NoSmoking = 57; | |||
public static final int Seal8 = 58; | |||
public static final int Seal16 = 59; | |||
public static final int Seal32 = 60; | |||
public static final int WedgeRectCallout = 61; | |||
public static final int WedgeRRectCallout = 62; | |||
public static final int WedgeEllipseCallout = 63; | |||
public static final int Wave = 64; | |||
public static final int FoldedCorner = 65; | |||
public static final int LeftArrow = 66; | |||
public static final int DownArrow = 67; | |||
public static final int UpArrow = 68; | |||
public static final int LeftRightArrow = 69; | |||
public static final int UpDownArrow = 70; | |||
public static final int IrregularSeal1 = 71; | |||
public static final int IrregularSeal2 = 72; | |||
public static final int LightningBolt = 73; | |||
public static final int Heart = 74; | |||
public static final int PictureFrame = 75; | |||
public static final int QuadArrow = 76; | |||
public static final int LeftArrowCallout = 77; | |||
public static final int RightArrowCallout = 78; | |||
public static final int UpArrowCallout = 79; | |||
public static final int DownArrowCallout = 80; | |||
public static final int LeftRightArrowCallout = 81; | |||
public static final int UpDownArrowCallout = 82; | |||
public static final int QuadArrowCallout = 83; | |||
public static final int Bevel = 84; | |||
public static final int LeftBracket = 85; | |||
public static final int RightBracket = 86; | |||
public static final int LeftBrace = 87; | |||
public static final int RightBrace = 88; | |||
public static final int LeftUpArrow = 89; | |||
public static final int BentUpArrow = 90; | |||
public static final int BentArrow = 91; | |||
public static final int Seal24 = 92; | |||
public static final int StripedRightArrow = 93; | |||
public static final int NotchedRightArrow = 94; | |||
public static final int BlockArc = 95; | |||
public static final int SmileyFace = 96; | |||
public static final int VerticalScroll = 97; | |||
public static final int HorizontalScroll = 98; | |||
public static final int CircularArrow = 99; | |||
public static final int NotchedCircularArrow = 100; | |||
public static final int UturnArrow = 101; | |||
public static final int CurvedRightArrow = 102; | |||
public static final int CurvedLeftArrow = 103; | |||
public static final int CurvedUpArrow = 104; | |||
public static final int CurvedDownArrow = 105; | |||
public static final int CloudCallout = 106; | |||
public static final int EllipseRibbon = 107; | |||
public static final int EllipseRibbon2 = 108; | |||
public static final int FlowChartProcess = 109; | |||
public static final int FlowChartDecision = 110; | |||
public static final int FlowChartInputOutput = 111; | |||
public static final int FlowChartPredefinedProcess = 112; | |||
public static final int FlowChartInternalStorage = 113; | |||
public static final int FlowChartDocument = 114; | |||
public static final int FlowChartMultidocument = 115; | |||
public static final int FlowChartTerminator = 116; | |||
public static final int FlowChartPreparation = 117; | |||
public static final int FlowChartManualInput = 118; | |||
public static final int FlowChartManualOperation = 119; | |||
public static final int FlowChartConnector = 120; | |||
public static final int FlowChartPunchedCard = 121; | |||
public static final int FlowChartPunchedTape = 122; | |||
public static final int FlowChartSummingJunction = 123; | |||
public static final int FlowChartOr = 124; | |||
public static final int FlowChartCollate = 125; | |||
public static final int FlowChartSort = 126; | |||
public static final int FlowChartExtract = 127; | |||
public static final int FlowChartMerge = 128; | |||
public static final int FlowChartOfflineStorage = 129; | |||
public static final int FlowChartOnlineStorage = 130; | |||
public static final int FlowChartMagneticTape = 131; | |||
public static final int FlowChartMagneticDisk = 132; | |||
public static final int FlowChartMagneticDrum = 133; | |||
public static final int FlowChartDisplay = 134; | |||
public static final int FlowChartDelay = 135; | |||
public static final int TextPlainText = 136; | |||
public static final int TextStop = 137; | |||
public static final int TextTriangle = 138; | |||
public static final int TextTriangleInverted = 139; | |||
public static final int TextChevron = 140; | |||
public static final int TextChevronInverted = 141; | |||
public static final int TextRingInside = 142; | |||
public static final int TextRingOutside = 143; | |||
public static final int TextArchUpCurve = 144; | |||
public static final int TextArchDownCurve = 145; | |||
public static final int TextCircleCurve = 146; | |||
public static final int TextButtonCurve = 147; | |||
public static final int TextArchUpPour = 148; | |||
public static final int TextArchDownPour = 149; | |||
public static final int TextCirclePour = 150; | |||
public static final int TextButtonPour = 151; | |||
public static final int TextCurveUp = 152; | |||
public static final int TextCurveDown = 153; | |||
public static final int TextCascadeUp = 154; | |||
public static final int TextCascadeDown = 155; | |||
public static final int TextWave1 = 156; | |||
public static final int TextWave2 = 157; | |||
public static final int TextWave3 = 158; | |||
public static final int TextWave4 = 159; | |||
public static final int TextInflate = 160; | |||
public static final int TextDeflate = 161; | |||
public static final int TextInflateBottom = 162; | |||
public static final int TextDeflateBottom = 163; | |||
public static final int TextInflateTop = 164; | |||
public static final int TextDeflateTop = 165; | |||
public static final int TextDeflateInflate = 166; | |||
public static final int TextDeflateInflateDeflate = 167; | |||
public static final int TextFadeRight = 168; | |||
public static final int TextFadeLeft = 169; | |||
public static final int TextFadeUp = 170; | |||
public static final int TextFadeDown = 171; | |||
public static final int TextSlantUp = 172; | |||
public static final int TextSlantDown = 173; | |||
public static final int TextCanUp = 174; | |||
public static final int TextCanDown = 175; | |||
public static final int FlowChartAlternateProcess = 176; | |||
public static final int FlowChartOffpageConnector = 177; | |||
public static final int Callout90 = 178; | |||
public static final int AccentCallout90 = 179; | |||
public static final int BorderCallout90 = 180; | |||
public static final int AccentBorderCallout90 = 181; | |||
public static final int LeftRightUpArrow = 182; | |||
public static final int Sun = 183; | |||
public static final int Moon = 184; | |||
public static final int BracketPair = 185; | |||
public static final int BracePair = 186; | |||
public static final int Seal4 = 187; | |||
public static final int DoubleWave = 188; | |||
public static final int ActionButtonBlank = 189; | |||
public static final int ActionButtonHome = 190; | |||
public static final int ActionButtonHelp = 191; | |||
public static final int ActionButtonInformation = 192; | |||
public static final int ActionButtonForwardNext = 193; | |||
public static final int ActionButtonBackPrevious = 194; | |||
public static final int ActionButtonEnd = 195; | |||
public static final int ActionButtonBeginning = 196; | |||
public static final int ActionButtonReturn = 197; | |||
public static final int ActionButtonDocument = 198; | |||
public static final int ActionButtonSound = 199; | |||
public static final int ActionButtonMovie = 200; | |||
public static final int HostControl = 201; | |||
public static final int TextBox = 202; | |||
/** | |||
* Return name of the shape by id | |||
* @param type - the id of the shape, one of the static constants defined in this class | |||
* @return the name of the shape | |||
*/ | |||
public static String typeName(int type) { | |||
String name = (String)types.get(new Integer(type)); | |||
return name; | |||
} | |||
public static HashMap types; | |||
static { | |||
types = new HashMap(); | |||
try { | |||
Field[] f = ShapeTypes.class.getFields(); | |||
for (int i = 0; i < f.length; i++){ | |||
Object val = f[i].get(null); | |||
if (val instanceof Integer) { | |||
types.put(val, f[i].getName()); | |||
} | |||
} | |||
} catch (IllegalAccessException e){ | |||
throw new RuntimeException("Failed to initialize shape types"); | |||
} | |||
} | |||
} |
@@ -19,7 +19,14 @@ | |||
package org.apache.poi.hslf.model; | |||
import org.apache.poi.ddf.EscherContainerRecord; | |||
import org.apache.poi.ddf.EscherDgRecord; | |||
import org.apache.poi.ddf.EscherRecord; | |||
import org.apache.poi.hslf.record.*; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Vector; | |||
/** | |||
@@ -40,6 +47,11 @@ public abstract class Sheet | |||
* Returns the sheet number | |||
*/ | |||
public abstract int getSheetNumber(); | |||
/** | |||
* Fetch the PPDrawing from the underlying record | |||
*/ | |||
protected abstract PPDrawing getPPDrawing(); | |||
/** | |||
* For a given PPDrawing, grab all the TextRuns | |||
@@ -106,4 +118,49 @@ public abstract class Sheet | |||
} | |||
} | |||
/** | |||
* Returns all shapes contained in this Sheet | |||
* | |||
* @return all shapes contained in this Sheet (Slide or Notes) | |||
*/ | |||
public Shape[] getShapes() { | |||
PPDrawing ppdrawing = getPPDrawing(); | |||
EscherContainerRecord dg = (EscherContainerRecord)ppdrawing.getEscherRecords()[0]; | |||
EscherContainerRecord spgr = null; | |||
List ch = dg.getChildRecords(); | |||
for (Iterator it = ch.iterator(); it.hasNext();) { | |||
EscherRecord rec = (EscherRecord)it.next(); | |||
if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){ | |||
spgr = (EscherContainerRecord)rec; | |||
break; | |||
} | |||
} | |||
ch = spgr.getChildRecords(); | |||
ArrayList shapes = new ArrayList(); | |||
for (int i=1;i<ch.size();i++) { | |||
EscherContainerRecord sp = (EscherContainerRecord)ch.get(i); | |||
shapes.add(ShapeFactory.createShape(sp, null)); | |||
} | |||
return (Shape[])shapes.toArray(new Shape[shapes.size()]); | |||
} | |||
/** | |||
* Add a new Shape to this Slide | |||
* | |||
* @param shape - the Shape to add | |||
*/ | |||
public void addShape(Shape shape){ | |||
PPDrawing ppdrawing = getPPDrawing(); | |||
EscherContainerRecord dgContainer = (EscherContainerRecord)ppdrawing.getEscherRecords()[0]; | |||
EscherContainerRecord spgr = (EscherContainerRecord)Shape.getEscherChild(dgContainer, EscherContainerRecord.SPGR_CONTAINER); | |||
spgr.addChildRecord(shape.getShapeRecord()); | |||
EscherDgRecord dg = (EscherDgRecord)Shape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID); | |||
dg.setNumShapes(dg.getNumShapes()+1); | |||
} | |||
} |
@@ -0,0 +1,147 @@ | |||
/* ==================================================================== | |||
Copyright 2002-2004 Apache Software Foundation | |||
Licensed 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 org.apache.poi.ddf.*; | |||
import org.apache.poi.util.LittleEndian; | |||
import java.awt.*; | |||
/** | |||
* An abstract simple (non-group) shape. | |||
* This is the parent class for all primitive shapes like Line, Rectangle, etc. | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public class SimpleShape extends Shape { | |||
protected SimpleShape(EscherContainerRecord escherRecord, Shape parent){ | |||
super(escherRecord, parent); | |||
} | |||
/** | |||
* Create a new Shape | |||
* | |||
* @param isChild <code>true</code> if the Line is inside a group, <code>false</code> otherwise | |||
* @return the record container which holds this shape | |||
*/ | |||
protected EscherContainerRecord create(boolean isChild) { | |||
EscherContainerRecord spContainer = new EscherContainerRecord(); | |||
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); | |||
//spContainer.setOptions((short)15); | |||
EscherSpRecord sp = new EscherSpRecord(); | |||
int flags = EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE; | |||
if (isChild) flags |= EscherSpRecord.FLAG_CHILD; | |||
sp.setFlags(flags); | |||
spContainer.addChildRecord(sp); | |||
EscherOptRecord opt = new EscherOptRecord(); | |||
opt.setRecordId(EscherOptRecord.RECORD_ID); | |||
spContainer.addChildRecord(opt); | |||
EscherRecord anchor; | |||
if(isChild) anchor = new EscherChildAnchorRecord(); | |||
else { | |||
anchor = new EscherClientAnchorRecord(); | |||
//hack. internal variable EscherClientAnchorRecord.shortRecord can be | |||
//initialized only in fillFields(). We need to set shortRecord=false; | |||
byte[] header = new byte[16]; | |||
LittleEndian.putUShort(header, 0, 0); | |||
LittleEndian.putUShort(header, 2, 0); | |||
LittleEndian.putInt(header, 4, 8); | |||
anchor.fillFields(header, 0, null); | |||
} | |||
spContainer.addChildRecord(anchor); | |||
return spContainer; | |||
} | |||
/** | |||
* Returns width of the line in in points | |||
*/ | |||
public double getLineWidth(){ | |||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); | |||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH); | |||
return prop == null ? 0 : (double)prop.getPropertyValue()/EMU_PER_POINT; | |||
} | |||
/** | |||
* Sets the width of line in in points | |||
* @param width the width of line in in points | |||
*/ | |||
public void setLineWidth(double width){ | |||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); | |||
setEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH, (int)(width*EMU_PER_POINT)); | |||
} | |||
/** | |||
* Sets the color of line | |||
* | |||
* @param color new color of the line | |||
*/ | |||
public void setLineColor(Color color){ | |||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); | |||
int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB(); | |||
setEscherProperty(opt, EscherProperties.LINESTYLE__COLOR, rgb); | |||
} | |||
/** | |||
* @return color of the line | |||
*/ | |||
public Color getLineColor(){ | |||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); | |||
EscherRGBProperty prop = (EscherRGBProperty)getEscherProperty(opt, EscherProperties.LINESTYLE__COLOR); | |||
Color color = null; | |||
if (prop != null){ | |||
Color swp = new Color(prop.getRgbColor()); | |||
color = new Color(swp.getBlue(), swp.getGreen(), swp.getRed()); | |||
} | |||
return color; | |||
} | |||
/** | |||
* Sets line style. One of the constants defined in this class. | |||
* | |||
* @param style new style of the line. | |||
*/ | |||
public void setLineStyle(int style){ | |||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); | |||
setEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING, style == Line.LineSolid ? -1 : style); | |||
} | |||
/** | |||
* Returns line style. One of the constants defined in this class. | |||
* | |||
* @return style of the line. | |||
*/ | |||
public int getLineStyle(){ | |||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); | |||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING); | |||
return prop == null ? Line.LineSolid : prop.getPropertyValue(); | |||
} | |||
public void setFillColor(Color color){ | |||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); | |||
int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB(); | |||
setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, rgb); | |||
setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 1376273); | |||
} | |||
} |
@@ -86,7 +86,13 @@ public class Slide extends Sheet | |||
_runs[i] = _otherRuns[k]; | |||
} | |||
} | |||
/** | |||
* Create a new Slide instance | |||
*/ | |||
public Slide(){ | |||
_slide = new org.apache.poi.hslf.record.Slide(); | |||
} | |||
/** | |||
* Sets the Notes that are associated with this. Updates the | |||
@@ -129,4 +135,6 @@ public class Slide extends Sheet | |||
* Returns the Notes Sheet for this slide, or null if there isn't one | |||
*/ | |||
public Notes getNotesSheet() { return _notes; } | |||
protected PPDrawing getPPDrawing() { return _slide.getPPDrawing(); } | |||
} |
@@ -118,6 +118,27 @@ public class ColorSchemeAtom extends RecordAtom | |||
accentAndHyperlinkColourRGB = (int)LittleEndian.getInt(source,start+8+24); | |||
accentAndFollowingHyperlinkColourRGB = (int)LittleEndian.getInt(source,start+8+28); | |||
} | |||
/** | |||
* Create a new ColorSchemeAtom, to go with a new Slide | |||
*/ | |||
public ColorSchemeAtom(){ | |||
_header = new byte[8]; | |||
LittleEndian.putUShort(_header, 0, 16); | |||
LittleEndian.putUShort(_header, 2, (int)_type); | |||
LittleEndian.putInt(_header, 4, 32); | |||
// Setup the default rgb values | |||
backgroundColourRGB = 16777215; | |||
textAndLinesColourRGB = 0; | |||
shadowsColourRGB = 8421504; | |||
titleTextColourRGB = 0; | |||
fillsColourRGB = 10079232; | |||
accentColourRGB = 13382451; | |||
accentAndHyperlinkColourRGB = 16764108; | |||
accentAndFollowingHyperlinkColourRGB = 11711154; | |||
} | |||
/** | |||
* We are of type 3999 |
@@ -81,8 +81,8 @@ public class FontCollection extends RecordContainer { | |||
fnt.setFontName(name); | |||
fonts.add(name); | |||
// append new child to the end | |||
_children = appendChildRecord(fnt,_children); | |||
// Append new child to the end | |||
appendChildRecord(fnt); | |||
return fonts.size()-1; //the added font is the last in the list | |||
} |
@@ -21,6 +21,7 @@ package org.apache.poi.hslf.record; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.ddf.*; | |||
import org.apache.poi.hslf.model.ShapeTypes; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
@@ -97,6 +98,20 @@ public class PPDrawing extends RecordAtom | |||
textboxWrappers[i] = (EscherTextboxWrapper)textboxes.get(i); | |||
} | |||
} | |||
/** | |||
* Creates a new, empty, PPDrawing (typically for use with a new Slide | |||
* or Notes) | |||
*/ | |||
public PPDrawing(){ | |||
_header = new byte[8]; | |||
LittleEndian.putUShort(_header, 0, 15); | |||
LittleEndian.putUShort(_header, 2, (int)RecordTypes.PPDrawing.typeID); | |||
LittleEndian.putInt(_header, 4, 0); | |||
textboxWrappers = new EscherTextboxWrapper[]{}; | |||
create(); | |||
} | |||
/** | |||
* Tree walking way of finding Escher Child Records | |||
@@ -188,4 +203,63 @@ public class PPDrawing extends RecordAtom | |||
// Finally, write out the children | |||
out.write(b); | |||
} | |||
/** | |||
* Create the Escher records associated with a new PPDrawing | |||
*/ | |||
private void create(){ | |||
EscherContainerRecord dgContainer = new EscherContainerRecord(); | |||
dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER ); | |||
dgContainer.setOptions((short)15); | |||
EscherDgRecord dg = new EscherDgRecord(); | |||
dg.setOptions((short)16); | |||
dg.setNumShapes(1); | |||
dgContainer.addChildRecord(dg); | |||
EscherContainerRecord spgrContainer = new EscherContainerRecord(); | |||
spgrContainer.setOptions((short)15); | |||
spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); | |||
EscherContainerRecord spContainer = new EscherContainerRecord(); | |||
spContainer.setOptions((short)15); | |||
spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); | |||
EscherSpgrRecord spgr = new EscherSpgrRecord(); | |||
spgr.setOptions((short)1); | |||
spContainer.addChildRecord(spgr); | |||
EscherSpRecord sp = new EscherSpRecord(); | |||
sp.setOptions((short)((ShapeTypes.NotPrimitive << 4) + 2)); | |||
sp.setFlags(EscherSpRecord.FLAG_PATRIARCH | EscherSpRecord.FLAG_GROUP); | |||
spContainer.addChildRecord(sp); | |||
spgrContainer.addChildRecord(spContainer); | |||
dgContainer.addChildRecord(spgrContainer); | |||
spContainer = new EscherContainerRecord(); | |||
spContainer.setOptions((short)15); | |||
spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); | |||
sp = new EscherSpRecord(); | |||
sp.setOptions((short)((ShapeTypes.Rectangle << 4) + 2)); | |||
sp.setFlags(EscherSpRecord.FLAG_BACKGROUND | EscherSpRecord.FLAG_HASSHAPETYPE); | |||
spContainer.addChildRecord(sp); | |||
EscherOptRecord opt = new EscherOptRecord(); | |||
opt.setRecordId(EscherOptRecord.RECORD_ID); | |||
opt.addEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, 134217728)); | |||
opt.addEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLBACKCOLOR, 134217733)); | |||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__RECTRIGHT, 10064750)); | |||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__RECTBOTTOM, 7778750)); | |||
opt.addEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 1179666)); | |||
opt.addEscherProperty(new EscherBoolProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 524288)); | |||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.SHAPE__BLACKANDWHITESETTINGS, 9)); | |||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.SHAPE__BACKGROUNDSHAPE, 65537)); | |||
spContainer.addChildRecord(opt); | |||
dgContainer.addChildRecord(spContainer); | |||
childRecords = new EscherRecord[]{ | |||
dgContainer | |||
}; | |||
} | |||
} |
@@ -77,6 +77,13 @@ public class PersistPtrHolder extends PositionDependentRecordAtom | |||
public Hashtable getSlideLocationsLookup() { | |||
return _slideLocations; | |||
} | |||
/** | |||
* Get the lookup from slide numbers to their offsets inside | |||
* _ptrData, used when adding or moving slides. | |||
*/ | |||
public Hashtable getSlideOffsetDataLocationsLookup() { | |||
return _slideOffsetDataLocation; | |||
} | |||
/** | |||
* Adds a new slide, notes or similar, to be looked up by this. | |||
@@ -104,6 +111,10 @@ public class PersistPtrHolder extends PositionDependentRecordAtom | |||
// Update the atom header | |||
LittleEndian.putInt(_header,4,newPtrData.length); | |||
// Update info (first 4 bytes in ptr data) | |||
int info = (slideID << 20 | 1); | |||
LittleEndian.putInt(_ptrData, 0, info); | |||
} | |||
/** |
@@ -48,17 +48,12 @@ public abstract class RecordContainer extends Record | |||
public boolean isAnAtom() { return false; } | |||
/** | |||
* Add a new child record onto a record's list of children, and | |||
* return the new list. | |||
* Add a new child record onto a record's list of children. | |||
*/ | |||
public Record[] appendChildRecord(Record newChild, Record[] children) { | |||
Record[] r; | |||
public void appendChildRecord(Record newChild) { | |||
synchronized(addingChildRecordLock) { | |||
r = new Record[children.length + 1]; | |||
System.arraycopy(children,0,r,0,children.length); | |||
r[r.length-1] = newChild; | |||
addChildAt(newChild, _children.length); | |||
} | |||
return r; | |||
} | |||
/** |
@@ -18,10 +18,10 @@ | |||
package org.apache.poi.hslf.record; | |||
import org.apache.poi.util.LittleEndian; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import org.apache.poi.util.LittleEndian; | |||
/** | |||
* Master container for Slides. There is one of these for every slide, | |||
@@ -73,6 +73,27 @@ public class Slide extends PositionDependentRecordContainer | |||
} | |||
} | |||
/** | |||
* Create a new, empty, Slide, along with its required | |||
* child records. | |||
*/ | |||
public Slide(){ | |||
_header = new byte[8]; | |||
LittleEndian.putUShort(_header, 0, 15); | |||
LittleEndian.putUShort(_header, 2, (int)_type); | |||
LittleEndian.putInt(_header, 4, 0); | |||
slideAtom = new SlideAtom(); | |||
ppDrawing = new PPDrawing(); | |||
ColorSchemeAtom colorAtom = new ColorSchemeAtom(); | |||
_children = new Record[] { | |||
slideAtom, | |||
ppDrawing, | |||
colorAtom | |||
}; | |||
} | |||
/** | |||
* We are of type 1006 |
@@ -111,6 +111,27 @@ public class SlideAtom extends RecordAtom | |||
reserved = new byte[len-30]; | |||
System.arraycopy(source,start+30,reserved,0,reserved.length); | |||
} | |||
/** | |||
* Create a new SlideAtom, to go with a new Slide | |||
*/ | |||
public SlideAtom(){ | |||
_header = new byte[8]; | |||
LittleEndian.putUShort(_header, 0, 2); | |||
LittleEndian.putUShort(_header, 2, (int)_type); | |||
LittleEndian.putInt(_header, 4, 24); | |||
byte[] ssdate = new byte[12]; | |||
layoutAtom = new SSlideLayoutAtom(ssdate); | |||
layoutAtom.setGeometryType(SSlideLayoutAtom.BLANK_SLIDE); | |||
followMasterObjects = true; | |||
followMasterScheme = true; | |||
followMasterBackground = true; | |||
masterID = -2147483648; | |||
notesID = 0; | |||
reserved = new byte[2]; | |||
} | |||
/** | |||
* We are of type 1007 | |||
@@ -180,6 +201,8 @@ public class SlideAtom extends RecordAtom | |||
/** Retrieve the geometry type */ | |||
public int getGeometryType() { return geometry; } | |||
/** Set the geometry type */ | |||
public void setGeometryType(int geom) { geometry = geom; } | |||
/** | |||
* Create a new Embeded SSlideLayoutAtom, from 12 bytes of data |
@@ -97,6 +97,17 @@ public class SlideListWithText extends RecordContainer | |||
} | |||
} | |||
/** | |||
* Create a new, empty, SlideListWithText | |||
*/ | |||
public SlideListWithText(){ | |||
_header = new byte[8]; | |||
LittleEndian.putUShort(_header, 0, 15); | |||
LittleEndian.putUShort(_header, 2, (int)_type); | |||
LittleEndian.putInt(_header, 4, 0); | |||
_children = new Record[0]; | |||
} | |||
/** | |||
* Get access to the SlideAtomsSets of the children of this record |
@@ -48,6 +48,14 @@ public class SlidePersistAtom extends RecordAtom | |||
public int getSlideIdentifier() { return slideIdentifier; } | |||
public int getNumPlaceholderTexts() { return numPlaceholderTexts; } | |||
public boolean getHasShapesOtherThanPlaceholders() { return hasShapesOtherThanPlaceholders; } | |||
// Only set these if you know what you're doing! | |||
public void setRefID(int id) { | |||
refID = id; | |||
} | |||
public void setSlideIdentifier(int id) { | |||
slideIdentifier = id; | |||
} | |||
/* *************** record code follows ********************** */ | |||
@@ -84,6 +92,19 @@ public class SlidePersistAtom extends RecordAtom | |||
reservedFields = new byte[len-24]; | |||
System.arraycopy(source,start+24,reservedFields,0,reservedFields.length); | |||
} | |||
/** | |||
* Create a new SlidePersistAtom, for use with a new Slide | |||
*/ | |||
public SlidePersistAtom(){ | |||
_header = new byte[8]; | |||
LittleEndian.putUShort(_header, 0, 0); | |||
LittleEndian.putUShort(_header, 2, (int)_type); | |||
LittleEndian.putInt(_header, 4, 20); | |||
hasShapesOtherThanPlaceholders = true; | |||
reservedFields = new byte[4]; | |||
} | |||
/** | |||
* We are of type 1011 |
@@ -66,6 +66,7 @@ public class UserEditAtom extends PositionDependentRecordAtom | |||
// More scary internal setters | |||
public void setLastUserEditAtomOffset(int offset) { lastUserEditAtomOffset = offset; } | |||
public void setPersistPointersOffset(int offset) { persistPointersOffset = offset; } | |||
public void setLastViewType(short type) { lastViewType=type; } | |||
/* *************** record code follows ********************** */ | |||
@@ -34,6 +34,8 @@ import org.apache.poi.hslf.record.RecordContainer; | |||
import org.apache.poi.hslf.record.RecordTypes; | |||
import org.apache.poi.hslf.record.SlideAtom; | |||
import org.apache.poi.hslf.record.SlideListWithText; | |||
import org.apache.poi.hslf.record.SlidePersistAtom; | |||
import org.apache.poi.hslf.record.UserEditAtom; | |||
import org.apache.poi.hslf.record.SlideListWithText.*; | |||
import org.apache.poi.hslf.record.PersistPtrHolder; | |||
import org.apache.poi.hslf.record.PositionDependentRecord; | |||
@@ -378,74 +380,94 @@ public class SlideShow | |||
* @throws IOException | |||
*/ | |||
public Slide createSlide() throws IOException { | |||
// RecordContainer slist=null; | |||
// Record[] rec = doc.getChildRecords(); | |||
// int num = 0; | |||
// for (int i = 0; i < rec.length; i++) { | |||
// Record record = rec[i]; | |||
// if (record.getRecordType() == RecordTypes.SlideListWithText.typeID){ | |||
// if (num > 0){ | |||
// slist = (RecordContainer)record; | |||
// } | |||
// num++; | |||
// } | |||
// } | |||
// if (num == 1){ | |||
// slist = new SlideListWithText(); | |||
// rec = doc.getChildRecords(); | |||
// for (int i = 0; i < rec.length-1; i++) { | |||
// Record record = rec[i+1]; | |||
// if (record.getRecordType() == RecordTypes.EndDocument.typeID){ | |||
// | |||
// doc.addChildAfter(slist, rec[i]); | |||
// } | |||
// } | |||
// } | |||
// rec = slist.getChildRecords(); | |||
// | |||
// //add SlidePersistAtom | |||
// SlidePersistAtom prev = rec.length == 0 ? null : (SlidePersistAtom)rec[rec.length - 1]; | |||
// SlidePersistAtom sp = new SlidePersistAtom(); | |||
// | |||
// //refernce is the 1-based index of the slide container in the document root. | |||
// //it always starts with 3 (1 is Document, 2 is MainMaster, 3 is the first slide) | |||
// sp.setRefID(prev == null ? 3 : (prev.getRefID() + 1)); | |||
// //first slideId is always 256 | |||
// sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1)); | |||
// | |||
// Record[] r = slist.appendChildRecord(sp, | |||
// slist.getChildRecords() == null ? new Record[]{} : slist.getChildRecords()); | |||
// slist.setChildRecords(r); | |||
// Slide slide = new Slide(); | |||
// | |||
// int offset = 0; | |||
// List lst = new ArrayList(); | |||
// for (int i = 0; i < _records.length; i++) { | |||
// Record record = _records[i]; | |||
// lst.add(record); | |||
// ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
// record.writeOut(out); | |||
// | |||
// if (_records[i].getRecordType() == RecordTypes.PersistPtrIncrementalBlock.typeID){ | |||
// lst.add(i, slide.getSlideRecord()); | |||
// | |||
// slide.getSlideRecord().setLastOnDiskOffset(offset); | |||
// PersistPtrHolder ptr = (PersistPtrHolder)_records[i]; | |||
// int id = sp.getRefID(); | |||
// ptr.getSlideDataLocationsLookup().put(new Integer(id), new Integer((i+1)*4)); | |||
// ptr.getSlideLocationsLookup().put(new Integer(id), new Integer(offset)); | |||
// ptr.addSlideLookup(id, offset); | |||
// | |||
// } | |||
// offset += out.size() ; | |||
// } | |||
// _records = (Record[])lst.toArray(new Record[lst.size()]); | |||
// _hslfSlideShow.setRecords(_records); | |||
// | |||
// UserEditAtom usr = (UserEditAtom)_records[_records.length-1]; | |||
// usr.setLastViewType((short)UserEditAtom.LAST_VIEW_SLIDE_VIEW); | |||
// return slide; | |||
return null; | |||
SlideListWithText[] slwts = _documentRecord.getSlideListWithTexts(); | |||
SlideListWithText slist = null; | |||
if(slwts.length > 1) { | |||
// Just use the last one | |||
slist = slwts[slwts.length - 1]; | |||
} else { | |||
// Need to add a new one | |||
slist = new SlideListWithText(); | |||
// Goes in just before the EndDocumentRecord | |||
Record[] docChildren = _documentRecord.getChildRecords(); | |||
Record endDoc = docChildren[docChildren.length - 1]; | |||
if(endDoc.getRecordType() != RecordTypes.EndDocument.typeID) { | |||
throw new IllegalStateException("The last child record of a Document should be EndDocument, but it was " + endDoc); | |||
} | |||
_documentRecord.addChildBefore(slist, endDoc); | |||
} | |||
Record[] rec = slist.getChildRecords(); | |||
// Add SlidePersistAtom | |||
SlidePersistAtom prev = rec.length == 0 ? null : (SlidePersistAtom)rec[rec.length - 1]; | |||
SlidePersistAtom sp = new SlidePersistAtom(); | |||
// Refernce is the 1-based index of the slide container in | |||
// the document root. | |||
// It always starts with 3 (1 is Document, 2 is MainMaster, 3 is | |||
// the first slide) | |||
sp.setRefID(prev == null ? 3 : (prev.getRefID() + 1)); | |||
// First slideId is always 256 | |||
sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1)); | |||
slist.appendChildRecord(sp); | |||
// Create a new Slide | |||
Slide slide = new Slide(); | |||
Slide[] s = new Slide[_slides.length+1]; | |||
System.arraycopy(_slides, 0, s, 0, _slides.length); | |||
s[_slides.length] = slide; | |||
_slides = s; | |||
System.out.println("Added slide " + _slides.length + " with ref " + sp.getRefID() + " and identifier " + sp.getSlideIdentifier()); | |||
// Add in to the core records | |||
org.apache.poi.hslf.record.Slide slideRecord = slide.getSlideRecord(); | |||
int slideRecordPos = _hslfSlideShow.appendRootLevelRecord(slideRecord); | |||
// Add the new Slide into the PersistPtr stuff | |||
int offset = 0; | |||
int slideOffset = 0; | |||
PersistPtrHolder ptr = null; | |||
UserEditAtom usr = null; | |||
for (int i = 0; i < _records.length; i++) { | |||
Record record = _records[i]; | |||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
record.writeOut(out); | |||
// Grab interesting records as they come past | |||
if(_records[i].getRecordType() == RecordTypes.PersistPtrIncrementalBlock.typeID){ | |||
ptr = (PersistPtrHolder)_records[i]; | |||
} | |||
if(_records[i].getRecordType() == RecordTypes.UserEditAtom.typeID) { | |||
usr = (UserEditAtom)_records[i]; | |||
} | |||
if(i == slideRecordPos) { | |||
slideOffset = offset; | |||
} | |||
offset += out.size(); | |||
} | |||
// Add the new slide into the last PersistPtr | |||
slideRecord.setLastOnDiskOffset(slideOffset); | |||
int id = sp.getRefID(); | |||
ptr.getSlideOffsetDataLocationsLookup().put( | |||
new Integer(id), | |||
new Integer((slideRecordPos+1)*4) | |||
); | |||
ptr.getSlideLocationsLookup().put( | |||
new Integer(id), new Integer(slideOffset)); | |||
ptr.addSlideLookup(id, slideOffset); | |||
System.out.println("New slide ended up at " + slideOffset); | |||
// Last view is now of the slide | |||
usr.setLastViewType((short)UserEditAtom.LAST_VIEW_SLIDE_VIEW); | |||
// All done and added | |||
return slide; | |||
} | |||