PAPFormattedDiskPagepublic class PAPFormattedDiskPage extends FormattedDiskPage Represents a PAP FKP. The style properties for paragraph and character runs
are stored in fkps. There are PAP fkps for paragraph properties and CHP fkps
for character run properties. The first part of the fkp for both CHP and PAP
fkps consists of an array of 4 byte int offsets in the main stream for that
Paragraph's or Character run's text. The ending offset is the next
value in the array. For example, if an fkp has X number of Paragraph's
stored in it then there are (x + 1) 4 byte ints in the beginning array. The
number X is determined by the last byte in a 512 byte fkp.
CHP and PAP fkps also store the compressed styles(grpprl) that correspond to
the offsets on the front of the fkp. The offset of the grpprls is determined
differently for CHP fkps and PAP fkps. |
Fields Summary |
---|
private static final int | BX_SIZE | private static final int | FC_SIZE | private ArrayList | _papxList | private ArrayList | _overFlow | private byte[] | _dataStream |
Constructors Summary |
---|
public PAPFormattedDiskPage(byte[] dataStream)
_dataStream = dataStream;
| public PAPFormattedDiskPage(byte[] documentStream, byte[] dataStream, int offset, int fcMin)Creates a PAPFormattedDiskPage from a 512 byte array
super(documentStream, offset);
for (int x = 0; x < _crun; x++)
{
_papxList.add(new PAPX(getStart(x) - fcMin, getEnd(x) - fcMin, getGrpprl(x), getParagraphHeight(x), dataStream));
}
_fkp = null;
_dataStream = dataStream;
|
Methods Summary |
---|
public void | fill(java.util.List filler)Fills the queue for writing.
_papxList.addAll(filler);
| protected byte[] | getGrpprl(int index)Gets the papx for the paragraph at index in this fkp.
int papxOffset = 2 * LittleEndian.getUnsignedByte(_fkp, _offset + (((_crun + 1) * FC_SIZE) + (index * BX_SIZE)));
int size = 2 * LittleEndian.getUnsignedByte(_fkp, _offset + papxOffset);
if(size == 0)
{
size = 2 * LittleEndian.getUnsignedByte(_fkp, _offset + ++papxOffset);
}
else
{
size--;
}
byte[] papx = new byte[size];
System.arraycopy(_fkp, _offset + ++papxOffset, papx, 0, size);
return papx;
| java.util.ArrayList | getOverflow()Used when writing out a Word docunment. This method is part of a sequence
that is necessary because there is no easy and efficient way to
determine the number PAPX's that will fit into one FKP. THe sequence is
as follows:
fill()
toByteArray()
getOverflow()
return _overFlow;
| public org.apache.poi.hwpf.model.PAPX | getPAPX(int index)Gets the PAPX at index.
return (PAPX)_papxList.get(index);
| private org.apache.poi.hwpf.model.ParagraphHeight | getParagraphHeight(int index)Used to get the ParagraphHeight of a PAPX at a particular index.
int pheOffset = _offset + 1 + (((_crun + 1) * 4) + (index * 13));
ParagraphHeight phe = new ParagraphHeight(_fkp, pheOffset);
return phe;
| protected byte[] | toByteArray(int fcMin)Creates a byte array representation of this data structure. Suitable for
writing to a Word document.
byte[] buf = new byte[512];
int size = _papxList.size();
int grpprlOffset = 0;
int bxOffset = 0;
int fcOffset = 0;
byte[] lastGrpprl = new byte[0];
// total size is currently the size of one FC
int totalSize = FC_SIZE;
int index = 0;
for (; index < size; index++)
{
byte[] grpprl = ((PAPX)_papxList.get(index)).getGrpprl();
int grpprlLength = grpprl.length;
// is grpprl huge?
if(grpprlLength > 488)
{
grpprlLength = 8; // set equal to size of sprmPHugePapx grpprl
}
// check to see if we have enough room for an FC, a BX, and the grpprl
// and the 1 byte size of the grpprl.
int addition = 0;
if (!Arrays.equals(grpprl, lastGrpprl))
{
addition = (FC_SIZE + BX_SIZE + grpprlLength + 1);
}
else
{
addition = (FC_SIZE + BX_SIZE);
}
totalSize += addition;
// if size is uneven we will have to add one so the first grpprl falls
// on a word boundary
if (totalSize > 511 + (index % 2))
{
totalSize -= addition;
break;
}
// grpprls must fall on word boundaries
if (grpprlLength % 2 > 0)
{
totalSize += 1;
}
else
{
totalSize += 2;
}
lastGrpprl = grpprl;
}
// see if we couldn't fit some
if (index != size)
{
_overFlow = new ArrayList();
_overFlow.addAll(_papxList.subList(index, size));
}
// index should equal number of papxs that will be in this fkp now.
buf[511] = (byte)index;
bxOffset = (FC_SIZE * index) + FC_SIZE;
grpprlOffset = 511;
PAPX papx = null;
lastGrpprl = new byte[0];
for (int x = 0; x < index; x++)
{
papx = (PAPX)_papxList.get(x);
byte[] phe = papx.getParagraphHeight().toByteArray();
byte[] grpprl = papx.getGrpprl();
// is grpprl huge?
if(grpprl.length > 488)
{
// if so do we have storage at getHugeGrpprlOffset()
int hugeGrpprlOffset = papx.getHugeGrpprlOffset();
if(hugeGrpprlOffset == -1) // then we have no storage...
{
throw new UnsupportedOperationException(
"This Paragraph has no dataStream storage.");
}
else // we have some storage...
{
// get the size of the existing storage
int maxHugeGrpprlSize = LittleEndian.getUShort(_dataStream,
hugeGrpprlOffset);
if (maxHugeGrpprlSize < grpprl.length-2) // grpprl.length-2 because we don't store the istd
throw new UnsupportedOperationException(
"This Paragraph's dataStream storage is too small.");
}
// store grpprl at hugeGrpprlOffset
System.arraycopy(grpprl, 2, _dataStream, hugeGrpprlOffset + 2,
grpprl.length - 2); // grpprl.length-2 because we don't store the istd
LittleEndian.putUShort(_dataStream, hugeGrpprlOffset, grpprl.length - 2);
// grpprl = grpprl containing only a sprmPHugePapx2
int istd = LittleEndian.getUShort(grpprl, 0);
grpprl = new byte[8];
LittleEndian.putUShort(grpprl, 0, istd);
LittleEndian.putUShort(grpprl, 2, 0x6646); // sprmPHugePapx2
LittleEndian.putInt(grpprl, 4, hugeGrpprlOffset);
}
boolean same = Arrays.equals(lastGrpprl, grpprl);
if (!same)
{
grpprlOffset -= (grpprl.length + (2 - grpprl.length % 2));
grpprlOffset -= (grpprlOffset % 2);
}
LittleEndian.putInt(buf, fcOffset, papx.getStart() + fcMin);
buf[bxOffset] = (byte)(grpprlOffset/2);
System.arraycopy(phe, 0, buf, bxOffset + 1, phe.length);
// refer to the section on PAPX in the spec. Places a size on the front
// of the PAPX. Has to do with how the grpprl stays on word
// boundaries.
if (!same)
{
int copyOffset = grpprlOffset;
if ( (grpprl.length % 2) > 0)
{
buf[copyOffset++] = (byte) ( (grpprl.length + 1) / 2);
}
else
{
buf[++copyOffset] = (byte) ( (grpprl.length) / 2);
copyOffset++;
}
System.arraycopy(grpprl, 0, buf, copyOffset, grpprl.length);
lastGrpprl = grpprl;
}
bxOffset += BX_SIZE;
fcOffset += FC_SIZE;
}
LittleEndian.putInt(buf, fcOffset, papx.getEnd() + fcMin);
return buf;
|
|