Yegor's TxMasterStyleAtom code from Bug #40057
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@423129 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
bc74b9a09f
commit
9356b01d88
@ -84,7 +84,7 @@ public class RecordTypes {
|
||||
public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class);
|
||||
public static final Type StyleTextPropAtom = new Type(4001,StyleTextPropAtom.class);
|
||||
public static final Type BaseTextPropAtom = new Type(4002,null);
|
||||
public static final Type TxMasterStyleAtom = new Type(4003,null);
|
||||
public static final Type TxMasterStyleAtom = new Type(4003,TxMasterStyleAtom.class);
|
||||
public static final Type TxCFStyleAtom = new Type(4004,null);
|
||||
public static final Type TxPFStyleAtom = new Type(4005,null);
|
||||
public static final Type TextRulerAtom = new Type(4006,null);
|
||||
|
@ -93,9 +93,9 @@ public class StyleTextPropAtom extends RecordAtom
|
||||
new TextProp(4, 0x20, "bullet.color"),
|
||||
new TextProp(2, 0x40, "bullet.size"),
|
||||
new TextProp(2, 0x80, "bullet.char"),
|
||||
new TextProp(2, 0x100, "para_unknown_1"),
|
||||
new TextProp(2, 0x100, "text.offset"),
|
||||
new TextProp(2, 0x200, "para_unknown_2"),
|
||||
new TextProp(2, 0x400, "para_unknown_3"),
|
||||
new TextProp(2, 0x400, "bullet.offset"),
|
||||
new AlignmentTextProp(), // 0x800
|
||||
new TextProp(2, 0x1000, "linespacing"),
|
||||
new TextProp(2, 0x2000, "spacebefore"),
|
||||
@ -348,7 +348,7 @@ public class StyleTextPropAtom extends RecordAtom
|
||||
* Used to hold the number of characters affected, the list of active
|
||||
* properties, and the random reserved field if required.
|
||||
*/
|
||||
public class TextPropCollection {
|
||||
public static class TextPropCollection {
|
||||
private int charactersCovered;
|
||||
private short reservedField;
|
||||
private LinkedList textPropList;
|
||||
@ -445,7 +445,7 @@ public class StyleTextPropAtom extends RecordAtom
|
||||
* Create a new collection of text properties (be they paragraph
|
||||
* or character) for a run of text without any
|
||||
*/
|
||||
private TextPropCollection(int textSize) {
|
||||
public TextPropCollection(int textSize) {
|
||||
charactersCovered = textSize;
|
||||
reservedField = -1;
|
||||
textPropList = new LinkedList();
|
||||
@ -511,7 +511,7 @@ public class StyleTextPropAtom extends RecordAtom
|
||||
/**
|
||||
* Generate the definition of a given type of text property.
|
||||
*/
|
||||
private TextProp(int sizeOfDataBlock, int maskInHeader, String propName) {
|
||||
public TextProp(int sizeOfDataBlock, int maskInHeader, String propName) {
|
||||
this.sizeOfDataBlock = sizeOfDataBlock;
|
||||
this.maskInHeader = maskInHeader;
|
||||
this.propName = propName;
|
||||
@ -580,7 +580,7 @@ public class StyleTextPropAtom extends RecordAtom
|
||||
/** Fetch the list of if the sub properties match or not */
|
||||
public boolean[] getSubPropMatches() { return subPropMatches; }
|
||||
|
||||
private BitMaskTextProp(int sizeOfDataBlock, int maskInHeader, String overallName, String[] subPropNames) {
|
||||
public BitMaskTextProp(int sizeOfDataBlock, int maskInHeader, String overallName, String[] subPropNames) {
|
||||
super(sizeOfDataBlock,maskInHeader,"bitmask");
|
||||
this.subPropNames = subPropNames;
|
||||
this.propName = overallName;
|
||||
@ -679,7 +679,7 @@ public class StyleTextPropAtom extends RecordAtom
|
||||
public static final int ENABLE_NUMBERING_1_IDX = 11;
|
||||
public static final int ENABLE_NUMBERING_2_IDX = 12;
|
||||
|
||||
private CharFlagsTextProp() {
|
||||
public CharFlagsTextProp() {
|
||||
super(2,0xffff, "char_flags", new String[] {
|
||||
"bold", // 0x0001
|
||||
"italic", // 0x0002
|
||||
|
@ -0,0 +1,213 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
|
||||
|
||||
/**
|
||||
* TxMasterStyleAtom atom (4003).
|
||||
* <p>
|
||||
* Stores default character and paragraph styles.
|
||||
* The atom instance value is the text type and is encoded like the txstyle field in
|
||||
* TextHeaderAtom. The text styles are located in the MainMaster container,
|
||||
* except for the "other" style, which is in the Document.Environment container.
|
||||
* </p>
|
||||
* <p>
|
||||
* This atom can store up to 5 pairs of paragraph+character styles,
|
||||
* each pair describes an indent level. The first pair describes
|
||||
* first-level paragraph with no indentation.
|
||||
* </p>
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TxMasterStyleAtom extends RecordAtom {
|
||||
|
||||
/**
|
||||
* Maximum number of indentatio levels allowed in PowerPoint documents
|
||||
*/
|
||||
private static final int MAX_INDENT = 5;
|
||||
|
||||
private byte[] _header;
|
||||
private static long _type = 4003;
|
||||
private byte[] _data;
|
||||
|
||||
private TextPropCollection[] prstyles;
|
||||
private TextPropCollection[] chstyles;
|
||||
|
||||
protected TxMasterStyleAtom(byte[] source, int start, int len) {
|
||||
_header = new byte[8];
|
||||
System.arraycopy(source,start,_header,0,8);
|
||||
|
||||
_data = new byte[len-8];
|
||||
System.arraycopy(source,start+8,_data,0,_data.length);
|
||||
|
||||
//read available styles
|
||||
try {
|
||||
init();
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We are of type 4003
|
||||
*
|
||||
* @return type of this record
|
||||
* @see RecordTypes.TxMasterStyleAtom
|
||||
*/
|
||||
public long getRecordType() {
|
||||
return _type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of the record back, so it can be written
|
||||
* to disk
|
||||
*/
|
||||
public void writeOut(OutputStream out) throws IOException {
|
||||
// Write out the (new) header
|
||||
out.write(_header);
|
||||
|
||||
// Write out the record data
|
||||
out.write(_data);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of character styles defined in this record.
|
||||
*
|
||||
* @return character styles defined in this record
|
||||
*/
|
||||
public TextPropCollection[] getCharacterStyles(){
|
||||
return chstyles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of paragraph styles defined in this record.
|
||||
*
|
||||
* @return paragraph styles defined in this record
|
||||
*/
|
||||
public TextPropCollection[] getParagraphStyles(){
|
||||
return prstyles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return type of the text.
|
||||
* Must be a constant defined in <code>TextHeaderAtom</code>
|
||||
*
|
||||
* @return type of the text
|
||||
* @see TextHeaderAtom
|
||||
*/
|
||||
public int getTextType(){
|
||||
//The atom instance value is the text type
|
||||
return LittleEndian.getShort(_header, 0) >> 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse the record data and initialize styles
|
||||
*/
|
||||
protected void init(){
|
||||
//type of the text
|
||||
int type = getTextType();
|
||||
|
||||
int head;
|
||||
int pos = 0;
|
||||
|
||||
//number of indentation levels
|
||||
short levels = LittleEndian.getShort(_data, 0);
|
||||
pos += LittleEndian.SHORT_SIZE;
|
||||
|
||||
prstyles = new TextPropCollection[levels];
|
||||
chstyles = new TextPropCollection[levels];
|
||||
|
||||
for(short j = 0; j < levels; j++) {
|
||||
|
||||
if (type >= TextHeaderAtom.CENTRE_BODY_TYPE) {
|
||||
// Fetch the 2 byte value, that is safe to ignore for some types of text
|
||||
short val = LittleEndian.getShort(_data, pos);
|
||||
pos += LittleEndian.SHORT_SIZE;
|
||||
}
|
||||
|
||||
head = LittleEndian.getInt(_data, pos);
|
||||
pos += LittleEndian.INT_SIZE;
|
||||
TextPropCollection prprops = new TextPropCollection(0);
|
||||
pos += prprops.buildTextPropList( head, getParagraphProps(type, j), _data, pos);
|
||||
prstyles[j] = prprops;
|
||||
|
||||
head = LittleEndian.getInt(_data, pos);
|
||||
pos += LittleEndian.INT_SIZE;
|
||||
TextPropCollection chprops = new TextPropCollection(0);
|
||||
pos += chprops.buildTextPropList( head, getCharacterProps(type, j), _data, pos);
|
||||
chstyles[j] = chprops;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Paragraph properties for the specified text type and indent level
|
||||
*/
|
||||
protected TextProp[] getParagraphProps(int type, int level){
|
||||
if (level != 0 || type >= MAX_INDENT){
|
||||
return StyleTextPropAtom.paragraphTextPropTypes;
|
||||
} else {
|
||||
return new TextProp[] {
|
||||
new BitMaskTextProp(2, 0xF, "paragraph_flags", new String[] {
|
||||
"bullet", "bullet.hardfont",
|
||||
"bullet.hardcolor", "bullet.hardsize"}
|
||||
),
|
||||
new TextProp(2, 0x80, "bullet.char"),
|
||||
new TextProp(2, 0x10, "bullet.font"),
|
||||
new TextProp(2, 0x40, "bullet.size"),
|
||||
new TextProp(4, 0x20, "bullet.color"),
|
||||
new TextProp(2, 0xD00, "alignment"),
|
||||
new TextProp(2, 0x1000, "linespacing"),
|
||||
new TextProp(2, 0x2000, "spacebefore"),
|
||||
new TextProp(2, 0x4000, "spaceafter"),
|
||||
new TextProp(2, 0x8000, "text.offset"),
|
||||
new TextProp(2, 0x10000, "bullet.offset"),
|
||||
new TextProp(2, 0x20000, "defaulttab"),
|
||||
new TextProp(2, 0x40000, "para_unknown_2"),
|
||||
new TextProp(2, 0x80000, "para_unknown_3"),
|
||||
new TextProp(2, 0x100000, "para_unknown_4"),
|
||||
new TextProp(2, 0x200000, "para_unknown_5")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Character properties for the specified text type and indent level
|
||||
*/
|
||||
protected TextProp[] getCharacterProps(int type, int level){
|
||||
if (level != 0 || type >= MAX_INDENT){
|
||||
return StyleTextPropAtom.characterTextPropTypes;
|
||||
} else
|
||||
return new TextProp[] {
|
||||
new CharFlagsTextProp(),
|
||||
new TextProp(2, 0x10000, "font.index"),
|
||||
new TextProp(2, 0x20000, "char_unknown_1"),
|
||||
new TextProp(4, 0x40000, "char_unknown_2"),
|
||||
new TextProp(2, 0x80000, "font.size"),
|
||||
new TextProp(2, 0x100000, "char_unknown_3"),
|
||||
new TextProp(4, 0x200000, "font.color"),
|
||||
new TextProp(2, 0x800000, "char_unknown_4")
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,233 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
* Test <code>TestTxMasterStyleAtom</code> record.
|
||||
* Check master style for the empty ppt which is created
|
||||
* by the default constructor of <code>SlideShow</code>
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TestTxMasterStyleAtom extends TestCase {
|
||||
protected SlideShow _ppt;
|
||||
|
||||
public void setUp() throws Exception{
|
||||
_ppt = new SlideShow();
|
||||
|
||||
}
|
||||
|
||||
public void testDefaultStyles() {
|
||||
TxMasterStyleAtom[] txmaster = getMasterStyles();
|
||||
for (int i = 0; i < txmaster.length; i++) {
|
||||
int txtype = txmaster[i].getTextType();
|
||||
switch (txtype){
|
||||
case TextHeaderAtom.TITLE_TYPE:
|
||||
checkTitleType(txmaster[i]);
|
||||
break;
|
||||
case TextHeaderAtom.BODY_TYPE:
|
||||
checkBodyType(txmaster[i]);
|
||||
break;
|
||||
case TextHeaderAtom.NOTES_TYPE:
|
||||
checkNotesType(txmaster[i]);
|
||||
break;
|
||||
case TextHeaderAtom.OTHER_TYPE:
|
||||
checkOtherType(txmaster[i]);
|
||||
break;
|
||||
case TextHeaderAtom.CENTRE_BODY_TYPE:
|
||||
break;
|
||||
case TextHeaderAtom.CENTER_TITLE_TYPE:
|
||||
break;
|
||||
case TextHeaderAtom.HALF_BODY_TYPE:
|
||||
break;
|
||||
case TextHeaderAtom.QUARTER_BODY_TYPE:
|
||||
break;
|
||||
default:
|
||||
fail("Unknown text type: " + txtype);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Test styles for type=TextHeaderAtom.TITLE_TYPE
|
||||
*/
|
||||
private void checkTitleType(TxMasterStyleAtom txmaster){
|
||||
TextPropCollection props;
|
||||
TextProp prop;
|
||||
|
||||
//paragraph styles
|
||||
props = txmaster.getParagraphStyles()[0];
|
||||
|
||||
prop = props.findByName("alignment");
|
||||
assertEquals(1, prop.getValue()); //title has center alignment
|
||||
|
||||
//character styles
|
||||
props = txmaster.getCharacterStyles()[0];
|
||||
|
||||
prop = props.findByName("font.color");
|
||||
assertEquals(0x3000000, prop.getValue());
|
||||
|
||||
prop = props.findByName("font.index");
|
||||
assertEquals(0, prop.getValue());
|
||||
|
||||
prop = props.findByName("font.size");
|
||||
assertEquals(49, prop.getValue());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test styles for type=TextHeaderAtom.BODY_TYPE
|
||||
*/
|
||||
private void checkBodyType(TxMasterStyleAtom txmaster){
|
||||
TextPropCollection props;
|
||||
TextProp prop;
|
||||
|
||||
TextPropCollection[] prstyles = txmaster.getParagraphStyles();
|
||||
TextPropCollection[] chstyles = txmaster.getCharacterStyles();
|
||||
assertEquals("TxMasterStyleAtom for TextHeaderAtom.BODY_TYPE " +
|
||||
"must contain styles for 5 indentation levels", 5, prstyles.length);
|
||||
assertEquals("TxMasterStyleAtom for TextHeaderAtom.BODY_TYPE " +
|
||||
"must contain styles for 5 indentation levels", 5, chstyles.length);
|
||||
|
||||
//paragraph styles
|
||||
props = prstyles[0];
|
||||
|
||||
prop = props.findByName("alignment");
|
||||
assertEquals(0, prop.getValue());
|
||||
|
||||
|
||||
for (int i = 0; i < prstyles.length; i++) {
|
||||
assertNotNull("text.offset is null for indentation level " + i, prstyles[i].findByName("text.offset"));
|
||||
assertNotNull("bullet.offset is null for indentation level " + i, prstyles[i].findByName("bullet.offset"));
|
||||
}
|
||||
|
||||
//character styles
|
||||
props = chstyles[0];
|
||||
|
||||
prop = props.findByName("font.color");
|
||||
assertEquals(0x1000000, prop.getValue());
|
||||
|
||||
prop = props.findByName("font.index");
|
||||
assertEquals(0, prop.getValue());
|
||||
|
||||
prop = props.findByName("font.size");
|
||||
assertEquals(36, prop.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test styles for type=TextHeaderAtom.OTHER_TYPE
|
||||
*/
|
||||
private void checkOtherType(TxMasterStyleAtom txmaster){
|
||||
TextPropCollection props;
|
||||
TextProp prop;
|
||||
|
||||
//paragraph styles
|
||||
props = txmaster.getParagraphStyles()[0];
|
||||
|
||||
prop = props.findByName("alignment");
|
||||
assertEquals(0, prop.getValue());
|
||||
|
||||
//character styles
|
||||
props = txmaster.getCharacterStyles()[0];
|
||||
|
||||
prop = props.findByName("font.color");
|
||||
assertEquals(0x1000000, prop.getValue());
|
||||
|
||||
prop = props.findByName("font.index");
|
||||
assertEquals(0, prop.getValue());
|
||||
|
||||
prop = props.findByName("font.size");
|
||||
assertEquals(24, prop.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test styles for type=TextHeaderAtom.NOTES_TYPE
|
||||
*/
|
||||
private void checkNotesType(TxMasterStyleAtom txmaster){
|
||||
TextPropCollection props;
|
||||
TextProp prop;
|
||||
|
||||
//paragraph styles
|
||||
props = txmaster.getParagraphStyles()[0];
|
||||
|
||||
prop = props.findByName("alignment");
|
||||
assertEquals(0, prop.getValue()); //title has center alignment
|
||||
|
||||
//character styles
|
||||
props = txmaster.getCharacterStyles()[0];
|
||||
|
||||
prop = props.findByName("font.color");
|
||||
assertEquals(0x1000000, prop.getValue());
|
||||
|
||||
prop = props.findByName("font.index");
|
||||
assertEquals(0, prop.getValue());
|
||||
|
||||
prop = props.findByName("font.size");
|
||||
assertEquals(12, prop.getValue());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect all TxMasterStyleAtom records contained in the supplied slide show.
|
||||
* There must be a TxMasterStyleAtom per each type of text defined in TextHeaderAtom
|
||||
*/
|
||||
protected TxMasterStyleAtom[] getMasterStyles(){
|
||||
ArrayList lst = new ArrayList();
|
||||
|
||||
Record[] core = _ppt.getMostRecentCoreRecords();
|
||||
for (int i = 0; i < core.length; i++) {
|
||||
if(core[i].getRecordType() == RecordTypes.MainMaster.typeID){
|
||||
Record[] rec = core[i].getChildRecords();
|
||||
int cnt = 0;
|
||||
for (int j = 0; j < rec.length; j++) {
|
||||
if (rec[j] instanceof TxMasterStyleAtom) {
|
||||
lst.add(rec[j]);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
assertEquals("MainMaster must contain 7 TxMasterStyleAtoms ", 7, cnt);
|
||||
} else if(core[i].getRecordType() == RecordTypes.Document.typeID){
|
||||
TxMasterStyleAtom txstyle = null;
|
||||
Document doc = (Document)core[i];
|
||||
Record[] rec = doc.getEnvironment().getChildRecords();
|
||||
for (int j = 0; j < rec.length; j++) {
|
||||
if (rec[j] instanceof TxMasterStyleAtom) {
|
||||
if (txstyle != null) fail("Document.Environment must contain 1 TxMasterStyleAtom");
|
||||
txstyle = (TxMasterStyleAtom)rec[j];
|
||||
}
|
||||
}
|
||||
assertNotNull("TxMasterStyleAtom not found in Document.Environment", txstyle);
|
||||
|
||||
assertEquals("Document.Environment must contain TxMasterStyleAtom with type=TextHeaderAtom.OTHER_TYPE",
|
||||
TextHeaderAtom.OTHER_TYPE, txstyle.getTextType());
|
||||
lst.add(txstyle);
|
||||
}
|
||||
}
|
||||
|
||||
return (TxMasterStyleAtom[])lst.toArray(new TxMasterStyleAtom[lst.size()]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user