View | Details | Raw Unified | Return to bug 40057
Collapse All | Expand All

(-)src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java (-1 / +1 lines)
Lines 84-90 Link Here
84
    public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class);
84
    public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class);
85
    public static final Type StyleTextPropAtom = new Type(4001,StyleTextPropAtom.class);
85
    public static final Type StyleTextPropAtom = new Type(4001,StyleTextPropAtom.class);
86
    public static final Type BaseTextPropAtom = new Type(4002,null);
86
    public static final Type BaseTextPropAtom = new Type(4002,null);
87
    public static final Type TxMasterStyleAtom = new Type(4003,null);
87
    public static final Type TxMasterStyleAtom = new Type(4003,TxMasterStyleAtom.class);
88
    public static final Type TxCFStyleAtom = new Type(4004,null);
88
    public static final Type TxCFStyleAtom = new Type(4004,null);
89
    public static final Type TxPFStyleAtom = new Type(4005,null);
89
    public static final Type TxPFStyleAtom = new Type(4005,null);
90
    public static final Type TextRulerAtom = new Type(4006,null);
90
    public static final Type TextRulerAtom = new Type(4006,null);
(-)src/scratchpad/src/org/apache/poi/hslf/record/TxMasterStyleAtom.java (+213 lines)
Line 0 Link Here
1
2
/* ====================================================================
3
   Copyright 2002-2004   Apache Software Foundation
4
5
   Licensed under the Apache License, Version 2.0 (the "License");
6
   you may not use this file except in compliance with the License.
7
   You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
package org.apache.poi.hslf.record;
19
20
import org.apache.poi.util.LittleEndian;
21
22
import java.io.OutputStream;
23
import java.io.IOException;
24
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
25
26
/**
27
 * TxMasterStyleAtom atom (4003).
28
 * <p>
29
 * Stores default character and paragraph styles.
30
 * The atom instance value is the text type and is encoded like the txstyle field in
31
 * TextHeaderAtom. The text styles are located in the MainMaster container,
32
 * except for the "other" style, which is in the Document.Environment container.
33
 * </p>
34
 * <p>
35
 *  This atom can store up to 5 pairs of paragraph+character styles,
36
 *  each pair describes an indent level. The first pair describes
37
 *  first-level paragraph with no indentation.
38
 * </p>
39
 *
40
 *  @author Yegor Kozlov
41
 */
42
public class TxMasterStyleAtom extends RecordAtom {
43
44
    /**
45
     * Maximum number of indentatio levels allowed in PowerPoint documents
46
     */
47
    private static final int MAX_INDENT = 5;
48
49
    private byte[] _header;
50
    private static long _type = 4003;
51
    private byte[] _data;
52
53
    private TextPropCollection[] prstyles;
54
    private TextPropCollection[] chstyles;
55
56
    protected TxMasterStyleAtom(byte[] source, int start, int len) {
57
        _header = new byte[8];
58
        System.arraycopy(source,start,_header,0,8);
59
60
        _data = new byte[len-8];
61
        System.arraycopy(source,start+8,_data,0,_data.length);
62
63
        //read available styles
64
        try {
65
            init();
66
        } catch (Exception e){
67
            e.printStackTrace();
68
        }
69
    }
70
71
    /**
72
     * We are of type 4003
73
     *
74
     * @return type of this record
75
     * @see RecordTypes.TxMasterStyleAtom
76
     */
77
    public long getRecordType() {
78
        return _type;
79
    }
80
81
    /**
82
     * Write the contents of the record back, so it can be written
83
     *  to disk
84
     */
85
    public void writeOut(OutputStream out) throws IOException {
86
        // Write out the (new) header
87
        out.write(_header);
88
89
        // Write out the record data
90
        out.write(_data);
91
92
    }
93
94
    /**
95
     * Returns array of character styles defined in this record.
96
     *
97
     * @return character styles defined in this record
98
     */
99
    public TextPropCollection[] getCharacterStyles(){
100
        return chstyles;
101
    }
102
103
    /**
104
     * Returns array of paragraph styles defined in this record.
105
     *
106
     * @return paragraph styles defined in this record
107
     */
108
    public TextPropCollection[] getParagraphStyles(){
109
        return prstyles;
110
    }
111
112
    /**
113
     * Return type of the text.
114
     * Must be a constant defined in <code>TextHeaderAtom</code>
115
     *
116
     * @return type of the text
117
     * @see TextHeaderAtom 
118
     */
119
    public int getTextType(){
120
        //The atom instance value is the text type
121
        return LittleEndian.getShort(_header, 0) >> 4;
122
    }
123
124
    /**
125
     * parse the record data and initialize styles
126
     */
127
    protected void init(){
128
        //type of the text
129
        int type = getTextType();
130
131
        int head;
132
        int pos = 0;
133
134
        //number of indentation levels
135
        short levels = LittleEndian.getShort(_data, 0);
136
        pos += LittleEndian.SHORT_SIZE;
137
138
        prstyles = new TextPropCollection[levels];
139
        chstyles = new TextPropCollection[levels];
140
141
        for(short j = 0; j < levels; j++) {
142
143
            if (type >= TextHeaderAtom.CENTRE_BODY_TYPE) {
144
                // Fetch the 2 byte value, that is safe to ignore for some types of text
145
                short val = LittleEndian.getShort(_data, pos);
146
                pos += LittleEndian.SHORT_SIZE;
147
            }
148
149
            head = LittleEndian.getInt(_data, pos);
150
            pos += LittleEndian.INT_SIZE;
151
            TextPropCollection prprops = new TextPropCollection(0);
152
            pos += prprops.buildTextPropList( head, getParagraphProps(type, j), _data, pos);
153
            prstyles[j] = prprops;
154
155
            head = LittleEndian.getInt(_data, pos);
156
            pos += LittleEndian.INT_SIZE;
157
            TextPropCollection chprops = new TextPropCollection(0);
158
            pos += chprops.buildTextPropList( head, getCharacterProps(type, j), _data, pos);
159
            chstyles[j] = chprops;
160
        }
161
162
    }
163
164
    /**
165
     *  Paragraph properties for the specified text type and indent level
166
     */
167
    protected TextProp[] getParagraphProps(int type, int level){
168
        if (level != 0 || type >= MAX_INDENT){
169
            return StyleTextPropAtom.paragraphTextPropTypes;
170
        } else {
171
            return new TextProp[] {
172
                    new BitMaskTextProp(2,  0xF, "paragraph_flags", new String[] {
173
                        "bullet", "bullet.hardfont",
174
                        "bullet.hardcolor", "bullet.hardsize"}
175
                    ),
176
                    new TextProp(2, 0x80, "bullet.char"),
177
                    new TextProp(2, 0x10, "bullet.font"),
178
                    new TextProp(2, 0x40, "bullet.size"),
179
                    new TextProp(4, 0x20, "bullet.color"),
180
                    new TextProp(2, 0xD00, "alignment"),
181
                    new TextProp(2, 0x1000, "linespacing"),
182
                    new TextProp(2, 0x2000, "spacebefore"),
183
                    new TextProp(2, 0x4000, "spaceafter"),
184
                    new TextProp(2, 0x8000, "text.offset"),
185
                    new TextProp(2, 0x10000, "bullet.offset"),
186
                    new TextProp(2, 0x20000, "defaulttab"),
187
                    new TextProp(2, 0x40000, "para_unknown_2"),
188
                    new TextProp(2, 0x80000, "para_unknown_3"),
189
                    new TextProp(2, 0x100000, "para_unknown_4"),
190
                    new TextProp(2, 0x200000, "para_unknown_5")
191
            };
192
        }
193
    }
194
195
    /**
196
     *  Character properties for the specified text type and indent level
197
     */
198
    protected TextProp[] getCharacterProps(int type, int level){
199
        if (level != 0 || type >= MAX_INDENT){
200
            return StyleTextPropAtom.characterTextPropTypes;
201
        } else
202
         return new TextProp[] {
203
				new CharFlagsTextProp(),
204
				new TextProp(2, 0x10000, "font.index"),
205
				new TextProp(2, 0x20000, "char_unknown_1"),
206
				new TextProp(4, 0x40000, "char_unknown_2"),
207
				new TextProp(2, 0x80000, "font.size"),
208
				new TextProp(2, 0x100000, "char_unknown_3"),
209
				new TextProp(4, 0x200000, "font.color"),
210
				new TextProp(2, 0x800000, "char_unknown_4")
211
	    };
212
    }
213
}
(-)src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java (-7 / +7 lines)
Lines 93-101 Link Here
93
				new TextProp(4, 0x20, "bullet.color"),
93
				new TextProp(4, 0x20, "bullet.color"),
94
				new TextProp(2, 0x40, "bullet.size"),
94
				new TextProp(2, 0x40, "bullet.size"),
95
				new TextProp(2, 0x80, "bullet.char"),
95
				new TextProp(2, 0x80, "bullet.char"),
96
				new TextProp(2, 0x100, "para_unknown_1"),
96
				new TextProp(2, 0x100, "text.offset"),
97
				new TextProp(2, 0x200, "para_unknown_2"),
97
				new TextProp(2, 0x200, "para_unknown_2"),
98
				new TextProp(2, 0x400, "para_unknown_3"),
98
				new TextProp(2, 0x400, "bullet.offset"),
99
				new TextProp(2, 0x800, "alignment"),
99
				new TextProp(2, 0x800, "alignment"),
100
				new TextProp(2, 0x1000, "linespacing"),
100
				new TextProp(2, 0x1000, "linespacing"),
101
				new TextProp(2, 0x2000, "spacebefore"),
101
				new TextProp(2, 0x2000, "spacebefore"),
Lines 348-354 Link Here
348
	 * Used to hold the number of characters affected, the list of active
348
	 * Used to hold the number of characters affected, the list of active
349
	 *  properties, and the random reserved field if required.
349
	 *  properties, and the random reserved field if required.
350
	 */
350
	 */
351
	public class TextPropCollection {
351
	public static class TextPropCollection {
352
		private int charactersCovered;
352
		private int charactersCovered;
353
		private short reservedField;
353
		private short reservedField;
354
		private LinkedList textPropList;
354
		private LinkedList textPropList;
Lines 445-451 Link Here
445
		 * Create a new collection of text properties (be they paragraph
445
		 * Create a new collection of text properties (be they paragraph
446
		 *  or character) for a run of text without any
446
		 *  or character) for a run of text without any
447
		 */
447
		 */
448
		private TextPropCollection(int textSize) {
448
		public TextPropCollection(int textSize) {
449
			charactersCovered = textSize;
449
			charactersCovered = textSize;
450
			reservedField = -1;
450
			reservedField = -1;
451
			textPropList = new LinkedList();
451
			textPropList = new LinkedList();
Lines 511-517 Link Here
511
		/** 
511
		/** 
512
		 * Generate the definition of a given type of text property.
512
		 * Generate the definition of a given type of text property.
513
		 */
513
		 */
514
		private TextProp(int sizeOfDataBlock, int maskInHeader, String propName) {
514
		public TextProp(int sizeOfDataBlock, int maskInHeader, String propName) {
515
			this.sizeOfDataBlock = sizeOfDataBlock;
515
			this.sizeOfDataBlock = sizeOfDataBlock;
516
			this.maskInHeader = maskInHeader;
516
			this.maskInHeader = maskInHeader;
517
			this.propName = propName;
517
			this.propName = propName;
Lines 580-586 Link Here
580
		/** Fetch the list of if the sub properties match or not */
580
		/** Fetch the list of if the sub properties match or not */
581
		public boolean[] getSubPropMatches() { return subPropMatches; }
581
		public boolean[] getSubPropMatches() { return subPropMatches; }
582
582
583
		private BitMaskTextProp(int sizeOfDataBlock, int maskInHeader, String overallName, String[] subPropNames) {
583
		public BitMaskTextProp(int sizeOfDataBlock, int maskInHeader, String overallName, String[] subPropNames) {
584
			super(sizeOfDataBlock,maskInHeader,"bitmask");
584
			super(sizeOfDataBlock,maskInHeader,"bitmask");
585
			this.subPropNames = subPropNames;
585
			this.subPropNames = subPropNames;
586
			this.propName = overallName;
586
			this.propName = overallName;
Lines 664-670 Link Here
664
		public static final int ENABLE_NUMBERING_1_IDX = 11;
664
		public static final int ENABLE_NUMBERING_1_IDX = 11;
665
		public static final int ENABLE_NUMBERING_2_IDX = 12;
665
		public static final int ENABLE_NUMBERING_2_IDX = 12;
666
666
667
		private CharFlagsTextProp() {
667
		public CharFlagsTextProp() {
668
			super(2,0xffff, "char_flags", new String[] {
668
			super(2,0xffff, "char_flags", new String[] {
669
					"bold",          // 0x0001
669
					"bold",          // 0x0001
670
					"italic",        // 0x0002
670
					"italic",        // 0x0002
(-)src/scratchpad/testcases/org/apache/poi/hslf/record/TestTxMasterStyleAtom.java (+233 lines)
Line 0 Link Here
1
2
/* ====================================================================
3
   Copyright 2002-2004   Apache Software Foundation
4
5
   Licensed under the Apache License, Version 2.0 (the "License");
6
   you may not use this file except in compliance with the License.
7
   You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
package org.apache.poi.hslf.record;
18
19
import junit.framework.TestCase;
20
import org.apache.poi.hslf.usermodel.SlideShow;
21
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
22
23
import java.util.ArrayList;
24
25
26
/**
27
 * Test <code>TestTxMasterStyleAtom</code> record.
28
 * Check master style for the empty ppt which is created
29
 * by the default constructor of <code>SlideShow</code>
30
 *
31
 * @author Yegor Kozlov
32
 */
33
public class TestTxMasterStyleAtom extends TestCase {
34
    protected SlideShow _ppt;
35
36
    public void setUp() throws Exception{
37
        _ppt = new SlideShow();
38
39
    }
40
41
    public void testDefaultStyles()  {
42
        TxMasterStyleAtom[] txmaster = getMasterStyles();
43
        for (int i = 0; i < txmaster.length; i++) {
44
            int txtype = txmaster[i].getTextType();
45
            switch (txtype){
46
                case TextHeaderAtom.TITLE_TYPE:
47
                    checkTitleType(txmaster[i]);
48
                    break;
49
                case TextHeaderAtom.BODY_TYPE:
50
                    checkBodyType(txmaster[i]);
51
                    break;
52
                case TextHeaderAtom.NOTES_TYPE:
53
                    checkNotesType(txmaster[i]);
54
                    break;
55
                case TextHeaderAtom.OTHER_TYPE:
56
                    checkOtherType(txmaster[i]);
57
                    break;
58
                case TextHeaderAtom.CENTRE_BODY_TYPE:
59
                    break;
60
                case TextHeaderAtom.CENTER_TITLE_TYPE:
61
                    break;
62
                case TextHeaderAtom.HALF_BODY_TYPE:
63
                    break;
64
                case TextHeaderAtom.QUARTER_BODY_TYPE:
65
                    break;
66
                default:
67
                    fail("Unknown text type: " + txtype);
68
            }
69
70
        }
71
    }
72
73
74
75
    /**
76
     * Test styles for type=TextHeaderAtom.TITLE_TYPE
77
     */
78
    private void checkTitleType(TxMasterStyleAtom txmaster){
79
        TextPropCollection props;
80
        TextProp prop;
81
82
        //paragraph styles
83
        props = txmaster.getParagraphStyles()[0];
84
85
        prop = props.findByName("alignment");
86
        assertEquals(1, prop.getValue()); //title has center alignment
87
88
        //character styles
89
        props = txmaster.getCharacterStyles()[0];
90
91
        prop = props.findByName("font.color");
92
        assertEquals(0x3000000, prop.getValue());
93
94
        prop = props.findByName("font.index");
95
        assertEquals(0, prop.getValue());
96
97
        prop = props.findByName("font.size");
98
        assertEquals(49, prop.getValue());
99
100
    }
101
102
    /**
103
     * Test styles for type=TextHeaderAtom.BODY_TYPE
104
     */
105
    private void checkBodyType(TxMasterStyleAtom txmaster){
106
        TextPropCollection props;
107
        TextProp prop;
108
109
        TextPropCollection[] prstyles = txmaster.getParagraphStyles();
110
        TextPropCollection[] chstyles = txmaster.getCharacterStyles();
111
        assertEquals("TxMasterStyleAtom for TextHeaderAtom.BODY_TYPE " +
112
                "must contain styles for 5 indentation levels", 5, prstyles.length);
113
        assertEquals("TxMasterStyleAtom for TextHeaderAtom.BODY_TYPE " +
114
                "must contain styles for 5 indentation levels", 5, chstyles.length);
115
116
        //paragraph styles
117
        props = prstyles[0];
118
119
        prop = props.findByName("alignment");
120
        assertEquals(0, prop.getValue());
121
122
123
        for (int i = 0; i < prstyles.length; i++) {
124
            assertNotNull("text.offset is null for indentation level " + i, prstyles[i].findByName("text.offset"));
125
            assertNotNull("bullet.offset is null for indentation level " + i, prstyles[i].findByName("bullet.offset"));
126
        }
127
128
        //character styles
129
        props = chstyles[0];
130
131
        prop = props.findByName("font.color");
132
        assertEquals(0x1000000, prop.getValue());
133
134
        prop = props.findByName("font.index");
135
        assertEquals(0, prop.getValue());
136
137
        prop = props.findByName("font.size");
138
        assertEquals(36, prop.getValue());
139
    }
140
141
    /**
142
     * Test styles for type=TextHeaderAtom.OTHER_TYPE
143
     */
144
    private void checkOtherType(TxMasterStyleAtom txmaster){
145
        TextPropCollection props;
146
        TextProp prop;
147
148
        //paragraph styles
149
        props = txmaster.getParagraphStyles()[0];
150
151
        prop = props.findByName("alignment");
152
        assertEquals(0, prop.getValue());
153
154
        //character styles
155
        props = txmaster.getCharacterStyles()[0];
156
157
        prop = props.findByName("font.color");
158
        assertEquals(0x1000000, prop.getValue());
159
160
        prop = props.findByName("font.index");
161
        assertEquals(0, prop.getValue());
162
163
        prop = props.findByName("font.size");
164
        assertEquals(24, prop.getValue());
165
    }
166
167
    /**
168
     * Test styles for type=TextHeaderAtom.NOTES_TYPE
169
     */
170
    private void checkNotesType(TxMasterStyleAtom txmaster){
171
        TextPropCollection props;
172
        TextProp prop;
173
174
        //paragraph styles
175
        props = txmaster.getParagraphStyles()[0];
176
177
        prop = props.findByName("alignment");
178
        assertEquals(0, prop.getValue()); //title has center alignment
179
180
        //character styles
181
        props = txmaster.getCharacterStyles()[0];
182
183
        prop = props.findByName("font.color");
184
        assertEquals(0x1000000, prop.getValue());
185
186
        prop = props.findByName("font.index");
187
        assertEquals(0, prop.getValue());
188
189
        prop = props.findByName("font.size");
190
        assertEquals(12, prop.getValue());
191
192
    }
193
194
    /**
195
     * Collect all TxMasterStyleAtom records contained in the supplied slide show.
196
     * There must be a TxMasterStyleAtom per each type of text defined in TextHeaderAtom
197
     */
198
    protected TxMasterStyleAtom[] getMasterStyles(){
199
        ArrayList lst = new ArrayList();
200
201
        Record[] core = _ppt.getMostRecentCoreRecords();
202
        for (int i = 0; i < core.length; i++) {
203
            if(core[i].getRecordType() == RecordTypes.MainMaster.typeID){
204
                Record[] rec = core[i].getChildRecords();
205
                int cnt = 0;
206
                for (int j = 0; j < rec.length; j++) {
207
                    if (rec[j] instanceof TxMasterStyleAtom) {
208
                        lst.add(rec[j]);
209
                        cnt++;
210
                    }
211
                }
212
                assertEquals("MainMaster must contain 7 TxMasterStyleAtoms ", 7, cnt);
213
            } else if(core[i].getRecordType() == RecordTypes.Document.typeID){
214
                TxMasterStyleAtom txstyle = null;
215
                Document doc = (Document)core[i];
216
                Record[] rec = doc.getEnvironment().getChildRecords();
217
                for (int j = 0; j < rec.length; j++) {
218
                    if (rec[j] instanceof TxMasterStyleAtom) {
219
                        if (txstyle != null)  fail("Document.Environment must contain 1 TxMasterStyleAtom");
220
                        txstyle = (TxMasterStyleAtom)rec[j];
221
                    }
222
                }
223
                assertNotNull("TxMasterStyleAtom not found in Document.Environment", txstyle);
224
225
                assertEquals("Document.Environment must contain TxMasterStyleAtom  with type=TextHeaderAtom.OTHER_TYPE",
226
                        TextHeaderAtom.OTHER_TYPE, txstyle.getTextType());
227
                lst.add(txstyle);
228
            }
229
        }
230
231
        return (TxMasterStyleAtom[])lst.toArray(new TxMasterStyleAtom[lst.size()]);
232
    }
233
}

Return to bug 40057