Browse Source

Fixes from Yegor, from bug #39395

git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@405092 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_0_ALPHA3
Nick Burch 18 years ago
parent
commit
ca8b649bfe

+ 24
- 1
src/documentation/content/xdocs/hslf/how-to-shapes.xml View File

@@ -18,6 +18,7 @@
<li><link href="#GetShapes">How to get shapes contained in a particular slide</link></li>
<li><link href="#Shapes">Drawing a shape on a slide</link></li>
<li><link href="#Pictures">How to add/retrieve pictures</link></li>
<li><link href="#SlideTitle">How to set slide title</link></li>
</ul>
</section>
<section><title>Features</title>
@@ -62,7 +63,7 @@
The following pictute shows the class tree of HSLF shapes:
</p>
<p>
<img src="hslf_shapes.gif" alt="Class Tree of HSLF Shapes" width="611" height="285"/>
<img src="hslf_shapes.gif" alt="Class Tree of HSLF Shapes" width="611" height="412"/>
</p>
<p>
The following fragment demonstrates how to iterate over shapes for each slide.
@@ -209,6 +210,28 @@
</source>
</section>
<anchor id="SlideTitle"/>
<section><title>How to set slide title</title>
<source>
SlideShow ppt = new SlideShow();
Slide slide = ppt.createSlide();
TextBox title = slide.addTitle();
title.setText("Hello, World!");
//save changes
FileOutputStream out = new FileOutputStream("slideshow.ppt");
wb.write(out);
out.close();
</source>
<p>
Below is the equivalent code in PowerPoint VBA:
</p>
<source>
Set myDocument = ActivePresentation.Slides(1)
myDocument.Shapes.AddTitle.TextFrame.TextRange.Text = "Hello, World!"
</source>
</section>
</section>
</section>
</body>

BIN
src/documentation/content/xdocs/hslf/hslf_shapes.gif View File


+ 0
- 59
src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java View File

@@ -1,59 +0,0 @@
/* ====================================================================
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 = createSpContainer(parent instanceof ShapeGroup);
}
public Ellipse(){
this(null);
}
protected EscherContainerRecord createSpContainer(boolean isChild){
EscherContainerRecord spcont = super.createSpContainer(isChild);
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;
}
}

+ 1
- 1
src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java View File

@@ -151,7 +151,7 @@ public class PPGraphics2D extends Graphics2D {
if (font != null){
txt.setFontSize(font.getSize());
txt.setFontName(font.getName());
//if(getColor() != null) txt.setFontColor(getColor());
if(getColor() != null) txt.setFontColor(getColor());
if (font.isBold()) txt.setBold(true);
if (font.isItalic()) txt.setItalic(true);
}

+ 97
- 0
src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java View File

@@ -0,0 +1,97 @@
/* ====================================================================
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.OEPlaceholderAtom;
import java.util.List;
import java.io.ByteArrayOutputStream;
/**
* Represents a Placeholder in PowerPoint.
*
* @author Yegor Kozlov
*/
public class Placeholder extends TextBox {
protected Placeholder(EscherContainerRecord escherRecord, Shape parent){
super(escherRecord, parent);
}
public Placeholder(Shape parent){
super(parent);
}
public Placeholder(){
super();
}
/**
* Create a new Placeholder 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);
spRecord.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER);
EscherClientDataRecord cldata = new EscherClientDataRecord();
cldata.setOptions((short)15);
EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);
//Placeholders can't be grouped
setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 262144);
//OEPlaceholderAtom tells powerpoint that this shape is a placeholder
//
OEPlaceholderAtom oep = new OEPlaceholderAtom();
/**
* Extarct from MSDN:
*
* There is a special case when the placeholder does not have a position in the layout.
* This occurs when the user has moved the placeholder from its original position.
* In this case the placeholder ID is -1.
*/
oep.setPlacementId(-1);
oep.setPlaceholderId(OEPlaceholderAtom.Body);
//convert hslf into ddf record
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
oep.writeOut(out);
} catch(Exception e){
throw new RuntimeException(e);
}
cldata.setRemainingData(out.toByteArray());
//append placeholder container before EscherTextboxRecord
List lst = spcont.getChildRecords();
for (int i = 0; i < lst.size(); i++) {
EscherRecord rec = (EscherRecord)lst.get(i);
if(rec.getRecordId() == EscherTextboxRecord.RECORD_ID){
lst.add(i++, cldata);
}
}
return spcont;
}
}

+ 0
- 52
src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java View File

@@ -1,52 +0,0 @@
/* ====================================================================
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 rectangle shae in a PowerPoint drawing
*
* @author Yegor Kozlov
*/
public class Rectangle extends TextBox {
protected Rectangle(EscherContainerRecord escherRecord, Shape parent){
super(escherRecord, parent);
}
public Rectangle(Shape parent){
super(parent);
}
public Rectangle(){
super();
}
protected EscherContainerRecord createSpContainer(boolean isChild){
EscherContainerRecord spcont = super.createSpContainer(isChild);
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
short type = (ShapeTypes.Rectangle << 4) + 2;
spRecord.setOptions(type);
return spcont;
}
}

+ 20
- 2
src/scratchpad/src/org/apache/poi/hslf/model/Shape.java View File

@@ -112,9 +112,27 @@ public abstract class Shape {
return ShapeTypes.typeName(spRecord.getOptions() >> 4);
}
/**
* @return type of the shape.
* @see org.apache.poi.hslf.record.RecordTypes
*/
public int getShapeType(){
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
return spRecord.getOptions() >> 4;
}
/**
* @param type type of the shape.
* @see org.apache.poi.hslf.record.RecordTypes
*/
public void setShapeType(int type){
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
spRecord.setOptions((short)(type << 4 | 0x2));
}
/**
* Returns the anchor (the bounding box rectangle) of this shape.
* All coordinates are expressed in Master units (576 dpi).
* All coordinates are expressed in points (72 dpi).
*
* @return the anchor of this shape
*/
@@ -143,7 +161,7 @@ public abstract class Shape {
/**
* Sets the anchor (the bounding box rectangle) of this shape.
* All coordinates should be expressed in poitns (72 dpi).
* All coordinates should be expressed in points (72 dpi).
*
* @param anchor new anchor
*/

+ 11
- 5
src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java View File

@@ -15,8 +15,7 @@
==================================================================== */
package org.apache.poi.hslf.model;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.*;
/**
* Create a <code>Shape</code> object depending on its type
@@ -38,12 +37,19 @@ public class ShapeFactory {
int type = spRecord.getOptions() >> 4;
switch (type){
case ShapeTypes.Rectangle:
EscherTextboxRecord txtbox = (EscherTextboxRecord)Shape.getEscherChild(spContainer, EscherTextboxRecord.RECORD_ID);
if (txtbox == null) shape = new AutoShape(spContainer, parent);
else{
if(Shape.getEscherChild(spContainer, EscherClientDataRecord.RECORD_ID) != null )
shape = new Placeholder(spContainer, parent);
else
shape = new TextBox(spContainer, parent);
}
break;
case ShapeTypes.TextBox:
shape = new TextBox(spContainer, parent);
break;
case ShapeTypes.Rectangle:
shape = new Rectangle(spContainer, parent);
break;
case ShapeTypes.PictureFrame:
shape = new Picture(spContainer, parent);
break;

+ 26
- 1
src/scratchpad/src/org/apache/poi/hslf/model/Slide.java View File

@@ -23,6 +23,7 @@ import java.util.Vector;

import org.apache.poi.hslf.record.PPDrawing;
import org.apache.poi.hslf.record.SlideAtom;
import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;

/**
@@ -117,6 +118,21 @@ public class Slide extends Sheet
sa.setNotesID(notes._getSheetNumber());
}
}
/**
* Create a <code>TextBox</code> object that represents the slide's title.
*
* @return <code>TextBox</code> object that represents the slide's title.
*/
public TextBox addTitle() {
Placeholder pl = new Placeholder();
pl.setShapeType(ShapeTypes.Rectangle);
pl.setTextType(TextHeaderAtom.TITLE_TYPE);
pl.setText("Click to edit title");
pl.setAnchor(new java.awt.Rectangle(54, 48, 612, 90));
addShape(pl);
return pl;
}


// Accesser methods follow
@@ -133,7 +149,7 @@ public class Slide extends Sheet
public int _getSheetRefId() { return _refSheetNo; }
/**
* Returns the (internal, SlideIdentifier based) sheet number
* @see getSlideNumber()
* @see #getSlideNumber()
*/
public int _getSheetNumber() { return _sheetNo; }
@@ -152,5 +168,14 @@ public class Slide extends Sheet
*/
public Notes getNotesSheet() { return _notes; }
/**
* Returns the PPDrawing associated with this slide, or null if there isn't one
*/
protected PPDrawing getPPDrawing() { return _slide.getPPDrawing(); }
/**
* @return set of records inside <code>SlideListWithtext</code> container
* which hold text data for this slide (typically for placeholders).
*/
protected SlideAtomsSet getSlideAtomsSet() { return _atomSet; }
}

+ 102
- 15
src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java View File

@@ -85,6 +85,8 @@ public class TextBox extends SimpleShape {
*/
protected EscherTextboxWrapper _txtbox;
private String _fontname;
/**
* Create a TextBox object and initialize it from the supplied Record container.
*
@@ -96,17 +98,6 @@ public class TextBox extends SimpleShape {
EscherTextboxRecord textbox = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID);
_txtbox = new EscherTextboxWrapper(textbox);
// Find our TextRun
Vector v = new Vector();
Sheet.findTextRuns(_txtbox.getChildRecords(), v);
// We should just have one
if(v.size() == 1) {
_txtrun = (TextRun)v.get(0);
} else {
throw new IllegalStateException("A TextBox should have one TextRun's worth of records in it, found " + v.size());
}
}
/**
@@ -206,6 +197,7 @@ public class TextBox extends SimpleShape {
} catch (IOException e){
throw new RuntimeException(e);
}
if(getAnchor().equals(new java.awt.Rectangle())) resizeToFitText();
}
/**
@@ -214,7 +206,7 @@ public class TextBox extends SimpleShape {
*
* @return the bounds of this <code>TextFrame</code>.
*/
protected Dimension getTextSize(){
protected Dimension getTextDimensions(){
FontRenderContext frc = new FontRenderContext(null, true, true);
RichTextRun rt = _txtrun.getRichTextRuns()[0];
int size = rt.getFontSize();
@@ -229,9 +221,9 @@ public class TextBox extends SimpleShape {
TextLayout layout = new TextLayout(getText(), font, frc);
int width = Math.round(layout.getAdvance());
width += getMarginLeft() + getMarginRight();
width += getMarginLeft() + getMarginRight() + 2;
int height = Math.round(layout.getAscent());
height += getMarginTop() + getMarginBottom();
height += getMarginTop() + getMarginBottom() + 12;
return new Dimension(width, height);
}
@@ -239,7 +231,7 @@ public class TextBox extends SimpleShape {
* Adjust the size of the TextBox so it encompasses the text inside it.
*/
public void resizeToFitText(){
Dimension size = getTextSize();
Dimension size = getTextDimensions();
java.awt.Rectangle anchor = getAnchor();
anchor.setSize(size);
setAnchor(anchor);
@@ -448,6 +440,17 @@ public class TextBox extends SimpleShape {
return rt.getFontSize();
}
/**
*
* @return the size of the font applied to this text shape
*/
public Color getFontColor(){
RichTextRun rt = _txtrun.getRichTextRuns()[0];
Color color = new Color(rt.getFontColor());
//in PowerPont RGB bytes are swapped,
return new Color(color.getBlue(), color.getGreen(), color.getRed(), 255);
}
/**
* Set whether to use bold or not
*
@@ -484,8 +487,92 @@ public class TextBox extends SimpleShape {
* @param name the name of the font to be applied to this text shape
*/
public void setFontName(String name){
if (_sheet == null) {
//we can't set font since slideshow is not assigned yet
_fontname = name;
} else{
RichTextRun rt = _txtrun.getRichTextRuns()[0];
rt.setFontName(name);
}
}
/**
* Sets the font color
* @param color the font color
*/
public void setFontColor(Color color){
//in PowerPont RGB bytes are swapped,
int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB();
RichTextRun rt = _txtrun.getRichTextRuns()[0];
rt.setFontColor(rgb);
}
/**
* Set type of the text.
* Must be one of the static constants defined in <code>TextHeaderAtom</code>
*
* @param type type of the text
*/
public void setTextType(int type){
_txtrun._headerAtom.setTextType(type);
}
public void setSheet(Sheet sheet){
_sheet = sheet;
//initialize _txtrun object.
//we can't do it in the constructor because the sheet is not assigned yet
if(_txtrun == null) initTextRun();
RichTextRun[] rt = _txtrun.getRichTextRuns();
for (int i = 0; i < rt.length; i++) {
rt[i].supplySlideShow(_sheet.getSlideShow());
}
if (_fontname != null) {
setFontName(_fontname);
_fontname = null;
}
}
private void initTextRun(){
TextHeaderAtom tha = null;
TextCharsAtom tca = null;
TextBytesAtom tba = null;
StyleTextPropAtom sta = null;
OutlineTextRefAtom ota = 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];
else if (child[i] instanceof OutlineTextRefAtom) ota = (OutlineTextRefAtom)child[i];
else if (child[i] instanceof TextCharsAtom) tca = (TextCharsAtom)child[i];
}
if (ota != null){
//TextHeaderAtom, TextBytesAtom and StyleTextPropAtom are stored outside of EscherContainerRecord
int idx = ota.getTextIndex();
Slide sl = (Slide)getSheet();
Record[] rec = sl.getSlideAtomsSet().getSlideRecords();
for (int i = 0, j = 0; i < rec.length; i++) {
if(rec[i].getRecordType() == RecordTypes.TextHeaderAtom.typeID){
if(j++ == idx) { //we found j-th TextHeaderAtom, read the text data
for (int k = i; k < rec.length; k++) {
if (rec[k] instanceof TextHeaderAtom) {
if (tha != null) break;
else tha = (TextHeaderAtom)rec[k];
}
else if (rec[k] instanceof TextBytesAtom) tba = (TextBytesAtom)rec[k];
else if (rec[k] instanceof TextCharsAtom) tca = (TextCharsAtom)rec[k];
else if (rec[k] instanceof StyleTextPropAtom) sta = (StyleTextPropAtom)rec[k];
}
}
}
}
}
if(tba != null) _txtrun = new TextRun(tha,tba,sta);
else if (tca != null) _txtrun = new TextRun(tha,tca,sta);
}
}

+ 200
- 0
src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java View File

@@ -0,0 +1,200 @@
/* ====================================================================
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.record;
import org.apache.poi.util.LittleEndian;
import java.io.IOException;
import java.io.OutputStream;
/**
* OEPlaceholderAtom (3011).
* <p>
* Atom that describes the placeholder.
* </p>
*
* @author Yegor Kozlov
*/
public class OEPlaceholderAtom extends RecordAtom{
public static final int PLACEHOLDER_FULLSIZE = 0;
public static final int PLACEHOLDER_HALFSIZE = 1;
public static final int PLACEHOLDER_QUARTSIZE = 2;
public static final byte None = 0;
public static final byte MasterTitle = 1;
public static final byte MasterBody = 2;
public static final byte MasterCenteredTitle = 3;
public static final byte MasterNotesSlideImage = 4;
public static final byte MasterNotesBodyImage = 5;
public static final byte MasterDate = 6;
public static final byte MasterSlideNumber = 7;
public static final byte MasterFooter = 8;
public static final byte MasterHeader = 9;
public static final byte MasterSubtitle = 10;
public static final byte GenericTextObject = 11;
public static final byte Title = 12;
public static final byte Body = 13;
public static final byte NotesBody = 14;
public static final byte CenteredTitle = 15;
public static final byte Subtitle = 16;
public static final byte VerticalTextTitle = 17;
public static final byte VerticalTextBody = 18;
public static final byte NotesSlideImage = 19;
public static final byte Object = 20;
public static final byte Graph = 21;
public static final byte Table = 22;
public static final byte ClipArt = 23;
public static final byte OrganizationChart = 24;
public static final byte MediaClip = 25;
private byte[] _header;
private int placementId;
private int placeholderId;
private int placeholderSize;
/**
* Create a new instance of <code>OEPlaceholderAtom</code>
*/
public OEPlaceholderAtom(){
_header = new byte[8];
LittleEndian.putUShort(_header, 0, 0);
LittleEndian.putUShort(_header, 2, (int)getRecordType());
LittleEndian.putInt(_header, 4, 8);
placementId = 0;
placeholderId = 0;
placeholderSize = 0;
}
/**
* Build an instance of <code>OEPlaceholderAtom</code> from on-disk data
*/
protected OEPlaceholderAtom(byte[] source, int start, int len) {
_header = new byte[8];
System.arraycopy(source,start,_header,0,8);
placementId = LittleEndian.getInt(source, start);
placeholderId = LittleEndian.getUnsignedByte(source, start+4);
placeholderSize = LittleEndian.getUnsignedByte(source, start+5);
}
/**
* @return type of this record {@link RecordTypes#OEPlaceholderAtom}.
*/
public long getRecordType() { return RecordTypes.OEPlaceholderAtom.typeID; }
/**
* Returns the placement Id.
*
* @return the placement Id.
*/
public int getPlacementId(){
return placementId;
}
/**
* Sets the placement Id.
*
* @param id the placement Id.
*/
public void setPlacementId(int id){
placementId = id;
}
/**
* Returns the placeholder Id.
*
* @return the placeholder Id.
*/
public int getPlaceholderId(){
return placeholderId;
}
/**
* Sets the placeholder Id.
*
* @param id the placeholder Id.
*/
public void setPlaceholderId(byte id){
placeholderId = id;
}
/**
* Returns the placeholder size.
* Must be one of the PLACEHOLDER_* static constants defined in this class.
*
* @return the placeholder size.
*/
public int getPlaceholderSize(){
return placeholderSize;
}
/**
* Sets the placeholder size.
* Must be one of the PLACEHOLDER_* static constants defined in this class.
*
* @param size the placeholder size.
*/
public void setPlaceholderSize(byte size){
placeholderSize = size;
}
/**
* Write the contents of the record back, so it can be written
* to disk
*/
public void writeOut(OutputStream out) throws IOException {
out.write(_header);
byte[] recdata = new byte[8];
LittleEndian.putInt(recdata, 0, placementId);
recdata[4] = (byte)placeholderId;
recdata[5] = (byte)placeholderSize;
out.write(recdata);
}
}

+ 107
- 0
src/scratchpad/src/org/apache/poi/hslf/record/OutlineTextRefAtom.java View File

@@ -0,0 +1,107 @@
/* ====================================================================
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.record;
import org.apache.poi.util.LittleEndian;
import java.io.OutputStream;
import java.io.IOException;
/**
* OEPlaceholderAtom (3998).
* <br>
* What MSDN says about <code>OutlineTextRefAtom</code>:
* <p>
* Appears in a slide to indicate a text that is already contained in the document,
* in a SlideListWithText containter. Sometimes slide texts are not contained
* within the slide container to be able to delay loading a slide and still display
* the title and body text in outline view.
* </p>
*
* @author Yegor Kozlov
*/
public class OutlineTextRefAtom extends RecordAtom {
/**
* record header
*/
private byte[] _header;
/**
* the text's index within the SlideListWithText (0 for title, 1..n for the nth body)
*/
private int _index;
/**
* Build an instance of <code>OutlineTextRefAtom</code> from on-disk data
*/
protected OutlineTextRefAtom(byte[] source, int start, int len) {
// Get the header
_header = new byte[8];
System.arraycopy(source,start,_header,0,8);
// Grab the record data
_index = LittleEndian.getInt(source, start+8);
}
/**
* Create a new instance of <code>FontEntityAtom</code>
*/
protected OutlineTextRefAtom() {
_index = 0;
_header = new byte[8];
LittleEndian.putUShort(_header, 0, 0);
LittleEndian.putUShort(_header, 2, (int)getRecordType());
LittleEndian.putInt(_header, 4, 4);
}
public long getRecordType() {
return RecordTypes.OutlineTextRefAtom.typeID;
}
/**
* Write the contents of the record back, so it can be written to disk
*/
public void writeOut(OutputStream out) throws IOException {
out.write(_header);
byte[] recdata = new byte[4];
LittleEndian.putInt(recdata, 0, _index);
out.write(recdata);
}
/**
* Sets text's index within the SlideListWithText container
* (0 for title, 1..n for the nth body).
*
* @param idx 0-based text's index
*/
public void setTextIndex(int idx){
_index = idx;
}
/**
* Return text's index within the SlideListWithText container
* (0 for title, 1..n for the nth body).
*
* @return idx text's index
*/
public int getTextIndex(){
return _index;
}
}

+ 2
- 2
src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java View File

@@ -76,10 +76,10 @@ public class RecordTypes {
public static final Type ColorSchemeAtom = new Type(2032,ColorSchemeAtom.class);
public static final Type ExObjRefAtom = new Type(3009,null);
public static final Type OEShapeAtom = new Type(3009,null);
public static final Type OEPlaceholderAtom = new Type(3011,null);
public static final Type OEPlaceholderAtom = new Type(3011,OEPlaceholderAtom.class);
public static final Type GPopublicintAtom = new Type(3024,null);
public static final Type GRatioAtom = new Type(3031,null);
public static final Type OutlineTextRefAtom = new Type(3998,null);
public static final Type OutlineTextRefAtom = new Type(3998,OutlineTextRefAtom.class);
public static final Type TextHeaderAtom = new Type(3999,TextHeaderAtom.class);
public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class);
public static final Type StyleTextPropAtom = new Type(4001,StyleTextPropAtom.class);

+ 16
- 1
src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java View File

@@ -93,7 +93,7 @@ public class RichTextRun
/**
* Supply the SlideShow we belong to
*/
protected void supplySlideShow(SlideShow ss) {
public void supplySlideShow(SlideShow ss) {
slideShow = ss;
}
@@ -281,6 +281,21 @@ public class RichTextRun
return slideShow.getFontCollection().getFontWithId(fontIdx);
}
/**
* @return font color as RGB value
* @see java.awt.Color
*/
public int getFontColor() {
return getCharTextPropVal("font.color");
}
/**
* Sets color of the text, as a RGB value
* @see java.awt.Color
*/
public void setFontColor(int rgb) {
setCharTextPropVal("font.color", rgb);
}
// --------------- Internal HSLF methods, not intended for end-user use! -------

+ 38
- 39
src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java View File

@@ -25,6 +25,7 @@ import java.awt.Rectangle;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
/**
* Test drawing shapes via Graphics2D
@@ -132,10 +133,12 @@ public class TestShapes extends TestCase {
// Create a new textbox, and give it lots of properties
TextBox txtbox = new TextBox();
txtbox.setText(val);
txtbox.setFontName("Arial");
txtbox.setFontSize(42);
txtbox.setBold(true);
txtbox.setItalic(true);
txtbox.setUnderline(false);
txtbox.setFontColor(Color.red);
sl.addShape(txtbox);
// Check it before save
@@ -145,6 +148,8 @@ public class TestShapes extends TestCase {
assertTrue(rt.isBold());
assertTrue(rt.isItalic());
assertFalse(rt.isUnderlined());
assertEquals("Arial", rt.getFontName());
assertEquals(Color.red, txtbox.getFontColor());
// Serialize and read again
ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -162,50 +167,44 @@ public class TestShapes extends TestCase {
assertTrue(rt.isBold());
assertTrue(rt.isItalic());
assertFalse(rt.isUnderlined());
assertEquals("Arial", rt.getFontName());
assertEquals(Color.red, txtbox.getFontColor());
}
/**
* Verify that we can add TextBox shapes to a slide
* and set some of the style attributes, with a unicode string
* If you iterate over text shapes in a slide and collect them in a set
* it must be the same as returned by Slide.getTextRuns().
*/
public void testTextBoxWriteChars() throws Exception {
ppt = new SlideShow();
Slide sl = ppt.createSlide();
RichTextRun rt;
String val = "Hello, World! (With some \u1234 and \uffee unicode in it)";
// Create a new textbox, and give it lots of properties
TextBox txtbox = new TextBox();
txtbox.setText(val);
txtbox.setFontSize(42);
txtbox.setBold(true);
txtbox.setUnderline(false);
sl.addShape(txtbox);
// Check it before save
rt = txtbox.getRichTextRuns()[0];
assertEquals(val, rt.getText());
assertEquals(42, rt.getFontSize());
assertTrue(rt.isBold());
assertFalse(rt.isItalic());
assertFalse(rt.isUnderlined());
// Serialize and read again
ByteArrayOutputStream out = new ByteArrayOutputStream();
ppt.write(out);
out.close();
ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())));
public void testTextBoxSet() throws Exception {
textBoxSet("/with_textbox.ppt");
textBoxSet("/basic_test_ppt_file.ppt");
textBoxSet("/next_test_ppt_file.ppt");
textBoxSet("/Single_Coloured_Page.ppt");
textBoxSet("/Single_Coloured_Page_With_Fonts_and_Alignments.ppt");
textBoxSet("/incorrect_slide_order.ppt");
}
txtbox = (TextBox)sl.getShapes()[0];
rt = txtbox.getRichTextRuns()[0];
private void textBoxSet(String filename) throws Exception {
String dirname = System.getProperty("HSLF.testdata.path");
SlideShow ppt = new SlideShow(new HSLFSlideShow(dirname + filename));
Slide[] sl = ppt.getSlides();
for (int k = 0; k < sl.length; k++) {
ArrayList lst1 = new ArrayList();
TextRun[] txt = sl[k].getTextRuns();
for (int i = 0; i < txt.length; i++) {
lst1.add(txt[i].getText());
}
// Check after save
assertEquals(val, rt.getText());
assertEquals(42, rt.getFontSize());
assertTrue(rt.isBold());
assertFalse(rt.isItalic());
assertFalse(rt.isUnderlined());
ArrayList lst2 = new ArrayList();
Shape[] sh = sl[k].getShapes();
for (int i = 0; i < sh.length; i++) {
if (sh[i] instanceof TextBox){
TextBox tbox = (TextBox)sh[i];
lst2.add(tbox.getText());
}
}
assertTrue(lst1.containsAll(lst2));
assertTrue(lst2.containsAll(lst1));
}
}
}

Loading…
Cancel
Save