You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ye...@apache.org on 2008/06/21 14:03:49 UTC
svn commit: r670186 [5/7] - in /poi/tags/REL_3_1_FINAL: ./ legal/
src/documentation/content/xdocs/ src/examples/src/org/apache/poi/hslf/
src/examples/src/org/apache/poi/hslf/usermodel/
src/examples/src/org/apache/poi/hslf/usermodel/examples/ src/java/o...
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java Sat Jun 21 05:03:44 2008
@@ -683,4 +683,13 @@
String ns = s.replaceAll("\\r?\\n", "\r");
return ns;
}
+
+ /**
+ * Returns records that make up this text run
+ *
+ * @return text run records
+ */
+ public Record[] getRecords(){
+ return _records;
+ }
}
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java Sat Jun 21 05:03:44 2008
@@ -1,537 +1,545 @@
-
-/* ====================================================================
- 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.model;
-
-import org.apache.poi.ddf.*;
-import org.apache.poi.hslf.record.*;
-import org.apache.poi.hslf.usermodel.RichTextRun;
-import org.apache.poi.hslf.exceptions.HSLFException;
-import org.apache.poi.util.POILogger;
-
-import java.awt.*;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.AffineTransform;
-import java.awt.font.FontRenderContext;
-import java.awt.font.TextLayout;
-import java.io.IOException;
-
-/**
- * A common superclass of all shapes that can hold text.
- *
- * @author Yegor Kozlov
- */
-public abstract class TextShape extends SimpleShape {
-
- /**
- * How to anchor the text
- */
- public static final int AnchorTop = 0;
- public static final int AnchorMiddle = 1;
- public static final int AnchorBottom = 2;
- public static final int AnchorTopCentered = 3;
- public static final int AnchorMiddleCentered = 4;
- public static final int AnchorBottomCentered = 5;
- public static final int AnchorTopBaseline = 6;
- public static final int AnchorBottomBaseline = 7;
- public static final int AnchorTopCenteredBaseline = 8;
- public static final int AnchorBottomCenteredBaseline = 9;
-
- /**
- * How to wrap the text
- */
- public static final int WrapSquare = 0;
- public static final int WrapByPoints = 1;
- public static final int WrapNone = 2;
- public static final int WrapTopBottom = 3;
- public static final int WrapThrough = 4;
-
- /**
- * How to align the text
- */
- public static final int AlignLeft = 0;
- public static final int AlignCenter = 1;
- public static final int AlignRight = 2;
- public static final int AlignJustify = 3;
-
- /**
- * TextRun object which holds actual text and format data
- */
- protected TextRun _txtrun;
-
- /**
- * Escher container which holds text attributes such as
- * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc.
- */
- protected EscherTextboxWrapper _txtbox;
-
- /**
- * Used to calculate text bounds
- */
- protected static final FontRenderContext _frc = new FontRenderContext(null, true, true);
-
- /**
- * Create a TextBox object and initialize it from the supplied Record container.
- *
- * @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
- * @param parent the parent of the shape
- */
- protected TextShape(EscherContainerRecord escherRecord, Shape parent){
- super(escherRecord, parent);
-
- }
-
- /**
- * Create a new TextBox. This constructor is used when a new shape is created.
- *
- * @param parent the parent of this Shape. For example, if this text box is a cell
- * in a table then the parent is Table.
- */
- public TextShape(Shape parent){
- super(null, parent);
- _escherContainer = createSpContainer(parent instanceof ShapeGroup);
- }
-
- /**
- * Create a new TextBox. This constructor is used when a new shape is created.
- *
- */
- public TextShape(){
- this(null);
- }
-
- public TextRun createTextRun(){
- _txtbox = getEscherTextboxWrapper();
- if(_txtbox == null) _txtbox = new EscherTextboxWrapper();
-
- _txtrun = getTextRun();
- if(_txtrun == null){
- TextHeaderAtom tha = new TextHeaderAtom();
- tha.setParentRecord(_txtbox);
- _txtbox.appendChildRecord(tha);
-
- TextCharsAtom tca = new TextCharsAtom();
- _txtbox.appendChildRecord(tca);
-
- StyleTextPropAtom sta = new StyleTextPropAtom(0);
- _txtbox.appendChildRecord(sta);
-
- _txtrun = new TextRun(tha,tca,sta);
- _txtrun.setText("");
-
- _escherContainer.addChildRecord(_txtbox.getEscherRecord());
-
- setDefaultTextProperties(_txtrun);
- }
-
- return _txtrun;
- }
-
- /**
- * Set default properties for the TextRun.
- * Depending on the text and shape type the defaults are different:
- * TextBox: align=left, valign=top
- * AutoShape: align=center, valign=middle
- *
- */
- protected void setDefaultTextProperties(TextRun _txtrun){
-
- }
-
- /**
- * Returns the text contained in this text frame.
- *
- * @return the text string for this textbox.
- */
- public String getText(){
- TextRun tx = getTextRun();
- return tx == null ? null : tx.getText();
- }
-
- /**
- * Sets the text contained in this text frame.
- *
- * @param text the text string used by this object.
- */
- public void setText(String text){
- TextRun tx = getTextRun();
- if(tx == null){
- tx = createTextRun();
- }
- tx.setText(text);
- setTextId(text.hashCode());
- }
-
- /**
- * When a textbox is added to a sheet we need to tell upper-level
- * <code>PPDrawing</code> about it.
- *
- * @param sh the sheet we are adding to
- */
- protected void afterInsert(Sheet sh){
- super.afterInsert(sh);
-
- EscherTextboxWrapper _txtbox = getEscherTextboxWrapper();
- if(_txtbox != null){
- PPDrawing ppdrawing = sh.getPPDrawing();
- ppdrawing.addTextboxWrapper(_txtbox);
- // Ensure the escher layer knows about the added records
- try {
- _txtbox.writeOut(null);
- } catch (IOException e){
- throw new HSLFException(e);
- }
- if(getAnchor().equals(new Rectangle()) && !"".equals(getText())) resizeToFitText();
- }
- }
-
- protected EscherTextboxWrapper getEscherTextboxWrapper(){
- if(_txtbox == null){
- EscherTextboxRecord textRecord = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID);
- if(textRecord != null) _txtbox = new EscherTextboxWrapper(textRecord);
- }
- return _txtbox;
- }
- /**
- * Adjust the size of the TextShape so it encompasses the text inside it.
- *
- * @return a <code>Rectangle2D</code> that is the bounds of this <code>TextShape</code>.
- */
- public Rectangle2D resizeToFitText(){
- String txt = getText();
- if(txt == null || txt.length() == 0) return new Rectangle2D.Float();
-
- RichTextRun rt = getTextRun().getRichTextRuns()[0];
- int size = rt.getFontSize();
- int style = 0;
- if (rt.isBold()) style |= Font.BOLD;
- if (rt.isItalic()) style |= Font.ITALIC;
- String fntname = rt.getFontName();
- Font font = new Font(fntname, style, size);
-
- float width = 0, height = 0;
- String[] lines = txt.split("\r");
- for (int i = 0; i < lines.length; i++) {
- if(lines[i].length() == 0) continue;
-
- TextLayout layout = new TextLayout(lines[i], font, _frc);
-
- width = Math.max(width, layout.getAdvance());
-
- /**
- * Even if top and bottom margins are set to 0 PowerPoint
- * always sets extra space between the text and its bounding box.
- *
- * The approximation height = ascent*2 works good enough in most cases
- */
- height = Math.max(height, 2*layout.getAscent());
- }
-
- width += getMarginLeft() + getMarginRight();
- height += getMarginTop() + getMarginBottom();
-
- Rectangle2D anchor = getAnchor2D();
- anchor.setRect(anchor.getX(), anchor.getY(), width, height);
- setAnchor(anchor);
-
- return anchor;
- }
-
- /**
- * Returns the type of vertical alignment for the text.
- * One of the <code>Anchor*</code> constants defined in this class.
- *
- * @return the type of alignment
- */
- public int getVerticalAlignment(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
- 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();
- 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();
- }
- return valign;
- }
-
- /**
- * Sets the type of vertical alignment for the text.
- * One of the <code>Anchor*</code> constants defined in this class.
- *
- * @param align - the type of alignment
- */
- public void setVerticalAlignment(int align){
- setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align);
- }
-
- /**
- * Sets the type of horizontal alignment for the text.
- * One of the <code>Align*</code> constants defined in this class.
- *
- * @param align - the type of horizontal alignment
- */
- public void setHorizontalAlignment(int align){
- TextRun tx = getTextRun();
- if(tx != null) tx.getRichTextRuns()[0].setAlignment(align);
- }
-
- /**
- * Gets the type of horizontal alignment for the text.
- * One of the <code>Align*</code> constants defined in this class.
- *
- * @return align - the type of horizontal alignment
- */
- public int getHorizontalAlignment(){
- TextRun tx = getTextRun();
- return tx == null ? -1 : tx.getRichTextRuns()[0].getAlignment();
- }
-
- /**
- * Returns the distance (in points) between the bottom of the text frame
- * and the bottom of the inscribed rectangle of the shape that contains the text.
- * Default value is 1/20 inch.
- *
- * @return the botom margin
- */
- public float getMarginBottom(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
- int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
- return (float)val/EMU_PER_POINT;
- }
-
- /**
- * Sets the botom margin.
- * @see #getMarginBottom()
- *
- * @param margin the bottom margin
- */
- public void setMarginBottom(float margin){
- setEscherProperty(EscherProperties.TEXT__TEXTBOTTOM, (int)(margin*EMU_PER_POINT));
- }
-
- /**
- * Returns the distance (in points) between the left edge of the text frame
- * and the left edge of the inscribed rectangle of the shape that contains
- * the text.
- * Default value is 1/10 inch.
- *
- * @return the left margin
- */
- public float getMarginLeft(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
- int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
- return (float)val/EMU_PER_POINT;
- }
-
- /**
- * Sets the left margin.
- * @see #getMarginLeft()
- *
- * @param margin the left margin
- */
- public void setMarginLeft(float margin){
- setEscherProperty(EscherProperties.TEXT__TEXTLEFT, (int)(margin*EMU_PER_POINT));
- }
-
- /**
- * Returns the distance (in points) between the right edge of the
- * text frame and the right edge of the inscribed rectangle of the shape
- * that contains the text.
- * Default value is 1/10 inch.
- *
- * @return the right margin
- */
- public float getMarginRight(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT);
- int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
- return (float)val/EMU_PER_POINT;
- }
-
- /**
- * Sets the right margin.
- * @see #getMarginRight()
- *
- * @param margin the right margin
- */
- public void setMarginRight(float margin){
- setEscherProperty(EscherProperties.TEXT__TEXTRIGHT, (int)(margin*EMU_PER_POINT));
- }
-
- /**
- * Returns the distance (in points) between the top of the text frame
- * and the top of the inscribed rectangle of the shape that contains the text.
- * Default value is 1/20 inch.
- *
- * @return the top margin
- */
- public float getMarginTop(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP);
- int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
- return (float)val/EMU_PER_POINT;
- }
-
- /**
- * Sets the top margin.
- * @see #getMarginTop()
- *
- * @param margin the top margin
- */
- public void setMarginTop(float margin){
- setEscherProperty(EscherProperties.TEXT__TEXTTOP, (int)(margin*EMU_PER_POINT));
- }
-
-
- /**
- * Returns the value indicating word wrap.
- *
- * @return the value indicating word wrap.
- * Must be one of the <code>Wrap*</code> constants defined in this class.
- */
- public int getWordWrap(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT);
- return prop == null ? WrapSquare : prop.getPropertyValue();
- }
-
- /**
- * Specifies how the text should be wrapped
- *
- * @param wrap the value indicating how the text should be wrapped.
- * Must be one of the <code>Wrap*</code> constants defined in this class.
- */
- public void setWordWrap(int wrap){
- setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap);
- }
-
- /**
- * @return id for the text.
- */
- public int getTextId(){
- EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
- EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTID);
- return prop == null ? 0 : prop.getPropertyValue();
- }
-
- /**
- * Sets text ID
- *
- * @param id of the text
- */
- public void setTextId(int id){
- setEscherProperty(EscherProperties.TEXT__TEXTID, id);
- }
-
- /**
- * @return the TextRun object for this text box
- */
- public TextRun getTextRun(){
- if(_txtrun == null) initTextRun();
- return _txtrun;
- }
-
- public void setSheet(Sheet sheet) {
- _sheet = sheet;
-
- // Initialize _txtrun object.
- // (We can't do it in the constructor because the sheet
- // is not assigned then, it's only built once we have
- // all the records)
- TextRun tx = getTextRun();
- if (tx != null) {
- // Supply the sheet to our child RichTextRuns
- tx.setSheet(_sheet);
- RichTextRun[] rt = tx.getRichTextRuns();
- for (int i = 0; i < rt.length; i++) {
- rt[i].supplySlideShow(_sheet.getSlideShow());
- }
- }
-
- }
-
- protected void initTextRun(){
- EscherTextboxWrapper txtbox = getEscherTextboxWrapper();
- Sheet sheet = getSheet();
-
- if(sheet == null || txtbox == null) return;
-
- OutlineTextRefAtom ota = null;
-
- Record[] child = txtbox.getChildRecords();
- for (int i = 0; i < child.length; i++) {
- if (child[i] instanceof OutlineTextRefAtom) {
- ota = (OutlineTextRefAtom)child[i];
- break;
- }
- }
-
- TextRun[] runs = _sheet.getTextRuns();
- if (ota != null) {
- int idx = ota.getTextIndex();
- for (int i = 0; i < runs.length; i++) {
- if(runs[i].getIndex() == idx){
- _txtrun = runs[i];
- break;
- }
- }
- if(_txtrun == null) {
- logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
- }
- } else {
- int shapeId = _escherContainer.getChildById(EscherSpRecord.RECORD_ID).getShapeId();
- if(runs != null) for (int i = 0; i < runs.length; i++) {
- if(runs[i].getShapeId() == shapeId){
- _txtrun = runs[i];
- break;
- }
- }
- }
- }
-
- public void draw(Graphics2D graphics){
- AffineTransform at = graphics.getTransform();
- ShapePainter.paint(this, graphics);
- new TextPainter(this).paint(graphics);
- graphics.setTransform(at);
- }
-
-}
+
+/* ====================================================================
+ 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.model;
+
+import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.usermodel.RichTextRun;
+import org.apache.poi.hslf.exceptions.HSLFException;
+import org.apache.poi.util.POILogger;
+
+import java.awt.*;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.AffineTransform;
+import java.awt.font.FontRenderContext;
+import java.awt.font.TextLayout;
+import java.io.IOException;
+import java.util.Iterator;
+
+/**
+ * A common superclass of all shapes that can hold text.
+ *
+ * @author Yegor Kozlov
+ */
+public abstract class TextShape extends SimpleShape {
+
+ /**
+ * How to anchor the text
+ */
+ public static final int AnchorTop = 0;
+ public static final int AnchorMiddle = 1;
+ public static final int AnchorBottom = 2;
+ public static final int AnchorTopCentered = 3;
+ public static final int AnchorMiddleCentered = 4;
+ public static final int AnchorBottomCentered = 5;
+ public static final int AnchorTopBaseline = 6;
+ public static final int AnchorBottomBaseline = 7;
+ public static final int AnchorTopCenteredBaseline = 8;
+ public static final int AnchorBottomCenteredBaseline = 9;
+
+ /**
+ * How to wrap the text
+ */
+ public static final int WrapSquare = 0;
+ public static final int WrapByPoints = 1;
+ public static final int WrapNone = 2;
+ public static final int WrapTopBottom = 3;
+ public static final int WrapThrough = 4;
+
+ /**
+ * How to align the text
+ */
+ public static final int AlignLeft = 0;
+ public static final int AlignCenter = 1;
+ public static final int AlignRight = 2;
+ public static final int AlignJustify = 3;
+
+ /**
+ * TextRun object which holds actual text and format data
+ */
+ protected TextRun _txtrun;
+
+ /**
+ * Escher container which holds text attributes such as
+ * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc.
+ */
+ protected EscherTextboxWrapper _txtbox;
+
+ /**
+ * Used to calculate text bounds
+ */
+ protected static final FontRenderContext _frc = new FontRenderContext(null, true, true);
+
+ /**
+ * Create a TextBox object and initialize it from the supplied Record container.
+ *
+ * @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
+ * @param parent the parent of the shape
+ */
+ protected TextShape(EscherContainerRecord escherRecord, Shape parent){
+ super(escherRecord, parent);
+
+ }
+
+ /**
+ * Create a new TextBox. This constructor is used when a new shape is created.
+ *
+ * @param parent the parent of this Shape. For example, if this text box is a cell
+ * in a table then the parent is Table.
+ */
+ public TextShape(Shape parent){
+ super(null, parent);
+ _escherContainer = createSpContainer(parent instanceof ShapeGroup);
+ }
+
+ /**
+ * Create a new TextBox. This constructor is used when a new shape is created.
+ *
+ */
+ public TextShape(){
+ this(null);
+ }
+
+ public TextRun createTextRun(){
+ _txtbox = getEscherTextboxWrapper();
+ if(_txtbox == null) _txtbox = new EscherTextboxWrapper();
+
+ _txtrun = getTextRun();
+ if(_txtrun == null){
+ TextHeaderAtom tha = new TextHeaderAtom();
+ tha.setParentRecord(_txtbox);
+ _txtbox.appendChildRecord(tha);
+
+ TextCharsAtom tca = new TextCharsAtom();
+ _txtbox.appendChildRecord(tca);
+
+ StyleTextPropAtom sta = new StyleTextPropAtom(0);
+ _txtbox.appendChildRecord(sta);
+
+ _txtrun = new TextRun(tha,tca,sta);
+ _txtrun.setText("");
+
+ _escherContainer.addChildRecord(_txtbox.getEscherRecord());
+
+ setDefaultTextProperties(_txtrun);
+ }
+
+ return _txtrun;
+ }
+
+ /**
+ * Set default properties for the TextRun.
+ * Depending on the text and shape type the defaults are different:
+ * TextBox: align=left, valign=top
+ * AutoShape: align=center, valign=middle
+ *
+ */
+ protected void setDefaultTextProperties(TextRun _txtrun){
+
+ }
+
+ /**
+ * Returns the text contained in this text frame.
+ *
+ * @return the text string for this textbox.
+ */
+ public String getText(){
+ TextRun tx = getTextRun();
+ return tx == null ? null : tx.getText();
+ }
+
+ /**
+ * Sets the text contained in this text frame.
+ *
+ * @param text the text string used by this object.
+ */
+ public void setText(String text){
+ TextRun tx = getTextRun();
+ if(tx == null){
+ tx = createTextRun();
+ }
+ tx.setText(text);
+ setTextId(text.hashCode());
+ }
+
+ /**
+ * When a textbox is added to a sheet we need to tell upper-level
+ * <code>PPDrawing</code> about it.
+ *
+ * @param sh the sheet we are adding to
+ */
+ protected void afterInsert(Sheet sh){
+ super.afterInsert(sh);
+
+ EscherTextboxWrapper _txtbox = getEscherTextboxWrapper();
+ if(_txtbox != null){
+ PPDrawing ppdrawing = sh.getPPDrawing();
+ ppdrawing.addTextboxWrapper(_txtbox);
+ // Ensure the escher layer knows about the added records
+ try {
+ _txtbox.writeOut(null);
+ } catch (IOException e){
+ throw new HSLFException(e);
+ }
+ if(getAnchor().equals(new Rectangle()) && !"".equals(getText())) resizeToFitText();
+ }
+ }
+
+ protected EscherTextboxWrapper getEscherTextboxWrapper(){
+ if(_txtbox == null){
+ EscherTextboxRecord textRecord = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID);
+ if(textRecord != null) _txtbox = new EscherTextboxWrapper(textRecord);
+ }
+ return _txtbox;
+ }
+ /**
+ * Adjust the size of the TextShape so it encompasses the text inside it.
+ *
+ * @return a <code>Rectangle2D</code> that is the bounds of this <code>TextShape</code>.
+ */
+ public Rectangle2D resizeToFitText(){
+ String txt = getText();
+ if(txt == null || txt.length() == 0) return new Rectangle2D.Float();
+
+ RichTextRun rt = getTextRun().getRichTextRuns()[0];
+ int size = rt.getFontSize();
+ int style = 0;
+ if (rt.isBold()) style |= Font.BOLD;
+ if (rt.isItalic()) style |= Font.ITALIC;
+ String fntname = rt.getFontName();
+ Font font = new Font(fntname, style, size);
+
+ float width = 0, height = 0, leading = 0;
+ String[] lines = txt.split("\n");
+ for (int i = 0; i < lines.length; i++) {
+ if(lines[i].length() == 0) continue;
+
+ TextLayout layout = new TextLayout(lines[i], font, _frc);
+
+ leading = Math.max(leading, layout.getLeading());
+ width = Math.max(width, layout.getAdvance());
+ height = Math.max(height, (height + (layout.getDescent() + layout.getAscent())));
+ }
+
+ // add one character to width
+ Rectangle2D charBounds = font.getMaxCharBounds(_frc);
+ width += getMarginLeft() + getMarginRight() + charBounds.getWidth();
+
+ // add leading to height
+ height += getMarginTop() + getMarginBottom() + leading;
+
+ Rectangle2D anchor = getAnchor2D();
+ anchor.setRect(anchor.getX(), anchor.getY(), width, height);
+ setAnchor(anchor);
+
+ return anchor;
+ }
+
+ /**
+ * Returns the type of vertical alignment for the text.
+ * One of the <code>Anchor*</code> constants defined in this class.
+ *
+ * @return the type of alignment
+ */
+ public int getVerticalAlignment(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
+ 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();
+ 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();
+ }
+ return valign;
+ }
+
+ /**
+ * Sets the type of vertical alignment for the text.
+ * One of the <code>Anchor*</code> constants defined in this class.
+ *
+ * @param align - the type of alignment
+ */
+ public void setVerticalAlignment(int align){
+ setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align);
+ }
+
+ /**
+ * Sets the type of horizontal alignment for the text.
+ * One of the <code>Align*</code> constants defined in this class.
+ *
+ * @param align - the type of horizontal alignment
+ */
+ public void setHorizontalAlignment(int align){
+ TextRun tx = getTextRun();
+ if(tx != null) tx.getRichTextRuns()[0].setAlignment(align);
+ }
+
+ /**
+ * Gets the type of horizontal alignment for the text.
+ * One of the <code>Align*</code> constants defined in this class.
+ *
+ * @return align - the type of horizontal alignment
+ */
+ public int getHorizontalAlignment(){
+ TextRun tx = getTextRun();
+ return tx == null ? -1 : tx.getRichTextRuns()[0].getAlignment();
+ }
+
+ /**
+ * Returns the distance (in points) between the bottom of the text frame
+ * and the bottom of the inscribed rectangle of the shape that contains the text.
+ * Default value is 1/20 inch.
+ *
+ * @return the botom margin
+ */
+ public float getMarginBottom(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
+ int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
+ return (float)val/EMU_PER_POINT;
+ }
+
+ /**
+ * Sets the botom margin.
+ * @see #getMarginBottom()
+ *
+ * @param margin the bottom margin
+ */
+ public void setMarginBottom(float margin){
+ setEscherProperty(EscherProperties.TEXT__TEXTBOTTOM, (int)(margin*EMU_PER_POINT));
+ }
+
+ /**
+ * Returns the distance (in points) between the left edge of the text frame
+ * and the left edge of the inscribed rectangle of the shape that contains
+ * the text.
+ * Default value is 1/10 inch.
+ *
+ * @return the left margin
+ */
+ public float getMarginLeft(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTLEFT);
+ int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
+ return (float)val/EMU_PER_POINT;
+ }
+
+ /**
+ * Sets the left margin.
+ * @see #getMarginLeft()
+ *
+ * @param margin the left margin
+ */
+ public void setMarginLeft(float margin){
+ setEscherProperty(EscherProperties.TEXT__TEXTLEFT, (int)(margin*EMU_PER_POINT));
+ }
+
+ /**
+ * Returns the distance (in points) between the right edge of the
+ * text frame and the right edge of the inscribed rectangle of the shape
+ * that contains the text.
+ * Default value is 1/10 inch.
+ *
+ * @return the right margin
+ */
+ public float getMarginRight(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT);
+ int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
+ return (float)val/EMU_PER_POINT;
+ }
+
+ /**
+ * Sets the right margin.
+ * @see #getMarginRight()
+ *
+ * @param margin the right margin
+ */
+ public void setMarginRight(float margin){
+ setEscherProperty(EscherProperties.TEXT__TEXTRIGHT, (int)(margin*EMU_PER_POINT));
+ }
+
+ /**
+ * Returns the distance (in points) between the top of the text frame
+ * and the top of the inscribed rectangle of the shape that contains the text.
+ * Default value is 1/20 inch.
+ *
+ * @return the top margin
+ */
+ public float getMarginTop(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP);
+ int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
+ return (float)val/EMU_PER_POINT;
+ }
+
+ /**
+ * Sets the top margin.
+ * @see #getMarginTop()
+ *
+ * @param margin the top margin
+ */
+ public void setMarginTop(float margin){
+ setEscherProperty(EscherProperties.TEXT__TEXTTOP, (int)(margin*EMU_PER_POINT));
+ }
+
+
+ /**
+ * Returns the value indicating word wrap.
+ *
+ * @return the value indicating word wrap.
+ * Must be one of the <code>Wrap*</code> constants defined in this class.
+ */
+ public int getWordWrap(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT);
+ return prop == null ? WrapSquare : prop.getPropertyValue();
+ }
+
+ /**
+ * Specifies how the text should be wrapped
+ *
+ * @param wrap the value indicating how the text should be wrapped.
+ * Must be one of the <code>Wrap*</code> constants defined in this class.
+ */
+ public void setWordWrap(int wrap){
+ setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap);
+ }
+
+ /**
+ * @return id for the text.
+ */
+ public int getTextId(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTID);
+ return prop == null ? 0 : prop.getPropertyValue();
+ }
+
+ /**
+ * Sets text ID
+ *
+ * @param id of the text
+ */
+ public void setTextId(int id){
+ setEscherProperty(EscherProperties.TEXT__TEXTID, id);
+ }
+
+ /**
+ * @return the TextRun object for this text box
+ */
+ public TextRun getTextRun(){
+ if(_txtrun == null) initTextRun();
+ return _txtrun;
+ }
+
+ public void setSheet(Sheet sheet) {
+ _sheet = sheet;
+
+ // Initialize _txtrun object.
+ // (We can't do it in the constructor because the sheet
+ // is not assigned then, it's only built once we have
+ // all the records)
+ TextRun tx = getTextRun();
+ if (tx != null) {
+ // Supply the sheet to our child RichTextRuns
+ tx.setSheet(_sheet);
+ RichTextRun[] rt = tx.getRichTextRuns();
+ for (int i = 0; i < rt.length; i++) {
+ rt[i].supplySlideShow(_sheet.getSlideShow());
+ }
+ }
+
+ }
+
+ protected void initTextRun(){
+ EscherTextboxWrapper txtbox = getEscherTextboxWrapper();
+ Sheet sheet = getSheet();
+
+ if(sheet == null || txtbox == null) return;
+
+ OutlineTextRefAtom ota = null;
+
+ Record[] child = txtbox.getChildRecords();
+ for (int i = 0; i < child.length; i++) {
+ if (child[i] instanceof OutlineTextRefAtom) {
+ ota = (OutlineTextRefAtom)child[i];
+ break;
+ }
+ }
+
+ TextRun[] runs = _sheet.getTextRuns();
+ if (ota != null) {
+ int idx = ota.getTextIndex();
+ for (int i = 0; i < runs.length; i++) {
+ if(runs[i].getIndex() == idx){
+ _txtrun = runs[i];
+ break;
+ }
+ }
+ if(_txtrun == null) {
+ logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
+ }
+ } else {
+ int shapeId = _escherContainer.getChildById(EscherSpRecord.RECORD_ID).getShapeId();
+ if(runs != null) for (int i = 0; i < runs.length; i++) {
+ if(runs[i].getShapeId() == shapeId){
+ _txtrun = runs[i];
+ break;
+ }
+ }
+ }
+ }
+
+ public void draw(Graphics2D graphics){
+ AffineTransform at = graphics.getTransform();
+ ShapePainter.paint(this, graphics);
+ new TextPainter(this).paint(graphics);
+ graphics.setTransform(at);
+ }
+
+ /**
+ * Return <code>OEPlaceholderAtom</code>, the atom that describes a placeholder.
+ *
+ * @return <code>OEPlaceholderAtom</code> or <code>null</code> if not found
+ */
+ public OEPlaceholderAtom getPlaceholderAtom(){
+ return (OEPlaceholderAtom)getClientDataRecord(RecordTypes.OEPlaceholderAtom.typeID);
+ }
+
+}
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java Sat Jun 21 05:03:44 2008
@@ -138,7 +138,7 @@
new TextProp(2, 0x4000, "spaceafter"),
new TextProp(2, 0x8000, "para_unknown_4"),
new TextProp(2, 0x10000, "para_unknown_5"),
- new TextProp(2, 0xE0000, "para_unknown_6"),
+ new TextProp(2, 0xA0000, "para_unknown_6"),
new TextProp(2, 0x200000, "para_unknown_7")
};
/** All the different kinds of character properties we might handle */
@@ -167,7 +167,7 @@
/**
* For the Text Style Properties (StyleTextProp) Atom
*/
- protected StyleTextPropAtom(byte[] source, int start, int len) {
+ public StyleTextPropAtom(byte[] source, int start, int len) {
// Sanity Checking - we're always at least 8+10 bytes long
if(len < 18) {
len = 18;
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java Sat Jun 21 05:03:44 2008
@@ -17,6 +17,8 @@
package org.apache.poi.hslf.usermodel;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.util.POILogFactory;
import org.apache.poi.hslf.model.Picture;
import org.apache.poi.hslf.blip.*;
import org.apache.poi.hslf.exceptions.HSLFException;
@@ -25,6 +27,7 @@
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.awt.*;
/**
* A class that represents image data contained in a slide show.
@@ -33,19 +36,21 @@
*/
public abstract class PictureData {
+ protected POILogger logger = POILogFactory.getLogger(this.getClass());
+
/**
* Size of the image checksum calculated using MD5 algorithm.
*/
protected static final int CHECKSUM_SIZE = 16;
- /**
- * Binary data of the picture
- */
+ /**
+ * Binary data of the picture
+ */
private byte[] rawdata;
- /**
- * The offset to the picture in the stream
- */
- protected int offset;
+ /**
+ * The offset to the picture in the stream
+ */
+ protected int offset;
/**
* Returns type of this picture.
@@ -71,6 +76,13 @@
*/
protected abstract int getSignature();
+ protected static ImagePainter[] painters = new ImagePainter[8];
+ static {
+ PictureData.setImagePainter(Picture.PNG, new BitmapPainter());
+ PictureData.setImagePainter(Picture.JPEG, new BitmapPainter());
+ PictureData.setImagePainter(Picture.DIB, new BitmapPainter());
+ }
+
/**
* Returns the raw binary data of this Picture excluding the first 8 bytes
* which hold image signature and size of the image data.
@@ -212,4 +224,30 @@
return getData().length;
}
+ public void draw(Graphics2D graphics, Picture parent){
+ ImagePainter painter = painters[getType()];
+ if(painter != null) painter.paint(graphics, this, parent);
+ else logger.log(POILogger.WARN, "Rendering is not supported: " + getClass().getName());
+ }
+
+ /**
+ * Register ImagePainter for the specified image type
+ *
+ * @param type image type, must be one of the static constants defined in the <code>Picture<code> class.
+ * @param painter
+ */
+ public static void setImagePainter(int type, ImagePainter painter){
+ painters[type] = painter;
+ }
+
+ /**
+ * Return ImagePainter for the specified image type
+ *
+ * @param type blip type, must be one of the static constants defined in the <code>Picture<code> class.
+ * @return ImagePainter for the specified image type
+ */
+ public static ImagePainter getImagePainter(int type){
+ return painters[type];
+ }
+
}
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java Sat Jun 21 05:03:44 2008
@@ -734,7 +734,7 @@
else if (format == Picture.WMF) bse.setBlipTypeMacOS((byte)Picture.PICT);
else if (format == Picture.PICT) bse.setBlipTypeWin32((byte)Picture.WMF);
- bse.setRef(1);
+ bse.setRef(0);
bse.setOffset(offset);
bstore.addChildRecord(bse);
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFChart.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFChart.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFChart.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFChart.java Sat Jun 21 05:03:44 2008
@@ -213,6 +213,23 @@
charts.toArray( new HSSFChart[charts.size()] );
}
+ /** Get the X offset of the chart */
+ public int getChartX() { return chartRecord.getX(); }
+ /** Get the Y offset of the chart */
+ public int getChartY() { return chartRecord.getY(); }
+ /** Get the width of the chart. {@link ChartRecord} */
+ public int getChartWidth() { return chartRecord.getWidth(); }
+ /** Get the height of the chart. {@link ChartRecord} */
+ public int getChartHeight() { return chartRecord.getHeight(); }
+
+ /** Sets the X offset of the chart */
+ public void setChartX(int x) { chartRecord.setX(x); }
+ /** Sets the Y offset of the chart */
+ public void setChartY(int y) { chartRecord.setY(y); }
+ /** Sets the width of the chart. {@link ChartRecord} */
+ public void setChartWidth(int width) { chartRecord.setWidth(width); }
+ /** Sets the height of the chart. {@link ChartRecord} */
+ public void setChartHeight(int height) { chartRecord.setHeight(height); }
/**
* Returns the series of the chart
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java Sat Jun 21 05:03:44 2008
@@ -53,10 +53,10 @@
protected FileInformationBlock _fib;
/** main document stream buffer*/
- private byte[] _mainStream;
+ protected byte[] _mainStream;
/** table stream buffer*/
- private byte[] _tableStream;
+ protected byte[] _tableStream;
/** data stream buffer*/
protected byte[] _dataStream;
@@ -93,6 +93,12 @@
/** Holds pictures table */
protected PicturesTable _pictures;
+
+ /** Holds FSBA (shape) information */
+ protected FSPATable _fspa;
+
+ /** Escher Drawing Group information */
+ protected EscherRecordHolder _dgg;
protected HWPFDocument()
{
@@ -204,9 +210,6 @@
{
_dataStream = new byte[0];
}
-
- // read in the pictures stream
- _pictures = new PicturesTable(this, _dataStream);
// get the start of text in the main stream
int fcMin = _fib.getFcMin();
@@ -226,6 +229,20 @@
_cbt.adjustForDelete(0, 0, cpMin);
_pbt.adjustForDelete(0, 0, cpMin);
}
+
+ // Read FSPA and Escher information
+ _fspa = new FSPATable(_tableStream, _fib.getFcPlcspaMom(), _fib.getLcbPlcspaMom(), getTextTable().getTextPieces());
+
+ if (_fib.getFcDggInfo() != 0)
+ {
+ _dgg = new EscherRecordHolder(_tableStream, _fib.getFcDggInfo(), _fib.getLcbDggInfo());
+ } else
+ {
+ _dgg = new EscherRecordHolder();
+ }
+
+ // read in the pictures stream
+ _pictures = new PicturesTable(this, _dataStream, _mainStream, _fspa, _dgg);
_st = new SectionTable(_mainStream, _tableStream, _fib.getFcPlcfsed(), _fib.getLcbPlcfsed(), fcMin, getTextTable().getTextPieces());
_ss = new StyleSheet(_tableStream, _fib.getFcStshf());
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java Sat Jun 21 05:03:44 2008
@@ -294,6 +294,16 @@
_longHandler.setLong(FIBLongHandler.CBMAC, cbMac);
}
+ public int getCcpText()
+ {
+ return _longHandler.getLong(FIBLongHandler.CCPTEXT);
+ }
+
+ public void setCcpText(int ccpText)
+ {
+ _longHandler.setLong(FIBLongHandler.CCPTEXT, ccpText);
+ }
+
public void clearOffsetsSizes()
{
_fieldHandler.clearFields();
@@ -308,6 +318,26 @@
{
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDMOM);
}
+
+ public int getFcPlcspaMom()
+ {
+ return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCSPAMOM);
+ }
+
+ public int getLcbPlcspaMom()
+ {
+ return _fieldHandler.getFieldSize(FIBFieldHandler.PLCSPAMOM);
+ }
+
+ public int getFcDggInfo()
+ {
+ return _fieldHandler.getFieldOffset(FIBFieldHandler.DGGINFO);
+ }
+
+ public int getLcbDggInfo()
+ {
+ return _fieldHandler.getFieldSize(FIBFieldHandler.DGGINFO);
+ }
public void writeTo (byte[] mainStream, HWPFOutputStream tableStream)
throws IOException
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java Sat Jun 21 05:03:44 2008
@@ -26,7 +26,12 @@
import java.util.List;
import java.util.ArrayList;
-
+import java.util.Iterator;
+import org.apache.poi.ddf.DefaultEscherRecordFactory;
+import org.apache.poi.ddf.EscherBSERecord;
+import org.apache.poi.ddf.EscherBlipRecord;
+import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.ddf.EscherRecordFactory;
/**
* Holds information about all pictures embedded in Word Document either via "Insert -> Picture -> From File" or via
@@ -57,6 +62,9 @@
private HWPFDocument _document;
private byte[] _dataStream;
+ private byte[] _mainStream;
+ private FSPATable _fspa;
+ private EscherRecordHolder _dgg;
/** @link dependency
* @stereotype instantiate*/
@@ -67,10 +75,13 @@
* @param document
* @param _dataStream
*/
- public PicturesTable(HWPFDocument _document, byte[] _dataStream)
+ public PicturesTable(HWPFDocument _document, byte[] _dataStream, byte[] _mainStream, FSPATable fspa, EscherRecordHolder dgg)
{
- this._document = _document;
+ this._document = _document;
this._dataStream = _dataStream;
+ this._mainStream = _mainStream;
+ this._fspa = fspa;
+ this._dgg = dgg;
}
/**
@@ -83,6 +94,13 @@
}
return false;
}
+
+ public boolean hasEscherPicture(CharacterRun run) {
+ if (run.isSpecialCharacter() && !run.isObj() && !run.isOle2() && !run.isData() && run.text().startsWith("\u0008")) {
+ return true;
+ }
+ return false;
+ }
/**
* determines whether specified CharacterRun contains reference to a picture
@@ -122,6 +140,46 @@
}
return null;
}
+
+ /**
+ * Performs a recursive search for pictures in the given list of escher records.
+ *
+ * @param escherRecords the escher records.
+ * @param pictures the list to populate with the pictures.
+ */
+ private void searchForPictures(List escherRecords, List pictures)
+ {
+ Iterator recordIter = escherRecords.iterator();
+ while (recordIter.hasNext())
+ {
+ Object obj = recordIter.next();
+ if (obj instanceof EscherRecord)
+ {
+ EscherRecord escherRecord = (EscherRecord) obj;
+
+ if (escherRecord instanceof EscherBSERecord)
+ {
+ EscherBSERecord bse = (EscherBSERecord) escherRecord;
+ EscherBlipRecord blip = bse.getBlipRecord();
+ if (blip != null)
+ {
+ pictures.add(new Picture(blip.getPicturedata()));
+ }
+ else if (bse.getOffset() > 0)
+ {
+ // Blip stored in delay stream, which in a word doc, is the main stream
+ EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
+ blip = (EscherBlipRecord) recordFactory.createRecord(_mainStream, bse.getOffset());
+ blip.fillFields(_mainStream, bse.getOffset(), recordFactory);
+ pictures.add(new Picture(blip.getPicturedata()));
+ }
+ }
+
+ // Recursive call.
+ searchForPictures(escherRecord.getChildRecords(), pictures);
+ }
+ }
+ }
/**
* Not all documents have all the images concatenated in the data stream
@@ -136,12 +194,13 @@
for (int i = 0; i < range.numCharacterRuns(); i++) {
CharacterRun run = range.getCharacterRun(i);
String text = run.text();
- int j = text.charAt(0);
Picture picture = extractPicture(run, false);
if (picture != null) {
pictures.add(picture);
}
}
+
+ searchForPictures(_dgg.getEscherRecords(), pictures);
return pictures;
}
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/TextPiece.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/TextPiece.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/TextPiece.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/TextPiece.java Sat Jun 21 05:03:44 2008
@@ -90,12 +90,20 @@
public void adjustForDelete(int start, int length)
{
+
+ if (usesUnicode()) {
+
+ start /= 2;
+ length /= 2;
+ }
+
int myStart = getStart();
int myEnd = getEnd();
int end = start + length;
/* do we have to delete from this text piece? */
if (start <= myEnd && end >= myStart) {
+
/* find where the deleted area overlaps with this text piece */
int overlapStart = Math.max(myStart, start);
int overlapEnd = Math.min(myEnd, end);
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java Sat Jun 21 05:03:44 2008
@@ -98,6 +98,15 @@
fillImageContent();
}
}
+
+ public Picture(byte[] _dataStream)
+ {
+ this._dataStream = _dataStream;
+ this.dataBlockStartOfsset = 0;
+ this.dataBlockSize = _dataStream.length;
+ this.pictureBytesStartOffset = 0;
+ this.size = _dataStream.length;
+ }
private void fillWidthHeight()
{
@@ -363,6 +372,7 @@
do {
firstByte = _dataStream[pointer];
secondByte = _dataStream[pointer+1];
+ pointer += 2;
} while (!(firstByte==(byte)0xFF) && pointer<endOfPicture-1);
if (firstByte==((byte)0xFF) && pointer<endOfPicture-1) {
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java Sat Jun 21 05:03:44 2008
@@ -227,6 +227,25 @@
}
/**
+ * Does any <code>TextPiece</code> in this Range use unicode?
+ *
+ * @return true if it does and false if it doesn't
+ */
+ public boolean usesUnicode() {
+
+ initText();
+
+ for (int i = _textStart; i < _textEnd; i++)
+ {
+ TextPiece piece = (TextPiece)_text.get(i);
+ if (piece.usesUnicode())
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
* Gets the text that this Range contains.
*
* @return The text for this range.
@@ -306,13 +325,19 @@
// Since this is the first item in our list, it is safe to assume that
// _start >= tp.getStart()
int insertIndex = _start - tp.getStart();
+ if (tp.usesUnicode())
+ insertIndex /= 2;
sb.insert(insertIndex, text);
+
int adjustedLength = _doc.getTextTable().adjustForInsert(_textStart, text.length());
_doc.getCharacterTable().adjustForInsert(_charStart, adjustedLength);
_doc.getParagraphTable().adjustForInsert(_parStart, adjustedLength);
_doc.getSectionTable().adjustForInsert(_sectionStart, adjustedLength);
adjustForInsert(text.length());
+ // update the FIB.CCPText field
+ adjustFIB(text.length());
+
return getCharacterRun(0);
}
@@ -489,6 +514,7 @@
public void delete()
{
+
initAll();
int numSections = _sections.size();
@@ -519,6 +545,12 @@
TextPiece piece = (TextPiece)_text.get(x);
piece.adjustForDelete(_start, _end - _start);
}
+
+ // update the FIB.CCPText field
+ if (usesUnicode())
+ adjustFIB(-((_end - _start) / 2));
+ else
+ adjustFIB(-(_end - _start));
}
/**
@@ -600,6 +632,47 @@
return (ListEntry)insertAfter(props, styleIndex);
}
+ /**
+ * Replace (one instance of) a piece of text with another...
+ *
+ * @param pPlaceHolder The text to be replaced (e.g., "${organization}")
+ * @param pValue The replacement text (e.g., "Apache Software Foundation")
+ * @param pOffset The offset or index where the text to be replaced begins
+ * (relative to/within this <code>Range</code>)
+ */
+ public void replaceText(String pPlaceHolder, String pValue, int pOffset)
+ {
+ int absPlaceHolderIndex = getStartOffset() + pOffset;
+ Range subRange = new Range(
+ absPlaceHolderIndex,
+ (absPlaceHolderIndex + pPlaceHolder.length()), getDocument()
+ );
+ if (subRange.usesUnicode()) {
+ absPlaceHolderIndex = getStartOffset() + (pOffset * 2);
+ subRange = new Range(
+ absPlaceHolderIndex,
+ (absPlaceHolderIndex + (pPlaceHolder.length() * 2)),
+ getDocument()
+ );
+ }
+
+ subRange.insertBefore(pValue);
+
+ // re-create the sub-range so we can delete it
+ subRange = new Range(
+ (absPlaceHolderIndex + pValue.length()),
+ (absPlaceHolderIndex + pPlaceHolder.length() + pValue.length()),
+ getDocument()
+ );
+ if (subRange.usesUnicode())
+ subRange = new Range(
+ (absPlaceHolderIndex + (pValue.length() * 2)),
+ (absPlaceHolderIndex + (pPlaceHolder.length() * 2) +
+ (pValue.length() * 2)), getDocument()
+ );
+
+ subRange.delete();
+ }
/**
* Gets the character run at index. The index is relative to this range.
@@ -828,12 +901,26 @@
}
/**
+ * Adjust the value of <code>FIB.CCPText</code> after an insert or a delete...
+ *
+ * @param adjustment The (signed) value that should be added to <code>FIB.CCPText</code>
+ */
+ protected void adjustFIB(int adjustment) {
+
+ // update the FIB.CCPText field (this should happen once per adjustment, so we don't want it in
+ // adjustForInsert() or it would get updated multiple times if the range has a parent)
+ // without this, OpenOffice.org (v. 2.2.x) does not see all the text in the document
+ _doc.getFileInformationBlock().setCcpText(_doc.getFileInformationBlock().getCcpText() + adjustment);
+ }
+
+ /**
* adjust this range after an insert happens.
* @param length the length to adjust for
*/
private void adjustForInsert(int length)
{
_end += length;
+
reset();
Range parent = (Range)_parent.get();
if (parent != null)
@@ -842,4 +929,19 @@
}
}
+
+ public int getStartOffset() {
+
+ return _start;
+ }
+
+ public int getEndOffset() {
+
+ return _end;
+ }
+
+ protected HWPFDocument getDocument() {
+
+ return _doc;
+ }
}
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java Sat Jun 21 05:03:44 2008
@@ -23,6 +23,7 @@
import java.io.*;
import java.util.ArrayList;
+import java.util.HashMap;
import org.apache.poi.hslf.usermodel.SlideShow;
import org.apache.poi.hslf.record.TextHeaderAtom;
@@ -157,4 +158,46 @@
assertEquals("Testing TextShape", shape1.getTextRun().getText());
}
+ public void testMargins() throws IOException {
+ FileInputStream is = new FileInputStream(new File(cwd, "text-margins.ppt"));
+ SlideShow ppt = new SlideShow(is);
+ is.close();
+
+ Slide slide = ppt.getSlides()[0];
+
+ HashMap map = new HashMap();
+ Shape[] shape = slide.getShapes();
+ for (int i = 0; i < shape.length; i++) {
+ if(shape[i] instanceof TextShape){
+ TextShape tx = (TextShape)shape[i];
+ map.put(tx.getText(), tx);
+ }
+ }
+
+ TextShape tx;
+
+ tx = (TextShape)map.get("TEST1");
+ assertEquals(0.1, tx.getMarginLeft()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.1, tx.getMarginRight()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.39, tx.getMarginTop()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getMarginBottom()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+
+ tx = (TextShape)map.get("TEST2");
+ assertEquals(0.1, tx.getMarginLeft()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.1, tx.getMarginRight()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getMarginTop()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.39, tx.getMarginBottom()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+
+ tx = (TextShape)map.get("TEST3");
+ assertEquals(0.39, tx.getMarginLeft()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.1, tx.getMarginRight()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getMarginTop()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getMarginBottom()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+
+ tx = (TextShape)map.get("TEST4");
+ assertEquals(0.1, tx.getMarginLeft()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.39, tx.getMarginRight()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getMarginTop()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getMarginBottom()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+ }
}
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hssf/usermodel/TestHSSFChart.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hssf/usermodel/TestHSSFChart.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hssf/usermodel/TestHSSFChart.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hssf/usermodel/TestHSSFChart.java Sat Jun 21 05:03:44 2008
@@ -53,6 +53,12 @@
assertEquals("1st Column", charts[0].getSeries()[0].getSeriesTitle());
assertEquals("2nd Column", charts[0].getSeries()[1].getSeriesTitle());
assertEquals(null, charts[0].getChartTitle());
+
+ // Check x, y, width, height
+ assertEquals(0, charts[0].getChartX());
+ assertEquals(0, charts[0].getChartY());
+ assertEquals(26492928, charts[0].getChartWidth());
+ assertEquals(15040512, charts[0].getChartHeight());
}
public void testTwoCharts() throws Exception {
Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hwpf/TestHWPFPictures.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hwpf/TestHWPFPictures.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hwpf/TestHWPFPictures.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hwpf/TestHWPFPictures.java Sat Jun 21 05:03:44 2008
@@ -35,10 +35,12 @@
private String docAFile;
private String docBFile;
private String docCFile;
+ private String docDFile;
private String imgAFile;
private String imgBFile;
private String imgCFile;
+ private String imgDFile;
protected void setUp() throws Exception {
String dirname = System.getProperty("HWPF.testdata.path");
@@ -46,10 +48,12 @@
docAFile = dirname + "/testPictures.doc";
docBFile = dirname + "/two_images.doc";
docCFile = dirname + "/vector_image.doc";
+ docDFile = dirname + "/GaiaTest.doc";
imgAFile = dirname + "/simple_image.jpg";
imgBFile = dirname + "/simple_image.png";
imgCFile = dirname + "/vector_image.emf";
+ imgDFile = dirname + "/GaiaTestImg.png";
}
/**
@@ -126,7 +130,26 @@
assertEquals(picBytes.length, pic.getContent().length);
assertBytesSame(picBytes, pic.getContent());
}
-
+
+ /**
+ * Pending the missing files being uploaded to
+ * bug #44937
+ */
+ public void BROKENtestEscherDrawing() throws Exception
+ {
+ HWPFDocument docD = new HWPFDocument(new FileInputStream(docDFile));
+ List allPictures = docD.getPicturesTable().getAllPictures();
+
+ assertEquals(1, allPictures.size());
+
+ Picture pic = (Picture) allPictures.get(0);
+ assertNotNull(pic);
+ byte[] picD = readFile(imgDFile);
+
+ assertEquals(picD.length, pic.getContent().length);
+
+ assertBytesSame(picD, pic.getContent());
+ }
private void assertBytesSame(byte[] a, byte[] b) {
assertEquals(a.length, b.length);
Modified: poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java (original)
+++ poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java Sat Jun 21 05:03:44 2008
@@ -165,6 +165,28 @@
);
}
+ public void testWithComments() throws Exception {
+ ExcelExtractor extractor = createExtractor("SimpleWithComments.xls");
+ extractor.setIncludeSheetNames(false);
+
+ // Check without comments
+ assertEquals(
+ "1.0\tone\n" +
+ "2.0\ttwo\n" +
+ "3.0\tthree\n",
+ extractor.getText()
+ );
+
+ // Now with
+ extractor.setIncludeCellComments(true);
+ assertEquals(
+ "1.0\tone Comment by Yegor Kozlov: Yegor Kozlov: first cell\n" +
+ "2.0\ttwo Comment by Yegor Kozlov: Yegor Kozlov: second cell\n" +
+ "3.0\tthree Comment by Yegor Kozlov: Yegor Kozlov: third cell\n",
+ extractor.getText()
+ );
+ }
+
/**
* Embded in a non-excel file
Modified: poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/model/AllModelTests.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/model/AllModelTests.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/model/AllModelTests.java (original)
+++ poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/model/AllModelTests.java Sat Jun 21 05:03:44 2008
@@ -33,6 +33,9 @@
result.addTestSuite(TestDrawingManager2.class);
result.addTestSuite(TestFormulaParser.class);
result.addTestSuite(TestFormulaParserEval.class);
+ result.addTestSuite(TestFormulaParserIf.class);
+ result.addTestSuite(TestOperandClassTransformer.class);
+ result.addTestSuite(TestRVA.class);
result.addTestSuite(TestSheet.class);
result.addTestSuite(TestSheetAdditional.class);
return result;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org