mirror of https://github.com/apache/poi.git
Refactor the TextPropCollection and TextProp classes into their own model package. Some of the logic in StyleTextPropAtom should probably be refactored out too, but that's still to do
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@496405 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
808ac3d6c7
commit
5c518687f5
|
@ -21,6 +21,9 @@
|
|||
package org.apache.poi.hslf.dev;
|
||||
|
||||
import org.apache.poi.hslf.*;
|
||||
import org.apache.poi.hslf.model.textproperties.BitMaskTextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||
import org.apache.poi.hslf.record.*;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
package org.apache.poi.hslf.model;
|
||||
|
||||
import org.apache.poi.hslf.model.textproperties.TextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||
import org.apache.poi.hslf.record.*;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
|
||||
|
|
|
@ -23,8 +23,8 @@ package org.apache.poi.hslf.model;
|
|||
import java.util.LinkedList;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||
import org.apache.poi.hslf.record.*;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.TextPropCollection;
|
||||
import org.apache.poi.hslf.usermodel.RichTextRun;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* ====================================================================
|
||||
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.textproperties;
|
||||
|
||||
/**
|
||||
* Definition for the alignment text property.
|
||||
*/
|
||||
public class AlignmentTextProp extends TextProp {
|
||||
public static final int LEFT = 0;
|
||||
public static final int CENTER = 1;
|
||||
public static final int RIGHT = 2;
|
||||
public static final int JUSTIFY = 3;
|
||||
public static final int THAIDISTRIBUTED = 5;
|
||||
public static final int JUSTIFYLOW = 6;
|
||||
|
||||
public AlignmentTextProp() {
|
||||
super(2, 0x800, "alignment");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/* ====================================================================
|
||||
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.textproperties;
|
||||
|
||||
/**
|
||||
* Definition of a special kind of property of some text, or its
|
||||
* paragraph. For these properties, a flag in the "contains" header
|
||||
* field tells you the data property family will exist. The value
|
||||
* of the property is itself a mask, encoding several different
|
||||
* (but related) properties
|
||||
*/
|
||||
public class BitMaskTextProp extends TextProp implements Cloneable {
|
||||
private String[] subPropNames;
|
||||
private int[] subPropMasks;
|
||||
private boolean[] subPropMatches;
|
||||
|
||||
/** Fetch the list of the names of the sub properties */
|
||||
public String[] getSubPropNames() { return subPropNames; }
|
||||
/** Fetch the list of if the sub properties match or not */
|
||||
public boolean[] getSubPropMatches() { return subPropMatches; }
|
||||
|
||||
public BitMaskTextProp(int sizeOfDataBlock, int maskInHeader, String overallName, String[] subPropNames) {
|
||||
super(sizeOfDataBlock,maskInHeader,"bitmask");
|
||||
this.subPropNames = subPropNames;
|
||||
this.propName = overallName;
|
||||
subPropMasks = new int[subPropNames.length];
|
||||
subPropMatches = new boolean[subPropNames.length];
|
||||
|
||||
// Initialise the masks list
|
||||
for(int i=0; i<subPropMasks.length; i++) {
|
||||
subPropMasks[i] = (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* As we're purely mask based, just set flags for stuff
|
||||
* that is set
|
||||
*/
|
||||
public int getWriteMask() {
|
||||
return dataValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the text property, and recompute the sub
|
||||
* properties based on it
|
||||
*/
|
||||
public void setValue(int val) {
|
||||
dataValue = val;
|
||||
|
||||
// Figure out the values of the sub properties
|
||||
for(int i=0; i< subPropMatches.length; i++) {
|
||||
subPropMatches[i] = false;
|
||||
if((dataValue & subPropMasks[i]) != 0) {
|
||||
subPropMatches[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the true/false status of the subproperty with the given index
|
||||
*/
|
||||
public boolean getSubValue(int idx) {
|
||||
return subPropMatches[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the true/false status of the subproperty with the given index
|
||||
*/
|
||||
public void setSubValue(boolean value, int idx) {
|
||||
if(subPropMatches[idx] == value) { return; }
|
||||
if(value) {
|
||||
dataValue += subPropMasks[idx];
|
||||
} else {
|
||||
dataValue -= subPropMasks[idx];
|
||||
}
|
||||
subPropMatches[idx] = value;
|
||||
}
|
||||
|
||||
public Object clone(){
|
||||
BitMaskTextProp newObj = (BitMaskTextProp)super.clone();
|
||||
|
||||
// Don't carry over matches, but keep everything
|
||||
// else as it was
|
||||
newObj.subPropMatches = new boolean[subPropMatches.length];
|
||||
|
||||
return newObj;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* ====================================================================
|
||||
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.textproperties;
|
||||
|
||||
/**
|
||||
* Definition for the common character text property bitset, which
|
||||
* handles bold/italic/underline etc.
|
||||
*/
|
||||
public class CharFlagsTextProp extends BitMaskTextProp {
|
||||
public static final int BOLD_IDX = 0;
|
||||
public static final int ITALIC_IDX = 1;
|
||||
public static final int UNDERLINE_IDX = 2;
|
||||
public static final int SHADOW_IDX = 4;
|
||||
public static final int STRIKETHROUGH_IDX = 8;
|
||||
public static final int RELIEF_IDX = 9;
|
||||
public static final int RESET_NUMBERING_IDX = 10;
|
||||
public static final int ENABLE_NUMBERING_1_IDX = 11;
|
||||
public static final int ENABLE_NUMBERING_2_IDX = 12;
|
||||
|
||||
public CharFlagsTextProp() {
|
||||
super(2,0xffff, "char_flags", new String[] {
|
||||
"bold", // 0x0001
|
||||
"italic", // 0x0002
|
||||
"underline", // 0x0004
|
||||
"char_unknown_1",// 0x0008
|
||||
"shadow", // 0x0010
|
||||
"char_unknown_2",// 0x0020
|
||||
"char_unknown_3",// 0x0040
|
||||
"char_unknown_4",// 0x0080
|
||||
"strikethrough", // 0x0100
|
||||
"relief", // 0x0200
|
||||
"reset_numbering", // 0x0400
|
||||
"enable_numbering_1", // 0x0800
|
||||
"enable_numbering_2", // 0x1000
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/* ====================================================================
|
||||
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.textproperties;
|
||||
|
||||
/**
|
||||
* Definition of a property of some text, or its paragraph. Defines
|
||||
* how to find out if it's present (via the mask on the paragraph or
|
||||
* character "contains" header field), how long the value of it is,
|
||||
* and how to get and set the value.
|
||||
*
|
||||
* As the exact form of these (such as mask value, size of data
|
||||
* block etc) is different for StyleTextProps and
|
||||
* TxMasterTextProps, the definitions of the standard
|
||||
* TextProps is stored in the different record classes
|
||||
*/
|
||||
public class TextProp implements Cloneable {
|
||||
protected int sizeOfDataBlock; // Number of bytes the data part uses
|
||||
protected String propName;
|
||||
protected int dataValue;
|
||||
protected int maskInHeader;
|
||||
|
||||
/**
|
||||
* Generate the definition of a given type of text property.
|
||||
*/
|
||||
public TextProp(int sizeOfDataBlock, int maskInHeader, String propName) {
|
||||
this.sizeOfDataBlock = sizeOfDataBlock;
|
||||
this.maskInHeader = maskInHeader;
|
||||
this.propName = propName;
|
||||
this.dataValue = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of the text property
|
||||
*/
|
||||
public String getName() { return propName; }
|
||||
|
||||
/**
|
||||
* Size of the data section of the text property (2 or 4 bytes)
|
||||
*/
|
||||
public int getSize() { return sizeOfDataBlock; }
|
||||
|
||||
/**
|
||||
* Mask in the paragraph or character "contains" header field
|
||||
* that indicates that this text property is present.
|
||||
*/
|
||||
public int getMask() { return maskInHeader; }
|
||||
/**
|
||||
* Get the mask that's used at write time. Only differs from
|
||||
* the result of getMask() for the mask based properties
|
||||
*/
|
||||
public int getWriteMask() { return getMask(); }
|
||||
|
||||
/**
|
||||
* Fetch the value of the text property (meaning is specific to
|
||||
* each different kind of text property)
|
||||
*/
|
||||
public int getValue() { return dataValue; }
|
||||
|
||||
/**
|
||||
* Set the value of the text property.
|
||||
*/
|
||||
public void setValue(int val) { dataValue = val; }
|
||||
|
||||
/**
|
||||
* Clone, eg when you want to actually make use of one of these.
|
||||
*/
|
||||
public Object clone(){
|
||||
try {
|
||||
return super.clone();
|
||||
} catch(CloneNotSupportedException e) {
|
||||
throw new InternalError(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
/* ====================================================================
|
||||
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.textproperties;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* For a given run of characters, holds the properties (which could
|
||||
* be paragraph properties or character properties).
|
||||
* Used to hold the number of characters affected, the list of active
|
||||
* properties, and the random reserved field if required.
|
||||
*/
|
||||
public class TextPropCollection {
|
||||
private int charactersCovered;
|
||||
private short reservedField;
|
||||
private LinkedList textPropList;
|
||||
|
||||
/** Fetch the number of characters this styling applies to */
|
||||
public int getCharactersCovered() { return charactersCovered; }
|
||||
/** Fetch the TextProps that define this styling */
|
||||
public LinkedList getTextPropList() { return textPropList; }
|
||||
|
||||
/** Fetch the TextProp with this name, or null if it isn't present */
|
||||
public TextProp findByName(String textPropName) {
|
||||
for(int i=0; i<textPropList.size(); i++) {
|
||||
TextProp prop = (TextProp)textPropList.get(i);
|
||||
if(prop.getName().equals(textPropName)) {
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Add the TextProp with this name to the list */
|
||||
public TextProp addWithName(String name) {
|
||||
// Find the base TextProp to base on
|
||||
TextProp base = null;
|
||||
for(int i=0; i < StyleTextPropAtom.characterTextPropTypes.length; i++) {
|
||||
if(StyleTextPropAtom.characterTextPropTypes[i].getName().equals(name)) {
|
||||
base = StyleTextPropAtom.characterTextPropTypes[i];
|
||||
}
|
||||
}
|
||||
for(int i=0; i < StyleTextPropAtom.paragraphTextPropTypes.length; i++) {
|
||||
if(StyleTextPropAtom.paragraphTextPropTypes[i].getName().equals(name)) {
|
||||
base = StyleTextPropAtom.paragraphTextPropTypes[i];
|
||||
}
|
||||
}
|
||||
if(base == null) {
|
||||
throw new IllegalArgumentException("No TextProp with name " + name + " is defined to add from");
|
||||
}
|
||||
|
||||
// Add a copy of this property, in the right place to the list
|
||||
TextProp textProp = (TextProp)base.clone();
|
||||
int pos = 0;
|
||||
for(int i=0; i<textPropList.size(); i++) {
|
||||
TextProp curProp = (TextProp)textPropList.get(i);
|
||||
if(textProp.getMask() > curProp.getMask()) {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
textPropList.add(pos, textProp);
|
||||
return textProp;
|
||||
}
|
||||
|
||||
/**
|
||||
* For an existing set of text properties, build the list of
|
||||
* properties coded for in a given run of properties.
|
||||
* @return the number of bytes that were used encoding the properties list
|
||||
*/
|
||||
public int buildTextPropList(int containsField, TextProp[] potentialProperties, byte[] data, int dataOffset) {
|
||||
int bytesPassed = 0;
|
||||
|
||||
// For each possible entry, see if we match the mask
|
||||
// If we do, decode that, save it, and shuffle on
|
||||
for(int i=0; i<potentialProperties.length; i++) {
|
||||
// Check there's still data left to read
|
||||
if(dataOffset+bytesPassed >= data.length) {
|
||||
// Out of data, can't be any more properties to go
|
||||
return bytesPassed;
|
||||
}
|
||||
|
||||
// Check if this property is found in the mask
|
||||
if((containsField & potentialProperties[i].getMask()) != 0) {
|
||||
// Bingo, data contains this property
|
||||
TextProp prop = (TextProp)potentialProperties[i].clone();
|
||||
int val = 0;
|
||||
if(prop.getSize() == 2) {
|
||||
val = LittleEndian.getShort(data,dataOffset+bytesPassed);
|
||||
} else {
|
||||
val = LittleEndian.getInt(data,dataOffset+bytesPassed);
|
||||
}
|
||||
prop.setValue(val);
|
||||
bytesPassed += prop.getSize();
|
||||
textPropList.add(prop);
|
||||
}
|
||||
}
|
||||
|
||||
// Return how many bytes were used
|
||||
return bytesPassed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new collection of text properties (be they paragraph
|
||||
* or character) which will be groked via a subsequent call to
|
||||
* buildTextPropList().
|
||||
*/
|
||||
public TextPropCollection(int charactersCovered, short reservedField) {
|
||||
this.charactersCovered = charactersCovered;
|
||||
this.reservedField = reservedField;
|
||||
textPropList = new LinkedList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new collection of text properties (be they paragraph
|
||||
* or character) for a run of text without any
|
||||
*/
|
||||
public TextPropCollection(int textSize) {
|
||||
charactersCovered = textSize;
|
||||
reservedField = -1;
|
||||
textPropList = new LinkedList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the size of the text that this set of properties
|
||||
* applies to
|
||||
*/
|
||||
public void updateTextSize(int textSize) {
|
||||
charactersCovered = textSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes out to disk the header, and then all the properties
|
||||
*/
|
||||
public void writeOut(OutputStream o) throws IOException {
|
||||
// First goes the number of characters we affect
|
||||
StyleTextPropAtom.writeLittleEndian(charactersCovered,o);
|
||||
|
||||
// Then we have the reserved field if required
|
||||
if(reservedField > -1) {
|
||||
StyleTextPropAtom.writeLittleEndian(reservedField,o);
|
||||
}
|
||||
|
||||
// The the mask field
|
||||
int mask = 0;
|
||||
for(int i=0; i<textPropList.size(); i++) {
|
||||
TextProp textProp = (TextProp)textPropList.get(i);
|
||||
mask += textProp.getWriteMask();
|
||||
}
|
||||
StyleTextPropAtom.writeLittleEndian(mask,o);
|
||||
|
||||
// Then the contents of all the properties
|
||||
for(int i=0; i<textPropList.size(); i++) {
|
||||
TextProp textProp = (TextProp)textPropList.get(i);
|
||||
int val = textProp.getValue();
|
||||
if(textProp.getSize() == 2) {
|
||||
StyleTextPropAtom.writeLittleEndian((short)val,o);
|
||||
} else {
|
||||
StyleTextPropAtom.writeLittleEndian(val,o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public short getReservedField(){
|
||||
return reservedField;
|
||||
}
|
||||
|
||||
public void setReservedField(short val){
|
||||
reservedField = val;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,11 @@
|
|||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import org.apache.poi.hslf.model.textproperties.AlignmentTextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.BitMaskTextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
@ -361,378 +366,6 @@ public class StyleTextPropAtom extends RecordAtom
|
|||
|
||||
|
||||
/**
|
||||
* For a given run of characters, holds the properties (which could
|
||||
* be paragraph properties or character properties).
|
||||
* Used to hold the number of characters affected, the list of active
|
||||
* properties, and the random reserved field if required.
|
||||
*/
|
||||
public static class TextPropCollection {
|
||||
private int charactersCovered;
|
||||
private short reservedField;
|
||||
private LinkedList textPropList;
|
||||
|
||||
/** Fetch the number of characters this styling applies to */
|
||||
public int getCharactersCovered() { return charactersCovered; }
|
||||
/** Fetch the TextProps that define this styling */
|
||||
public LinkedList getTextPropList() { return textPropList; }
|
||||
|
||||
/** Fetch the TextProp with this name, or null if it isn't present */
|
||||
public TextProp findByName(String textPropName) {
|
||||
for(int i=0; i<textPropList.size(); i++) {
|
||||
TextProp prop = (TextProp)textPropList.get(i);
|
||||
if(prop.getName().equals(textPropName)) {
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Add the TextProp with this name to the list */
|
||||
public TextProp addWithName(String name) {
|
||||
// Find the base TextProp to base on
|
||||
TextProp base = null;
|
||||
for(int i=0; i < StyleTextPropAtom.characterTextPropTypes.length; i++) {
|
||||
if(StyleTextPropAtom.characterTextPropTypes[i].getName().equals(name)) {
|
||||
base = StyleTextPropAtom.characterTextPropTypes[i];
|
||||
}
|
||||
}
|
||||
for(int i=0; i < StyleTextPropAtom.paragraphTextPropTypes.length; i++) {
|
||||
if(StyleTextPropAtom.paragraphTextPropTypes[i].getName().equals(name)) {
|
||||
base = StyleTextPropAtom.paragraphTextPropTypes[i];
|
||||
}
|
||||
}
|
||||
if(base == null) {
|
||||
throw new IllegalArgumentException("No TextProp with name " + name + " is defined to add from");
|
||||
}
|
||||
|
||||
// Add a copy of this property, in the right place to the list
|
||||
TextProp textProp = (TextProp)base.clone();
|
||||
int pos = 0;
|
||||
for(int i=0; i<textPropList.size(); i++) {
|
||||
TextProp curProp = (TextProp)textPropList.get(i);
|
||||
if(textProp.getMask() > curProp.getMask()) {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
textPropList.add(pos, textProp);
|
||||
return textProp;
|
||||
}
|
||||
|
||||
/**
|
||||
* For an existing set of text properties, build the list of
|
||||
* properties coded for in a given run of properties.
|
||||
* @return the number of bytes that were used encoding the properties list
|
||||
*/
|
||||
public int buildTextPropList(int containsField, TextProp[] potentialProperties, byte[] data, int dataOffset) {
|
||||
int bytesPassed = 0;
|
||||
|
||||
// For each possible entry, see if we match the mask
|
||||
// If we do, decode that, save it, and shuffle on
|
||||
for(int i=0; i<potentialProperties.length; i++) {
|
||||
// Check there's still data left to read
|
||||
if(dataOffset+bytesPassed >= data.length) {
|
||||
// Out of data, can't be any more properties to go
|
||||
return bytesPassed;
|
||||
}
|
||||
|
||||
// Check if this property is found in the mask
|
||||
if((containsField & potentialProperties[i].getMask()) != 0) {
|
||||
// Bingo, data contains this property
|
||||
TextProp prop = (TextProp)potentialProperties[i].clone();
|
||||
int val = 0;
|
||||
if(prop.getSize() == 2) {
|
||||
val = LittleEndian.getShort(data,dataOffset+bytesPassed);
|
||||
} else {
|
||||
val = LittleEndian.getInt(data,dataOffset+bytesPassed);
|
||||
}
|
||||
prop.setValue(val);
|
||||
bytesPassed += prop.getSize();
|
||||
textPropList.add(prop);
|
||||
}
|
||||
}
|
||||
|
||||
// Return how many bytes were used
|
||||
return bytesPassed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new collection of text properties (be they paragraph
|
||||
* or character) which will be groked via a subsequent call to
|
||||
* buildTextPropList().
|
||||
*/
|
||||
private TextPropCollection(int charactersCovered, short reservedField) {
|
||||
this.charactersCovered = charactersCovered;
|
||||
this.reservedField = reservedField;
|
||||
textPropList = new LinkedList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new collection of text properties (be they paragraph
|
||||
* or character) for a run of text without any
|
||||
*/
|
||||
public TextPropCollection(int textSize) {
|
||||
charactersCovered = textSize;
|
||||
reservedField = -1;
|
||||
textPropList = new LinkedList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the size of the text that this set of properties
|
||||
* applies to
|
||||
*/
|
||||
public void updateTextSize(int textSize) {
|
||||
charactersCovered = textSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes out to disk the header, and then all the properties
|
||||
*/
|
||||
protected void writeOut(OutputStream o) throws IOException {
|
||||
// First goes the number of characters we affect
|
||||
writeLittleEndian(charactersCovered,o);
|
||||
|
||||
// Then we have the reserved field if required
|
||||
if(reservedField > -1) {
|
||||
writeLittleEndian(reservedField,o);
|
||||
}
|
||||
|
||||
// The the mask field
|
||||
int mask = 0;
|
||||
for(int i=0; i<textPropList.size(); i++) {
|
||||
TextProp textProp = (TextProp)textPropList.get(i);
|
||||
mask += textProp.getWriteMask();
|
||||
}
|
||||
writeLittleEndian(mask,o);
|
||||
|
||||
// Then the contents of all the properties
|
||||
for(int i=0; i<textPropList.size(); i++) {
|
||||
TextProp textProp = (TextProp)textPropList.get(i);
|
||||
int val = textProp.getValue();
|
||||
if(textProp.getSize() == 2) {
|
||||
writeLittleEndian((short)val,o);
|
||||
} else {
|
||||
writeLittleEndian(val,o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public short getReservedField(){
|
||||
return reservedField;
|
||||
}
|
||||
|
||||
public void setReservedField(short val){
|
||||
reservedField = val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ************************************************************************ */
|
||||
|
||||
|
||||
/**
|
||||
* Definition of a property of some text, or its paragraph. Defines
|
||||
* how to find out if it's present (via the mask on the paragraph or
|
||||
* character "contains" header field), how long the value of it is,
|
||||
* and how to get and set the value.
|
||||
*/
|
||||
public static class TextProp implements Cloneable {
|
||||
protected int sizeOfDataBlock; // Number of bytes the data part uses
|
||||
protected String propName;
|
||||
protected int dataValue;
|
||||
protected int maskInHeader;
|
||||
|
||||
/**
|
||||
* Generate the definition of a given type of text property.
|
||||
*/
|
||||
public TextProp(int sizeOfDataBlock, int maskInHeader, String propName) {
|
||||
this.sizeOfDataBlock = sizeOfDataBlock;
|
||||
this.maskInHeader = maskInHeader;
|
||||
this.propName = propName;
|
||||
this.dataValue = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of the text property
|
||||
*/
|
||||
public String getName() { return propName; }
|
||||
|
||||
/**
|
||||
* Size of the data section of the text property (2 or 4 bytes)
|
||||
*/
|
||||
public int getSize() { return sizeOfDataBlock; }
|
||||
|
||||
/**
|
||||
* Mask in the paragraph or character "contains" header field
|
||||
* that indicates that this text property is present.
|
||||
*/
|
||||
public int getMask() { return maskInHeader; }
|
||||
/**
|
||||
* Get the mask that's used at write time. Only differs from
|
||||
* the result of getMask() for the mask based properties
|
||||
*/
|
||||
public int getWriteMask() { return getMask(); }
|
||||
|
||||
/**
|
||||
* Fetch the value of the text property (meaning is specific to
|
||||
* each different kind of text property)
|
||||
*/
|
||||
public int getValue() { return dataValue; }
|
||||
|
||||
/**
|
||||
* Set the value of the text property.
|
||||
*/
|
||||
public void setValue(int val) { dataValue = val; }
|
||||
|
||||
/**
|
||||
* Clone, eg when you want to actually make use of one of these.
|
||||
*/
|
||||
public Object clone(){
|
||||
try {
|
||||
return super.clone();
|
||||
} catch(CloneNotSupportedException e) {
|
||||
throw new InternalError(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Definition of a special kind of property of some text, or its
|
||||
* paragraph. For these properties, a flag in the "contains" header
|
||||
* field tells you the data property family will exist. The value
|
||||
* of the property is itself a mask, encoding several different
|
||||
* (but related) properties
|
||||
*/
|
||||
public static class BitMaskTextProp extends TextProp implements Cloneable {
|
||||
private String[] subPropNames;
|
||||
private int[] subPropMasks;
|
||||
private boolean[] subPropMatches;
|
||||
|
||||
/** Fetch the list of the names of the sub properties */
|
||||
public String[] getSubPropNames() { return subPropNames; }
|
||||
/** Fetch the list of if the sub properties match or not */
|
||||
public boolean[] getSubPropMatches() { return subPropMatches; }
|
||||
|
||||
public BitMaskTextProp(int sizeOfDataBlock, int maskInHeader, String overallName, String[] subPropNames) {
|
||||
super(sizeOfDataBlock,maskInHeader,"bitmask");
|
||||
this.subPropNames = subPropNames;
|
||||
this.propName = overallName;
|
||||
subPropMasks = new int[subPropNames.length];
|
||||
subPropMatches = new boolean[subPropNames.length];
|
||||
|
||||
// Initialise the masks list
|
||||
for(int i=0; i<subPropMasks.length; i++) {
|
||||
subPropMasks[i] = (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* As we're purely mask based, just set flags for stuff
|
||||
* that is set
|
||||
*/
|
||||
public int getWriteMask() {
|
||||
return dataValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the text property, and recompute the sub
|
||||
* properties based on it
|
||||
*/
|
||||
public void setValue(int val) {
|
||||
dataValue = val;
|
||||
|
||||
// Figure out the values of the sub properties
|
||||
for(int i=0; i< subPropMatches.length; i++) {
|
||||
subPropMatches[i] = false;
|
||||
if((dataValue & subPropMasks[i]) != 0) {
|
||||
subPropMatches[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the true/false status of the subproperty with the given index
|
||||
*/
|
||||
public boolean getSubValue(int idx) {
|
||||
return subPropMatches[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the true/false status of the subproperty with the given index
|
||||
*/
|
||||
public void setSubValue(boolean value, int idx) {
|
||||
if(subPropMatches[idx] == value) { return; }
|
||||
if(value) {
|
||||
dataValue += subPropMasks[idx];
|
||||
} else {
|
||||
dataValue -= subPropMasks[idx];
|
||||
}
|
||||
subPropMatches[idx] = value;
|
||||
}
|
||||
|
||||
public Object clone(){
|
||||
BitMaskTextProp newObj = (BitMaskTextProp)super.clone();
|
||||
|
||||
// Don't carry over matches, but keep everything
|
||||
// else as it was
|
||||
newObj.subPropMatches = new boolean[subPropMatches.length];
|
||||
|
||||
return newObj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Definition for the alignment text property.
|
||||
*/
|
||||
public static class AlignmentTextProp extends TextProp {
|
||||
public static final int LEFT = 0;
|
||||
public static final int CENTER = 1;
|
||||
public static final int RIGHT = 2;
|
||||
public static final int JUSTIFY = 3;
|
||||
public static final int THAIDISTRIBUTED = 5;
|
||||
public static final int JUSTIFYLOW = 6;
|
||||
|
||||
public AlignmentTextProp() {
|
||||
super(2, 0x800, "alignment");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Definition for the common character text property bitset, which
|
||||
* handles bold/italic/underline etc.
|
||||
*/
|
||||
public static class CharFlagsTextProp extends BitMaskTextProp {
|
||||
public static final int BOLD_IDX = 0;
|
||||
public static final int ITALIC_IDX = 1;
|
||||
public static final int UNDERLINE_IDX = 2;
|
||||
public static final int SHADOW_IDX = 4;
|
||||
public static final int STRIKETHROUGH_IDX = 8;
|
||||
public static final int RELIEF_IDX = 9;
|
||||
public static final int RESET_NUMBERING_IDX = 10;
|
||||
public static final int ENABLE_NUMBERING_1_IDX = 11;
|
||||
public static final int ENABLE_NUMBERING_2_IDX = 12;
|
||||
|
||||
public CharFlagsTextProp() {
|
||||
super(2,0xffff, "char_flags", new String[] {
|
||||
"bold", // 0x0001
|
||||
"italic", // 0x0002
|
||||
"underline", // 0x0004
|
||||
"char_unknown_1",// 0x0008
|
||||
"shadow", // 0x0010
|
||||
"char_unknown_2",// 0x0020
|
||||
"char_unknown_3",// 0x0040
|
||||
"char_unknown_4",// 0x0080
|
||||
"strikethrough", // 0x0100
|
||||
"relief", // 0x0200
|
||||
"reset_numbering", // 0x0400
|
||||
"enable_numbering_1", // 0x0800
|
||||
"enable_numbering_2", // 0x1000
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump the record content into <code>StringBuffer</code>
|
||||
*
|
||||
* @return the string representation of the record data
|
||||
|
|
|
@ -22,7 +22,11 @@ import org.apache.poi.util.LittleEndian;
|
|||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
|
||||
|
||||
import org.apache.poi.hslf.model.textproperties.BitMaskTextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||
|
||||
/**
|
||||
* TxMasterStyleAtom atom (4003).
|
||||
|
@ -163,7 +167,10 @@ public class TxMasterStyleAtom extends RecordAtom {
|
|||
}
|
||||
|
||||
/**
|
||||
* Paragraph properties for the specified text type and indent level
|
||||
* Paragraph properties for the specified text type and
|
||||
* indent level
|
||||
* Depending on the level and type, it may be our special
|
||||
* ones, or the standard StyleTextPropAtom ones
|
||||
*/
|
||||
protected TextProp[] getParagraphProps(int type, int level){
|
||||
if (level != 0 || type >= MAX_INDENT){
|
||||
|
@ -194,7 +201,10 @@ public class TxMasterStyleAtom extends RecordAtom {
|
|||
}
|
||||
|
||||
/**
|
||||
* Character properties for the specified text type and indent level
|
||||
* Character properties for the specified text type and
|
||||
* indent level.
|
||||
* Depending on the level and type, it may be our special
|
||||
* ones, or the standard StyleTextPropAtom ones
|
||||
*/
|
||||
protected TextProp[] getCharacterProps(int type, int level){
|
||||
if (level != 0 || type >= MAX_INDENT){
|
||||
|
|
|
@ -23,9 +23,9 @@ package org.apache.poi.hslf.usermodel;
|
|||
import org.apache.poi.hslf.model.TextRun;
|
||||
import org.apache.poi.hslf.model.Sheet;
|
||||
import org.apache.poi.hslf.model.SlideMaster;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.CharFlagsTextProp;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.TextProp;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.TextPropCollection;
|
||||
import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||
import org.apache.poi.hslf.record.ColorSchemeAtom;
|
||||
|
||||
import java.awt.*;
|
||||
|
|
|
@ -21,6 +21,7 @@ import junit.framework.TestCase;
|
|||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.hslf.usermodel.RichTextRun;
|
||||
import org.apache.poi.hslf.HSLFSlideShow;
|
||||
import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
|
||||
import org.apache.poi.hslf.record.*;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
|
||||
|
||||
|
|
|
@ -24,10 +24,10 @@ package org.apache.poi.hslf.model;
|
|||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hslf.HSLFSlideShow;
|
||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||
import org.apache.poi.hslf.record.TextBytesAtom;
|
||||
import org.apache.poi.hslf.record.TextCharsAtom;
|
||||
import org.apache.poi.hslf.record.TextHeaderAtom;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.TextPropCollection;
|
||||
import org.apache.poi.hslf.usermodel.RichTextRun;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
package org.apache.poi.hslf.record;
|
||||
|
||||
import org.apache.poi.hslf.HSLFSlideShow;
|
||||
import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ package org.apache.poi.hslf.record;
|
|||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.hslf.model.textproperties.TextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
Loading…
Reference in New Issue