From ca8b649bfe1f79b33772d832ddc457b6c2edad98 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Mon, 8 May 2006 16:43:11 +0000 Subject: [PATCH] Fixes from Yegor, from bug #39395 git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@405092 13f79535-47bb-0310-9956-ffa450edef68 --- .../content/xdocs/hslf/how-to-shapes.xml | 25 ++- .../content/xdocs/hslf/hslf_shapes.gif | Bin 5855 -> 7140 bytes .../org/apache/poi/hslf/model/Ellipse.java | 59 ------ .../apache/poi/hslf/model/PPGraphics2D.java | 2 +- .../apache/poi/hslf/model/Placeholder.java | 97 +++++++++ .../org/apache/poi/hslf/model/Rectangle.java | 52 ----- .../src/org/apache/poi/hslf/model/Shape.java | 22 +- .../apache/poi/hslf/model/ShapeFactory.java | 16 +- .../src/org/apache/poi/hslf/model/Slide.java | 27 ++- .../org/apache/poi/hslf/model/TextBox.java | 117 ++++++++-- .../poi/hslf/record/OEPlaceholderAtom.java | 200 ++++++++++++++++++ .../poi/hslf/record/OutlineTextRefAtom.java | 107 ++++++++++ .../apache/poi/hslf/record/RecordTypes.java | 4 +- .../poi/hslf/usermodel/RichTextRun.java | 17 +- .../org/apache/poi/hslf/model/TestShapes.java | 77 ++++--- 15 files changed, 644 insertions(+), 178 deletions(-) delete mode 100644 src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java create mode 100644 src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java delete mode 100644 src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java create mode 100644 src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java create mode 100644 src/scratchpad/src/org/apache/poi/hslf/record/OutlineTextRefAtom.java diff --git a/src/documentation/content/xdocs/hslf/how-to-shapes.xml b/src/documentation/content/xdocs/hslf/how-to-shapes.xml index 21cdb00d18..f20bcef03b 100644 --- a/src/documentation/content/xdocs/hslf/how-to-shapes.xml +++ b/src/documentation/content/xdocs/hslf/how-to-shapes.xml @@ -18,6 +18,7 @@
  • How to get shapes contained in a particular slide
  • Drawing a shape on a slide
  • How to add/retrieve pictures
  • +
  • How to set slide title
  • Features @@ -62,7 +63,7 @@ The following pictute shows the class tree of HSLF shapes:

    - Class Tree of HSLF Shapes + Class Tree of HSLF Shapes

    The following fragment demonstrates how to iterate over shapes for each slide. @@ -209,6 +210,28 @@

    + +
    How to set slide title + + SlideShow ppt = new SlideShow(); + Slide slide = ppt.createSlide(); + TextBox title = slide.addTitle(); + title.setText("Hello, World!"); + + //save changes + FileOutputStream out = new FileOutputStream("slideshow.ppt"); + wb.write(out); + out.close(); + +

    + Below is the equivalent code in PowerPoint VBA: +

    + + Set myDocument = ActivePresentation.Slides(1) + myDocument.Shapes.AddTitle.TextFrame.TextRange.Text = "Hello, World!" + +
    + diff --git a/src/documentation/content/xdocs/hslf/hslf_shapes.gif b/src/documentation/content/xdocs/hslf/hslf_shapes.gif index 9a078b45ac1c7fe1ad30d1bb55b5d05b15988204..ee5eec9f152eeb32ab85e3948c2be8023644e8d4 100644 GIT binary patch delta 6428 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 delta 5132 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 diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java b/src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java deleted file mode 100644 index 0c58bdc128..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java +++ /dev/null @@ -1,59 +0,0 @@ -/* ==================================================================== - Copyright 2002-2004 Apache Software Foundation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import org.apache.poi.ddf.*; - -import java.awt.*; - -/** - * Represents a ellipse in a PowerPoint drawing - * - * @author Yegor Kozlov - */ -public class Ellipse extends SimpleShape { - - protected Ellipse(EscherContainerRecord escherRecord, Shape parent){ - super(escherRecord, parent); - } - - public Ellipse(Shape parent){ - super(null, parent); - _escherContainer = createSpContainer(parent instanceof ShapeGroup); - } - - public Ellipse(){ - this(null); - } - - protected EscherContainerRecord createSpContainer(boolean isChild){ - EscherContainerRecord spcont = super.createSpContainer(isChild); - - EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID); - short type = (ShapeTypes.Ellipse << 4) + 2; - spRecord.setOptions(type); - - //set default properties for a line - EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID); - - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__SHAPEPATH, 4)); - opt.sortProperties(); - - return spcont; - } - -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java b/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java index 80f97416cd..f7cf9f85ab 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java @@ -151,7 +151,7 @@ public class PPGraphics2D extends Graphics2D { if (font != null){ txt.setFontSize(font.getSize()); txt.setFontName(font.getName()); - //if(getColor() != null) txt.setFontColor(getColor()); + if(getColor() != null) txt.setFontColor(getColor()); if (font.isBold()) txt.setBold(true); if (font.isItalic()) txt.setItalic(true); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java b/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java new file mode 100644 index 0000000000..228eddb205 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java @@ -0,0 +1,97 @@ +/* ==================================================================== + Copyright 2002-2004 Apache Software Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import org.apache.poi.ddf.*; +import org.apache.poi.hslf.record.OEPlaceholderAtom; + +import java.util.List; +import java.io.ByteArrayOutputStream; + +/** + * Represents a Placeholder in PowerPoint. + * + * @author Yegor Kozlov + */ +public class Placeholder extends TextBox { + + protected Placeholder(EscherContainerRecord escherRecord, Shape parent){ + super(escherRecord, parent); + } + + public Placeholder(Shape parent){ + super(parent); + } + + public Placeholder(){ + super(); + } + + /** + * Create a new Placeholder and initialize internal structures + * + * @return the created EscherContainerRecord which holds shape data + */ + protected EscherContainerRecord createSpContainer(boolean isChild){ + EscherContainerRecord spcont = super.createSpContainer(isChild); + + EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID); + spRecord.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER); + + EscherClientDataRecord cldata = new EscherClientDataRecord(); + cldata.setOptions((short)15); + + EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID); + + //Placeholders can't be grouped + setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 262144); + + //OEPlaceholderAtom tells powerpoint that this shape is a placeholder + // + OEPlaceholderAtom oep = new OEPlaceholderAtom(); + /** + * Extarct from MSDN: + * + * There is a special case when the placeholder does not have a position in the layout. + * This occurs when the user has moved the placeholder from its original position. + * In this case the placeholder ID is -1. + */ + oep.setPlacementId(-1); + + oep.setPlaceholderId(OEPlaceholderAtom.Body); + + //convert hslf into ddf record + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + oep.writeOut(out); + } catch(Exception e){ + throw new RuntimeException(e); + } + cldata.setRemainingData(out.toByteArray()); + + //append placeholder container before EscherTextboxRecord + List lst = spcont.getChildRecords(); + for (int i = 0; i < lst.size(); i++) { + EscherRecord rec = (EscherRecord)lst.get(i); + if(rec.getRecordId() == EscherTextboxRecord.RECORD_ID){ + lst.add(i++, cldata); + } + } + + return spcont; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java b/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java deleted file mode 100644 index 1d69c47a44..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java +++ /dev/null @@ -1,52 +0,0 @@ -/* ==================================================================== - Copyright 2002-2004 Apache Software Foundation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import org.apache.poi.ddf.*; - -import java.awt.*; - -/** - * Represents a rectangle shae in a PowerPoint drawing - * - * @author Yegor Kozlov - */ -public class Rectangle extends TextBox { - - protected Rectangle(EscherContainerRecord escherRecord, Shape parent){ - super(escherRecord, parent); - } - - public Rectangle(Shape parent){ - super(parent); - } - - public Rectangle(){ - super(); - } - - protected EscherContainerRecord createSpContainer(boolean isChild){ - EscherContainerRecord spcont = super.createSpContainer(isChild); - - EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID); - short type = (ShapeTypes.Rectangle << 4) + 2; - spRecord.setOptions(type); - - return spcont; - } - -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java b/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java index 666568bfd6..0a51ed8f7c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java @@ -112,9 +112,27 @@ public abstract class Shape { return ShapeTypes.typeName(spRecord.getOptions() >> 4); } + /** + * @return type of the shape. + * @see org.apache.poi.hslf.record.RecordTypes + */ + public int getShapeType(){ + EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); + return spRecord.getOptions() >> 4; + } + + /** + * @param type type of the shape. + * @see org.apache.poi.hslf.record.RecordTypes + */ + public void setShapeType(int type){ + EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); + spRecord.setOptions((short)(type << 4 | 0x2)); + } + /** * Returns the anchor (the bounding box rectangle) of this shape. - * All coordinates are expressed in Master units (576 dpi). + * All coordinates are expressed in points (72 dpi). * * @return the anchor of this shape */ @@ -143,7 +161,7 @@ public abstract class Shape { /** * Sets the anchor (the bounding box rectangle) of this shape. - * All coordinates should be expressed in poitns (72 dpi). + * All coordinates should be expressed in points (72 dpi). * * @param anchor new anchor */ diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java index 5c7f1c89a9..f8a86a1963 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java @@ -15,8 +15,7 @@ ==================================================================== */ package org.apache.poi.hslf.model; -import org.apache.poi.ddf.EscherSpRecord; -import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.*; /** * Create a Shape object depending on its type @@ -38,12 +37,19 @@ public class ShapeFactory { int type = spRecord.getOptions() >> 4; switch (type){ + case ShapeTypes.Rectangle: + EscherTextboxRecord txtbox = (EscherTextboxRecord)Shape.getEscherChild(spContainer, EscherTextboxRecord.RECORD_ID); + if (txtbox == null) shape = new AutoShape(spContainer, parent); + else{ + if(Shape.getEscherChild(spContainer, EscherClientDataRecord.RECORD_ID) != null ) + shape = new Placeholder(spContainer, parent); + else + shape = new TextBox(spContainer, parent); + } + break; case ShapeTypes.TextBox: shape = new TextBox(spContainer, parent); break; - case ShapeTypes.Rectangle: - shape = new Rectangle(spContainer, parent); - break; case ShapeTypes.PictureFrame: shape = new Picture(spContainer, parent); break; diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java index 69ee02a439..96ca4a42e9 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java @@ -23,6 +23,7 @@ import java.util.Vector; import org.apache.poi.hslf.record.PPDrawing; import org.apache.poi.hslf.record.SlideAtom; +import org.apache.poi.hslf.record.TextHeaderAtom; import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet; /** @@ -117,6 +118,21 @@ public class Slide extends Sheet sa.setNotesID(notes._getSheetNumber()); } } + + /** + * Create a TextBox object that represents the slide's title. + * + * @return TextBox object that represents the slide's title. + */ + public TextBox addTitle() { + Placeholder pl = new Placeholder(); + pl.setShapeType(ShapeTypes.Rectangle); + pl.setTextType(TextHeaderAtom.TITLE_TYPE); + pl.setText("Click to edit title"); + pl.setAnchor(new java.awt.Rectangle(54, 48, 612, 90)); + addShape(pl); + return pl; + } // Accesser methods follow @@ -133,7 +149,7 @@ public class Slide extends Sheet public int _getSheetRefId() { return _refSheetNo; } /** * Returns the (internal, SlideIdentifier based) sheet number - * @see getSlideNumber() + * @see #getSlideNumber() */ public int _getSheetNumber() { return _sheetNo; } @@ -152,5 +168,14 @@ public class Slide extends Sheet */ public Notes getNotesSheet() { return _notes; } + /** + * Returns the PPDrawing associated with this slide, or null if there isn't one + */ protected PPDrawing getPPDrawing() { return _slide.getPPDrawing(); } + + /** + * @return set of records inside SlideListWithtext container + * which hold text data for this slide (typically for placeholders). + */ + protected SlideAtomsSet getSlideAtomsSet() { return _atomSet; } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java index de1d81c854..465896d61d 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java @@ -85,6 +85,8 @@ public class TextBox extends SimpleShape { */ protected EscherTextboxWrapper _txtbox; + private String _fontname; + /** * Create a TextBox object and initialize it from the supplied Record container. * @@ -96,17 +98,6 @@ public class TextBox extends SimpleShape { EscherTextboxRecord textbox = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID); _txtbox = new EscherTextboxWrapper(textbox); - - // Find our TextRun - Vector v = new Vector(); - Sheet.findTextRuns(_txtbox.getChildRecords(), v); - - // We should just have one - if(v.size() == 1) { - _txtrun = (TextRun)v.get(0); - } else { - throw new IllegalStateException("A TextBox should have one TextRun's worth of records in it, found " + v.size()); - } } /** @@ -206,6 +197,7 @@ public class TextBox extends SimpleShape { } catch (IOException e){ throw new RuntimeException(e); } + if(getAnchor().equals(new java.awt.Rectangle())) resizeToFitText(); } /** @@ -214,7 +206,7 @@ public class TextBox extends SimpleShape { * * @return the bounds of this TextFrame. */ - protected Dimension getTextSize(){ + protected Dimension getTextDimensions(){ FontRenderContext frc = new FontRenderContext(null, true, true); RichTextRun rt = _txtrun.getRichTextRuns()[0]; int size = rt.getFontSize(); @@ -229,9 +221,9 @@ public class TextBox extends SimpleShape { TextLayout layout = new TextLayout(getText(), font, frc); int width = Math.round(layout.getAdvance()); - width += getMarginLeft() + getMarginRight(); + width += getMarginLeft() + getMarginRight() + 2; int height = Math.round(layout.getAscent()); - height += getMarginTop() + getMarginBottom(); + height += getMarginTop() + getMarginBottom() + 12; return new Dimension(width, height); } @@ -239,7 +231,7 @@ public class TextBox extends SimpleShape { * Adjust the size of the TextBox so it encompasses the text inside it. */ public void resizeToFitText(){ - Dimension size = getTextSize(); + Dimension size = getTextDimensions(); java.awt.Rectangle anchor = getAnchor(); anchor.setSize(size); setAnchor(anchor); @@ -448,6 +440,17 @@ public class TextBox extends SimpleShape { return rt.getFontSize(); } + /** + * + * @return the size of the font applied to this text shape + */ + public Color getFontColor(){ + RichTextRun rt = _txtrun.getRichTextRuns()[0]; + Color color = new Color(rt.getFontColor()); + //in PowerPont RGB bytes are swapped, + return new Color(color.getBlue(), color.getGreen(), color.getRed(), 255); + } + /** * Set whether to use bold or not * @@ -484,8 +487,92 @@ public class TextBox extends SimpleShape { * @param name the name of the font to be applied to this text shape */ public void setFontName(String name){ + if (_sheet == null) { + //we can't set font since slideshow is not assigned yet + _fontname = name; + } else{ RichTextRun rt = _txtrun.getRichTextRuns()[0]; rt.setFontName(name); } + } + + /** + * Sets the font color + * @param color the font color + */ + public void setFontColor(Color color){ + //in PowerPont RGB bytes are swapped, + int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB(); + RichTextRun rt = _txtrun.getRichTextRuns()[0]; + rt.setFontColor(rgb); + } + + /** + * Set type of the text. + * Must be one of the static constants defined in TextHeaderAtom + * + * @param type type of the text + */ + public void setTextType(int type){ + _txtrun._headerAtom.setTextType(type); + } + public void setSheet(Sheet sheet){ + _sheet = sheet; + + //initialize _txtrun object. + //we can't do it in the constructor because the sheet is not assigned yet + if(_txtrun == null) initTextRun(); + + RichTextRun[] rt = _txtrun.getRichTextRuns(); + for (int i = 0; i < rt.length; i++) { + rt[i].supplySlideShow(_sheet.getSlideShow()); + } + if (_fontname != null) { + setFontName(_fontname); + _fontname = null; + } + + } + + private void initTextRun(){ + + TextHeaderAtom tha = null; + TextCharsAtom tca = null; + TextBytesAtom tba = null; + StyleTextPropAtom sta = null; + OutlineTextRefAtom ota = null; + Record[] child = _txtbox.getChildRecords(); + for (int i = 0; i < child.length; i++) { + if (child[i] instanceof TextHeaderAtom) tha = (TextHeaderAtom)child[i]; + else if (child[i] instanceof TextBytesAtom) tba = (TextBytesAtom)child[i]; + else if (child[i] instanceof StyleTextPropAtom) sta = (StyleTextPropAtom)child[i]; + else if (child[i] instanceof OutlineTextRefAtom) ota = (OutlineTextRefAtom)child[i]; + else if (child[i] instanceof TextCharsAtom) tca = (TextCharsAtom)child[i]; + } + + if (ota != null){ + //TextHeaderAtom, TextBytesAtom and StyleTextPropAtom are stored outside of EscherContainerRecord + int idx = ota.getTextIndex(); + Slide sl = (Slide)getSheet(); + Record[] rec = sl.getSlideAtomsSet().getSlideRecords(); + for (int i = 0, j = 0; i < rec.length; i++) { + if(rec[i].getRecordType() == RecordTypes.TextHeaderAtom.typeID){ + if(j++ == idx) { //we found j-th TextHeaderAtom, read the text data + for (int k = i; k < rec.length; k++) { + if (rec[k] instanceof TextHeaderAtom) { + if (tha != null) break; + else tha = (TextHeaderAtom)rec[k]; + } + else if (rec[k] instanceof TextBytesAtom) tba = (TextBytesAtom)rec[k]; + else if (rec[k] instanceof TextCharsAtom) tca = (TextCharsAtom)rec[k]; + else if (rec[k] instanceof StyleTextPropAtom) sta = (StyleTextPropAtom)rec[k]; + } + } + } + } + } + if(tba != null) _txtrun = new TextRun(tha,tba,sta); + else if (tca != null) _txtrun = new TextRun(tha,tca,sta); + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java new file mode 100644 index 0000000000..7c588b98f9 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java @@ -0,0 +1,200 @@ + +/* ==================================================================== + Copyright 2002-2004 Apache Software Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + + +package org.apache.poi.hslf.record; + +import org.apache.poi.util.LittleEndian; +import java.io.IOException; +import java.io.OutputStream; + +/** + * OEPlaceholderAtom (3011). + *

    + * Atom that describes the placeholder. + *

    + * + * @author Yegor Kozlov + */ + +public class OEPlaceholderAtom extends RecordAtom{ + + public static final int PLACEHOLDER_FULLSIZE = 0; + public static final int PLACEHOLDER_HALFSIZE = 1; + public static final int PLACEHOLDER_QUARTSIZE = 2; + + public static final byte None = 0; + + public static final byte MasterTitle = 1; + + public static final byte MasterBody = 2; + + public static final byte MasterCenteredTitle = 3; + + public static final byte MasterNotesSlideImage = 4; + + public static final byte MasterNotesBodyImage = 5; + + public static final byte MasterDate = 6; + + public static final byte MasterSlideNumber = 7; + + public static final byte MasterFooter = 8; + + public static final byte MasterHeader = 9; + + public static final byte MasterSubtitle = 10; + + public static final byte GenericTextObject = 11; + + public static final byte Title = 12; + + public static final byte Body = 13; + + public static final byte NotesBody = 14; + + public static final byte CenteredTitle = 15; + + public static final byte Subtitle = 16; + + public static final byte VerticalTextTitle = 17; + + public static final byte VerticalTextBody = 18; + + public static final byte NotesSlideImage = 19; + + public static final byte Object = 20; + + public static final byte Graph = 21; + + public static final byte Table = 22; + + public static final byte ClipArt = 23; + + public static final byte OrganizationChart = 24; + + public static final byte MediaClip = 25; + + private byte[] _header; + + private int placementId; + private int placeholderId; + private int placeholderSize; + + + /** + * Create a new instance of OEPlaceholderAtom + */ + public OEPlaceholderAtom(){ + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 0); + LittleEndian.putUShort(_header, 2, (int)getRecordType()); + LittleEndian.putInt(_header, 4, 8); + + placementId = 0; + placeholderId = 0; + placeholderSize = 0; + } + + /** + * Build an instance of OEPlaceholderAtom from on-disk data + */ + protected OEPlaceholderAtom(byte[] source, int start, int len) { + _header = new byte[8]; + System.arraycopy(source,start,_header,0,8); + + placementId = LittleEndian.getInt(source, start); + placeholderId = LittleEndian.getUnsignedByte(source, start+4); + placeholderSize = LittleEndian.getUnsignedByte(source, start+5); + } + + /** + * @return type of this record {@link RecordTypes#OEPlaceholderAtom}. + */ + public long getRecordType() { return RecordTypes.OEPlaceholderAtom.typeID; } + + /** + * Returns the placement Id. + * + * @return the placement Id. + */ + public int getPlacementId(){ + return placementId; + } + + /** + * Sets the placement Id. + * + * @param id the placement Id. + */ + public void setPlacementId(int id){ + placementId = id; + } + + /** + * Returns the placeholder Id. + * + * @return the placeholder Id. + */ + public int getPlaceholderId(){ + return placeholderId; + } + + /** + * Sets the placeholder Id. + * + * @param id the placeholder Id. + */ + public void setPlaceholderId(byte id){ + placeholderId = id; + } + + /** + * Returns the placeholder size. + * Must be one of the PLACEHOLDER_* static constants defined in this class. + * + * @return the placeholder size. + */ + public int getPlaceholderSize(){ + return placeholderSize; + } + + /** + * Sets the placeholder size. + * Must be one of the PLACEHOLDER_* static constants defined in this class. + * + * @param size the placeholder size. + */ + public void setPlaceholderSize(byte size){ + placeholderSize = size; + } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + out.write(_header); + + byte[] recdata = new byte[8]; + LittleEndian.putInt(recdata, 0, placementId); + recdata[4] = (byte)placeholderId; + recdata[5] = (byte)placeholderSize; + + out.write(recdata); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/OutlineTextRefAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/OutlineTextRefAtom.java new file mode 100644 index 0000000000..ed92d8a7e5 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/record/OutlineTextRefAtom.java @@ -0,0 +1,107 @@ +/* ==================================================================== + Copyright 2002-2004 Apache Software Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hslf.record; + +import org.apache.poi.util.LittleEndian; + +import java.io.OutputStream; +import java.io.IOException; + +/** + * OEPlaceholderAtom (3998). + *
    + * What MSDN says about OutlineTextRefAtom: + *

    + * Appears in a slide to indicate a text that is already contained in the document, + * in a SlideListWithText containter. Sometimes slide texts are not contained + * within the slide container to be able to delay loading a slide and still display + * the title and body text in outline view. + *

    + * + * @author Yegor Kozlov + */ + +public class OutlineTextRefAtom extends RecordAtom { + /** + * record header + */ + private byte[] _header; + + /** + * the text's index within the SlideListWithText (0 for title, 1..n for the nth body) + */ + private int _index; + + /** + * Build an instance of OutlineTextRefAtom from on-disk data + */ + protected OutlineTextRefAtom(byte[] source, int start, int len) { + // Get the header + _header = new byte[8]; + System.arraycopy(source,start,_header,0,8); + + // Grab the record data + _index = LittleEndian.getInt(source, start+8); + } + + /** + * Create a new instance of FontEntityAtom + */ + protected OutlineTextRefAtom() { + _index = 0; + + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 0); + LittleEndian.putUShort(_header, 2, (int)getRecordType()); + LittleEndian.putInt(_header, 4, 4); + } + + public long getRecordType() { + return RecordTypes.OutlineTextRefAtom.typeID; + } + + /** + * Write the contents of the record back, so it can be written to disk + */ + public void writeOut(OutputStream out) throws IOException { + out.write(_header); + + byte[] recdata = new byte[4]; + LittleEndian.putInt(recdata, 0, _index); + out.write(recdata); + } + + /** + * Sets text's index within the SlideListWithText container + * (0 for title, 1..n for the nth body). + * + * @param idx 0-based text's index + */ + public void setTextIndex(int idx){ + _index = idx; + } + + /** + * Return text's index within the SlideListWithText container + * (0 for title, 1..n for the nth body). + * + * @return idx text's index + */ + public int getTextIndex(){ + return _index; + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java index 41935120c1..e9b7062d72 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java @@ -76,10 +76,10 @@ public class RecordTypes { public static final Type ColorSchemeAtom = new Type(2032,ColorSchemeAtom.class); public static final Type ExObjRefAtom = new Type(3009,null); public static final Type OEShapeAtom = new Type(3009,null); - public static final Type OEPlaceholderAtom = new Type(3011,null); + public static final Type OEPlaceholderAtom = new Type(3011,OEPlaceholderAtom.class); public static final Type GPopublicintAtom = new Type(3024,null); public static final Type GRatioAtom = new Type(3031,null); - public static final Type OutlineTextRefAtom = new Type(3998,null); + public static final Type OutlineTextRefAtom = new Type(3998,OutlineTextRefAtom.class); public static final Type TextHeaderAtom = new Type(3999,TextHeaderAtom.class); public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class); public static final Type StyleTextPropAtom = new Type(4001,StyleTextPropAtom.class); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java index b94250e6c6..bb9bdb5800 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java @@ -93,7 +93,7 @@ public class RichTextRun /** * Supply the SlideShow we belong to */ - protected void supplySlideShow(SlideShow ss) { + public void supplySlideShow(SlideShow ss) { slideShow = ss; } @@ -281,6 +281,21 @@ public class RichTextRun return slideShow.getFontCollection().getFontWithId(fontIdx); } + /** + * @return font color as RGB value + * @see java.awt.Color + */ + public int getFontColor() { + return getCharTextPropVal("font.color"); + } + /** + * Sets color of the text, as a RGB value + * @see java.awt.Color + */ + public void setFontColor(int rgb) { + setCharTextPropVal("font.color", rgb); + } + // --------------- Internal HSLF methods, not intended for end-user use! ------- diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java index ed98fad0ab..a410f8468f 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java @@ -25,6 +25,7 @@ import java.awt.Rectangle; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.FileOutputStream; +import java.util.ArrayList; /** * Test drawing shapes via Graphics2D @@ -132,10 +133,12 @@ public class TestShapes extends TestCase { // Create a new textbox, and give it lots of properties TextBox txtbox = new TextBox(); txtbox.setText(val); + txtbox.setFontName("Arial"); txtbox.setFontSize(42); txtbox.setBold(true); txtbox.setItalic(true); txtbox.setUnderline(false); + txtbox.setFontColor(Color.red); sl.addShape(txtbox); // Check it before save @@ -145,6 +148,8 @@ public class TestShapes extends TestCase { assertTrue(rt.isBold()); assertTrue(rt.isItalic()); assertFalse(rt.isUnderlined()); + assertEquals("Arial", rt.getFontName()); + assertEquals(Color.red, txtbox.getFontColor()); // Serialize and read again ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -162,50 +167,44 @@ public class TestShapes extends TestCase { assertTrue(rt.isBold()); assertTrue(rt.isItalic()); assertFalse(rt.isUnderlined()); + assertEquals("Arial", rt.getFontName()); + assertEquals(Color.red, txtbox.getFontColor()); } /** - * Verify that we can add TextBox shapes to a slide - * and set some of the style attributes, with a unicode string + * If you iterate over text shapes in a slide and collect them in a set + * it must be the same as returned by Slide.getTextRuns(). */ - public void testTextBoxWriteChars() throws Exception { - ppt = new SlideShow(); - Slide sl = ppt.createSlide(); - RichTextRun rt; - - String val = "Hello, World! (With some \u1234 and \uffee unicode in it)"; - - // Create a new textbox, and give it lots of properties - TextBox txtbox = new TextBox(); - txtbox.setText(val); - txtbox.setFontSize(42); - txtbox.setBold(true); - txtbox.setUnderline(false); - sl.addShape(txtbox); - - // Check it before save - rt = txtbox.getRichTextRuns()[0]; - assertEquals(val, rt.getText()); - assertEquals(42, rt.getFontSize()); - assertTrue(rt.isBold()); - assertFalse(rt.isItalic()); - assertFalse(rt.isUnderlined()); - - // Serialize and read again - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ppt.write(out); - out.close(); - - ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()))); + public void testTextBoxSet() throws Exception { + textBoxSet("/with_textbox.ppt"); + textBoxSet("/basic_test_ppt_file.ppt"); + textBoxSet("/next_test_ppt_file.ppt"); + textBoxSet("/Single_Coloured_Page.ppt"); + textBoxSet("/Single_Coloured_Page_With_Fonts_and_Alignments.ppt"); + textBoxSet("/incorrect_slide_order.ppt"); + } - txtbox = (TextBox)sl.getShapes()[0]; - rt = txtbox.getRichTextRuns()[0]; + private void textBoxSet(String filename) throws Exception { + String dirname = System.getProperty("HSLF.testdata.path"); + SlideShow ppt = new SlideShow(new HSLFSlideShow(dirname + filename)); + Slide[] sl = ppt.getSlides(); + for (int k = 0; k < sl.length; k++) { + ArrayList lst1 = new ArrayList(); + TextRun[] txt = sl[k].getTextRuns(); + for (int i = 0; i < txt.length; i++) { + lst1.add(txt[i].getText()); + } - // Check after save - assertEquals(val, rt.getText()); - assertEquals(42, rt.getFontSize()); - assertTrue(rt.isBold()); - assertFalse(rt.isItalic()); - assertFalse(rt.isUnderlined()); + ArrayList lst2 = new ArrayList(); + Shape[] sh = sl[k].getShapes(); + for (int i = 0; i < sh.length; i++) { + if (sh[i] instanceof TextBox){ + TextBox tbox = (TextBox)sh[i]; + lst2.add(tbox.getText()); + } + } + assertTrue(lst1.containsAll(lst2)); + assertTrue(lst2.containsAll(lst1)); + } } } -- 2.39.5