ASF Bugzilla – Attachment 29460 Details for
Bug 53979
Patch to fetch Numbered List info from PPT files
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Code, JUnit tests and test data file with two slides to read numbered list info from ppt files.
extractingNumberedListInfoFromPpt.patch.txt (text/plain), 34.06 KB, created by
Alex Nikiforov
on 2012-10-08 14:33:55 UTC
(
hide
)
Description:
Code, JUnit tests and test data file with two slides to read numbered list info from ppt files.
Filename:
MIME Type:
Creator:
Alex Nikiforov
Created:
2012-10-08 14:33:55 UTC
Size:
34.06 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P trunk >Index: src/scratchpad/src/org/apache/poi/hslf/record/TextAutoNumberSchemeEnum.java >=================================================================== >--- src/scratchpad/src/org/apache/poi/hslf/record/TextAutoNumberSchemeEnum.java (revision 0) >+++ src/scratchpad/src/org/apache/poi/hslf/record/TextAutoNumberSchemeEnum.java (working copy) >@@ -0,0 +1,109 @@ >+package org.apache.poi.hslf.record; >+ >+public enum TextAutoNumberSchemeEnum { >+ //Name Value Meaning >+ ANM_AlphaLcPeriod ((short) 0x0000), // "Lowercase Latin character followed by a period. Example: a., b., c., ..."), >+ ANM_AlphaUcPeriod ((short) 0x0001), // "Uppercase Latin character followed by a period. Example: A., B., C., ..."), >+ ANM_ArabicParenRight ((short) 0x0002), // "Arabic numeral followed by a closing parenthesis. Example: 1), 2), 3), ..."), >+ ANM_ArabicPeriod ((short) 0x0003), // "Arabic numeral followed by a period. Example: 1., 2., 3., ..."), >+ ANM_RomanLcParenBoth ((short) 0x0004), // "Lowercase Roman numeral enclosed in parentheses. Example: (i), (ii), (iii), ..."), >+ ANM_RomanLcParenRight ((short) 0x0005), // "Lowercase Roman numeral followed by a closing parenthesis. Example: i), ii), iii), ..."), >+ ANM_RomanLcPeriod ((short) 0x0006), // "Lowercase Roman numeral followed by a period. Example: i., ii., iii., ..."), >+ ANM_RomanUcPeriod ((short) 0x0007), // "Uppercase Roman numeral followed by a period. Example: I., II., III., ..."), >+ ANM_AlphaLcParenBoth ((short) 0x0008), // "Lowercase alphabetic character enclosed in parentheses. Example: (a), (b), (c), ..."), >+ ANM_AlphaLcParenRight ((short) 0x0009), // "Lowercase alphabetic character followed by a closing parenthesis. Example: a), b), c), ..."), >+ ANM_AlphaUcParenBoth ((short) 0x000A), // "Uppercase alphabetic character enclosed in parentheses. Example: (A), (B), (C), ..."), >+ ANM_AlphaUcParenRight ((short) 0x000B), // "Uppercase alphabetic character followed by a closing parenthesis. Example: A), B), C), ..."), >+ ANM_ArabicParenBoth ((short) 0x000C), // "Arabic numeral enclosed in parentheses. Example: (1), (2), (3), ..."), >+ ANM_ArabicPlain ((short) 0x000D), // "Arabic numeral. Example: 1, 2, 3, ..."), >+ ANM_RomanUcParenBoth ((short) 0x000E), // "Uppercase Roman numeral enclosed in parentheses. Example: (I), (II), (III), ..."), >+ ANM_RomanUcParenRight ((short) 0x000F), // "Uppercase Roman numeral followed by a closing parenthesis. Example: I), II), III), ..."), >+ ANM_ChsPlain ((short) 0x0010), // "Simplified Chinese."), >+ ANM_ChsPeriod ((short) 0x0011), // "Simplified Chinese with single-byte period."), >+ ANM_CircleNumDBPlain ((short) 0x0012), // "Double byte circle numbers."), >+ ANM_CircleNumWDBWhitePlain ((short) 0x0013), // "Wingdings white circle numbers."), >+ ANM_CircleNumWDBBlackPlain ((short) 0x0014), // "Wingdings black circle numbers."), >+ ANM_ChtPlain ((short) 0x0015), // "Traditional Chinese."), >+ ANM_ChtPeriod ((short) 0x0016), // "Traditional Chinese with single-byte period."), >+ ANM_Arabic1Minus ((short) 0x0017), // "Bidi Arabic 1 (AraAlpha) with ANSI minus symbol."), >+ ANM_Arabic2Minus ((short) 0x0018), // "Bidi Arabic 2 (AraAbjad) with ANSI minus symbol."), >+ ANM_Hebrew2Minus ((short) 0x0019), // "Bidi Hebrew 2 with ANSI minus symbol."), >+ ANM_JpnKorPlain ((short) 0x001A), // "Japanese/Korean."), >+ ANM_JpnKorPeriod ((short) 0x001B), // "Japanese/Korean with single-byte period."), >+ ANM_ArabicDbPlain ((short) 0x001C), // "Double-byte Arabic numbers."), >+ ANM_ArabicDbPeriod ((short) 0x001D), // "Double-byte Arabic numbers with double-byte period."), >+ ANM_ThaiAlphaPeriod ((short) 0x001E), // "Thai alphabetic character followed by a period."), >+ ANM_ThaiAlphaParenRight ((short) 0x001F), // "Thai alphabetic character followed by a closing parenthesis."), >+ ANM_ThaiAlphaParenBoth ((short) 0x0020), // "Thai alphabetic character enclosed by parentheses."), >+ ANM_ThaiNumPeriod ((short) 0x0021), // "Thai numeral followed by a period."), >+ ANM_ThaiNumParenRight ((short) 0x0022), // "Thai numeral followed by a closing parenthesis."), >+ ANM_ThaiNumParenBoth ((short) 0x0023), // "Thai numeral enclosed in parentheses."), >+ ANM_HindiAlphaPeriod ((short) 0x0024), // "Hindi alphabetic character followed by a period."), >+ ANM_HindiNumPeriod ((short) 0x0025), // "Hindi numeric character followed by a period."), >+ ANM_JpnChsDBPeriod ((short) 0x0026), // "Japanese with double-byte period."), >+ ANM_HindiNumParenRight ((short) 0x0027), // "Hindi numeric character followed by a closing parenthesis."), >+ ANM_HindiAlpha1Period ((short) 0x0028); // "Hindi alphabetic character followed by a period."); >+ >+ private final short value; >+ private TextAutoNumberSchemeEnum(final short code) { >+ this.value = code; >+ } >+ private short getValue() { return value; } >+ public String getDescription() { >+ return TextAutoNumberSchemeEnum.getDescription(this); >+ } >+ public static String getDescription(final TextAutoNumberSchemeEnum code) { >+ switch (code) { >+ case ANM_AlphaLcPeriod : return "Lowercase Latin character followed by a period. Example: a., b., c., ..."; >+ case ANM_AlphaUcPeriod : return "Uppercase Latin character followed by a period. Example: A., B., C., ..."; >+ case ANM_ArabicParenRight : return "Arabic numeral followed by a closing parenthesis. Example: 1), 2), 3), ..."; >+ case ANM_ArabicPeriod : return "Arabic numeral followed by a period. Example: 1., 2., 3., ..."; >+ case ANM_RomanLcParenBoth : return "Lowercase Roman numeral enclosed in parentheses. Example: (i), (ii), (iii), ..."; >+ case ANM_RomanLcParenRight : return "Lowercase Roman numeral followed by a closing parenthesis. Example: i), ii), iii), ..."; >+ case ANM_RomanLcPeriod : return "Lowercase Roman numeral followed by a period. Example: i., ii., iii., ..."; >+ case ANM_RomanUcPeriod : return "Uppercase Roman numeral followed by a period. Example: I., II., III., ..."; >+ case ANM_AlphaLcParenBoth : return "Lowercase alphabetic character enclosed in parentheses. Example: (a), (b), (c), ..."; >+ case ANM_AlphaLcParenRight : return "Lowercase alphabetic character followed by a closing parenthesis. Example: a), b), c), ..."; >+ case ANM_AlphaUcParenBoth : return "Uppercase alphabetic character enclosed in parentheses. Example: (A), (B), (C), ..."; >+ case ANM_AlphaUcParenRight : return "Uppercase alphabetic character followed by a closing parenthesis. Example: A), B), C), ..."; >+ case ANM_ArabicParenBoth : return "Arabic numeral enclosed in parentheses. Example: (1), (2), (3), ..."; >+ case ANM_ArabicPlain : return "Arabic numeral. Example: 1, 2, 3, ..."; >+ case ANM_RomanUcParenBoth : return "Uppercase Roman numeral enclosed in parentheses. Example: (I), (II), (III), ..."; >+ case ANM_RomanUcParenRight : return "Uppercase Roman numeral followed by a closing parenthesis. Example: I), II), III), ..."; >+ case ANM_ChsPlain : return "Simplified Chinese."; >+ case ANM_ChsPeriod : return "Simplified Chinese with single-byte period."; >+ case ANM_CircleNumDBPlain : return "Double byte circle numbers."; >+ case ANM_CircleNumWDBWhitePlain : return "Wingdings white circle numbers."; >+ case ANM_CircleNumWDBBlackPlain : return "Wingdings black circle numbers."; >+ case ANM_ChtPlain : return "Traditional Chinese."; >+ case ANM_ChtPeriod : return "Traditional Chinese with single-byte period."; >+ case ANM_Arabic1Minus : return "Bidi Arabic 1 (AraAlpha) with ANSI minus symbol."; >+ case ANM_Arabic2Minus : return "Bidi Arabic 2 (AraAbjad) with ANSI minus symbol."; >+ case ANM_Hebrew2Minus : return "Bidi Hebrew 2 with ANSI minus symbol."; >+ case ANM_JpnKorPlain : return "Japanese/Korean."; >+ case ANM_JpnKorPeriod : return "Japanese/Korean with single-byte period."; >+ case ANM_ArabicDbPlain : return "Double-byte Arabic numbers."; >+ case ANM_ArabicDbPeriod : return "Double-byte Arabic numbers with double-byte period."; >+ case ANM_ThaiAlphaPeriod : return "Thai alphabetic character followed by a period."; >+ case ANM_ThaiAlphaParenRight : return "Thai alphabetic character followed by a closing parenthesis."; >+ case ANM_ThaiAlphaParenBoth : return "Thai alphabetic character enclosed by parentheses."; >+ case ANM_ThaiNumPeriod : return "Thai numeral followed by a period."; >+ case ANM_ThaiNumParenRight : return "Thai numeral followed by a closing parenthesis."; >+ case ANM_ThaiNumParenBoth : return "Thai numeral enclosed in parentheses."; >+ case ANM_HindiAlphaPeriod : return "Hindi alphabetic character followed by a period."; >+ case ANM_HindiNumPeriod : return "Hindi numeric character followed by a period."; >+ case ANM_JpnChsDBPeriod : return "Japanese with double-byte period."; >+ case ANM_HindiNumParenRight : return "Hindi numeric character followed by a closing parenthesis."; >+ case ANM_HindiAlpha1Period : return "Hindi alphabetic character followed by a period."; >+ default : return "Unknown Numbered Scheme"; >+ } >+ } >+ public static TextAutoNumberSchemeEnum valueOf(short autoNumberScheme) { >+ for (TextAutoNumberSchemeEnum item: TextAutoNumberSchemeEnum.values()) { >+ if (autoNumberScheme == item.getValue()) { >+ return item; >+ } >+ } >+ return null; >+ } >+} >Index: src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java >=================================================================== >--- src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java (revision 1393837) >+++ src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java (working copy) >@@ -169,7 +169,7 @@ > TextBytesAtom tba = (TextBytesAtom) records[i + 1]; > trun = new TextRun(tha, tba, stpa); > } else if (records[i + 1].getRecordType() == 4001l) { >- // StyleTextPropAtom - Safe to ignore >+ stpa = (StyleTextPropAtom) records[i + 1]; > } else if (records[i + 1].getRecordType() == 4010l) { > // TextSpecInfoAtom - Safe to ignore > } else { >@@ -177,7 +177,7 @@ > } > > if (trun != null) { >- ArrayList lst = new ArrayList(); >+ List<Record> lst = new ArrayList<Record>(); > for (int j = i; j < records.length; j++) { > if(j > i && records[j] instanceof TextHeaderAtom) break; > lst.add(records[j]); >Index: src/scratchpad/src/org/apache/poi/hslf/record/StyleTextProp9Atom.java >=================================================================== >--- src/scratchpad/src/org/apache/poi/hslf/record/StyleTextProp9Atom.java (revision 0) >+++ src/scratchpad/src/org/apache/poi/hslf/record/StyleTextProp9Atom.java (working copy) >@@ -0,0 +1,146 @@ >+/* ==================================================================== >+ 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.record; >+ >+import java.io.IOException; >+import java.io.OutputStream; >+import java.util.LinkedList; >+import java.util.List; >+ >+import org.apache.poi.util.LittleEndian; >+ >+/** >+ * The atom record that specifies additional text formatting. >+ * >+ * @author Alex Nikiforov [mailto:anikif@gmail.com] >+ */ >+public final class StyleTextProp9Atom extends RecordAtom { >+ private final static byte[] MARKER = {0, 0, (byte)0x80, 3, (byte)255, (byte)255, 1, 0}; >+ private TextAutoNumberSchemeEnum[] autoNumberSchemes; >+ private Short[] startNumbers; >+ /** Record header. */ >+ private byte[] header; >+ /** Record data. */ >+ private byte[] data; >+ private short version; >+ private short recordId; >+ private int length; >+ >+ /** >+ * Constructs the link related atom record from its >+ * source data. >+ * >+ * @param source the source data as a byte array. >+ * @param start the start offset into the byte array. >+ * @param len the length of the slice in the byte array. >+ */ >+ protected StyleTextProp9Atom(byte[] source, int start, int len) { >+ // Get the header. >+ List<Short> startNumberList = new LinkedList<Short>(); >+ List<TextAutoNumberSchemeEnum> schemes = new LinkedList<TextAutoNumberSchemeEnum>(); >+ header = new byte[8]; >+ System.arraycopy(source,start, header,0,8); >+ this.version = LittleEndian.getShort(header, 0); >+ this.recordId = LittleEndian.getShort(header, 2); >+ this.length = LittleEndian.getInt(header, 4); >+ >+ // Get the record data. >+ data = new byte[len-8]; >+ System.arraycopy(source, start+8, data, 0, len-8); >+ boolean markerFound = false; >+ for (int i = 0; i < data.length; i++) { >+ markerFound = true; >+ for (int j = 0; j < MARKER.length; j++) { >+ if (i + j >= data.length || MARKER[j] != data[i + j]) { >+ markerFound = false; >+ break; >+ } >+ } >+ if (markerFound) { >+ i += MARKER.length; >+ schemes.add(TextAutoNumberSchemeEnum.valueOf(LittleEndian.getShort(data, i ))); >+ i += 2; >+ startNumberList.add(LittleEndian.getShort(data, i )); >+ i += 2; >+ } >+ if (i >= data.length) { >+ break; >+ } >+ } >+ this.autoNumberSchemes = (TextAutoNumberSchemeEnum[]) schemes.toArray(new TextAutoNumberSchemeEnum[schemes.size()]); >+ this.startNumbers = (Short[]) startNumberList.toArray(new Short[startNumberList.size()]); >+ } >+ >+ /** >+ * Gets the record type. >+ * @return the record type. >+ */ >+ public long getRecordType() { return this.recordId; } >+ >+ public short getVersion() { >+ return version; >+ } >+ >+ public int getLength() { >+ return length; >+ } >+ public TextAutoNumberSchemeEnum[] getAutoNumberTypes() { >+ return this.autoNumberSchemes; >+ } >+ public Short[] getStartNumbers() { >+ return this.startNumbers; >+ } >+ >+ /** >+ * Write the contents of the record back, so it can be written >+ * to disk >+ * >+ * @param out the output stream to write to. >+ * @throws java.io.IOException if an error occurs. >+ */ >+ public void writeOut(OutputStream out) throws IOException { >+ out.write(header); >+ out.write(data); >+ } >+ >+ /** >+ * Update the text length >+ * >+ * @param size the text length >+ */ >+ public void setTextSize(int size){ >+ LittleEndian.putInt(data, 0, size); >+ } >+ >+ /** >+ * Reset the content to one info run with the default values >+ * @param size the site of parent text >+ */ >+ public void reset(int size){ >+ data = new byte[10]; >+ // 01 00 00 00 >+ LittleEndian.putInt(data, 0, size); >+ // 01 00 00 00 >+ LittleEndian.putInt(data, 4, 1); //mask >+ // 00 00 >+ LittleEndian.putShort(data, 8, (short)0); //langId >+ >+ // Update the size (header bytes 5-8) >+ LittleEndian.putInt(header, 4, data.length); >+ } >+} >\ No newline at end of file >Index: src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java >=================================================================== >--- src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java (revision 1393837) >+++ src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java (working copy) >@@ -84,7 +84,7 @@ > public static final Type OutlineTextRefAtom = new Type(3998,OutlineTextRefAtom.class); > public static final Type TextHeaderAtom = new Type(3999,TextHeaderAtom.class); > public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class); >- public static final Type StyleTextPropAtom = new Type(4001,StyleTextPropAtom.class); >+ public static final Type StyleTextPropAtom = new Type(4001, StyleTextPropAtom.class);//0x0fa1 RT_StyleTextPropAtom > public static final Type BaseTextPropAtom = new Type(4002,null); > public static final Type TxMasterStyleAtom = new Type(4003,TxMasterStyleAtom.class); > public static final Type TxCFStyleAtom = new Type(4004,null); >@@ -95,6 +95,7 @@ > public static final Type TxSIStyleAtom = new Type(4009,null); > public static final Type TextSpecInfoAtom = new Type(4010, TextSpecInfoAtom.class); > public static final Type DefaultRulerAtom = new Type(4011,null); >+ public static final Type StyleTextProp9Atom = new Type(4012, StyleTextProp9Atom.class); //0x0FAC RT_StyleTextProp9Atom > public static final Type FontEntityAtom = new Type(4023,FontEntityAtom.class); > public static final Type FontEmbeddedData = new Type(4024,null); > public static final Type CString = new Type(4026,CString.class); >@@ -146,7 +147,7 @@ > public static final Type ProgTags = new Type(5000,DummyPositionSensitiveRecordWithChildren.class); > public static final Type ProgStringTag = new Type(5001,null); > public static final Type ProgBinaryTag = new Type(5002,DummyPositionSensitiveRecordWithChildren.class); >- public static final Type BinaryTagData = new Type(5003,DummyPositionSensitiveRecordWithChildren.class); >+ public static final Type BinaryTagData = new Type(5003, BinaryTagDataBlob.class);//0x138b RT_BinaryTagDataBlob > public static final Type PrpublicintOptions = new Type(6000,null); > public static final Type PersistPtrFullBlock = new Type(6001,PersistPtrHolder.class); > public static final Type PersistPtrIncrementalBlock = new Type(6002,PersistPtrHolder.class); >Index: src/scratchpad/src/org/apache/poi/hslf/model/Slide.java >=================================================================== >--- src/scratchpad/src/org/apache/poi/hslf/model/Slide.java (revision 1393837) >+++ src/scratchpad/src/org/apache/poi/hslf/model/Slide.java (working copy) >@@ -18,21 +18,30 @@ > package org.apache.poi.hslf.model; > > import java.awt.Graphics2D; >-import java.util.Vector; >+import java.util.LinkedList; >+import java.util.List; > > import org.apache.poi.ddf.EscherContainerRecord; > import org.apache.poi.ddf.EscherDgRecord; > import org.apache.poi.ddf.EscherDggRecord; >+import org.apache.poi.ddf.EscherRecord; > import org.apache.poi.ddf.EscherSpRecord; >+import org.apache.poi.ddf.UnknownEscherRecord; >+import org.apache.poi.hslf.record.BinaryTagDataBlob; >+import org.apache.poi.hslf.record.CString; > import org.apache.poi.hslf.record.ColorSchemeAtom; > import org.apache.poi.hslf.record.Comment2000; >+import org.apache.poi.hslf.record.EscherTextboxWrapper; > import org.apache.poi.hslf.record.HeadersFootersContainer; >+import org.apache.poi.hslf.record.PPDrawing; > import org.apache.poi.hslf.record.Record; > import org.apache.poi.hslf.record.RecordContainer; > import org.apache.poi.hslf.record.RecordTypes; > import org.apache.poi.hslf.record.SlideAtom; >+import org.apache.poi.hslf.record.StyleTextProp9Atom; > import org.apache.poi.hslf.record.TextHeaderAtom; > import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet; >+import org.apache.poi.util.LittleEndian; > > /** > * This class represents a slide in a PowerPoint Document. It allows >@@ -53,7 +62,7 @@ > /** > * Constructs a Slide from the Slide record, and the SlideAtomsSet > * containing the text. >- * Initialises TextRuns, to provide easier access to the text >+ * Initializes TextRuns, to provide easier access to the text > * > * @param slide the Slide record we're based on > * @param notes the Notes sheet attached to us >@@ -72,7 +81,7 @@ > // For the text coming in from the SlideAtomsSet: > // Build up TextRuns from pairs of TextHeaderAtom and > // one of TextBytesAtom or TextCharsAtom >- Vector textRuns = new Vector(); >+ final List<TextRun> textRuns = new LinkedList<TextRun>(); > if(_atomSet != null) { > findTextRuns(_atomSet.getSlideRecords(),textRuns); > } else { >@@ -476,4 +485,72 @@ > _runs = tmp; > } > } >+ protected EscherContainerRecord findFirstEscherContainerRecordOfType(short type, EscherContainerRecord parent) { >+ if (null == parent) { return null; } >+ final List<EscherContainerRecord> children = parent.getChildContainers(); >+ for (EscherContainerRecord child : children) { >+ if (type == child.getRecordId()) { >+ return child; >+ } >+ } >+ return null; >+ } >+ protected EscherContainerRecord[] findAllEscherContainerRecordOfType(short type, EscherContainerRecord parent) { >+ if (null == parent) { return new EscherContainerRecord[0]; } >+ final List<EscherContainerRecord> children = parent.getChildContainers(); >+ final List<EscherContainerRecord> result = new LinkedList<EscherContainerRecord>(); >+ for (EscherContainerRecord child : children) { >+ if (type == child.getRecordId()) { >+ result.add(child); >+ } >+ } >+ return (EscherContainerRecord[]) result.toArray(new EscherContainerRecord[result.size()]); >+ } >+ >+ protected Record buildFromUnknownEscherRecord(UnknownEscherRecord unknown) { >+ byte[] bingo = unknown.getData(); >+ byte[] restoredRecord = new byte[8 + bingo.length]; >+ System.arraycopy(bingo, 0, restoredRecord, 8, bingo.length); >+ short recordVersion = unknown.getVersion(); >+ short recordId = unknown.getRecordId(); >+ int recordLength = unknown.getRecordSize(); >+ LittleEndian.putShort(restoredRecord, 0, recordVersion); >+ LittleEndian.putShort(restoredRecord, 2, recordId); >+ LittleEndian.putInt(restoredRecord, 4, recordLength); >+ return Record.createRecordForType(recordId, restoredRecord, 0, restoredRecord.length); >+ } >+ public StyleTextProp9Atom getNumberedListInfo() { >+ PPDrawing drawing = this.getPPDrawing(); >+ EscherRecord[] escherRecords = drawing.getEscherRecords(); >+ for (EscherRecord escherRecord : escherRecords) { >+ if (escherRecord instanceof EscherContainerRecord && (short)0xf002 == escherRecord.getRecordId()) { >+ EscherContainerRecord escherContainerF002 = (EscherContainerRecord) escherRecord; >+ final EscherContainerRecord escherContainerF003 = findFirstEscherContainerRecordOfType((short)0xf003, escherContainerF002); >+ final EscherContainerRecord[] escherContainersF004 = findAllEscherContainerRecordOfType((short)0xf004, escherContainerF003); >+ for (EscherContainerRecord containerF004 : escherContainersF004) { >+ final EscherContainerRecord escherContainerF011 = findFirstEscherContainerRecordOfType((short)0xf011, containerF004); >+ if (null == escherContainerF011) { continue; } >+ final EscherContainerRecord escherContainer1388 = findFirstEscherContainerRecordOfType((short)0x1388, escherContainerF011); >+ if (null == escherContainer1388) { continue; } >+ final EscherContainerRecord escherContainer138A = findFirstEscherContainerRecordOfType((short)0x138A, escherContainer1388); >+ if (null == escherContainer138A) { continue; } >+ int size = escherContainer138A.getChildRecords().size(); >+ if (2 != size) { continue; } >+ final Record r0 = buildFromUnknownEscherRecord((UnknownEscherRecord) escherContainer138A.getChild(0)); >+ final Record r1 = buildFromUnknownEscherRecord((UnknownEscherRecord) escherContainer138A.getChild(1)); >+ if (!(r0 instanceof CString)) { continue; } >+ if (!("___PPT9".equals(((CString) r0).getText()))) { continue; }; >+ if (!(r1 instanceof BinaryTagDataBlob )) { continue; } >+ final BinaryTagDataBlob blob = (BinaryTagDataBlob) r1; >+ if (1 != blob.getChildRecords().length) { continue; } >+ return (StyleTextProp9Atom)blob.findFirstOfType(0x0FACL); >+ } >+ } >+ } >+ return null; >+ } >+ >+ public EscherTextboxWrapper[] getTextboxWrappers() { >+ return this.getPPDrawing().getTextboxWrappers(); >+ } > } >Index: src/scratchpad/src/org/apache/poi/hslf/record/EscherTextboxWrapper.java >=================================================================== >--- src/scratchpad/src/org/apache/poi/hslf/record/EscherTextboxWrapper.java (revision 1393837) >+++ src/scratchpad/src/org/apache/poi/hslf/record/EscherTextboxWrapper.java (working copy) >@@ -36,6 +36,7 @@ > private EscherTextboxRecord _escherRecord; > private long _type; > private int shapeId; >+ private StyleTextPropAtom styleTextPropAtom; > > /** > * Returns the underlying DDF Escher Record >@@ -52,6 +53,9 @@ > // Find the child records in the escher data > byte[] data = _escherRecord.getData(); > _children = Record.findChildRecords(data,0,data.length); >+ for (Record r : this._children) { >+ if (r instanceof StyleTextPropAtom) { this.styleTextPropAtom = (StyleTextPropAtom) r; } >+ } > } > > /** >@@ -104,4 +108,8 @@ > public void setShapeId(int id){ > shapeId = id; > } >+ >+ public StyleTextPropAtom getStyleTextPropAtom() { >+ return styleTextPropAtom; >+ } > } >Index: test-data/slideshow/numbers.ppt >=================================================================== >Cannot display: file marked as a binary type. >svn:mime-type = application/octet-stream >Index: test-data/slideshow/numbers.ppt >=================================================================== >--- test-data/slideshow/numbers.ppt (revision 0) >+++ test-data/slideshow/numbers.ppt (working copy) > >Property changes on: test-data/slideshow/numbers.ppt >___________________________________________________________________ >Added: svn:mime-type >## -0,0 +1 ## >+application/octet-stream >Index: src/scratchpad/src/org/apache/poi/hslf/record/BinaryTagDataBlob.java >=================================================================== >--- src/scratchpad/src/org/apache/poi/hslf/record/BinaryTagDataBlob.java (revision 0) >+++ src/scratchpad/src/org/apache/poi/hslf/record/BinaryTagDataBlob.java (working copy) >@@ -0,0 +1,67 @@ >+/* ==================================================================== >+ 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.record; >+ >+import org.apache.poi.util.LittleEndian; >+import java.io.IOException; >+import java.io.OutputStream; >+ >+/** >+ * If we come across a record we know has children of (potential) >+ * interest, but where the record itself is boring, but where other >+ * records may care about where this one lives, we create one >+ * of these. It allows us to get at the children, and track where on >+ * disk this is, but not much else. >+ * Anything done using this should quite quickly be transitioned to its >+ * own proper record class! >+ * >+ * @author Nick Burch >+ */ >+ >+public final class BinaryTagDataBlob extends PositionDependentRecordContainer >+{ >+ private byte[] _header; >+ private long _type; >+ >+ /** >+ * Create a new holder for a boring record with children, but with >+ * position dependent characteristics >+ */ >+ protected BinaryTagDataBlob(byte[] source, int start, int len) { >+ // Just grab the header, not the whole contents >+ _header = new byte[8]; >+ System.arraycopy(source,start,_header,0,8); >+ _type = LittleEndian.getUShort(_header,2); >+ >+ // Find our children >+ _children = Record.findChildRecords(source,start+8,len-8); >+ } >+ >+ /** >+ * Return the value we were given at creation >+ */ >+ 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 { >+ writeOut(_header[0],_header[1],_type,_children,out); >+ } >+} >Index: src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNumberedList.java >=================================================================== >--- src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNumberedList.java (revision 0) >+++ src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNumberedList.java (working copy) >@@ -0,0 +1,131 @@ >+/* ==================================================================== >+ 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.usermodel; >+ >+import java.util.List; >+ >+import junit.framework.TestCase; >+ >+import org.apache.poi.hslf.model.Slide; >+import org.apache.poi.hslf.model.TextRun; >+import org.apache.poi.hslf.model.textproperties.TextPropCollection; >+import org.apache.poi.hslf.record.EscherTextboxWrapper; >+import org.apache.poi.hslf.record.StyleTextProp9Atom; >+import org.apache.poi.hslf.record.StyleTextPropAtom; >+import org.apache.poi.hslf.record.TextAutoNumberSchemeEnum; >+import org.apache.poi.POIDataSamples; >+ >+ >+/** >+ * Test that checks numbered list functionality. >+ * >+ * @author Alex Nikiforov [mailto:anikif@gmail.com] >+ */ >+public final class TestNumberedList extends TestCase { >+ private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); >+ >+ protected void setUp() throws Exception { >+ } >+ >+ public void testNumberedList() throws Exception { >+ SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("numbers.ppt")); >+ assertTrue("No Exceptions while reading file", true); >+ >+ final Slide[] slides = ppt.getSlides(); >+ assertEquals(2, slides.length); >+ checkSlide0(slides[0]); >+ checkSlide1(slides[1]); >+ } >+ private void checkSlide0(final Slide s) { >+ final StyleTextProp9Atom numberedListInfo = s.getNumberedListInfo(); >+ assertNotNull(numberedListInfo); >+ { >+ final Short[] startNumbers = numberedListInfo.getStartNumbers(); >+ assertNotNull(startNumbers); >+ assertEquals(2, startNumbers.length); >+ assertTrue(4 == startNumbers[0]); >+ assertTrue(3 == startNumbers[1]); >+ } >+ { >+ final TextAutoNumberSchemeEnum[] enums = numberedListInfo.getAutoNumberTypes(); >+ assertNotNull(enums); >+ assertEquals(2, enums.length); >+ assertTrue(TextAutoNumberSchemeEnum.ANM_ArabicPeriod == enums[0]); >+ assertTrue(TextAutoNumberSchemeEnum.ANM_AlphaLcParenRight == enums[1]); >+ } >+ >+ TextRun[] textRuns = s.getTextRuns(); >+ assertEquals(2, textRuns.length); >+ >+ RichTextRun textRun = textRuns[0].getRichTextRuns()[0]; >+ assertEquals("titTe", textRun.getRawText()); >+ assertEquals(1, textRuns[0].getRichTextRuns().length); >+ assertFalse(textRun.isBullet()); >+ >+ assertEquals("This is a text placeholder that \rfollows the design pattern\rJust a test\rWithout any paragraph\rSecond paragraph first line c) ;\rSecond paragraph second line d) . \r", textRuns[1].getRawText()); >+ >+ final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers(); >+ assertEquals(textRuns.length, styleAtoms.length); >+ final EscherTextboxWrapper wrapper = styleAtoms[1]; >+ final StyleTextPropAtom styleTextPropAtom = wrapper.getStyleTextPropAtom(); >+ final List<TextPropCollection> textProps = styleTextPropAtom.getCharacterStyles(); >+ final TextPropCollection[] props = (TextPropCollection[]) textProps.toArray(new TextPropCollection[textProps.size()]); >+ assertEquals(60, props[0].getCharactersCovered()); >+ assertEquals(34, props[1].getCharactersCovered()); >+ assertEquals(68, props[2].getCharactersCovered()); >+ } >+ private void checkSlide1(final Slide s) { >+ final StyleTextProp9Atom numberedListInfo = s.getNumberedListInfo(); >+ assertNotNull(numberedListInfo); >+ { >+ final Short[] startNumbers = numberedListInfo.getStartNumbers(); >+ assertNotNull(startNumbers); >+ assertEquals(2, startNumbers.length); >+ assertTrue(9 == startNumbers[0]); >+ assertTrue(3 == startNumbers[1]); >+ } >+ { >+ final TextAutoNumberSchemeEnum[] enums = numberedListInfo.getAutoNumberTypes(); >+ assertNotNull(enums); >+ assertEquals(2, enums.length); >+ assertTrue(TextAutoNumberSchemeEnum.ANM_ArabicParenRight == enums[0]); >+ assertTrue(TextAutoNumberSchemeEnum.ANM_AlphaUcPeriod == enums[1]); >+ } >+ >+ TextRun[] textRuns = s.getTextRuns(); >+ assertEquals(2, textRuns.length); >+ >+ RichTextRun textRun = textRuns[0].getRichTextRuns()[0]; >+ assertEquals("Second Slide Title", textRun.getRawText()); >+ assertEquals(1, textRuns[0].getRichTextRuns().length); >+ assertFalse(textRun.isBullet()); >+ >+ assertEquals("This is a text placeholder that \rfollows the design pattern\rJust a test\rWithout any paragraph\rSecond paragraph first line c) ;\rSecond paragraph second line d) . \r", textRuns[1].getRawText()); >+ >+ final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers(); >+ assertEquals(textRuns.length, styleAtoms.length); >+ final EscherTextboxWrapper wrapper = styleAtoms[1]; >+ final StyleTextPropAtom styleTextPropAtom = wrapper.getStyleTextPropAtom(); >+ final List<TextPropCollection> textProps = styleTextPropAtom.getCharacterStyles(); >+ >+ final TextPropCollection[] props = (TextPropCollection[]) textProps.toArray(new TextPropCollection[textProps.size()]); >+ assertEquals(33, props[0].getCharactersCovered()); >+ assertEquals(61, props[1].getCharactersCovered()); >+ assertEquals(68, props[2].getCharactersCovered()); >+ } >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 53979
:
29460
|
29467
|
29470
|
29471
|
29472
|
29478
|
29479
|
29480
|
29481