Updates from Yegor: New shape and picture stuff (see bug 39256)
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@393576 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
9e9dc0e4d9
commit
1bb312f416
65
src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java
Normal file
65
src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java
Normal file
@ -0,0 +1,65 @@
|
||||
/* ====================================================================
|
||||
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 autoshape in a PowerPoint drawing
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class AutoShape extends SimpleShape {
|
||||
|
||||
protected AutoShape(EscherContainerRecord escherRecord, Shape parent){
|
||||
super(escherRecord, parent);
|
||||
}
|
||||
|
||||
public AutoShape(int type, Shape parent){
|
||||
super(null, parent);
|
||||
_escherContainer = createSpContainer(type, parent instanceof ShapeGroup);
|
||||
}
|
||||
|
||||
public AutoShape(int type){
|
||||
this(type, null);
|
||||
}
|
||||
|
||||
protected EscherContainerRecord createSpContainer(int shapeType, boolean isChild){
|
||||
EscherContainerRecord spcont = super.createSpContainer(isChild);
|
||||
|
||||
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
|
||||
short type = (short)((shapeType << 4) | 0x2);
|
||||
spRecord.setOptions(type);
|
||||
|
||||
//set default properties for a line
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);
|
||||
|
||||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__FILLCOLOR, 134217732));
|
||||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__FILLBACKCOLOR, 134217728));
|
||||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__NOFILLHITTEST, 1048592));
|
||||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__COLOR, 134217729));
|
||||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 524296));
|
||||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.SHADOWSTYLE__COLOR, 134217730));
|
||||
|
||||
opt.sortProperties();
|
||||
|
||||
return spcont;
|
||||
}
|
||||
|
||||
}
|
@ -107,13 +107,12 @@ public class Line extends SimpleShape {
|
||||
EscherContainerRecord spcont = super.createSpContainer(isChild);
|
||||
|
||||
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
|
||||
short type = (ShapeTypes.Line << 4) + 2;
|
||||
short type = (ShapeTypes.Line << 4) | 0x2;
|
||||
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;
|
||||
|
@ -139,6 +139,34 @@ public class PPGraphics2D extends Graphics2D {
|
||||
}
|
||||
|
||||
public void drawString(String string, float x, float y){
|
||||
|
||||
TextBox txt = new TextBox(group);
|
||||
txt.setMarginBottom(0);
|
||||
txt.setMarginTop(0);
|
||||
txt.setMarginLeft(0);
|
||||
txt.setMarginRight(0);
|
||||
txt.setText(string);
|
||||
txt.setWordWrap(TextBox.WrapNone);
|
||||
|
||||
if (font != null){
|
||||
txt.setFontSize(font.getSize());
|
||||
txt.setFontName(font.getName());
|
||||
//if(getColor() != null) txt.setFontColor(getColor());
|
||||
if (font.isBold()) txt.setBold(true);
|
||||
if (font.isItalic()) txt.setItalic(true);
|
||||
}
|
||||
|
||||
txt.resizeToFitText();
|
||||
int height = (int)txt.getAnchor().getHeight();
|
||||
|
||||
/*
|
||||
In powerpoint anchor of a shape is its top left corner.
|
||||
Java graphics sets string coordinates by the baseline of the first character
|
||||
so we need to shift down by the height of the textbox
|
||||
*/
|
||||
txt.moveTo((int)x, (int)(y - height));
|
||||
|
||||
group.addShape(txt);
|
||||
}
|
||||
|
||||
public void fill(Shape shape){
|
||||
@ -212,7 +240,7 @@ public class PPGraphics2D extends Graphics2D {
|
||||
}
|
||||
|
||||
public void drawOval(int x, int y, int width, int height) {
|
||||
Ellipse ellipse = new Ellipse();
|
||||
AutoShape ellipse = new AutoShape(ShapeTypes.Ellipse);
|
||||
ellipse.setAnchor(new java.awt.Rectangle(x-width/2, y-height/2, width, height));
|
||||
if (stroke instanceof BasicStroke){
|
||||
BasicStroke bs = (BasicStroke)stroke;
|
||||
|
@ -3,11 +3,14 @@ package org.apache.poi.hslf.model;
|
||||
import org.apache.poi.ddf.*;
|
||||
import org.apache.poi.hslf.usermodel.PictureData;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.hslf.record.Document;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
@ -122,16 +125,49 @@ public class Picture extends SimpleShape {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default size of the picture
|
||||
*
|
||||
* @param ppt presentation which holds the picture
|
||||
* Resize this picture to the default size.
|
||||
*/
|
||||
public void setDefaultSize(SlideShow ppt) throws IOException {
|
||||
int idx = getPictureIndex();
|
||||
|
||||
PictureData pict = ppt.getPictures()[idx-1];
|
||||
BufferedImage img = ImageIO.read(new ByteArrayInputStream(pict.getData()));
|
||||
|
||||
setAnchor(new java.awt.Rectangle(0, 0, img.getWidth()*6, img.getHeight()*6));
|
||||
public void setDefaultSize(){
|
||||
PictureData pict = getPictureData();
|
||||
try {
|
||||
BufferedImage img = ImageIO.read(new ByteArrayInputStream(pict.getData()));
|
||||
setAnchor(new java.awt.Rectangle(0, 0, img.getWidth(), img.getHeight()));
|
||||
} catch (IOException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the picture data for this picture.
|
||||
*
|
||||
* @return the picture data for this picture.
|
||||
*/
|
||||
public PictureData getPictureData(){
|
||||
SlideShow ppt = getSheet().getSlideShow();
|
||||
PictureData[] pict = ppt.getPictureData();
|
||||
Document doc = ppt.getDocumentRecord();
|
||||
EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer();
|
||||
EscherContainerRecord bstore = (EscherContainerRecord)Shape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);
|
||||
|
||||
List lst = bstore.getChildRecords();
|
||||
int idx = getPictureIndex()-1;
|
||||
EscherBSERecord bse = (EscherBSERecord)lst.get(idx);
|
||||
for ( int i = 0; i < pict.length; i++ ) {
|
||||
if (Arrays.equals(bse.getUid(), pict[i].getUID())){
|
||||
return pict[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default set the orininal image size
|
||||
*/
|
||||
protected void afterInsert(Sheet sh){
|
||||
java.awt.Rectangle anchor = getAnchor();
|
||||
if (anchor.equals(new java.awt.Rectangle())){
|
||||
setDefaultSize();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,39 +21,31 @@ import org.apache.poi.ddf.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Represents a line in a PowerPoint drawing
|
||||
* Represents a rectangle shae in a PowerPoint drawing
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class Rectangle extends SimpleShape {
|
||||
public class Rectangle extends TextBox {
|
||||
|
||||
protected Rectangle(EscherContainerRecord escherRecord, Shape parent){
|
||||
super(escherRecord, parent);
|
||||
}
|
||||
|
||||
public Rectangle(Shape parent){
|
||||
super(null, parent);
|
||||
_escherContainer = createSpContainer(parent instanceof ShapeGroup);
|
||||
super(parent);
|
||||
}
|
||||
|
||||
public Rectangle(){
|
||||
this(null);
|
||||
super();
|
||||
}
|
||||
|
||||
protected EscherContainerRecord createSpContainer(boolean isChild){
|
||||
EscherContainerRecord spcont = super.createSpContainer(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;
|
||||
}
|
||||
|
||||
|
@ -22,13 +22,47 @@ import java.awt.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Represents a Shape which is the elemental object that composes a drawing.
|
||||
* This class is a wrapper around EscherSpContainer which holds all information
|
||||
* about a shape in PowerPoint document.
|
||||
* </p>
|
||||
* <p>
|
||||
* When you add a shape, you usually specify the dimensions of the shape and the position
|
||||
* of the upper<EFBFBD>left corner of the bounding box for the shape relative to the upper<EFBFBD>left
|
||||
* corner of the page, worksheet, or slide. Distances in the drawing layer are measured
|
||||
* in points (72 points = 1 inch).
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public abstract class Shape {
|
||||
|
||||
/**
|
||||
* In Escher absolute distances are specified in
|
||||
* English Metric Units (EMUs), occasionally referred to as A units;
|
||||
* there are 360000 EMUs per centimeter, 914400 EMUs per inch, 12700 EMUs per point.
|
||||
*/
|
||||
public static final int EMU_PER_INCH = 914400;
|
||||
public static final int EMU_PER_POINT = 12700;
|
||||
public static final int EMU_PER_CENTIMETER = 360000;
|
||||
|
||||
/**
|
||||
* Master DPI (576 pixels per inch).
|
||||
* Used by the reference coordinate system in PowerPoint.
|
||||
*/
|
||||
public static final int MASTER_DPI = 576;
|
||||
|
||||
/**
|
||||
* Pixels DPI (96 pixels per inch)
|
||||
*/
|
||||
public static final int PIXEL_DPI = 96;
|
||||
|
||||
/**
|
||||
* Points DPI (72 pixels per inch)
|
||||
*/
|
||||
public static final int POINT_DPI = 72;
|
||||
|
||||
/**
|
||||
* Either EscherSpContainer or EscheSpgrContainer record
|
||||
@ -42,6 +76,11 @@ public abstract class Shape {
|
||||
*/
|
||||
protected Shape _parent;
|
||||
|
||||
/**
|
||||
* The <code>Sheet</code> this shape belongs to
|
||||
*/
|
||||
protected Sheet _sheet;
|
||||
|
||||
/**
|
||||
* Create a Shape object. This constructor is used when an existing Shape is read from from a PowerPoint document.
|
||||
*
|
||||
@ -86,25 +125,25 @@ public abstract class Shape {
|
||||
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;
|
||||
anchor.x = rec.getDx1()*POINT_DPI/MASTER_DPI;
|
||||
anchor.y = rec.getDy1()*POINT_DPI/MASTER_DPI;
|
||||
anchor.width = (rec.getDx2() - anchor.x)*POINT_DPI/MASTER_DPI;
|
||||
anchor.height = (rec.getDy2() - anchor.y)*POINT_DPI/MASTER_DPI;
|
||||
}
|
||||
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;
|
||||
anchor.y = rec.getFlag()*POINT_DPI/MASTER_DPI;
|
||||
anchor.x = rec.getCol1()*POINT_DPI/MASTER_DPI;
|
||||
anchor.width = (rec.getDx1() - rec.getCol1())*POINT_DPI/MASTER_DPI;
|
||||
anchor.height = (rec.getRow1() - rec.getFlag())*POINT_DPI/MASTER_DPI;
|
||||
}
|
||||
return anchor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the anchor (the bounding box rectangle) of this shape.
|
||||
* All coordinates should be expressed in Master units (576 dpi).
|
||||
* All coordinates should be expressed in poitns (72 dpi).
|
||||
*
|
||||
* @param anchor new anchor
|
||||
*/
|
||||
@ -113,17 +152,17 @@ public abstract class Shape {
|
||||
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);
|
||||
rec.setDx1(anchor.x*MASTER_DPI/POINT_DPI);
|
||||
rec.setDy1(anchor.y*MASTER_DPI/POINT_DPI);
|
||||
rec.setDx2((anchor.width + anchor.x)*MASTER_DPI/POINT_DPI);
|
||||
rec.setDy2((anchor.height + anchor.y)*MASTER_DPI/POINT_DPI);
|
||||
}
|
||||
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));
|
||||
rec.setFlag((short)(anchor.y*MASTER_DPI/POINT_DPI));
|
||||
rec.setCol1((short)(anchor.x*MASTER_DPI/POINT_DPI));
|
||||
rec.setDx1((short)((anchor.width + anchor.x)*MASTER_DPI/POINT_DPI));
|
||||
rec.setRow1((short)((anchor.height + anchor.y)*MASTER_DPI/POINT_DPI));
|
||||
}
|
||||
|
||||
}
|
||||
@ -171,11 +210,11 @@ public abstract class Shape {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an escher property in the opt record.
|
||||
* Set an escher property for this shape.
|
||||
*
|
||||
* @param opt The opt record to set the properties to.
|
||||
* @param propId The id of the property. One of the constants defined in EscherOptRecord.
|
||||
* @param value value of the property
|
||||
* @param value value of the property. If value = -1 then the property is removed.
|
||||
*/
|
||||
public static void setEscherProperty(EscherOptRecord opt, short propId, int value){
|
||||
java.util.List props = opt.getEscherProperties();
|
||||
@ -198,4 +237,33 @@ public abstract class Shape {
|
||||
public EscherContainerRecord getSpContainer(){
|
||||
return _escherContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event which fires when a shape is inserted in the sheet.
|
||||
* In some cases we need to propagate changes to upper level containers.
|
||||
* <br>
|
||||
* Default implementation does nothing.
|
||||
*
|
||||
* @param sh - owning shape
|
||||
*/
|
||||
protected void afterInsert(Sheet sh){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the <code>SlideShow</code> this shape belongs to
|
||||
*/
|
||||
public Sheet getSheet(){
|
||||
return _sheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign the <code>SlideShow</code> this shape belongs to
|
||||
*
|
||||
* @param sheet owner of this shape
|
||||
*/
|
||||
public void setSheet(Sheet sheet){
|
||||
_sheet = sheet;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,9 @@ import org.apache.poi.ddf.EscherContainerRecord;
|
||||
*/
|
||||
public class ShapeFactory {
|
||||
|
||||
/**
|
||||
* Create a new shape from the data provided.
|
||||
*/
|
||||
public static Shape createShape(EscherContainerRecord spContainer, Shape parent){
|
||||
if (spContainer.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){
|
||||
return new ShapeGroup(spContainer, parent);
|
||||
@ -36,6 +39,8 @@ public class ShapeFactory {
|
||||
int type = spRecord.getOptions() >> 4;
|
||||
switch (type){
|
||||
case ShapeTypes.TextBox:
|
||||
shape = new TextBox(spContainer, parent);
|
||||
break;
|
||||
case ShapeTypes.Rectangle:
|
||||
shape = new Rectangle(spContainer, parent);
|
||||
break;
|
||||
@ -45,14 +50,11 @@ public class ShapeFactory {
|
||||
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 SimpleShape(spContainer, parent);
|
||||
shape = new AutoShape(spContainer, parent);
|
||||
break;
|
||||
}
|
||||
return shape;
|
||||
|
@ -27,11 +27,21 @@ import java.util.List;
|
||||
*/
|
||||
public class ShapeGroup extends Shape{
|
||||
|
||||
/**
|
||||
* Create a new ShapeGroup. This constructor is used when a new shape is created.
|
||||
*
|
||||
*/
|
||||
public ShapeGroup(){
|
||||
this(null, null);
|
||||
_escherContainer = createSpContainer(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ShapeGroup object and initilize it from the supplied Record container.
|
||||
*
|
||||
* @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
|
||||
* @param parent the parent of the shape
|
||||
*/
|
||||
protected ShapeGroup(EscherContainerRecord escherRecord, Shape parent){
|
||||
super(escherRecord, parent);
|
||||
}
|
||||
|
@ -82,9 +82,9 @@ public class ShapeTypes {
|
||||
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 Star8 = 58;
|
||||
public static final int Star16 = 59;
|
||||
public static final int Star32 = 60;
|
||||
public static final int WedgeRectCallout = 61;
|
||||
public static final int WedgeRRectCallout = 62;
|
||||
public static final int WedgeEllipseCallout = 63;
|
||||
@ -116,7 +116,7 @@ public class ShapeTypes {
|
||||
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 Star24 = 92;
|
||||
public static final int StripedRightArrow = 93;
|
||||
public static final int NotchedRightArrow = 94;
|
||||
public static final int BlockArc = 95;
|
||||
@ -211,7 +211,7 @@ public class ShapeTypes {
|
||||
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 Star4 = 187;
|
||||
public static final int DoubleWave = 188;
|
||||
public static final int ActionButtonBlank = 189;
|
||||
public static final int ActionButtonHome = 190;
|
||||
|
@ -23,6 +23,7 @@ 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.usermodel.SlideShow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@ -38,6 +39,11 @@ import java.util.Vector;
|
||||
|
||||
public abstract class Sheet
|
||||
{
|
||||
/**
|
||||
* The <code>SlideShow</code> we belong to
|
||||
*/
|
||||
private SlideShow _slideShow;
|
||||
|
||||
/**
|
||||
* Returns an array of all the TextRuns in the sheet.
|
||||
*/
|
||||
@ -59,7 +65,19 @@ public abstract class Sheet
|
||||
* Fetch the PPDrawing from the underlying record
|
||||
*/
|
||||
protected abstract PPDrawing getPPDrawing();
|
||||
|
||||
|
||||
/**
|
||||
* Fetch the SlideShow we're attached to
|
||||
*/
|
||||
public SlideShow getSlideShow() { return _slideShow; }
|
||||
|
||||
/**
|
||||
* Set the SlideShow we're attached to
|
||||
*/
|
||||
public void setSlideShow(SlideShow ss) { _slideShow = ss; }
|
||||
|
||||
|
||||
/**
|
||||
* For a given PPDrawing, grab all the TextRuns
|
||||
*/
|
||||
@ -149,7 +167,9 @@ public abstract class Sheet
|
||||
ArrayList shapes = new ArrayList();
|
||||
for (int i=1;i<ch.size();i++) {
|
||||
EscherContainerRecord sp = (EscherContainerRecord)ch.get(i);
|
||||
shapes.add(ShapeFactory.createShape(sp, null));
|
||||
Shape sh = ShapeFactory.createShape(sp, null);
|
||||
sh.setSheet(this);
|
||||
shapes.add(sh);
|
||||
}
|
||||
|
||||
return (Shape[])shapes.toArray(new Shape[shapes.size()]);
|
||||
@ -169,5 +189,8 @@ public abstract class Sheet
|
||||
|
||||
EscherDgRecord dg = (EscherDgRecord)Shape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID);
|
||||
dg.setNumShapes(dg.getNumShapes()+1);
|
||||
|
||||
shape.setSheet(this);
|
||||
shape.afterInsert(this);
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,12 @@ import java.awt.*;
|
||||
*/
|
||||
public class SimpleShape extends Shape {
|
||||
|
||||
/**
|
||||
* Create a SimpleShape object and initialize it from the supplied Record container.
|
||||
*
|
||||
* @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
|
||||
* @param parent the parent of the shape
|
||||
*/
|
||||
protected SimpleShape(EscherContainerRecord escherRecord, Shape parent){
|
||||
super(escherRecord, parent);
|
||||
}
|
||||
@ -102,12 +108,12 @@ public class SimpleShape extends Shape {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return color of the line
|
||||
* @return color of the line. If color is not set returns <code>java.awt.Color.black</code>
|
||||
*/
|
||||
public Color getLineColor(){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
EscherRGBProperty prop = (EscherRGBProperty)getEscherProperty(opt, EscherProperties.LINESTYLE__COLOR);
|
||||
Color color = null;
|
||||
Color color = Color.black;
|
||||
if (prop != null){
|
||||
Color swp = new Color(prop.getRgbColor());
|
||||
color = new Color(swp.getBlue(), swp.getGreen(), swp.getRed());
|
||||
@ -136,6 +142,11 @@ public class SimpleShape extends Shape {
|
||||
return prop == null ? Line.LineSolid : prop.getPropertyValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* The color used to fill this shape.
|
||||
*
|
||||
* @param color the background color
|
||||
*/
|
||||
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();
|
||||
|
490
src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java
Normal file
490
src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java
Normal file
@ -0,0 +1,490 @@
|
||||
|
||||
/* ====================================================================
|
||||
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.record.*;
|
||||
import org.apache.poi.hslf.usermodel.RichTextRun;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Represents a TextFrame shape in PowerPoint.
|
||||
* <p>
|
||||
* Contains the text in a text frame as well as the properties and methods
|
||||
* that control alignment and anchoring of the text.
|
||||
* </p>
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TextBox extends SimpleShape {
|
||||
|
||||
/**
|
||||
* How to anchor the text
|
||||
*/
|
||||
public static final int AnchorTop = 0;
|
||||
public static final int AnchorMiddle = 1;
|
||||
public static final int AnchorBottom = 2;
|
||||
public static final int AnchorTopCentered = 3;
|
||||
public static final int AnchorMiddleCentered = 4;
|
||||
public static final int AnchorBottomCentered = 5;
|
||||
public static final int AnchorTopBaseline = 6;
|
||||
public static final int AnchorBottomBaseline = 7;
|
||||
public static final int AnchorTopCenteredBaseline = 8;
|
||||
public static final int AnchorBottomCenteredBaseline = 9;
|
||||
|
||||
/**
|
||||
* How to wrap the text
|
||||
*/
|
||||
public static final int WrapSquare = 0;
|
||||
public static final int WrapByPoints = 1;
|
||||
public static final int WrapNone = 2;
|
||||
public static final int WrapTopBottom = 3;
|
||||
public static final int WrapThrough = 4;
|
||||
|
||||
/**
|
||||
* How to align the text
|
||||
*/
|
||||
public static final int AlignLeft = 0;
|
||||
public static final int AlignCenter = 1;
|
||||
public static final int AlignRight = 2;
|
||||
public static final int AlignJustify = 3;
|
||||
|
||||
/**
|
||||
* Default font size
|
||||
*/
|
||||
public static final int DefaultFontSize = 24;
|
||||
|
||||
/**
|
||||
* Low-level object which holds actual text and format data
|
||||
*/
|
||||
protected TextRun _txtrun;
|
||||
|
||||
/**
|
||||
* Escher container which holds text attributes such as
|
||||
* TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc.
|
||||
*/
|
||||
protected EscherTextboxWrapper _txtbox;
|
||||
|
||||
/**
|
||||
* Create a TextBox object and initialize it from the supplied Record container.
|
||||
*
|
||||
* @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
|
||||
* @param parent the parent of the shape
|
||||
*/
|
||||
protected TextBox(EscherContainerRecord escherRecord, Shape parent){
|
||||
super(escherRecord, parent);
|
||||
|
||||
EscherTextboxRecord textbox = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID);
|
||||
_txtbox = new EscherTextboxWrapper(textbox);
|
||||
|
||||
TextHeaderAtom tha = null;
|
||||
TextBytesAtom tba = null;
|
||||
StyleTextPropAtom sta = null;
|
||||
Record[] child = _txtbox.getChildRecords();
|
||||
for (int i = 0; i < child.length; i++) {
|
||||
if (child[i] instanceof TextHeaderAtom) tha = (TextHeaderAtom)child[i];
|
||||
else if (child[i] instanceof TextBytesAtom) tba = (TextBytesAtom)child[i];
|
||||
else if (child[i] instanceof StyleTextPropAtom) sta = (StyleTextPropAtom)child[i];
|
||||
}
|
||||
|
||||
_txtrun = new TextRun(tha,tba,sta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TextBox. This constructor is used when a new shape is created.
|
||||
*
|
||||
* @param parent the parent of this Shape. For example, if this text box is a cell
|
||||
* in a table then the parent is Table.
|
||||
*/
|
||||
public TextBox(Shape parent){
|
||||
super(null, parent);
|
||||
_escherContainer = createSpContainer(parent instanceof ShapeGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TextBox. This constructor is used when a new shape is created.
|
||||
*
|
||||
*/
|
||||
public TextBox(){
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new textBox and initialize internal structures
|
||||
*
|
||||
* @return the created <code>EscherContainerRecord</code> which holds shape data
|
||||
*/
|
||||
protected EscherContainerRecord createSpContainer(boolean isChild){
|
||||
EscherContainerRecord spcont = super.createSpContainer(isChild);
|
||||
|
||||
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
|
||||
short type = (ShapeTypes.TextBox << 4) | 0x2;
|
||||
spRecord.setOptions(type);
|
||||
|
||||
//set default properties for a textbox
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);
|
||||
setEscherProperty(opt, EscherProperties.TEXT__TEXTID, 0);
|
||||
|
||||
setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, 134217732);
|
||||
setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, 134217728);
|
||||
setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 1048576);
|
||||
setEscherProperty(opt, EscherProperties.LINESTYLE__COLOR, 134217729);
|
||||
setEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH, 524288);
|
||||
setEscherProperty(opt, EscherProperties.SHADOWSTYLE__COLOR, 134217730);
|
||||
|
||||
opt.sortProperties();
|
||||
|
||||
//create EscherTextboxWrapper
|
||||
_txtbox = new EscherTextboxWrapper();
|
||||
|
||||
TextHeaderAtom tha = new TextHeaderAtom();
|
||||
_txtbox.appendChildRecord(tha);
|
||||
|
||||
TextBytesAtom tba = new TextBytesAtom();
|
||||
_txtbox.appendChildRecord(tba);
|
||||
|
||||
StyleTextPropAtom sta = new StyleTextPropAtom(0);
|
||||
_txtbox.appendChildRecord(sta);
|
||||
|
||||
_txtrun = new TextRun(tha,tba,sta);
|
||||
_txtrun.setText("");
|
||||
spcont.addChildRecord(_txtbox.getEscherRecord());
|
||||
|
||||
return spcont;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text contained in this text frame.
|
||||
*
|
||||
* @return the text string for this textbox.
|
||||
*/
|
||||
public String getText(){
|
||||
return _txtrun.getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text contained in this text frame.
|
||||
*
|
||||
* @param text the text string used by this object.
|
||||
*/
|
||||
public void setText(String text){
|
||||
_txtrun.setText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* When a textbox is added to a sheet we need to tell upper-level
|
||||
* <code>PPDrawing</code> about it.
|
||||
*
|
||||
* @param sh the sheet we are adding to
|
||||
*/
|
||||
protected void afterInsert(Sheet sh){
|
||||
PPDrawing ppdrawing = sh.getPPDrawing();
|
||||
ppdrawing.addTextboxWrapper(_txtbox);
|
||||
// Ensure the escher layer knows about the added records
|
||||
try {
|
||||
_txtbox.writeOut(null);
|
||||
} catch (IOException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bounds of this <code>TextFrame</code>.
|
||||
* <code>Note</b>, this is very primitive estimation, the precision is poor.
|
||||
*
|
||||
* @return the bounds of this <code>TextFrame</code>.
|
||||
*/
|
||||
protected Dimension getTextSize(){
|
||||
FontRenderContext frc = new FontRenderContext(null, true, true);
|
||||
RichTextRun rt = _txtrun.getRichTextRuns()[0];
|
||||
int size = rt.getFontSize();
|
||||
if (size == -1) size = TextBox.DefaultFontSize;
|
||||
int style = 0;
|
||||
if (rt.isBold()) style |= Font.BOLD;
|
||||
if (rt.isItalic()) style |= Font.ITALIC;
|
||||
String fntname = rt.getFontName();
|
||||
if (fntname == null) //get the default font from Document.Environment.FontCollection
|
||||
fntname = getSheet().getSlideShow().getDocumentRecord().getEnvironment().getFontCollection().getFontWithId(0);
|
||||
Font font = new Font(fntname, style, size);
|
||||
|
||||
TextLayout layout = new TextLayout(getText(), font, frc);
|
||||
int width = Math.round(layout.getAdvance());
|
||||
width += getMarginLeft() + getMarginRight();
|
||||
int height = Math.round(layout.getAscent());
|
||||
height += getMarginTop() + getMarginBottom();
|
||||
return new Dimension(width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the size of the TextBox so it encompasses the text inside it.
|
||||
*/
|
||||
public void resizeToFitText(){
|
||||
Dimension size = getTextSize();
|
||||
java.awt.Rectangle anchor = getAnchor();
|
||||
anchor.setSize(size);
|
||||
setAnchor(anchor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of vertical alignment for the text.
|
||||
* One of the <code>Anchor*</code> constants defined in this class.
|
||||
*
|
||||
* @return the type of alignment
|
||||
*/
|
||||
public int getVerticalAlignment(){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
|
||||
return prop == null ? AlignCenter : prop.getPropertyValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of vertical alignment for the text.
|
||||
* One of the <code>Anchor*</code> constants defined in this class.
|
||||
*
|
||||
* @param align - the type of alignment
|
||||
*/
|
||||
public void setVerticalAlignment(int align){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
setEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT, align);
|
||||
}
|
||||
/**
|
||||
* Returns the distance (in points) between the bottom of the text frame
|
||||
* and the bottom of the inscribed rectangle of the shape that contains the text.
|
||||
* Default value is 1/20 inch.
|
||||
*
|
||||
* @return the botom margin
|
||||
*/
|
||||
public int getMarginBottom(){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
|
||||
int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
|
||||
return val/EMU_PER_POINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the botom margin.
|
||||
* @see #getMarginBottom()
|
||||
*
|
||||
* @param margin the bottom margin
|
||||
*/
|
||||
public void setMarginBottom(int margin){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
setEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM, margin*EMU_PER_POINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance (in EMUs) between the left edge of the text frame
|
||||
* and the left edge of the inscribed rectangle of the shape that contains
|
||||
* the text.
|
||||
* Default value is 1/10 inch.
|
||||
*
|
||||
* @return the left margin
|
||||
*/
|
||||
public int getMarginLeft(){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
|
||||
int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
|
||||
return val/EMU_PER_POINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the left margin.
|
||||
* @see #getMarginLeft()
|
||||
*
|
||||
* @param margin the left margin
|
||||
*/
|
||||
public void setMarginLeft(int margin){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
setEscherProperty(opt, EscherProperties.TEXT__TEXTLEFT, margin*EMU_PER_POINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance (in EMUs) between the right edge of the
|
||||
* text frame and the right edge of the inscribed rectangle of the shape
|
||||
* that contains the text.
|
||||
* Default value is 1/10 inch.
|
||||
*
|
||||
* @return the right margin
|
||||
*/
|
||||
public int getMarginRight(){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT);
|
||||
int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
|
||||
return val/EMU_PER_POINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the right margin.
|
||||
* @see #getMarginRight()
|
||||
*
|
||||
* @param margin the right margin
|
||||
*/
|
||||
public void setMarginRight(int margin){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
setEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT, margin*EMU_PER_POINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance (in EMUs) between the top of the text frame
|
||||
* and the top of the inscribed rectangle of the shape that contains the text.
|
||||
* Default value is 1/20 inch.
|
||||
*
|
||||
* @return the top margin
|
||||
*/
|
||||
public int getMarginTop(){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP);
|
||||
int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
|
||||
return val/EMU_PER_POINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the top margin.
|
||||
* @see #getMarginTop()
|
||||
*
|
||||
* @param margin the top margin
|
||||
*/
|
||||
public void setMarginTop(int margin){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
setEscherProperty(opt, EscherProperties.TEXT__TEXTTOP, margin*EMU_PER_POINT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value indicating word wrap.
|
||||
* One of the <code>Wrap*</code> constants defined in this class.
|
||||
*
|
||||
* @return the value indicating word wrap
|
||||
*/
|
||||
public int getWordWrap(){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT);
|
||||
return prop == null ? WrapSquare : prop.getPropertyValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies how the text should be wrapped
|
||||
*
|
||||
* @param wrap the value indicating how the text should be wrapped
|
||||
*/
|
||||
public void setWordWrap(int wrap){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
setEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT, wrap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return id for the text.
|
||||
*/
|
||||
public int getTextId(){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTID);
|
||||
return prop == null ? 0 : prop.getPropertyValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets text ID
|
||||
*
|
||||
* @param id of the text
|
||||
*/
|
||||
public void setTextId(int id){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
setEscherProperty(opt, EscherProperties.TEXT__TEXTID, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The color used to fill this shape.
|
||||
*
|
||||
* @param color the background color
|
||||
*/
|
||||
public void setBackgroundColor(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__FILLBACKCOLOR, rgb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array of RichTextRun objects which control text formatting in this text box
|
||||
*/
|
||||
public RichTextRun[] getRichTextRuns(){
|
||||
return _txtrun.getRichTextRuns();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <code>Font</code> object for this text frame
|
||||
*
|
||||
* @param size the size of the font
|
||||
*/
|
||||
public void setFontSize(int size){
|
||||
RichTextRun rt = _txtrun.getRichTextRuns()[0];
|
||||
rt.setFontSize(size);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the size of the font applied to this text shape
|
||||
*/
|
||||
public int getFontSize(){
|
||||
RichTextRun rt = _txtrun.getRichTextRuns()[0];
|
||||
return rt.getFontSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to use bold or not
|
||||
*
|
||||
* @param bold <code>true</code> if the text should be bold, <code>false</code> otherwise
|
||||
*/
|
||||
public void setBold(boolean bold){
|
||||
RichTextRun rt = _txtrun.getRichTextRuns()[0];
|
||||
rt.setBold(bold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to use italic or not
|
||||
*
|
||||
* @param italic <code>true</code> if the text should be italic, <code>false</code> otherwise
|
||||
*/
|
||||
public void setItalic(boolean italic){
|
||||
RichTextRun rt = _txtrun.getRichTextRuns()[0];
|
||||
rt.setItalic(italic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to use underline or not
|
||||
*
|
||||
* @param underline <code>true</code> if the text should be underlined, <code>false</code> otherwise
|
||||
*/
|
||||
public void setUnderline(boolean underline){
|
||||
RichTextRun rt = _txtrun.getRichTextRuns()[0];
|
||||
rt.setUnderlined(underline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the font of this text shape
|
||||
*
|
||||
* @param name the name of the font to be applied to this text shape
|
||||
*/
|
||||
public void setFontName(String name){
|
||||
RichTextRun rt = _txtrun.getRichTextRuns()[0];
|
||||
rt.setFontName(name);
|
||||
}
|
||||
|
||||
}
|
@ -47,7 +47,7 @@ public class EscherTextboxWrapper extends RecordContainer
|
||||
/**
|
||||
* Creates the wrapper for the given DDF Escher Record and children
|
||||
*/
|
||||
protected EscherTextboxWrapper(EscherTextboxRecord textbox) {
|
||||
public EscherTextboxWrapper(EscherTextboxRecord textbox) {
|
||||
_escherRecord = textbox;
|
||||
_type = (long)_escherRecord.getRecordId();
|
||||
|
||||
@ -55,7 +55,18 @@ public class EscherTextboxWrapper extends RecordContainer
|
||||
byte[] data = _escherRecord.getData();
|
||||
_children = Record.findChildRecords(data,0,data.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new, empty wrapper for DDF Escher Records and their children
|
||||
*/
|
||||
public EscherTextboxWrapper() {
|
||||
_escherRecord = new EscherTextboxRecord();
|
||||
_escherRecord.setRecordId(EscherTextboxRecord.RECORD_ID);
|
||||
_escherRecord.setOptions((short)15);
|
||||
|
||||
_children = new Record[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the type of the escher record (normally in the 0xFnnn range)
|
||||
|
@ -262,4 +262,15 @@ public class PPDrawing extends RecordAtom
|
||||
dgContainer
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new EscherTextboxWrapper to this <code>PPDrawing</code>.
|
||||
*/
|
||||
public void addTextboxWrapper(EscherTextboxWrapper txtbox){
|
||||
EscherTextboxWrapper[] tw = new EscherTextboxWrapper[textboxWrappers.length + 1];
|
||||
System.arraycopy(textboxWrappers, 0, tw, 0, textboxWrappers.length);
|
||||
|
||||
tw[textboxWrappers.length] = txtbox;
|
||||
textboxWrappers = tw;
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,18 @@ public class TextBytesAtom extends RecordAtom
|
||||
_text = new byte[len-8];
|
||||
System.arraycopy(source,start+8,_text,0,len-8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty TextBytes Atom
|
||||
*/
|
||||
public TextBytesAtom() {
|
||||
_header = new byte[8];
|
||||
LittleEndian.putUShort(_header, 0, 0);
|
||||
LittleEndian.putUShort(_header, 2, (int)_type);
|
||||
LittleEndian.putInt(_header, 4, 0);
|
||||
|
||||
_text = new byte[]{};
|
||||
}
|
||||
|
||||
/**
|
||||
* We are of type 4008
|
||||
|
@ -75,6 +75,18 @@ public class TextHeaderAtom extends RecordAtom implements ParentAwareRecord
|
||||
// Grab the type
|
||||
textType = (int)LittleEndian.getInt(source,start+8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TextHeader Atom, for an unknown type of text
|
||||
*/
|
||||
public TextHeaderAtom() {
|
||||
_header = new byte[8];
|
||||
LittleEndian.putUShort(_header, 0, 0);
|
||||
LittleEndian.putUShort(_header, 2, (int)_type);
|
||||
LittleEndian.putInt(_header, 4, 4);
|
||||
|
||||
textType = OTHER_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* We are of type 3999
|
||||
|
@ -25,6 +25,7 @@ import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* A class that represents the image data contained in the Presentation.
|
||||
*
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
@ -35,6 +36,9 @@ public class PictureData {
|
||||
*/
|
||||
public static final int HEADER_SIZE = 25;
|
||||
|
||||
protected static final int JPEG_HEADER = -266516832;
|
||||
protected static final int PNG_HEADER = -266441216;
|
||||
|
||||
/**
|
||||
* Binary data of the picture
|
||||
*/
|
||||
@ -118,11 +122,27 @@ public class PictureData {
|
||||
*/
|
||||
public void setType(int format){
|
||||
switch (format){
|
||||
case Picture.JPEG: LittleEndian.putInt(header, 0, -266516832); break;
|
||||
case Picture.PNG: LittleEndian.putInt(header, 0, -266441216); break;
|
||||
case Picture.JPEG: LittleEndian.putInt(header, 0, PictureData.JPEG_HEADER); break;
|
||||
case Picture.PNG: LittleEndian.putInt(header, 0, PictureData.PNG_HEADER); break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns type of this picture.
|
||||
* Must be one of the static constans defined in the <code>Picture<code> class.
|
||||
*
|
||||
* @return type of this picture.
|
||||
*/
|
||||
public int getType(){
|
||||
int format = 0;
|
||||
int val = LittleEndian.getInt(header, 0);
|
||||
switch (val){
|
||||
case PictureData.JPEG_HEADER: format = Picture.JPEG; break;
|
||||
case PictureData.PNG_HEADER: format = Picture.PNG; break;
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the header of the Picture
|
||||
*
|
||||
|
@ -401,6 +401,7 @@ public class SlideShow
|
||||
_notes = new Notes[notesV.size()];
|
||||
for(int i=0; i<_notes.length; i++) {
|
||||
_notes[i] = (Notes)notesV.get(i);
|
||||
_notes[i].setSlideShow(this);
|
||||
|
||||
// Now supply ourselves to all the rich text runs
|
||||
// of this note's TextRuns
|
||||
@ -418,6 +419,7 @@ public class SlideShow
|
||||
_slides = new Slide[slidesV.size()];
|
||||
for(int i=0; i<_slides.length; i++) {
|
||||
_slides[i] = (Slide)slidesV.get(i);
|
||||
_slides[i].setSlideShow(this);
|
||||
|
||||
// Now supply ourselves to all the rich text runs
|
||||
// of this slide's TextRuns
|
||||
@ -472,9 +474,9 @@ public class SlideShow
|
||||
//public MetaSheet[] getMetaSheets() { return _msheets; }
|
||||
|
||||
/**
|
||||
* Returns all the pictures attached to the SlideShow
|
||||
* Returns the data of all the pictures attached to the SlideShow
|
||||
*/
|
||||
public PictureData[] getPictures() throws IOException {
|
||||
public PictureData[] getPictureData() {
|
||||
return _hslfSlideShow.getPictures();
|
||||
}
|
||||
|
||||
@ -483,7 +485,20 @@ public class SlideShow
|
||||
*/
|
||||
public Dimension getPageSize(){
|
||||
DocumentAtom docatom = _documentRecord.getDocumentAtom();
|
||||
return new Dimension((int)docatom.getSlideSizeX(), (int)docatom.getSlideSizeY());
|
||||
int pgx = (int)docatom.getSlideSizeX()*Shape.POINT_DPI/Shape.MASTER_DPI;
|
||||
int pgy = (int)docatom.getSlideSizeY()*Shape.POINT_DPI/Shape.MASTER_DPI;
|
||||
return new Dimension(pgx, pgy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the current page size
|
||||
*
|
||||
* @param pgsize page size (in points)
|
||||
*/
|
||||
public void setPageSize(Dimension pgsize){
|
||||
DocumentAtom docatom = _documentRecord.getDocumentAtom();
|
||||
docatom.setSlideSizeX(pgsize.width*Shape.MASTER_DPI/Shape.POINT_DPI);
|
||||
docatom.setSlideSizeY(pgsize.height*Shape.MASTER_DPI/Shape.POINT_DPI);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -491,9 +506,9 @@ public class SlideShow
|
||||
*/
|
||||
protected FontCollection getFontCollection() { return _fonts; }
|
||||
/**
|
||||
* Helper method for usermodel: Get the document record
|
||||
* Helper method for usermodel and model: Get the document record
|
||||
*/
|
||||
protected Document getDocumentRecord() { return _documentRecord; }
|
||||
public Document getDocumentRecord() { return _documentRecord; }
|
||||
|
||||
|
||||
/* ===============================================================
|
||||
@ -607,6 +622,7 @@ public class SlideShow
|
||||
usr.setLastViewType((short)UserEditAtom.LAST_VIEW_SLIDE_VIEW);
|
||||
|
||||
// All done and added
|
||||
slide.setSlideShow(this);
|
||||
return slide;
|
||||
}
|
||||
|
||||
|
@ -17,12 +17,14 @@ package org.apache.poi.hslf.model;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.hslf.usermodel.RichTextRun;
|
||||
import org.apache.poi.hslf.HSLFSlideShow;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Rectangle;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
/**
|
||||
* Test drawing shapes via Graphics2D
|
||||
@ -36,21 +38,23 @@ public class TestShapes extends TestCase {
|
||||
String dirname = System.getProperty("HSLF.testdata.path");
|
||||
String filename = dirname + "/empty.ppt";
|
||||
ppt = new SlideShow(new HSLFSlideShow(filename));
|
||||
getClass().getResourceAsStream("");
|
||||
}
|
||||
|
||||
public void testGraphics() throws Exception {
|
||||
Slide slide = ppt.createSlide();
|
||||
|
||||
Line line = new Line();
|
||||
line.setAnchor(new Rectangle(1296, 2544, 1344, 528));
|
||||
java.awt.Rectangle lineAnchor = new java.awt.Rectangle(100, 200, 50, 60);
|
||||
line.setAnchor(lineAnchor);
|
||||
System.out.println(line.getAnchor());
|
||||
line.setLineWidth(3);
|
||||
line.setLineStyle(Line.LineDashSys);
|
||||
line.setLineColor(Color.red);
|
||||
slide.addShape(line);
|
||||
|
||||
Ellipse ellipse = new Ellipse();
|
||||
ellipse.setAnchor(new Rectangle(4000, 1000, 1000, 1000));
|
||||
AutoShape ellipse = new AutoShape(ShapeTypes.Ellipse);
|
||||
java.awt.Rectangle ellipseAnchor = new Rectangle(320, 154, 55, 111);
|
||||
ellipse.setAnchor(ellipseAnchor);
|
||||
ellipse.setLineWidth(2);
|
||||
ellipse.setLineStyle(Line.LineSolid);
|
||||
ellipse.setLineColor(Color.green);
|
||||
@ -64,17 +68,103 @@ public class TestShapes extends TestCase {
|
||||
//read ppt from byte array
|
||||
|
||||
ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())));
|
||||
assertEquals(ppt.getSlides().length, 1);
|
||||
assertEquals(1, ppt.getSlides().length);
|
||||
|
||||
slide = ppt.getSlides()[0];
|
||||
Shape[] shape = slide.getShapes();
|
||||
assertEquals(shape.length, 2);
|
||||
assertEquals(2, shape.length);
|
||||
|
||||
assertTrue(shape[0] instanceof Line); //group shape
|
||||
assertEquals(shape[0].getAnchor(), new Rectangle(1296, 2544, 1344, 528)); //group shape
|
||||
assertEquals(lineAnchor, shape[0].getAnchor()); //group shape
|
||||
|
||||
assertTrue(shape[1] instanceof Ellipse); //group shape
|
||||
assertEquals(shape[1].getAnchor(), new Rectangle(4000, 1000, 1000, 1000)); //group shape
|
||||
assertTrue(shape[1] instanceof AutoShape); //group shape
|
||||
assertEquals(ellipseAnchor, shape[1].getAnchor()); //group shape
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that we can read TextBox shapes
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testTextBoxRead() throws Exception {
|
||||
String dirname = System.getProperty("HSLF.testdata.path");
|
||||
String filename = dirname + "/with_textbox.ppt";
|
||||
ppt = new SlideShow(new HSLFSlideShow(filename));
|
||||
Slide sl = ppt.getSlides()[0];
|
||||
Shape[] sh = sl.getShapes();
|
||||
for (int i = 0; i < sh.length; i++) {
|
||||
assertTrue(sh[i] instanceof TextBox);
|
||||
TextBox txtbox = (TextBox)sh[i];
|
||||
String text = txtbox.getText();
|
||||
assertNotNull(text);
|
||||
|
||||
assertEquals(txtbox.getRichTextRuns().length, 1);
|
||||
RichTextRun rt = txtbox.getRichTextRuns()[0];
|
||||
|
||||
if (text.equals("Hello, World!!!")){
|
||||
assertEquals(32, rt.getFontSize());
|
||||
assertTrue(rt.isBold());
|
||||
assertTrue(rt.isItalic());
|
||||
} else if (text.equals("I am just a poor boy")){
|
||||
assertEquals(44, rt.getFontSize());
|
||||
assertTrue(rt.isBold());
|
||||
} else if (text.equals("This is Times New Roman")){
|
||||
assertEquals(16, rt.getFontSize());
|
||||
assertTrue(rt.isBold());
|
||||
assertTrue(rt.isItalic());
|
||||
assertTrue(rt.isUnderlined());
|
||||
} else if (text.equals("Plain Text")){
|
||||
assertEquals(18, rt.getFontSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that we can add TextBox shapes to a slide
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testTextBoxWrite() throws Exception {
|
||||
ppt = new SlideShow();
|
||||
Slide sl = ppt.createSlide();
|
||||
|
||||
TextBox txtbox = new TextBox();
|
||||
txtbox.setText("Hello, World!");
|
||||
txtbox.setFontSize(42);
|
||||
txtbox.setBold(true);
|
||||
txtbox.setItalic(true);
|
||||
|
||||
sl.addShape(txtbox);
|
||||
|
||||
txtbox = new TextBox();
|
||||
txtbox.setText("Plain text in default font");
|
||||
sl.addShape(txtbox);
|
||||
|
||||
assertEquals(sl.getShapes().length, 2);
|
||||
|
||||
//serialize and read again
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ppt.write(out);
|
||||
out.close();
|
||||
|
||||
ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())));
|
||||
sl = ppt.getSlides()[0];
|
||||
assertEquals(sl.getShapes().length, 2);
|
||||
|
||||
Shape[] sh = sl.getShapes();
|
||||
for (int i = 0; i < sh.length; i++) {
|
||||
assertTrue(sh[i] instanceof TextBox);
|
||||
txtbox = (TextBox)sh[i];
|
||||
String text = txtbox.getText();
|
||||
assertNotNull(text);
|
||||
|
||||
assertEquals(txtbox.getRichTextRuns().length, 1);
|
||||
RichTextRun rt = txtbox.getRichTextRuns()[0];
|
||||
|
||||
if (text.equals("Hello, World!")){
|
||||
assertEquals(42, rt.getFontSize());
|
||||
assertTrue(rt.isBold());
|
||||
assertTrue(rt.isItalic());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -50,10 +50,37 @@ public class TestPictures extends TestCase{
|
||||
|
||||
BufferedImage img = ImageIO.read(new ByteArrayInputStream(data));
|
||||
assertNotNull(img);
|
||||
assertEquals(Picture.PNG, pict[i].getType());
|
||||
}
|
||||
ppt.close();
|
||||
}
|
||||
|
||||
public void testReadPicturesForSlide() throws Exception {
|
||||
|
||||
SlideShow ppt = new SlideShow(new HSLFSlideShow(filename));
|
||||
|
||||
Slide[] slide = ppt.getSlides();
|
||||
for (int i = 0; i < slide.length; i++) {
|
||||
Slide sl = slide[i];
|
||||
Shape[] sh = sl.getShapes();
|
||||
for (int j = 0; j < sh.length; j++) {
|
||||
Shape shape = sh[j];
|
||||
if (shape instanceof Picture){
|
||||
Picture picture = (Picture)shape;
|
||||
|
||||
PictureData pictdata = picture.getPictureData();
|
||||
assertEquals(Picture.PNG, pictdata.getType());
|
||||
|
||||
//raw data.
|
||||
byte[] data = pictdata.getData();
|
||||
BufferedImage img = ImageIO.read(new ByteArrayInputStream(data));
|
||||
assertNotNull(img);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void testSerializePictures() throws Exception {
|
||||
HSLFSlideShow ppt = new HSLFSlideShow(filename);
|
||||
PictureData[] pict = ppt.getPictures();
|
||||
@ -78,12 +105,10 @@ public class TestPictures extends TestCase{
|
||||
idx = ppt.addPicture(new File(dirname + "/clock.jpg"), Picture.JPEG);
|
||||
slide = ppt.createSlide();
|
||||
pict = new Picture(idx);
|
||||
pict.setDefaultSize(ppt);
|
||||
slide.addShape(pict);
|
||||
|
||||
idx = ppt.addPicture(new File(dirname + "/painting.png"), Picture.PNG);
|
||||
pict = new Picture(idx);
|
||||
pict.setDefaultSize(ppt);
|
||||
slide.addShape(pict);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
@ -91,7 +116,7 @@ public class TestPictures extends TestCase{
|
||||
out.close();
|
||||
|
||||
ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())));
|
||||
assertTrue(ppt.getPictures().length == 2 );
|
||||
assertTrue(ppt.getPictureData().length == 2 );
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user