more work on rendering ppt slides
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@652298 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
598fbaef20
commit
ee9a91198b
@ -369,5 +369,12 @@ public class AutoShapes {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
shapes[ShapeTypes.StraightConnector1] = new ShapeOutline(){
|
||||||
|
public java.awt.Shape getOutline(Shape shape){
|
||||||
|
return new Line2D.Float(0, 0, 21600, 21600);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package org.apache.poi.hslf.model;
|
|||||||
import org.apache.poi.ddf.*;
|
import org.apache.poi.ddf.*;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
|
import org.apache.poi.util.HexDump;
|
||||||
|
|
||||||
import java.awt.geom.*;
|
import java.awt.geom.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -185,10 +186,6 @@ public class Freeform extends AutoShape {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle2D bounds = getAnchor2D();
|
|
||||||
float right = (float)bounds.getX();
|
|
||||||
float bottom = (float)bounds.getY();
|
|
||||||
|
|
||||||
GeneralPath path = new GeneralPath();
|
GeneralPath path = new GeneralPath();
|
||||||
int numPoints = verticesProp.getNumberOfElementsInArray();
|
int numPoints = verticesProp.getNumberOfElementsInArray();
|
||||||
int numSegments = segmentsProp.getNumberOfElementsInArray();
|
int numSegments = segmentsProp.getNumberOfElementsInArray();
|
||||||
@ -199,8 +196,8 @@ public class Freeform extends AutoShape {
|
|||||||
short x = LittleEndian.getShort(p, 0);
|
short x = LittleEndian.getShort(p, 0);
|
||||||
short y = LittleEndian.getShort(p, 2);
|
short y = LittleEndian.getShort(p, 2);
|
||||||
path.moveTo(
|
path.moveTo(
|
||||||
((float)x*POINT_DPI/MASTER_DPI + right),
|
((float)x*POINT_DPI/MASTER_DPI),
|
||||||
((float)y*POINT_DPI/MASTER_DPI + bottom));
|
((float)y*POINT_DPI/MASTER_DPI));
|
||||||
} else if (Arrays.equals(elem, SEGMENTINFO_CUBICTO) || Arrays.equals(elem, SEGMENTINFO_CUBICTO2)){
|
} else if (Arrays.equals(elem, SEGMENTINFO_CUBICTO) || Arrays.equals(elem, SEGMENTINFO_CUBICTO2)){
|
||||||
i++;
|
i++;
|
||||||
byte[] p1 = verticesProp.getElement(j++);
|
byte[] p1 = verticesProp.getElement(j++);
|
||||||
@ -213,9 +210,9 @@ public class Freeform extends AutoShape {
|
|||||||
short x3 = LittleEndian.getShort(p3, 0);
|
short x3 = LittleEndian.getShort(p3, 0);
|
||||||
short y3 = LittleEndian.getShort(p3, 2);
|
short y3 = LittleEndian.getShort(p3, 2);
|
||||||
path.curveTo(
|
path.curveTo(
|
||||||
((float)x1*POINT_DPI/MASTER_DPI + right), ((float)y1*POINT_DPI/MASTER_DPI + bottom),
|
((float)x1*POINT_DPI/MASTER_DPI), ((float)y1*POINT_DPI/MASTER_DPI),
|
||||||
((float)x2*POINT_DPI/MASTER_DPI + right), ((float)y2*POINT_DPI/MASTER_DPI + bottom),
|
((float)x2*POINT_DPI/MASTER_DPI), ((float)y2*POINT_DPI/MASTER_DPI),
|
||||||
((float)x3*POINT_DPI/MASTER_DPI + right), ((float)y3*POINT_DPI/MASTER_DPI + bottom));
|
((float)x3*POINT_DPI/MASTER_DPI), ((float)y3*POINT_DPI/MASTER_DPI));
|
||||||
|
|
||||||
} else if (Arrays.equals(elem, SEGMENTINFO_LINETO)){
|
} else if (Arrays.equals(elem, SEGMENTINFO_LINETO)){
|
||||||
i++;
|
i++;
|
||||||
@ -226,18 +223,26 @@ public class Freeform extends AutoShape {
|
|||||||
short x = LittleEndian.getShort(p, 0);
|
short x = LittleEndian.getShort(p, 0);
|
||||||
short y = LittleEndian.getShort(p, 2);
|
short y = LittleEndian.getShort(p, 2);
|
||||||
path.lineTo(
|
path.lineTo(
|
||||||
((float)x*POINT_DPI/MASTER_DPI + right), ((float)y*POINT_DPI/MASTER_DPI + bottom));
|
((float)x*POINT_DPI/MASTER_DPI), ((float)y*POINT_DPI/MASTER_DPI));
|
||||||
}
|
}
|
||||||
} else if (Arrays.equals(pnext, SEGMENTINFO_CLOSE)){
|
} else if (Arrays.equals(pnext, SEGMENTINFO_CLOSE)){
|
||||||
path.closePath();
|
path.closePath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public java.awt.Shape getOutline(){
|
public java.awt.Shape getOutline(){
|
||||||
return getPath();
|
GeneralPath path = getPath();
|
||||||
|
Rectangle2D anchor = getAnchor2D();
|
||||||
|
Rectangle2D bounds = path.getBounds2D();
|
||||||
|
AffineTransform at = new AffineTransform();
|
||||||
|
at.translate(anchor.getX(), anchor.getY());
|
||||||
|
at.scale(
|
||||||
|
anchor.getWidth()/bounds.getWidth(),
|
||||||
|
anchor.getHeight()/bounds.getHeight()
|
||||||
|
);
|
||||||
|
return at.createTransformedShape(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,4 +67,21 @@ public abstract class MasterSheet extends Sheet {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return placeholder by text type
|
||||||
|
*/
|
||||||
|
public TextShape getPlaceholder(int type){
|
||||||
|
Shape[] shape = getShapes();
|
||||||
|
for (int i = 0; i < shape.length; i++) {
|
||||||
|
if(shape[i] instanceof TextShape){
|
||||||
|
TextShape tx = (TextShape)shape[i];
|
||||||
|
TextRun run = tx.getTextRun();
|
||||||
|
if(run != null && run.getRunType() == type){
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import javax.imageio.ImageIO;
|
|||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
@ -244,6 +245,9 @@ public class Picture extends SimpleShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void draw(Graphics2D graphics){
|
public void draw(Graphics2D graphics){
|
||||||
|
AffineTransform at = graphics.getTransform();
|
||||||
|
ShapePainter.paint(this, graphics);
|
||||||
|
|
||||||
PictureData data = getPictureData();
|
PictureData data = getPictureData();
|
||||||
if (data instanceof Bitmap){
|
if (data instanceof Bitmap){
|
||||||
BufferedImage img = null;
|
BufferedImage img = null;
|
||||||
@ -260,5 +264,6 @@ public class Picture extends SimpleShape {
|
|||||||
} else {
|
} else {
|
||||||
logger.log(POILogger.WARN, "Rendering of metafiles is not yet supported. image.type: " + (data == null ? "NA" : data.getClass().getName()));
|
logger.log(POILogger.WARN, "Rendering of metafiles is not yet supported. image.type: " + (data == null ? "NA" : data.getClass().getName()));
|
||||||
}
|
}
|
||||||
|
graphics.setTransform(at);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -341,58 +341,7 @@ public abstract class Shape {
|
|||||||
* @param sh - owning shape
|
* @param sh - owning shape
|
||||||
*/
|
*/
|
||||||
protected void afterInsert(Sheet sh){
|
protected void afterInsert(Sheet sh){
|
||||||
PPDrawing ppdrawing = sh.getPPDrawing();
|
|
||||||
|
|
||||||
EscherContainerRecord dgContainer = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
|
|
||||||
|
|
||||||
EscherDgRecord dg = (EscherDgRecord) Shape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID);
|
|
||||||
|
|
||||||
int id = allocateShapeId(dg);
|
|
||||||
setShapeId(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates new shape id for the new drawing group id.
|
|
||||||
*
|
|
||||||
* @param dg EscherDgRecord of the sheet that owns the shape being created
|
|
||||||
*
|
|
||||||
* @return a new shape id.
|
|
||||||
*/
|
|
||||||
protected int allocateShapeId(EscherDgRecord dg)
|
|
||||||
{
|
|
||||||
EscherDggRecord dgg = _sheet.getSlideShow().getDocumentRecord().getPPDrawingGroup().getEscherDggRecord();
|
|
||||||
if(dgg == null){
|
|
||||||
logger.log(POILogger.ERROR, "EscherDggRecord not found");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dgg.setNumShapesSaved( dgg.getNumShapesSaved() + 1 );
|
|
||||||
|
|
||||||
// Add to existing cluster if space available
|
|
||||||
for (int i = 0; i < dgg.getFileIdClusters().length; i++)
|
|
||||||
{
|
|
||||||
EscherDggRecord.FileIdCluster c = dgg.getFileIdClusters()[i];
|
|
||||||
if (c.getDrawingGroupId() == dg.getDrawingGroupId() && c.getNumShapeIdsUsed() != 1024)
|
|
||||||
{
|
|
||||||
int result = c.getNumShapeIdsUsed() + (1024 * (i+1));
|
|
||||||
c.incrementShapeId();
|
|
||||||
dg.setNumShapes( dg.getNumShapes() + 1 );
|
|
||||||
dg.setLastMSOSPID( result );
|
|
||||||
if (result >= dgg.getShapeIdMax())
|
|
||||||
dgg.setShapeIdMax( result + 1 );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new cluster
|
|
||||||
dgg.addCluster( dg.getDrawingGroupId(), 0 );
|
|
||||||
dgg.getFileIdClusters()[dgg.getFileIdClusters().length-1].incrementShapeId();
|
|
||||||
dg.setNumShapes( dg.getNumShapes() + 1 );
|
|
||||||
int result = (1024 * dgg.getFileIdClusters().length);
|
|
||||||
dg.setLastMSOSPID( result );
|
|
||||||
if (result >= dgg.getShapeIdMax())
|
|
||||||
dgg.setShapeIdMax( result + 1 );
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -196,13 +196,8 @@ public class ShapeGroup extends Shape{
|
|||||||
|
|
||||||
Sheet sheet = getSheet();
|
Sheet sheet = getSheet();
|
||||||
shape.setSheet(sheet);
|
shape.setSheet(sheet);
|
||||||
|
shape.setShapeId(sheet.allocateShapeId());
|
||||||
shape.afterInsert(sheet);
|
shape.afterInsert(sheet);
|
||||||
|
|
||||||
if (shape instanceof TextShape) {
|
|
||||||
TextShape tbox = (TextShape) shape;
|
|
||||||
EscherTextboxWrapper txWrapper = tbox.getEscherTextboxWrapper();
|
|
||||||
if(txWrapper != null) getSheet().getPPDrawing().addTextboxWrapper(txWrapper);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -277,20 +272,9 @@ public class ShapeGroup extends Shape{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void draw(Graphics2D graphics){
|
public void draw(Graphics2D graphics){
|
||||||
Rectangle2D anchor = getAnchor2D();
|
|
||||||
Rectangle2D coords = getCoordinates();
|
|
||||||
|
|
||||||
//transform coordinates
|
|
||||||
AffineTransform at = graphics.getTransform();
|
AffineTransform at = graphics.getTransform();
|
||||||
/*
|
|
||||||
if(!anchor.equals(coords)){
|
|
||||||
graphics.scale(anchor.getWidth()/coords.getWidth(), anchor.getHeight()/coords.getHeight());
|
|
||||||
|
|
||||||
graphics.translate(
|
|
||||||
anchor.getX()*coords.getWidth()/anchor.getWidth() - coords.getX(),
|
|
||||||
anchor.getY()*coords.getHeight()/anchor.getHeight() - coords.getY());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
Shape[] sh = getShapes();
|
Shape[] sh = getShapes();
|
||||||
for (int i = 0; i < sh.length; i++) {
|
for (int i = 0; i < sh.length; i++) {
|
||||||
sh[i].draw(graphics);
|
sh[i].draw(graphics);
|
||||||
|
@ -18,12 +18,10 @@
|
|||||||
|
|
||||||
package org.apache.poi.hslf.model;
|
package org.apache.poi.hslf.model;
|
||||||
|
|
||||||
import org.apache.poi.ddf.EscherContainerRecord;
|
import org.apache.poi.ddf.*;
|
||||||
import org.apache.poi.ddf.EscherDgRecord;
|
|
||||||
import org.apache.poi.ddf.EscherRecord;
|
|
||||||
import org.apache.poi.ddf.EscherSpRecord;
|
|
||||||
import org.apache.poi.hslf.record.*;
|
import org.apache.poi.hslf.record.*;
|
||||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||||
|
import org.apache.poi.util.POILogger;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -248,15 +246,47 @@ public abstract class Sheet {
|
|||||||
spgr.addChildRecord(shape.getSpContainer());
|
spgr.addChildRecord(shape.getSpContainer());
|
||||||
|
|
||||||
shape.setSheet(this);
|
shape.setSheet(this);
|
||||||
|
shape.setShapeId(allocateShapeId());
|
||||||
shape.afterInsert(this);
|
shape.afterInsert(this);
|
||||||
|
}
|
||||||
|
|
||||||
// If it's a TextShape, we need to tell the PPDrawing, as it has to
|
/**
|
||||||
// track TextboxWrappers specially
|
* Allocates new shape id for the new drawing group id.
|
||||||
if (shape instanceof TextShape) {
|
*
|
||||||
TextShape tbox = (TextShape) shape;
|
* @return a new shape id.
|
||||||
EscherTextboxWrapper txWrapper = tbox.getEscherTextboxWrapper();
|
*/
|
||||||
if(txWrapper != null) ppdrawing.addTextboxWrapper(txWrapper);
|
public int allocateShapeId()
|
||||||
|
{
|
||||||
|
EscherDggRecord dgg = _slideShow.getDocumentRecord().getPPDrawingGroup().getEscherDggRecord();
|
||||||
|
EscherDgRecord dg = _container.getPPDrawing().getEscherDgRecord();
|
||||||
|
|
||||||
|
dgg.setNumShapesSaved( dgg.getNumShapesSaved() + 1 );
|
||||||
|
|
||||||
|
// Add to existing cluster if space available
|
||||||
|
for (int i = 0; i < dgg.getFileIdClusters().length; i++)
|
||||||
|
{
|
||||||
|
EscherDggRecord.FileIdCluster c = dgg.getFileIdClusters()[i];
|
||||||
|
if (c.getDrawingGroupId() == dg.getDrawingGroupId() && c.getNumShapeIdsUsed() != 1024)
|
||||||
|
{
|
||||||
|
int result = c.getNumShapeIdsUsed() + (1024 * (i+1));
|
||||||
|
c.incrementShapeId();
|
||||||
|
dg.setNumShapes( dg.getNumShapes() + 1 );
|
||||||
|
dg.setLastMSOSPID( result );
|
||||||
|
if (result >= dgg.getShapeIdMax())
|
||||||
|
dgg.setShapeIdMax( result + 1 );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create new cluster
|
||||||
|
dgg.addCluster( dg.getDrawingGroupId(), 0, false );
|
||||||
|
dgg.getFileIdClusters()[dgg.getFileIdClusters().length-1].incrementShapeId();
|
||||||
|
dg.setNumShapes( dg.getNumShapes() + 1 );
|
||||||
|
int result = (1024 * dgg.getFileIdClusters().length);
|
||||||
|
dg.setLastMSOSPID( result );
|
||||||
|
if (result >= dgg.getShapeIdMax())
|
||||||
|
dgg.setShapeIdMax( result + 1 );
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -284,6 +314,13 @@ public abstract class Sheet {
|
|||||||
return lst.remove(shape.getSpContainer());
|
return lst.remove(shape.getSpContainer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by SlideShow ater a new sheet is created
|
||||||
|
*/
|
||||||
|
public void onCreate(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the master sheet .
|
* Return the master sheet .
|
||||||
*/
|
*/
|
||||||
|
@ -126,8 +126,8 @@ public class SimpleShape extends Shape {
|
|||||||
EscherSimpleProperty p2 = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH);
|
EscherSimpleProperty p2 = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH);
|
||||||
int p2val = p2 == null ? 0 : p2.getPropertyValue();
|
int p2val = p2 == null ? 0 : p2.getPropertyValue();
|
||||||
Color clr = null;
|
Color clr = null;
|
||||||
if (p1 != null && (p2val & 0x8) != 0){
|
if ((p2val & 0x8) != 0 || (p2val & 0x10) != 0){
|
||||||
int rgb = p1.getPropertyValue();
|
int rgb = p1 == null ? 0 : p1.getPropertyValue();
|
||||||
if (rgb >= 0x8000000) {
|
if (rgb >= 0x8000000) {
|
||||||
int idx = rgb % 0x8000000;
|
int idx = rgb % 0x8000000;
|
||||||
if(getSheet() != null) {
|
if(getSheet() != null) {
|
||||||
|
@ -21,12 +21,17 @@
|
|||||||
package org.apache.poi.hslf.model;
|
package org.apache.poi.hslf.model;
|
||||||
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
|
||||||
import org.apache.poi.hslf.record.SlideAtom;
|
import org.apache.poi.hslf.record.SlideAtom;
|
||||||
import org.apache.poi.hslf.record.TextHeaderAtom;
|
import org.apache.poi.hslf.record.TextHeaderAtom;
|
||||||
import org.apache.poi.hslf.record.ColorSchemeAtom;
|
import org.apache.poi.hslf.record.ColorSchemeAtom;
|
||||||
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
|
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
|
||||||
|
import org.apache.poi.ddf.EscherDggRecord;
|
||||||
|
import org.apache.poi.ddf.EscherContainerRecord;
|
||||||
|
import org.apache.poi.ddf.EscherDgRecord;
|
||||||
|
import org.apache.poi.ddf.EscherSpRecord;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a slide in a PowerPoint Document. It allows
|
* This class represents a slide in a PowerPoint Document. It allows
|
||||||
@ -126,6 +131,42 @@ public class Slide extends Sheet
|
|||||||
_slideNo = newSlideNumber;
|
_slideNo = newSlideNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by SlideShow ater a new slide is created.
|
||||||
|
* <p>
|
||||||
|
* For Slide we need to do the following:
|
||||||
|
* <li> set id of the drawing group.
|
||||||
|
* <li> set shapeId for the container descriptor and background
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public void onCreate(){
|
||||||
|
//initialize drawing group id
|
||||||
|
EscherDggRecord dgg = getSlideShow().getDocumentRecord().getPPDrawingGroup().getEscherDggRecord();
|
||||||
|
EscherContainerRecord dgContainer = (EscherContainerRecord)getSheetContainer().getPPDrawing().getEscherRecords()[0];
|
||||||
|
EscherDgRecord dg = (EscherDgRecord) Shape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID);
|
||||||
|
int dgId = dgg.getMaxDrawingGroupId() + 1;
|
||||||
|
dg.setOptions((short)(dgId << 4));
|
||||||
|
dgg.setDrawingsSaved(dgg.getDrawingsSaved() + 1);
|
||||||
|
|
||||||
|
for (Iterator it = dgContainer.getChildContainers().iterator(); it.hasNext(); ) {
|
||||||
|
EscherContainerRecord c = (EscherContainerRecord)it.next();
|
||||||
|
EscherSpRecord spr = null;
|
||||||
|
switch(c.getRecordId()){
|
||||||
|
case EscherContainerRecord.SPGR_CONTAINER:
|
||||||
|
EscherContainerRecord dc = (EscherContainerRecord)c.getChildRecords().get(0);
|
||||||
|
spr = dc.getChildById(EscherSpRecord.RECORD_ID);
|
||||||
|
break;
|
||||||
|
case EscherContainerRecord.SP_CONTAINER:
|
||||||
|
spr = c.getChildById(EscherSpRecord.RECORD_ID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(spr != null) spr.setShapeId(allocateShapeId());
|
||||||
|
}
|
||||||
|
|
||||||
|
//PPT doen't increment the number of saved shapes for group descriptor and background
|
||||||
|
dg.setNumShapes(1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a <code>TextBox</code> object that represents the slide's title.
|
* Create a <code>TextBox</code> object that represents the slide's title.
|
||||||
*
|
*
|
||||||
|
@ -92,6 +92,7 @@ public class SlideMaster extends MasterSheet {
|
|||||||
} else {
|
} else {
|
||||||
switch (txtype) {
|
switch (txtype) {
|
||||||
case TextHeaderAtom.CENTRE_BODY_TYPE:
|
case TextHeaderAtom.CENTRE_BODY_TYPE:
|
||||||
|
case TextHeaderAtom.HALF_BODY_TYPE:
|
||||||
case TextHeaderAtom.QUARTER_BODY_TYPE:
|
case TextHeaderAtom.QUARTER_BODY_TYPE:
|
||||||
txtype = TextHeaderAtom.BODY_TYPE;
|
txtype = TextHeaderAtom.BODY_TYPE;
|
||||||
break;
|
break;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package org.apache.poi.hslf.model;
|
package org.apache.poi.hslf.model;
|
||||||
|
|
||||||
import org.apache.poi.hslf.usermodel.RichTextRun;
|
import org.apache.poi.hslf.usermodel.RichTextRun;
|
||||||
|
import org.apache.poi.hslf.record.TextRulerAtom;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
|
|
||||||
@ -38,6 +39,13 @@ import java.util.ArrayList;
|
|||||||
public class TextPainter {
|
public class TextPainter {
|
||||||
protected POILogger logger = POILogFactory.getLogger(this.getClass());
|
protected POILogger logger = POILogFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display unicode square if a bullet char can't be displayed,
|
||||||
|
* for example, if Wingdings font is used.
|
||||||
|
* TODO: map Wingdngs and Symbol to unicode Arial
|
||||||
|
*/
|
||||||
|
protected static final char DEFAULT_BULLET_CHAR = '\u25a0';
|
||||||
|
|
||||||
protected TextShape _shape;
|
protected TextShape _shape;
|
||||||
|
|
||||||
public TextPainter(TextShape shape){
|
public TextPainter(TextShape shape){
|
||||||
@ -49,6 +57,10 @@ public class TextPainter {
|
|||||||
*/
|
*/
|
||||||
public AttributedString getAttributedString(TextRun txrun){
|
public AttributedString getAttributedString(TextRun txrun){
|
||||||
String text = txrun.getText();
|
String text = txrun.getText();
|
||||||
|
//TODO: properly process tabs
|
||||||
|
text = text.replace('\t', ' ');
|
||||||
|
text = text.replace((char)160, ' ');
|
||||||
|
|
||||||
AttributedString at = new AttributedString(text);
|
AttributedString at = new AttributedString(text);
|
||||||
RichTextRun[] rt = txrun.getRichTextRuns();
|
RichTextRun[] rt = txrun.getRichTextRuns();
|
||||||
for (int i = 0; i < rt.length; i++) {
|
for (int i = 0; i < rt.length; i++) {
|
||||||
@ -109,7 +121,24 @@ public class TextPainter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float wrappingWidth = (float)anchor.getWidth() - _shape.getMarginLeft() - _shape.getMarginRight();
|
float wrappingWidth = (float)anchor.getWidth() - _shape.getMarginLeft() - _shape.getMarginRight();
|
||||||
wrappingWidth -= rt.getTextOffset();
|
int bulletOffset = rt.getBulletOffset();
|
||||||
|
int textOffset = rt.getTextOffset();
|
||||||
|
int indent = rt.getIndentLevel();
|
||||||
|
|
||||||
|
TextRulerAtom ruler = run.getTextRuler();
|
||||||
|
if(ruler != null) {
|
||||||
|
int bullet_val = ruler.getBulletOffsets()[indent]*Shape.POINT_DPI/Shape.MASTER_DPI;
|
||||||
|
int text_val = ruler.getTextOffsets()[indent]*Shape.POINT_DPI/Shape.MASTER_DPI;
|
||||||
|
if(bullet_val > text_val){
|
||||||
|
int a = bullet_val;
|
||||||
|
bullet_val = text_val;
|
||||||
|
text_val = a;
|
||||||
|
}
|
||||||
|
if(bullet_val != 0 ) bulletOffset = bullet_val;
|
||||||
|
if(text_val != 0) textOffset = text_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
wrappingWidth -= textOffset;
|
||||||
|
|
||||||
if (_shape.getWordWrap() == TextShape.WrapNone) {
|
if (_shape.getWordWrap() == TextShape.WrapNone) {
|
||||||
wrappingWidth = _shape.getSheet().getSlideShow().getPageSize().width;
|
wrappingWidth = _shape.getSheet().getSlideShow().getPageSize().width;
|
||||||
@ -141,8 +170,9 @@ public class TextPainter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
el._align = rt.getAlignment();
|
el._align = rt.getAlignment();
|
||||||
el._text = textLayout;
|
el.advance = textLayout.getAdvance();
|
||||||
el._textOffset = rt.getTextOffset();
|
el._textOffset = textOffset;
|
||||||
|
el._text = new AttributedString(it, startIndex, endIndex);
|
||||||
|
|
||||||
if (prStart){
|
if (prStart){
|
||||||
int sp = rt.getSpaceBefore();
|
int sp = rt.getSpaceBefore();
|
||||||
@ -182,13 +212,25 @@ public class TextPainter {
|
|||||||
Color clr = rt.getBulletColor();
|
Color clr = rt.getBulletColor();
|
||||||
if (clr != null) bat.addAttribute(TextAttribute.FOREGROUND, clr);
|
if (clr != null) bat.addAttribute(TextAttribute.FOREGROUND, clr);
|
||||||
else bat.addAttribute(TextAttribute.FOREGROUND, it.getAttribute(TextAttribute.FOREGROUND));
|
else bat.addAttribute(TextAttribute.FOREGROUND, it.getAttribute(TextAttribute.FOREGROUND));
|
||||||
bat.addAttribute(TextAttribute.FAMILY, it.getAttribute(TextAttribute.FAMILY));
|
|
||||||
bat.addAttribute(TextAttribute.SIZE, it.getAttribute(TextAttribute.SIZE));
|
|
||||||
|
|
||||||
TextLayout bulletLayout = new TextLayout(bat.getIterator(), graphics.getFontRenderContext());
|
int fontIdx = rt.getBulletFont();
|
||||||
|
if(fontIdx == -1) fontIdx = rt.getFontIndex();
|
||||||
|
PPFont bulletFont = _shape.getSheet().getSlideShow().getFont(fontIdx);
|
||||||
|
bat.addAttribute(TextAttribute.FAMILY, bulletFont.getFontName());
|
||||||
|
|
||||||
|
int bulletSize = rt.getBulletSize();
|
||||||
|
int fontSize = rt.getFontSize();
|
||||||
|
if(bulletSize != -1) fontSize = Math.round(fontSize*bulletSize*0.01f);
|
||||||
|
bat.addAttribute(TextAttribute.SIZE, new Float(fontSize));
|
||||||
|
|
||||||
|
if(!new Font(bulletFont.getFontName(), Font.PLAIN, 1).canDisplay(rt.getBulletChar())){
|
||||||
|
bat.addAttribute(TextAttribute.FAMILY, "Arial");
|
||||||
|
bat = new AttributedString("" + DEFAULT_BULLET_CHAR, bat.getIterator().getAttributes());
|
||||||
|
}
|
||||||
|
|
||||||
if(text.substring(startIndex, endIndex).length() > 1){
|
if(text.substring(startIndex, endIndex).length() > 1){
|
||||||
el._bullet = bulletLayout;
|
el._bullet = bat;
|
||||||
el._bulletOffset = rt.getBulletOffset();
|
el._bulletOffset = bulletOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lines.add(el);
|
lines.add(el);
|
||||||
@ -225,29 +267,32 @@ public class TextPainter {
|
|||||||
break;
|
break;
|
||||||
case TextShape.AlignCenter:
|
case TextShape.AlignCenter:
|
||||||
pen.x = anchor.getX() + _shape.getMarginLeft() +
|
pen.x = anchor.getX() + _shape.getMarginLeft() +
|
||||||
(anchor.getWidth() - elem._text.getAdvance() - _shape.getMarginLeft() - _shape.getMarginRight()) / 2;
|
(anchor.getWidth() - elem.advance - _shape.getMarginLeft() - _shape.getMarginRight()) / 2;
|
||||||
break;
|
break;
|
||||||
case TextShape.AlignRight:
|
case TextShape.AlignRight:
|
||||||
pen.x = anchor.getX() + _shape.getMarginLeft() +
|
pen.x = anchor.getX() + _shape.getMarginLeft() +
|
||||||
(anchor.getWidth() - elem._text.getAdvance() - _shape.getMarginLeft() - _shape.getMarginRight());
|
(anchor.getWidth() - elem.advance - _shape.getMarginLeft() - _shape.getMarginRight());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(elem._bullet != null){
|
if(elem._bullet != null){
|
||||||
elem._bullet.draw(graphics, (float)(pen.x + elem._bulletOffset), (float)pen.y);
|
graphics.drawString(elem._bullet.getIterator(), (float)(pen.x + elem._bulletOffset), (float)pen.y);
|
||||||
|
}
|
||||||
|
AttributedCharacterIterator chIt = elem._text.getIterator();
|
||||||
|
if(chIt.getEndIndex() > chIt.getBeginIndex()) {
|
||||||
|
graphics.drawString(chIt, (float)(pen.x + elem._textOffset), (float)pen.y);
|
||||||
}
|
}
|
||||||
elem._text.draw(graphics, (float)(pen.x + elem._textOffset), (float)pen.y);
|
|
||||||
|
|
||||||
y0 += elem.descent;
|
y0 += elem.descent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class TextElement {
|
public static class TextElement {
|
||||||
public TextLayout _text;
|
public AttributedString _text;
|
||||||
public int _textOffset;
|
public int _textOffset;
|
||||||
public TextLayout _bullet;
|
public AttributedString _bullet;
|
||||||
public int _bulletOffset;
|
public int _bulletOffset;
|
||||||
public int _align;
|
public int _align;
|
||||||
public float ascent, descent;
|
public float ascent, descent;
|
||||||
|
public float advance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -535,9 +535,13 @@ public class TextRun
|
|||||||
// them to \n
|
// them to \n
|
||||||
String text = rawText.replace('\r','\n');
|
String text = rawText.replace('\r','\n');
|
||||||
|
|
||||||
//0xB acts like cariage return in page titles
|
int type = _headerAtom == null ? 0 : _headerAtom.getTextType();
|
||||||
text = text.replace((char) 0x0B, '\n');
|
if(type == TextHeaderAtom.TITLE_TYPE || type == TextHeaderAtom.CENTER_TITLE_TYPE){
|
||||||
|
//0xB acts like cariage return in page titles and like blank in the others
|
||||||
|
text = text.replace((char) 0x0B, '\n');
|
||||||
|
} else {
|
||||||
|
text = text.replace((char) 0x0B, ' ');
|
||||||
|
}
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,4 +659,11 @@ public class TextRun
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TextRulerAtom getTextRuler(){
|
||||||
|
for (int i = 0; i < _records.length; i++) {
|
||||||
|
if(_records[i] instanceof TextRulerAtom) return (TextRulerAtom)_records[i];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,17 +261,28 @@ public abstract class TextShape extends SimpleShape {
|
|||||||
public int getVerticalAlignment(){
|
public int getVerticalAlignment(){
|
||||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
|
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
|
||||||
int valign;
|
int valign = TextShape.AnchorTop;
|
||||||
if (prop == null){
|
if (prop == null){
|
||||||
|
/**
|
||||||
|
* If vertical alignment was not found in the shape properties then try to
|
||||||
|
* fetch the master shape and search for the align property there.
|
||||||
|
*/
|
||||||
int type = getTextRun().getRunType();
|
int type = getTextRun().getRunType();
|
||||||
switch (type){
|
MasterSheet master = getSheet().getMasterSheet();
|
||||||
case TextHeaderAtom.TITLE_TYPE:
|
if(master != null){
|
||||||
case TextHeaderAtom.CENTER_TITLE_TYPE:
|
TextShape masterShape = master.getPlaceholder(type);
|
||||||
valign = TextShape.AnchorMiddle;
|
if(masterShape != null) valign = masterShape.getVerticalAlignment();
|
||||||
break;
|
} else {
|
||||||
default:
|
//not found in the master sheet. Use the hardcoded defaults.
|
||||||
valign = TextShape.AnchorTop;
|
switch (type){
|
||||||
break;
|
case TextHeaderAtom.TITLE_TYPE:
|
||||||
|
case TextHeaderAtom.CENTER_TITLE_TYPE:
|
||||||
|
valign = TextShape.AnchorMiddle;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
valign = TextShape.AnchorTop;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
valign = prop.getPropertyValue();
|
valign = prop.getPropertyValue();
|
||||||
|
@ -24,11 +24,13 @@ import org.apache.poi.util.POILogger;
|
|||||||
|
|
||||||
import org.apache.poi.ddf.*;
|
import org.apache.poi.ddf.*;
|
||||||
import org.apache.poi.hslf.model.ShapeTypes;
|
import org.apache.poi.hslf.model.ShapeTypes;
|
||||||
|
import org.apache.poi.hslf.model.Shape;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These are actually wrappers onto Escher drawings. Make use of
|
* These are actually wrappers onto Escher drawings. Make use of
|
||||||
@ -52,6 +54,8 @@ public class PPDrawing extends RecordAtom
|
|||||||
private EscherRecord[] childRecords;
|
private EscherRecord[] childRecords;
|
||||||
private EscherTextboxWrapper[] textboxWrappers;
|
private EscherTextboxWrapper[] textboxWrappers;
|
||||||
|
|
||||||
|
//cached EscherDgRecord
|
||||||
|
private EscherDgRecord dg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get access to the underlying Escher Records
|
* Get access to the underlying Escher Records
|
||||||
@ -296,4 +300,24 @@ public class PPDrawing extends RecordAtom
|
|||||||
tw[textboxWrappers.length] = txtbox;
|
tw[textboxWrappers.length] = txtbox;
|
||||||
textboxWrappers = tw;
|
textboxWrappers = tw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return EscherDgRecord which keeps track of the number of shapes and shapeId in this drawing group
|
||||||
|
*
|
||||||
|
* @return EscherDgRecord
|
||||||
|
*/
|
||||||
|
public EscherDgRecord getEscherDgRecord(){
|
||||||
|
if(dg == null){
|
||||||
|
EscherContainerRecord dgContainer = (EscherContainerRecord)childRecords[0];
|
||||||
|
for(Iterator it = dgContainer.getChildRecords().iterator(); it.hasNext();){
|
||||||
|
EscherRecord r = (EscherRecord) it.next();
|
||||||
|
if(r instanceof EscherDgRecord){
|
||||||
|
dg = (EscherDgRecord)r;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dg;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ public class RecordTypes {
|
|||||||
public static final Type TxMasterStyleAtom = new Type(4003,TxMasterStyleAtom.class);
|
public static final Type TxMasterStyleAtom = new Type(4003,TxMasterStyleAtom.class);
|
||||||
public static final Type TxCFStyleAtom = new Type(4004,null);
|
public static final Type TxCFStyleAtom = new Type(4004,null);
|
||||||
public static final Type TxPFStyleAtom = new Type(4005,null);
|
public static final Type TxPFStyleAtom = new Type(4005,null);
|
||||||
public static final Type TextRulerAtom = new Type(4006,null);
|
public static final Type TextRulerAtom = new Type(4006,TextRulerAtom.class);
|
||||||
public static final Type TextBookmarkAtom = new Type(4007,null);
|
public static final Type TextBookmarkAtom = new Type(4007,null);
|
||||||
public static final Type TextBytesAtom = new Type(4008,TextBytesAtom.class);
|
public static final Type TextBytesAtom = new Type(4008,TextBytesAtom.class);
|
||||||
public static final Type TxSIStyleAtom = new Type(4009,null);
|
public static final Type TxSIStyleAtom = new Type(4009,null);
|
||||||
|
@ -127,8 +127,8 @@ public class StyleTextPropAtom extends RecordAtom
|
|||||||
new ParagraphFlagsTextProp(),
|
new ParagraphFlagsTextProp(),
|
||||||
new TextProp(2, 0x80, "bullet.char"),
|
new TextProp(2, 0x80, "bullet.char"),
|
||||||
new TextProp(2, 0x10, "bullet.font"),
|
new TextProp(2, 0x10, "bullet.font"),
|
||||||
|
new TextProp(2, 0x40, "bullet.size"),
|
||||||
new TextProp(4, 0x20, "bullet.color"),
|
new TextProp(4, 0x20, "bullet.color"),
|
||||||
new TextProp(2, 0x40, "bullet.size"),
|
|
||||||
new AlignmentTextProp(),
|
new AlignmentTextProp(),
|
||||||
new TextProp(2, 0x100, "text.offset"),
|
new TextProp(2, 0x100, "text.offset"),
|
||||||
new TextProp(2, 0x200, "para_unknown_2"),
|
new TextProp(2, 0x200, "para_unknown_2"),
|
||||||
|
194
src/scratchpad/src/org/apache/poi/hslf/record/TextRulerAtom.java
Executable file
194
src/scratchpad/src/org/apache/poi/hslf/record/TextRulerAtom.java
Executable file
@ -0,0 +1,194 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.hslf.record;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.zip.InflaterInputStream;
|
||||||
|
|
||||||
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
import org.apache.poi.util.POILogger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ruler of a text as it differs from the style's ruler settings.
|
||||||
|
*
|
||||||
|
* @author Yegor Kozlov
|
||||||
|
*/
|
||||||
|
public class TextRulerAtom extends RecordAtom {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record header.
|
||||||
|
*/
|
||||||
|
private byte[] _header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record data.
|
||||||
|
*/
|
||||||
|
private byte[] _data;
|
||||||
|
|
||||||
|
//ruler internals
|
||||||
|
private int defaultTabSize;
|
||||||
|
private int numLevels;
|
||||||
|
private int[] tabStops;
|
||||||
|
private int[] bulletOffsets = new int[5];
|
||||||
|
private int[] textOffsets = new int[5];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new empty ruler atom.
|
||||||
|
*/
|
||||||
|
protected TextRulerAtom() {
|
||||||
|
_header = new byte[8];
|
||||||
|
_data = new byte[0];
|
||||||
|
|
||||||
|
LittleEndian.putShort(_header, 2, (short)getRecordType());
|
||||||
|
LittleEndian.putInt(_header, 4, _data.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the ruler atom record from its
|
||||||
|
* source data.
|
||||||
|
*
|
||||||
|
* @param source the source data as a byte array.
|
||||||
|
* @param start the start offset into the byte array.
|
||||||
|
* @param len the length of the slice in the byte array.
|
||||||
|
*/
|
||||||
|
protected TextRulerAtom(byte[] source, int start, int len) {
|
||||||
|
// Get the header.
|
||||||
|
_header = new byte[8];
|
||||||
|
System.arraycopy(source,start,_header,0,8);
|
||||||
|
|
||||||
|
// Get the record data.
|
||||||
|
_data = new byte[len-8];
|
||||||
|
System.arraycopy(source,start+8,_data,0,len-8);
|
||||||
|
|
||||||
|
try {
|
||||||
|
read();
|
||||||
|
} catch (Exception e){
|
||||||
|
logger.log(POILogger.ERROR, "Failed to parse TextRulerAtom: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the record type.
|
||||||
|
*
|
||||||
|
* @return the record type.
|
||||||
|
*/
|
||||||
|
public long getRecordType() {
|
||||||
|
return RecordTypes.TextRulerAtom.typeID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the contents of the record back, so it can be written
|
||||||
|
* to disk.
|
||||||
|
*
|
||||||
|
* @param out the output stream to write to.
|
||||||
|
* @throws java.io.IOException if an error occurs.
|
||||||
|
*/
|
||||||
|
public void writeOut(OutputStream out) throws IOException {
|
||||||
|
out.write(_header);
|
||||||
|
out.write(_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the record bytes and initialize the internal variables
|
||||||
|
*/
|
||||||
|
private void read(){
|
||||||
|
int pos = 0;
|
||||||
|
short mask = LittleEndian.getShort(_data); pos += 4;
|
||||||
|
short val;
|
||||||
|
int[] bits = {1, 0, 2, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12};
|
||||||
|
for (int i = 0; i < bits.length; i++) {
|
||||||
|
if((mask & 1 << bits[i]) != 0){
|
||||||
|
switch (bits[i]){
|
||||||
|
case 0:
|
||||||
|
//defaultTabSize
|
||||||
|
defaultTabSize = LittleEndian.getShort(_data, pos); pos += 2;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
//numLevels
|
||||||
|
numLevels = LittleEndian.getShort(_data, pos); pos += 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
//tabStops
|
||||||
|
val = LittleEndian.getShort(_data, pos); pos += 2;
|
||||||
|
tabStops = new int[val*2];
|
||||||
|
for (int j = 0; j < tabStops.length; j++) {
|
||||||
|
tabStops[j] = LittleEndian.getUShort(_data, pos); pos += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
//bullet.offset
|
||||||
|
val = LittleEndian.getShort(_data, pos); pos += 2;
|
||||||
|
bulletOffsets[bits[i]-3] = val;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
case 9:
|
||||||
|
case 10:
|
||||||
|
case 11:
|
||||||
|
case 12:
|
||||||
|
//text.offset
|
||||||
|
val = LittleEndian.getShort(_data, pos); pos += 2;
|
||||||
|
textOffsets[bits[i]-8] = val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default distance between tab stops, in master coordinates (576 dpi).
|
||||||
|
*/
|
||||||
|
public int getDefaultTabSize(){
|
||||||
|
return defaultTabSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of indent levels (maximum 5).
|
||||||
|
*/
|
||||||
|
public int getNumberOfLevels(){
|
||||||
|
return numLevels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default distance between tab stops, in master coordinates (576 dpi).
|
||||||
|
*/
|
||||||
|
public int[] getTabStops(){
|
||||||
|
return tabStops;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paragraph's distance from shape's left margin, in master coordinates (576 dpi).
|
||||||
|
*/
|
||||||
|
public int[] getTextOffsets(){
|
||||||
|
return textOffsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* First line of paragraph's distance from shape's left margin, in master coordinates (576 dpi).
|
||||||
|
*/
|
||||||
|
public int[] getBulletOffsets(){
|
||||||
|
return bulletOffsets;
|
||||||
|
}
|
||||||
|
}
|
@ -32,6 +32,8 @@ import org.apache.poi.hslf.model.textproperties.ParagraphFlagsTextProp;
|
|||||||
import org.apache.poi.hslf.model.textproperties.TextProp;
|
import org.apache.poi.hslf.model.textproperties.TextProp;
|
||||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||||
import org.apache.poi.hslf.record.ColorSchemeAtom;
|
import org.apache.poi.hslf.record.ColorSchemeAtom;
|
||||||
|
import org.apache.poi.util.POILogger;
|
||||||
|
import org.apache.poi.util.POILogFactory;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,6 +41,8 @@ import org.apache.poi.hslf.record.ColorSchemeAtom;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RichTextRun {
|
public class RichTextRun {
|
||||||
|
protected POILogger logger = POILogFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
/** The TextRun we belong to */
|
/** The TextRun we belong to */
|
||||||
private TextRun parentRun;
|
private TextRun parentRun;
|
||||||
/** The SlideShow we belong to */
|
/** The SlideShow we belong to */
|
||||||
@ -199,10 +203,15 @@ public class RichTextRun {
|
|||||||
}
|
}
|
||||||
if (prop == null){
|
if (prop == null){
|
||||||
Sheet sheet = parentRun.getSheet();
|
Sheet sheet = parentRun.getSheet();
|
||||||
int txtype = parentRun.getRunType();
|
if(sheet != null){
|
||||||
MasterSheet master = sheet.getMasterSheet();
|
int txtype = parentRun.getRunType();
|
||||||
if (master != null)
|
MasterSheet master = sheet.getMasterSheet();
|
||||||
prop = (BitMaskTextProp)master.getStyleAttribute(txtype, getIndentLevel(), propname, isCharacter);
|
if (master != null){
|
||||||
|
prop = (BitMaskTextProp)master.getStyleAttribute(txtype, getIndentLevel(), propname, isCharacter);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.log(POILogger.WARN, "MasterSheet is not available");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return prop == null ? false : prop.getSubValue(index);
|
return prop == null ? false : prop.getSubValue(index);
|
||||||
@ -213,7 +222,7 @@ public class RichTextRun {
|
|||||||
* it if required.
|
* it if required.
|
||||||
*/
|
*/
|
||||||
private void setCharFlagsTextPropVal(int index, boolean value) {
|
private void setCharFlagsTextPropVal(int index, boolean value) {
|
||||||
setFlag(true, index, value);
|
if(getFlag(true, index) != value) setFlag(true, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFlag(boolean isCharacter, int index, boolean value) {
|
public void setFlag(boolean isCharacter, int index, boolean value) {
|
||||||
@ -281,10 +290,14 @@ public class RichTextRun {
|
|||||||
*/
|
*/
|
||||||
private int getParaTextPropVal(String propName) {
|
private int getParaTextPropVal(String propName) {
|
||||||
TextProp prop = null;
|
TextProp prop = null;
|
||||||
|
boolean hardAttribute = false;
|
||||||
if (paragraphStyle != null){
|
if (paragraphStyle != null){
|
||||||
prop = paragraphStyle.findByName(propName);
|
prop = paragraphStyle.findByName(propName);
|
||||||
|
|
||||||
|
BitMaskTextProp maskProp = (BitMaskTextProp)paragraphStyle.findByName(ParagraphFlagsTextProp.NAME);
|
||||||
|
hardAttribute = maskProp != null && maskProp.getValue() == 0;
|
||||||
}
|
}
|
||||||
if (prop == null){
|
if (prop == null && !hardAttribute){
|
||||||
Sheet sheet = parentRun.getSheet();
|
Sheet sheet = parentRun.getSheet();
|
||||||
int txtype = parentRun.getRunType();
|
int txtype = parentRun.getRunType();
|
||||||
MasterSheet master = sheet.getMasterSheet();
|
MasterSheet master = sheet.getMasterSheet();
|
||||||
@ -574,6 +587,13 @@ public class RichTextRun {
|
|||||||
return getFlag(false, ParagraphFlagsTextProp.BULLET_IDX);
|
return getFlag(false, ParagraphFlagsTextProp.BULLET_IDX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this rich text run has bullets
|
||||||
|
*/
|
||||||
|
public boolean isBulletHard() {
|
||||||
|
return getFlag(false, ParagraphFlagsTextProp.BULLET_IDX);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the bullet character
|
* Sets the bullet character
|
||||||
*/
|
*/
|
||||||
|
@ -24,10 +24,7 @@ import java.util.*;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import org.apache.poi.ddf.EscherBSERecord;
|
import org.apache.poi.ddf.*;
|
||||||
import org.apache.poi.ddf.EscherContainerRecord;
|
|
||||||
import org.apache.poi.ddf.EscherOptRecord;
|
|
||||||
import org.apache.poi.ddf.EscherRecord;
|
|
||||||
import org.apache.poi.hslf.*;
|
import org.apache.poi.hslf.*;
|
||||||
import org.apache.poi.hslf.model.*;
|
import org.apache.poi.hslf.model.*;
|
||||||
import org.apache.poi.hslf.model.Notes;
|
import org.apache.poi.hslf.model.Notes;
|
||||||
@ -66,9 +63,7 @@ public class SlideShow
|
|||||||
// Lookup between the PersitPtr "sheet" IDs, and the position
|
// Lookup between the PersitPtr "sheet" IDs, and the position
|
||||||
// in the mostRecentCoreRecords array
|
// in the mostRecentCoreRecords array
|
||||||
private Hashtable _sheetIdToCoreRecordsLookup;
|
private Hashtable _sheetIdToCoreRecordsLookup;
|
||||||
// Used when adding new core records
|
|
||||||
private int _highestSheetId;
|
|
||||||
|
|
||||||
// Records that are interesting
|
// Records that are interesting
|
||||||
private Document _documentRecord;
|
private Document _documentRecord;
|
||||||
|
|
||||||
@ -203,8 +198,6 @@ public class SlideShow
|
|||||||
for(int i=0; i<allIDs.length; i++) {
|
for(int i=0; i<allIDs.length; i++) {
|
||||||
_sheetIdToCoreRecordsLookup.put(new Integer(allIDs[i]), new Integer(i));
|
_sheetIdToCoreRecordsLookup.put(new Integer(allIDs[i]), new Integer(i));
|
||||||
}
|
}
|
||||||
// Capture the ID of the highest sheet
|
|
||||||
_highestSheetId = allIDs[(allIDs.length-1)];
|
|
||||||
|
|
||||||
// Now convert the byte offsets back into record offsets
|
// Now convert the byte offsets back into record offsets
|
||||||
for(int i=0; i<_records.length; i++) {
|
for(int i=0; i<_records.length; i++) {
|
||||||
@ -612,38 +605,35 @@ public class SlideShow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up a new SlidePersistAtom for this slide
|
// Set up a new SlidePersistAtom for this slide
|
||||||
SlidePersistAtom sp = new SlidePersistAtom();
|
SlidePersistAtom sp = new SlidePersistAtom();
|
||||||
|
|
||||||
// Reference is the 1-based index of the slide container in
|
|
||||||
// the PersistPtr root.
|
|
||||||
// It always starts with 3 (1 is Document, 2 is MainMaster, 3 is
|
|
||||||
// the first slide), but quicksaves etc can leave gaps
|
|
||||||
_highestSheetId++;
|
|
||||||
sp.setRefID(_highestSheetId);
|
|
||||||
// First slideId is always 256
|
// First slideId is always 256
|
||||||
sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1));
|
sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1));
|
||||||
|
|
||||||
// Add this new SlidePersistAtom to the SlideListWithText
|
// Add this new SlidePersistAtom to the SlideListWithText
|
||||||
slist.addSlidePersistAtom(sp);
|
slist.addSlidePersistAtom(sp);
|
||||||
|
|
||||||
|
|
||||||
// Create a new Slide
|
// Create a new Slide
|
||||||
Slide slide = new Slide(sp.getSlideIdentifier(), sp.getRefID(), _slides.length+1);
|
Slide slide = new Slide(sp.getSlideIdentifier(), sp.getRefID(), _slides.length+1);
|
||||||
|
slide.setSlideShow(this);
|
||||||
|
slide.onCreate();
|
||||||
|
|
||||||
// Add in to the list of Slides
|
// Add in to the list of Slides
|
||||||
Slide[] s = new Slide[_slides.length+1];
|
Slide[] s = new Slide[_slides.length+1];
|
||||||
System.arraycopy(_slides, 0, s, 0, _slides.length);
|
System.arraycopy(_slides, 0, s, 0, _slides.length);
|
||||||
s[_slides.length] = slide;
|
s[_slides.length] = slide;
|
||||||
_slides = s;
|
_slides = s;
|
||||||
logger.log(POILogger.INFO, "Added slide " + _slides.length + " with ref " + sp.getRefID() + " and identifier " + sp.getSlideIdentifier());
|
logger.log(POILogger.INFO, "Added slide " + _slides.length + " with ref " + sp.getRefID() + " and identifier " + sp.getSlideIdentifier());
|
||||||
|
|
||||||
// Add the core records for this new Slide to the record tree
|
// Add the core records for this new Slide to the record tree
|
||||||
org.apache.poi.hslf.record.Slide slideRecord = slide.getSlideRecord();
|
org.apache.poi.hslf.record.Slide slideRecord = slide.getSlideRecord();
|
||||||
slideRecord.setSheetId(sp.getRefID());
|
|
||||||
int slideRecordPos = _hslfSlideShow.appendRootLevelRecord(slideRecord);
|
int slideRecordPos = _hslfSlideShow.appendRootLevelRecord(slideRecord);
|
||||||
_records = _hslfSlideShow.getRecords();
|
_records = _hslfSlideShow.getRecords();
|
||||||
|
|
||||||
|
|
||||||
// Add the new Slide into the PersistPtr stuff
|
// Add the new Slide into the PersistPtr stuff
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int slideOffset = 0;
|
int slideOffset = 0;
|
||||||
@ -653,7 +643,7 @@ public class SlideShow
|
|||||||
Record record = _records[i];
|
Record record = _records[i];
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
record.writeOut(out);
|
record.writeOut(out);
|
||||||
|
|
||||||
// Grab interesting records as they come past
|
// Grab interesting records as they come past
|
||||||
if(_records[i].getRecordType() == RecordTypes.PersistPtrIncrementalBlock.typeID){
|
if(_records[i].getRecordType() == RecordTypes.PersistPtrIncrementalBlock.typeID){
|
||||||
ptr = (PersistPtrHolder)_records[i];
|
ptr = (PersistPtrHolder)_records[i];
|
||||||
@ -661,25 +651,29 @@ public class SlideShow
|
|||||||
if(_records[i].getRecordType() == RecordTypes.UserEditAtom.typeID) {
|
if(_records[i].getRecordType() == RecordTypes.UserEditAtom.typeID) {
|
||||||
usr = (UserEditAtom)_records[i];
|
usr = (UserEditAtom)_records[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i == slideRecordPos) {
|
if(i == slideRecordPos) {
|
||||||
slideOffset = offset;
|
slideOffset = offset;
|
||||||
}
|
}
|
||||||
offset += out.size();
|
offset += out.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// persist ID is UserEditAtom.maxPersistWritten + 1
|
||||||
|
int psrId = usr.getMaxPersistWritten() + 1;
|
||||||
|
sp.setRefID(psrId);
|
||||||
|
slideRecord.setSheetId(psrId);
|
||||||
|
|
||||||
|
// Last view is now of the slide
|
||||||
|
usr.setLastViewType((short)UserEditAtom.LAST_VIEW_SLIDE_VIEW);
|
||||||
|
usr.setMaxPersistWritten(psrId); //increment the number of persit objects
|
||||||
|
|
||||||
// Add the new slide into the last PersistPtr
|
// Add the new slide into the last PersistPtr
|
||||||
// (Also need to tell it where it is)
|
// (Also need to tell it where it is)
|
||||||
slideRecord.setLastOnDiskOffset(slideOffset);
|
slideRecord.setLastOnDiskOffset(slideOffset);
|
||||||
ptr.addSlideLookup(sp.getRefID(), slideOffset);
|
ptr.addSlideLookup(sp.getRefID(), slideOffset);
|
||||||
logger.log(POILogger.INFO, "New slide ended up at " + slideOffset);
|
logger.log(POILogger.INFO, "New slide ended up at " + slideOffset);
|
||||||
|
|
||||||
// Last view is now of the slide
|
|
||||||
usr.setLastViewType((short)UserEditAtom.LAST_VIEW_SLIDE_VIEW);
|
|
||||||
usr.setMaxPersistWritten(_highestSheetId);
|
|
||||||
|
|
||||||
// All done and added
|
// All done and added
|
||||||
slide.setSlideShow(this);
|
|
||||||
return slide;
|
return slide;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ public class TestFreeform extends TestCase {
|
|||||||
Freeform p = new Freeform();
|
Freeform p = new Freeform();
|
||||||
p.setPath(path1);
|
p.setPath(path1);
|
||||||
|
|
||||||
GeneralPath path2 = p.getPath();
|
java.awt.Shape path2 = p.getOutline();
|
||||||
assertTrue(new Area(path1).equals(new Area(path2)));
|
assertTrue(new Area(path1).equals(new Area(path2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ public class TestFreeform extends TestCase {
|
|||||||
Freeform p = new Freeform();
|
Freeform p = new Freeform();
|
||||||
p.setPath(path1);
|
p.setPath(path1);
|
||||||
|
|
||||||
GeneralPath path2 = p.getPath();
|
java.awt.Shape path2 = p.getOutline();
|
||||||
assertTrue(new Area(path1).equals(new Area(path2)));
|
assertTrue(new Area(path1).equals(new Area(path2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ public class TestFreeform extends TestCase {
|
|||||||
Freeform p = new Freeform();
|
Freeform p = new Freeform();
|
||||||
p.setPath(path1);
|
p.setPath(path1);
|
||||||
|
|
||||||
GeneralPath path2 = p.getPath();
|
java.awt.Shape path2 = p.getOutline();
|
||||||
assertTrue(new Area(path1).equals(new Area(path2)));
|
assertTrue(new Area(path1).equals(new Area(path2)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ import junit.framework.TestCase;
|
|||||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||||
import org.apache.poi.hslf.usermodel.RichTextRun;
|
import org.apache.poi.hslf.usermodel.RichTextRun;
|
||||||
import org.apache.poi.hslf.HSLFSlideShow;
|
import org.apache.poi.hslf.HSLFSlideShow;
|
||||||
|
import org.apache.poi.ddf.EscherDggRecord;
|
||||||
|
import org.apache.poi.ddf.EscherDgRecord;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
@ -311,18 +313,49 @@ public class TestShapes extends TestCase {
|
|||||||
public void testShapeId() throws IOException {
|
public void testShapeId() throws IOException {
|
||||||
SlideShow ppt = new SlideShow();
|
SlideShow ppt = new SlideShow();
|
||||||
Slide slide = ppt.createSlide();
|
Slide slide = ppt.createSlide();
|
||||||
Shape shape;
|
Shape shape = null;
|
||||||
|
|
||||||
shape = new Line();
|
//EscherDgg is a document-level record which keeps track of the drawing groups
|
||||||
assertEquals(0, shape.getShapeId());
|
EscherDggRecord dgg = ppt.getDocumentRecord().getPPDrawingGroup().getEscherDggRecord();
|
||||||
slide.addShape(shape);
|
EscherDgRecord dg = slide.getSheetContainer().getPPDrawing().getEscherDgRecord();
|
||||||
assertTrue(shape.getShapeId() > 0);
|
|
||||||
|
|
||||||
int shapeId = shape.getShapeId();
|
int dggShapesUsed = dgg.getNumShapesSaved(); //total number of shapes in the ppt
|
||||||
|
int dggMaxId = dgg.getShapeIdMax(); //max number of shapeId
|
||||||
|
|
||||||
shape = new Line();
|
int dgMaxId = dg.getLastMSOSPID(); //max shapeId in the slide
|
||||||
assertEquals(0, shape.getShapeId());
|
int dgShapesUsed = dg.getNumShapes(); // number of shapes in the slide
|
||||||
slide.addShape(shape);
|
//insert 3 shapes and make sure the Ids are properly incremented
|
||||||
assertEquals(shapeId + 1, shape.getShapeId());
|
for (int i = 0; i < 3; i++) {
|
||||||
|
shape = new Line();
|
||||||
|
assertEquals(0, shape.getShapeId());
|
||||||
|
slide.addShape(shape);
|
||||||
|
assertTrue(shape.getShapeId() > 0);
|
||||||
|
|
||||||
|
//check that EscherDgRecord is updated
|
||||||
|
assertEquals(shape.getShapeId(), dg.getLastMSOSPID());
|
||||||
|
assertEquals(dgMaxId + 1, dg.getLastMSOSPID());
|
||||||
|
assertEquals(dgShapesUsed + 1, dg.getNumShapes());
|
||||||
|
|
||||||
|
//check that EscherDggRecord is updated
|
||||||
|
assertEquals(shape.getShapeId() + 1, dgg.getShapeIdMax());
|
||||||
|
assertEquals(dggMaxId + 1, dgg.getShapeIdMax());
|
||||||
|
assertEquals(dggShapesUsed + 1, dgg.getNumShapesSaved());
|
||||||
|
|
||||||
|
dggShapesUsed = dgg.getNumShapesSaved();
|
||||||
|
dggMaxId = dgg.getShapeIdMax();
|
||||||
|
dgMaxId = dg.getLastMSOSPID();
|
||||||
|
dgShapesUsed = dg.getNumShapes();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//For each drawing group PPT allocates clusters with size=1024
|
||||||
|
//if the number of shapes is greater that 1024 a new cluster is allocated
|
||||||
|
//make sure it is so
|
||||||
|
int numClusters = dgg.getNumIdClusters();
|
||||||
|
for (int i = 0; i < 1025; i++) {
|
||||||
|
shape = new Line();
|
||||||
|
slide.addShape(shape);
|
||||||
|
}
|
||||||
|
assertEquals(numClusters + 1, dgg.getNumIdClusters());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
76
src/scratchpad/testcases/org/apache/poi/hslf/record/TestTextRulerAtom.java
Executable file
76
src/scratchpad/testcases/org/apache/poi/hslf/record/TestTextRulerAtom.java
Executable file
@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
package org.apache.poi.hslf.record;
|
||||||
|
|
||||||
|
import org.apache.poi.hslf.HSLFSlideShow;
|
||||||
|
import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
|
||||||
|
import org.apache.poi.hslf.model.textproperties.TextProp;
|
||||||
|
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||||
|
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
|
||||||
|
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||||
|
import org.apache.poi.util.HexDump;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests TextRulerAtom
|
||||||
|
*
|
||||||
|
* @author Yegor Kozlov
|
||||||
|
*/
|
||||||
|
public class TestTextRulerAtom extends TestCase {
|
||||||
|
|
||||||
|
//from a real file
|
||||||
|
private byte[] data_1 = new byte[] {
|
||||||
|
0x00, 0x00, (byte)0xA6, 0x0F, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
(byte)0xF8, 0x1F, 0x00, 0x00, 0x75, 0x00, (byte)0xE2, 0x00, 0x59,
|
||||||
|
0x01, (byte)0xC3, 0x01, 0x1A, 0x03, (byte)0x87, 0x03, (byte)0xF8,
|
||||||
|
0x03, 0x69, 0x04, (byte)0xF6, 0x05, (byte)0xF6, 0x05
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public void testReadRuler() throws Exception {
|
||||||
|
TextRulerAtom ruler = new TextRulerAtom(data_1, 0, data_1.length);
|
||||||
|
assertEquals(ruler.getNumberOfLevels(), 0);
|
||||||
|
assertEquals(ruler.getDefaultTabSize(), 0);
|
||||||
|
|
||||||
|
int[] tabStops = ruler.getTabStops();
|
||||||
|
assertNull(tabStops);
|
||||||
|
|
||||||
|
int[] textOffsets = ruler.getTextOffsets();
|
||||||
|
assertTrue(Arrays.equals(new int[]{226, 451, 903, 1129, 1526}, textOffsets));
|
||||||
|
|
||||||
|
int[] bulletOffsets = ruler.getBulletOffsets();
|
||||||
|
assertTrue(Arrays.equals(new int[]{117, 345, 794, 1016, 1526}, bulletOffsets));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteRuler() throws Exception {
|
||||||
|
TextRulerAtom ruler = new TextRulerAtom(data_1, 0, data_1.length);
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
ruler.writeOut(out);
|
||||||
|
|
||||||
|
byte[] result = out.toByteArray();
|
||||||
|
assertTrue(Arrays.equals(result, data_1));
|
||||||
|
}
|
||||||
|
}
|
@ -90,9 +90,11 @@ public class TestRichTextRun extends TestCase {
|
|||||||
|
|
||||||
// Now set it to not bold
|
// Now set it to not bold
|
||||||
rtr.setBold(false);
|
rtr.setBold(false);
|
||||||
assertNotNull(rtr._getRawCharacterStyle());
|
//setting bold=false doesn't change the internal state
|
||||||
assertNotNull(rtr._getRawParagraphStyle());
|
assertNull(rtr._getRawCharacterStyle());
|
||||||
assertFalse(rtr.isBold());
|
assertNull(rtr._getRawParagraphStyle());
|
||||||
|
|
||||||
|
assertFalse(rtr.isBold());
|
||||||
|
|
||||||
// And now make it bold
|
// And now make it bold
|
||||||
rtr.setBold(true);
|
rtr.setBold(true);
|
||||||
|
Loading…
Reference in New Issue
Block a user