Add Yegor's new slide functionality (see bug 38954), with a bit of refactoring

git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@387008 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2006-03-19 17:53:49 +00:00
parent 9cf5b40189
commit a193016805
24 changed files with 1839 additions and 82 deletions

View File

@ -262,6 +262,7 @@ public class HSLFSlideShow
int oldPos = pdr.getLastOnDiskOffset(); int oldPos = pdr.getLastOnDiskOffset();
int newPos = baos.size(); int newPos = baos.size();
pdr.setLastOnDiskOffset(newPos); pdr.setLastOnDiskOffset(newPos);
//System.out.println(i + " " + oldPos + " " + newPos);
oldToNewPositions.put(new Integer(oldPos),new Integer(newPos)); oldToNewPositions.put(new Integer(oldPos),new Integer(newPos));
pdr.updateOtherRecordReferences(oldToNewPositions); pdr.updateOtherRecordReferences(oldToNewPositions);
} }
@ -318,6 +319,31 @@ public class HSLFSlideShow
*/ */
public Record[] getRecords() { return _records; } 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 * Returns an array of the bytes of the file. Only correct after a
* call to open or write - at all other times might be wrong! * call to open or write - at all other times might be wrong!

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -70,4 +70,5 @@ public class Notes extends Sheet
* Returns the sheet number * Returns the sheet number
*/ */
public int getSheetNumber() { return _sheetNo; } public int getSheetNumber() { return _sheetNo; }
}
protected PPDrawing getPPDrawing() { return _notes.getPPDrawing(); }}

View File

@ -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");
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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");
}
}
}

View File

@ -19,7 +19,14 @@
package org.apache.poi.hslf.model; 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 org.apache.poi.hslf.record.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector; import java.util.Vector;
/** /**
@ -41,6 +48,11 @@ public abstract class Sheet
*/ */
public abstract int getSheetNumber(); public abstract int getSheetNumber();
/**
* Fetch the PPDrawing from the underlying record
*/
protected abstract PPDrawing getPPDrawing();
/** /**
* For a given PPDrawing, grab all the TextRuns * 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);
}
} }

View File

@ -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);
}
}

View File

@ -87,6 +87,12 @@ public class Slide extends Sheet
} }
} }
/**
* 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 * 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 * Returns the Notes Sheet for this slide, or null if there isn't one
*/ */
public Notes getNotesSheet() { return _notes; } public Notes getNotesSheet() { return _notes; }
protected PPDrawing getPPDrawing() { return _slide.getPPDrawing(); }
} }

View File

@ -119,6 +119,27 @@ public class ColorSchemeAtom extends RecordAtom
accentAndFollowingHyperlinkColourRGB = (int)LittleEndian.getInt(source,start+8+28); 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 * We are of type 3999
*/ */

View File

@ -81,8 +81,8 @@ public class FontCollection extends RecordContainer {
fnt.setFontName(name); fnt.setFontName(name);
fonts.add(name); fonts.add(name);
// append new child to the end // Append new child to the end
_children = appendChildRecord(fnt,_children); appendChildRecord(fnt);
return fonts.size()-1; //the added font is the last in the list return fonts.size()-1; //the added font is the last in the list
} }

View File

@ -21,6 +21,7 @@ package org.apache.poi.hslf.record;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.ddf.*; import org.apache.poi.ddf.*;
import org.apache.poi.hslf.model.ShapeTypes;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@ -98,6 +99,20 @@ public class PPDrawing extends RecordAtom
} }
} }
/**
* 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 * Tree walking way of finding Escher Child Records
*/ */
@ -188,4 +203,63 @@ public class PPDrawing extends RecordAtom
// Finally, write out the children // Finally, write out the children
out.write(b); 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
};
}
} }

View File

@ -77,6 +77,13 @@ public class PersistPtrHolder extends PositionDependentRecordAtom
public Hashtable getSlideLocationsLookup() { public Hashtable getSlideLocationsLookup() {
return _slideLocations; 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. * 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 // Update the atom header
LittleEndian.putInt(_header,4,newPtrData.length); LittleEndian.putInt(_header,4,newPtrData.length);
// Update info (first 4 bytes in ptr data)
int info = (slideID << 20 | 1);
LittleEndian.putInt(_ptrData, 0, info);
} }
/** /**

View File

@ -48,17 +48,12 @@ public abstract class RecordContainer extends Record
public boolean isAnAtom() { return false; } public boolean isAnAtom() { return false; }
/** /**
* Add a new child record onto a record's list of children, and * Add a new child record onto a record's list of children.
* return the new list.
*/ */
public Record[] appendChildRecord(Record newChild, Record[] children) { public void appendChildRecord(Record newChild) {
Record[] r;
synchronized(addingChildRecordLock) { synchronized(addingChildRecordLock) {
r = new Record[children.length + 1]; addChildAt(newChild, _children.length);
System.arraycopy(children,0,r,0,children.length);
r[r.length-1] = newChild;
} }
return r;
} }
/** /**

View File

@ -18,10 +18,10 @@
package org.apache.poi.hslf.record; package org.apache.poi.hslf.record;
import org.apache.poi.util.LittleEndian;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; 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, * 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 * We are of type 1006

View File

@ -112,6 +112,27 @@ public class SlideAtom extends RecordAtom
System.arraycopy(source,start+30,reserved,0,reserved.length); 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 * We are of type 1007
*/ */
@ -180,6 +201,8 @@ public class SlideAtom extends RecordAtom
/** Retrieve the geometry type */ /** Retrieve the geometry type */
public int getGeometryType() { return geometry; } 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 * Create a new Embeded SSlideLayoutAtom, from 12 bytes of data

View File

@ -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 * Get access to the SlideAtomsSets of the children of this record

View File

@ -49,6 +49,14 @@ public class SlidePersistAtom extends RecordAtom
public int getNumPlaceholderTexts() { return numPlaceholderTexts; } public int getNumPlaceholderTexts() { return numPlaceholderTexts; }
public boolean getHasShapesOtherThanPlaceholders() { return hasShapesOtherThanPlaceholders; } 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 ********************** */ /* *************** record code follows ********************** */
/** /**
@ -85,6 +93,19 @@ public class SlidePersistAtom extends RecordAtom
System.arraycopy(source,start+24,reservedFields,0,reservedFields.length); 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 * We are of type 1011
*/ */

View File

@ -66,6 +66,7 @@ public class UserEditAtom extends PositionDependentRecordAtom
// More scary internal setters // More scary internal setters
public void setLastUserEditAtomOffset(int offset) { lastUserEditAtomOffset = offset; } public void setLastUserEditAtomOffset(int offset) { lastUserEditAtomOffset = offset; }
public void setPersistPointersOffset(int offset) { persistPointersOffset = offset; } public void setPersistPointersOffset(int offset) { persistPointersOffset = offset; }
public void setLastViewType(short type) { lastViewType=type; }
/* *************** record code follows ********************** */ /* *************** record code follows ********************** */

View File

@ -34,6 +34,8 @@ import org.apache.poi.hslf.record.RecordContainer;
import org.apache.poi.hslf.record.RecordTypes; import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.record.SlideAtom; import org.apache.poi.hslf.record.SlideAtom;
import org.apache.poi.hslf.record.SlideListWithText; 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.SlideListWithText.*;
import org.apache.poi.hslf.record.PersistPtrHolder; import org.apache.poi.hslf.record.PersistPtrHolder;
import org.apache.poi.hslf.record.PositionDependentRecord; import org.apache.poi.hslf.record.PositionDependentRecord;
@ -378,74 +380,94 @@ public class SlideShow
* @throws IOException * @throws IOException
*/ */
public Slide createSlide() throws IOException { public Slide createSlide() throws IOException {
// RecordContainer slist=null; SlideListWithText[] slwts = _documentRecord.getSlideListWithTexts();
// Record[] rec = doc.getChildRecords(); SlideListWithText slist = null;
// int num = 0;
// for (int i = 0; i < rec.length; i++) { if(slwts.length > 1) {
// Record record = rec[i]; // Just use the last one
// if (record.getRecordType() == RecordTypes.SlideListWithText.typeID){ slist = slwts[slwts.length - 1];
// if (num > 0){ } else {
// slist = (RecordContainer)record; // Need to add a new one
// } slist = new SlideListWithText();
// num++;
// } // Goes in just before the EndDocumentRecord
// } Record[] docChildren = _documentRecord.getChildRecords();
// if (num == 1){ Record endDoc = docChildren[docChildren.length - 1];
// slist = new SlideListWithText(); if(endDoc.getRecordType() != RecordTypes.EndDocument.typeID) {
// rec = doc.getChildRecords(); throw new IllegalStateException("The last child record of a Document should be EndDocument, but it was " + endDoc);
// for (int i = 0; i < rec.length-1; i++) { }
// Record record = rec[i+1]; _documentRecord.addChildBefore(slist, endDoc);
// if (record.getRecordType() == RecordTypes.EndDocument.typeID){ }
//
// doc.addChildAfter(slist, rec[i]); Record[] rec = slist.getChildRecords();
// }
// } // Add SlidePersistAtom
// } SlidePersistAtom prev = rec.length == 0 ? null : (SlidePersistAtom)rec[rec.length - 1];
// rec = slist.getChildRecords(); SlidePersistAtom sp = new SlidePersistAtom();
//
// //add SlidePersistAtom // Refernce is the 1-based index of the slide container in
// SlidePersistAtom prev = rec.length == 0 ? null : (SlidePersistAtom)rec[rec.length - 1]; // the document root.
// SlidePersistAtom sp = new SlidePersistAtom(); // It always starts with 3 (1 is Document, 2 is MainMaster, 3 is
// // the first slide)
// //refernce is the 1-based index of the slide container in the document root. sp.setRefID(prev == null ? 3 : (prev.getRefID() + 1));
// //it always starts with 3 (1 is Document, 2 is MainMaster, 3 is the first slide) // First slideId is always 256
// sp.setRefID(prev == null ? 3 : (prev.getRefID() + 1)); sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1));
// //first slideId is always 256
// sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1)); slist.appendChildRecord(sp);
//
// Record[] r = slist.appendChildRecord(sp, // Create a new Slide
// slist.getChildRecords() == null ? new Record[]{} : slist.getChildRecords()); Slide slide = new Slide();
// slist.setChildRecords(r); Slide[] s = new Slide[_slides.length+1];
// Slide slide = new Slide(); System.arraycopy(_slides, 0, s, 0, _slides.length);
// s[_slides.length] = slide;
// int offset = 0; _slides = s;
// List lst = new ArrayList(); System.out.println("Added slide " + _slides.length + " with ref " + sp.getRefID() + " and identifier " + sp.getSlideIdentifier());
// for (int i = 0; i < _records.length; i++) {
// Record record = _records[i]; // Add in to the core records
// lst.add(record); org.apache.poi.hslf.record.Slide slideRecord = slide.getSlideRecord();
// ByteArrayOutputStream out = new ByteArrayOutputStream(); int slideRecordPos = _hslfSlideShow.appendRootLevelRecord(slideRecord);
// record.writeOut(out);
// // Add the new Slide into the PersistPtr stuff
// if (_records[i].getRecordType() == RecordTypes.PersistPtrIncrementalBlock.typeID){ int offset = 0;
// lst.add(i, slide.getSlideRecord()); int slideOffset = 0;
// PersistPtrHolder ptr = null;
// slide.getSlideRecord().setLastOnDiskOffset(offset); UserEditAtom usr = null;
// PersistPtrHolder ptr = (PersistPtrHolder)_records[i]; for (int i = 0; i < _records.length; i++) {
// int id = sp.getRefID(); Record record = _records[i];
// ptr.getSlideDataLocationsLookup().put(new Integer(id), new Integer((i+1)*4)); ByteArrayOutputStream out = new ByteArrayOutputStream();
// ptr.getSlideLocationsLookup().put(new Integer(id), new Integer(offset)); record.writeOut(out);
// ptr.addSlideLookup(id, offset);
// // Grab interesting records as they come past
// } if(_records[i].getRecordType() == RecordTypes.PersistPtrIncrementalBlock.typeID){
// offset += out.size() ; ptr = (PersistPtrHolder)_records[i];
// } }
// _records = (Record[])lst.toArray(new Record[lst.size()]); if(_records[i].getRecordType() == RecordTypes.UserEditAtom.typeID) {
// _hslfSlideShow.setRecords(_records); usr = (UserEditAtom)_records[i];
// }
// UserEditAtom usr = (UserEditAtom)_records[_records.length-1];
// usr.setLastViewType((short)UserEditAtom.LAST_VIEW_SLIDE_VIEW); if(i == slideRecordPos) {
// return slide; slideOffset = offset;
return null; }
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;
} }