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.util.LittleEndian;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.apache.poi.util.HexDump;
|
||||
|
||||
import java.awt.geom.*;
|
||||
import java.util.ArrayList;
|
||||
@ -185,10 +186,6 @@ public class Freeform extends AutoShape {
|
||||
return null;
|
||||
}
|
||||
|
||||
Rectangle2D bounds = getAnchor2D();
|
||||
float right = (float)bounds.getX();
|
||||
float bottom = (float)bounds.getY();
|
||||
|
||||
GeneralPath path = new GeneralPath();
|
||||
int numPoints = verticesProp.getNumberOfElementsInArray();
|
||||
int numSegments = segmentsProp.getNumberOfElementsInArray();
|
||||
@ -199,8 +196,8 @@ public class Freeform extends AutoShape {
|
||||
short x = LittleEndian.getShort(p, 0);
|
||||
short y = LittleEndian.getShort(p, 2);
|
||||
path.moveTo(
|
||||
((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(elem, SEGMENTINFO_CUBICTO) || Arrays.equals(elem, SEGMENTINFO_CUBICTO2)){
|
||||
i++;
|
||||
byte[] p1 = verticesProp.getElement(j++);
|
||||
@ -213,9 +210,9 @@ public class Freeform extends AutoShape {
|
||||
short x3 = LittleEndian.getShort(p3, 0);
|
||||
short y3 = LittleEndian.getShort(p3, 2);
|
||||
path.curveTo(
|
||||
((float)x1*POINT_DPI/MASTER_DPI + right), ((float)y1*POINT_DPI/MASTER_DPI + bottom),
|
||||
((float)x2*POINT_DPI/MASTER_DPI + right), ((float)y2*POINT_DPI/MASTER_DPI + bottom),
|
||||
((float)x3*POINT_DPI/MASTER_DPI + right), ((float)y3*POINT_DPI/MASTER_DPI + bottom));
|
||||
((float)x1*POINT_DPI/MASTER_DPI), ((float)y1*POINT_DPI/MASTER_DPI),
|
||||
((float)x2*POINT_DPI/MASTER_DPI), ((float)y2*POINT_DPI/MASTER_DPI),
|
||||
((float)x3*POINT_DPI/MASTER_DPI), ((float)y3*POINT_DPI/MASTER_DPI));
|
||||
|
||||
} else if (Arrays.equals(elem, SEGMENTINFO_LINETO)){
|
||||
i++;
|
||||
@ -226,18 +223,26 @@ public class Freeform extends AutoShape {
|
||||
short x = LittleEndian.getShort(p, 0);
|
||||
short y = LittleEndian.getShort(p, 2);
|
||||
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)){
|
||||
path.closePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
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 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.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
@ -244,6 +245,9 @@ public class Picture extends SimpleShape {
|
||||
}
|
||||
|
||||
public void draw(Graphics2D graphics){
|
||||
AffineTransform at = graphics.getTransform();
|
||||
ShapePainter.paint(this, graphics);
|
||||
|
||||
PictureData data = getPictureData();
|
||||
if (data instanceof Bitmap){
|
||||
BufferedImage img = null;
|
||||
@ -260,5 +264,6 @@ public class Picture extends SimpleShape {
|
||||
} else {
|
||||
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
|
||||
*/
|
||||
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();
|
||||
shape.setSheet(sheet);
|
||||
shape.setShapeId(sheet.allocateShapeId());
|
||||
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){
|
||||
Rectangle2D anchor = getAnchor2D();
|
||||
Rectangle2D coords = getCoordinates();
|
||||
|
||||
//transform coordinates
|
||||
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();
|
||||
for (int i = 0; i < sh.length; i++) {
|
||||
sh[i].draw(graphics);
|
||||
|
@ -18,12 +18,10 @@
|
||||
|
||||
package org.apache.poi.hslf.model;
|
||||
|
||||
import org.apache.poi.ddf.EscherContainerRecord;
|
||||
import org.apache.poi.ddf.EscherDgRecord;
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
import org.apache.poi.ddf.EscherSpRecord;
|
||||
import org.apache.poi.ddf.*;
|
||||
import org.apache.poi.hslf.record.*;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@ -248,15 +246,47 @@ public abstract class Sheet {
|
||||
spgr.addChildRecord(shape.getSpContainer());
|
||||
|
||||
shape.setSheet(this);
|
||||
shape.setShapeId(allocateShapeId());
|
||||
shape.afterInsert(this);
|
||||
}
|
||||
|
||||
// If it's a TextShape, we need to tell the PPDrawing, as it has to
|
||||
// track TextboxWrappers specially
|
||||
if (shape instanceof TextShape) {
|
||||
TextShape tbox = (TextShape) shape;
|
||||
EscherTextboxWrapper txWrapper = tbox.getEscherTextboxWrapper();
|
||||
if(txWrapper != null) ppdrawing.addTextboxWrapper(txWrapper);
|
||||
/**
|
||||
* Allocates new shape id for the new drawing group id.
|
||||
*
|
||||
* @return a new shape id.
|
||||
*/
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by SlideShow ater a new sheet is created
|
||||
*/
|
||||
public void onCreate(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the master sheet .
|
||||
*/
|
||||
|
@ -126,8 +126,8 @@ public class SimpleShape extends Shape {
|
||||
EscherSimpleProperty p2 = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH);
|
||||
int p2val = p2 == null ? 0 : p2.getPropertyValue();
|
||||
Color clr = null;
|
||||
if (p1 != null && (p2val & 0x8) != 0){
|
||||
int rgb = p1.getPropertyValue();
|
||||
if ((p2val & 0x8) != 0 || (p2val & 0x10) != 0){
|
||||
int rgb = p1 == null ? 0 : p1.getPropertyValue();
|
||||
if (rgb >= 0x8000000) {
|
||||
int idx = rgb % 0x8000000;
|
||||
if(getSheet() != null) {
|
||||
|
@ -21,12 +21,17 @@
|
||||
package org.apache.poi.hslf.model;
|
||||
|
||||
import java.util.Vector;
|
||||
import java.util.Iterator;
|
||||
import java.awt.*;
|
||||
|
||||
import org.apache.poi.hslf.record.SlideAtom;
|
||||
import org.apache.poi.hslf.record.TextHeaderAtom;
|
||||
import org.apache.poi.hslf.record.ColorSchemeAtom;
|
||||
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
|
||||
@ -126,6 +131,42 @@ public class Slide extends Sheet
|
||||
_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.
|
||||
*
|
||||
|
@ -92,6 +92,7 @@ public class SlideMaster extends MasterSheet {
|
||||
} else {
|
||||
switch (txtype) {
|
||||
case TextHeaderAtom.CENTRE_BODY_TYPE:
|
||||
case TextHeaderAtom.HALF_BODY_TYPE:
|
||||
case TextHeaderAtom.QUARTER_BODY_TYPE:
|
||||
txtype = TextHeaderAtom.BODY_TYPE;
|
||||
break;
|
||||
|
@ -17,6 +17,7 @@
|
||||
package org.apache.poi.hslf.model;
|
||||
|
||||
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.POILogFactory;
|
||||
|
||||
@ -38,6 +39,13 @@ import java.util.ArrayList;
|
||||
public class TextPainter {
|
||||
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;
|
||||
|
||||
public TextPainter(TextShape shape){
|
||||
@ -49,6 +57,10 @@ public class TextPainter {
|
||||
*/
|
||||
public AttributedString getAttributedString(TextRun txrun){
|
||||
String text = txrun.getText();
|
||||
//TODO: properly process tabs
|
||||
text = text.replace('\t', ' ');
|
||||
text = text.replace((char)160, ' ');
|
||||
|
||||
AttributedString at = new AttributedString(text);
|
||||
RichTextRun[] rt = txrun.getRichTextRuns();
|
||||
for (int i = 0; i < rt.length; i++) {
|
||||
@ -109,7 +121,24 @@ public class TextPainter {
|
||||
}
|
||||
|
||||
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) {
|
||||
wrappingWidth = _shape.getSheet().getSlideShow().getPageSize().width;
|
||||
@ -141,8 +170,9 @@ public class TextPainter {
|
||||
}
|
||||
|
||||
el._align = rt.getAlignment();
|
||||
el._text = textLayout;
|
||||
el._textOffset = rt.getTextOffset();
|
||||
el.advance = textLayout.getAdvance();
|
||||
el._textOffset = textOffset;
|
||||
el._text = new AttributedString(it, startIndex, endIndex);
|
||||
|
||||
if (prStart){
|
||||
int sp = rt.getSpaceBefore();
|
||||
@ -182,13 +212,25 @@ public class TextPainter {
|
||||
Color clr = rt.getBulletColor();
|
||||
if (clr != null) bat.addAttribute(TextAttribute.FOREGROUND, clr);
|
||||
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){
|
||||
el._bullet = bulletLayout;
|
||||
el._bulletOffset = rt.getBulletOffset();
|
||||
el._bullet = bat;
|
||||
el._bulletOffset = bulletOffset;
|
||||
}
|
||||
}
|
||||
lines.add(el);
|
||||
@ -225,29 +267,32 @@ public class TextPainter {
|
||||
break;
|
||||
case TextShape.AlignCenter:
|
||||
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;
|
||||
case TextShape.AlignRight:
|
||||
pen.x = anchor.getX() + _shape.getMarginLeft() +
|
||||
(anchor.getWidth() - elem._text.getAdvance() - _shape.getMarginLeft() - _shape.getMarginRight());
|
||||
(anchor.getWidth() - elem.advance - _shape.getMarginLeft() - _shape.getMarginRight());
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class TextElement {
|
||||
public TextLayout _text;
|
||||
public static class TextElement {
|
||||
public AttributedString _text;
|
||||
public int _textOffset;
|
||||
public TextLayout _bullet;
|
||||
public AttributedString _bullet;
|
||||
public int _bulletOffset;
|
||||
public int _align;
|
||||
public float ascent, descent;
|
||||
public float advance;
|
||||
}
|
||||
}
|
||||
|
@ -535,9 +535,13 @@ public class TextRun
|
||||
// them to \n
|
||||
String text = rawText.replace('\r','\n');
|
||||
|
||||
//0xB acts like cariage return in page titles
|
||||
text = text.replace((char) 0x0B, '\n');
|
||||
|
||||
int type = _headerAtom == null ? 0 : _headerAtom.getTextType();
|
||||
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;
|
||||
}
|
||||
|
||||
@ -655,4 +659,11 @@ public class TextRun
|
||||
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(){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
|
||||
int valign;
|
||||
int valign = TextShape.AnchorTop;
|
||||
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();
|
||||
switch (type){
|
||||
case TextHeaderAtom.TITLE_TYPE:
|
||||
case TextHeaderAtom.CENTER_TITLE_TYPE:
|
||||
valign = TextShape.AnchorMiddle;
|
||||
break;
|
||||
default:
|
||||
valign = TextShape.AnchorTop;
|
||||
break;
|
||||
MasterSheet master = getSheet().getMasterSheet();
|
||||
if(master != null){
|
||||
TextShape masterShape = master.getPlaceholder(type);
|
||||
if(masterShape != null) valign = masterShape.getVerticalAlignment();
|
||||
} else {
|
||||
//not found in the master sheet. Use the hardcoded defaults.
|
||||
switch (type){
|
||||
case TextHeaderAtom.TITLE_TYPE:
|
||||
case TextHeaderAtom.CENTER_TITLE_TYPE:
|
||||
valign = TextShape.AnchorMiddle;
|
||||
break;
|
||||
default:
|
||||
valign = TextShape.AnchorTop;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
valign = prop.getPropertyValue();
|
||||
|
@ -24,11 +24,13 @@ import org.apache.poi.util.POILogger;
|
||||
|
||||
import org.apache.poi.ddf.*;
|
||||
import org.apache.poi.hslf.model.ShapeTypes;
|
||||
import org.apache.poi.hslf.model.Shape;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* These are actually wrappers onto Escher drawings. Make use of
|
||||
@ -52,6 +54,8 @@ public class PPDrawing extends RecordAtom
|
||||
private EscherRecord[] childRecords;
|
||||
private EscherTextboxWrapper[] textboxWrappers;
|
||||
|
||||
//cached EscherDgRecord
|
||||
private EscherDgRecord dg;
|
||||
|
||||
/**
|
||||
* Get access to the underlying Escher Records
|
||||
@ -296,4 +300,24 @@ public class PPDrawing extends RecordAtom
|
||||
tw[textboxWrappers.length] = txtbox;
|
||||
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 TxCFStyleAtom = new Type(4004,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 TextBytesAtom = new Type(4008,TextBytesAtom.class);
|
||||
public static final Type TxSIStyleAtom = new Type(4009,null);
|
||||
|
@ -127,8 +127,8 @@ public class StyleTextPropAtom extends RecordAtom
|
||||
new ParagraphFlagsTextProp(),
|
||||
new TextProp(2, 0x80, "bullet.char"),
|
||||
new TextProp(2, 0x10, "bullet.font"),
|
||||
new TextProp(2, 0x40, "bullet.size"),
|
||||
new TextProp(4, 0x20, "bullet.color"),
|
||||
new TextProp(2, 0x40, "bullet.size"),
|
||||
new AlignmentTextProp(),
|
||||
new TextProp(2, 0x100, "text.offset"),
|
||||
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.TextPropCollection;
|
||||
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 {
|
||||
protected POILogger logger = POILogFactory.getLogger(this.getClass());
|
||||
|
||||
/** The TextRun we belong to */
|
||||
private TextRun parentRun;
|
||||
/** The SlideShow we belong to */
|
||||
@ -199,10 +203,15 @@ public class RichTextRun {
|
||||
}
|
||||
if (prop == null){
|
||||
Sheet sheet = parentRun.getSheet();
|
||||
int txtype = parentRun.getRunType();
|
||||
MasterSheet master = sheet.getMasterSheet();
|
||||
if (master != null)
|
||||
prop = (BitMaskTextProp)master.getStyleAttribute(txtype, getIndentLevel(), propname, isCharacter);
|
||||
if(sheet != null){
|
||||
int txtype = parentRun.getRunType();
|
||||
MasterSheet master = sheet.getMasterSheet();
|
||||
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);
|
||||
@ -213,7 +222,7 @@ public class RichTextRun {
|
||||
* it if required.
|
||||
*/
|
||||
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) {
|
||||
@ -281,10 +290,14 @@ public class RichTextRun {
|
||||
*/
|
||||
private int getParaTextPropVal(String propName) {
|
||||
TextProp prop = null;
|
||||
boolean hardAttribute = false;
|
||||
if (paragraphStyle != null){
|
||||
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();
|
||||
int txtype = parentRun.getRunType();
|
||||
MasterSheet master = sheet.getMasterSheet();
|
||||
@ -574,6 +587,13 @@ public class RichTextRun {
|
||||
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
|
||||
*/
|
||||
|
@ -24,10 +24,7 @@ import java.util.*;
|
||||
import java.awt.Dimension;
|
||||
import java.io.*;
|
||||
|
||||
import org.apache.poi.ddf.EscherBSERecord;
|
||||
import org.apache.poi.ddf.EscherContainerRecord;
|
||||
import org.apache.poi.ddf.EscherOptRecord;
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
import org.apache.poi.ddf.*;
|
||||
import org.apache.poi.hslf.*;
|
||||
import org.apache.poi.hslf.model.*;
|
||||
import org.apache.poi.hslf.model.Notes;
|
||||
@ -66,9 +63,7 @@ public class SlideShow
|
||||
// Lookup between the PersitPtr "sheet" IDs, and the position
|
||||
// in the mostRecentCoreRecords array
|
||||
private Hashtable _sheetIdToCoreRecordsLookup;
|
||||
// Used when adding new core records
|
||||
private int _highestSheetId;
|
||||
|
||||
|
||||
// Records that are interesting
|
||||
private Document _documentRecord;
|
||||
|
||||
@ -203,8 +198,6 @@ public class SlideShow
|
||||
for(int i=0; i<allIDs.length; 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
|
||||
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();
|
||||
|
||||
// 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
|
||||
sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1));
|
||||
|
||||
|
||||
// Add this new SlidePersistAtom to the SlideListWithText
|
||||
slist.addSlidePersistAtom(sp);
|
||||
|
||||
|
||||
|
||||
|
||||
// Create a new Slide
|
||||
Slide slide = new Slide(sp.getSlideIdentifier(), sp.getRefID(), _slides.length+1);
|
||||
slide.setSlideShow(this);
|
||||
slide.onCreate();
|
||||
|
||||
// Add in to the list of Slides
|
||||
Slide[] s = new Slide[_slides.length+1];
|
||||
System.arraycopy(_slides, 0, s, 0, _slides.length);
|
||||
s[_slides.length] = slide;
|
||||
_slides = s;
|
||||
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
|
||||
org.apache.poi.hslf.record.Slide slideRecord = slide.getSlideRecord();
|
||||
slideRecord.setSheetId(sp.getRefID());
|
||||
int slideRecordPos = _hslfSlideShow.appendRootLevelRecord(slideRecord);
|
||||
_records = _hslfSlideShow.getRecords();
|
||||
|
||||
|
||||
// Add the new Slide into the PersistPtr stuff
|
||||
int offset = 0;
|
||||
int slideOffset = 0;
|
||||
@ -653,7 +643,7 @@ public class SlideShow
|
||||
Record record = _records[i];
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
record.writeOut(out);
|
||||
|
||||
|
||||
// Grab interesting records as they come past
|
||||
if(_records[i].getRecordType() == RecordTypes.PersistPtrIncrementalBlock.typeID){
|
||||
ptr = (PersistPtrHolder)_records[i];
|
||||
@ -661,25 +651,29 @@ public class SlideShow
|
||||
if(_records[i].getRecordType() == RecordTypes.UserEditAtom.typeID) {
|
||||
usr = (UserEditAtom)_records[i];
|
||||
}
|
||||
|
||||
|
||||
if(i == slideRecordPos) {
|
||||
slideOffset = offset;
|
||||
}
|
||||
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
|
||||
// (Also need to tell it where it is)
|
||||
slideRecord.setLastOnDiskOffset(slideOffset);
|
||||
ptr.addSlideLookup(sp.getRefID(), 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
|
||||
slide.setSlideShow(this);
|
||||
return slide;
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class TestFreeform extends TestCase {
|
||||
Freeform p = new Freeform();
|
||||
p.setPath(path1);
|
||||
|
||||
GeneralPath path2 = p.getPath();
|
||||
java.awt.Shape path2 = p.getOutline();
|
||||
assertTrue(new Area(path1).equals(new Area(path2)));
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ public class TestFreeform extends TestCase {
|
||||
Freeform p = new Freeform();
|
||||
p.setPath(path1);
|
||||
|
||||
GeneralPath path2 = p.getPath();
|
||||
java.awt.Shape path2 = p.getOutline();
|
||||
assertTrue(new Area(path1).equals(new Area(path2)));
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ public class TestFreeform extends TestCase {
|
||||
Freeform p = new Freeform();
|
||||
p.setPath(path1);
|
||||
|
||||
GeneralPath path2 = p.getPath();
|
||||
java.awt.Shape path2 = p.getOutline();
|
||||
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.RichTextRun;
|
||||
import org.apache.poi.hslf.HSLFSlideShow;
|
||||
import org.apache.poi.ddf.EscherDggRecord;
|
||||
import org.apache.poi.ddf.EscherDgRecord;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Rectangle;
|
||||
@ -311,18 +313,49 @@ public class TestShapes extends TestCase {
|
||||
public void testShapeId() throws IOException {
|
||||
SlideShow ppt = new SlideShow();
|
||||
Slide slide = ppt.createSlide();
|
||||
Shape shape;
|
||||
Shape shape = null;
|
||||
|
||||
shape = new Line();
|
||||
assertEquals(0, shape.getShapeId());
|
||||
slide.addShape(shape);
|
||||
assertTrue(shape.getShapeId() > 0);
|
||||
//EscherDgg is a document-level record which keeps track of the drawing groups
|
||||
EscherDggRecord dgg = ppt.getDocumentRecord().getPPDrawingGroup().getEscherDggRecord();
|
||||
EscherDgRecord dg = slide.getSheetContainer().getPPDrawing().getEscherDgRecord();
|
||||
|
||||
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();
|
||||
assertEquals(0, shape.getShapeId());
|
||||
slide.addShape(shape);
|
||||
assertEquals(shapeId + 1, shape.getShapeId());
|
||||
int dgMaxId = dg.getLastMSOSPID(); //max shapeId in the slide
|
||||
int dgShapesUsed = dg.getNumShapes(); // number of shapes in the slide
|
||||
//insert 3 shapes and make sure the Ids are properly incremented
|
||||
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
|
||||
rtr.setBold(false);
|
||||
assertNotNull(rtr._getRawCharacterStyle());
|
||||
assertNotNull(rtr._getRawParagraphStyle());
|
||||
assertFalse(rtr.isBold());
|
||||
//setting bold=false doesn't change the internal state
|
||||
assertNull(rtr._getRawCharacterStyle());
|
||||
assertNull(rtr._getRawParagraphStyle());
|
||||
|
||||
assertFalse(rtr.isBold());
|
||||
|
||||
// And now make it bold
|
||||
rtr.setBold(true);
|
||||
|
Loading…
Reference in New Issue
Block a user