| /* ==================================================================== |
| 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.hwpf.sprm; |
| |
| import org.apache.logging.log4j.LogManager; |
| import org.apache.logging.log4j.Logger; |
| import org.apache.poi.hwpf.usermodel.BorderCode; |
| import org.apache.poi.hwpf.usermodel.TableCellDescriptor; |
| import org.apache.poi.hwpf.usermodel.TableProperties; |
| import org.apache.poi.util.Internal; |
| import org.apache.poi.util.LittleEndian; |
| |
| @Internal |
| public final class TableSprmUncompressor extends SprmUncompressor { |
| |
| private static final Logger LOG = LogManager.getLogger(TableSprmUncompressor.class); |
| |
| public TableSprmUncompressor() |
| { |
| } |
| |
| public static TableProperties uncompressTAP( SprmBuffer sprmBuffer ) |
| { |
| TableProperties tableProperties; |
| |
| SprmOperation sprmOperation = sprmBuffer.findSprm( (short) 0xd608 ); |
| if ( sprmOperation != null ) |
| { |
| byte[] grpprl = sprmOperation.getGrpprl(); |
| int offset = sprmOperation.getGrpprlOffset(); |
| short itcMac = grpprl[offset]; |
| tableProperties = new TableProperties( itcMac ); |
| } |
| else |
| { |
| LOG.atWarn().log("Some table rows didn't specify number of columns in SPRMs"); |
| tableProperties = new TableProperties( (short) 1 ); |
| } |
| |
| for ( SprmIterator iterator = sprmBuffer.iterator(); iterator.hasNext(); ) |
| { |
| SprmOperation sprm = iterator.next(); |
| |
| /* |
| * TAPXs are actually PAPXs so we have to make sure we are only |
| * trying to uncompress the right type of sprm. |
| */ |
| if ( sprm.getType() == SprmOperation.TYPE_TAP ) |
| { |
| try |
| { |
| unCompressTAPOperation( tableProperties, sprm ); |
| } |
| catch ( ArrayIndexOutOfBoundsException ex ) |
| { |
| LOG.atError().withThrowable(ex).log("Unable to apply {}", sprm); |
| } |
| } |
| } |
| return tableProperties; |
| } |
| |
| /** |
| * Used to uncompress a table property. Performs an operation defined |
| * by a sprm stored in a tapx. |
| * |
| * @param newTAP The TableProperties object to perform the operation on. |
| * @param operand The operand that defines this operation. |
| * @param param The parameter for this operation. |
| * @param varParam Variable length parameter for this operation. |
| */ |
| static void unCompressTAPOperation (TableProperties newTAP, SprmOperation sprm) |
| { |
| switch (sprm.getOperation()) |
| { |
| case 0: |
| newTAP.setJc ((short) sprm.getOperand()); |
| break; |
| case 0x01: |
| { |
| short[] rgdxaCenter = newTAP.getRgdxaCenter (); |
| short itcMac = newTAP.getItcMac (); |
| int adjust = sprm.getOperand() - (rgdxaCenter[0] + newTAP.getDxaGapHalf ()); |
| for (int x = 0; x < itcMac; x++) |
| { |
| rgdxaCenter[x] += adjust; |
| } |
| break; |
| } |
| case 0x02: |
| { |
| short[] rgdxaCenter = newTAP.getRgdxaCenter (); |
| if (rgdxaCenter != null) |
| { |
| int adjust = newTAP.getDxaGapHalf () - sprm.getOperand(); |
| rgdxaCenter[0] += adjust; |
| } |
| newTAP.setDxaGapHalf (sprm.getOperand()); |
| break; |
| } |
| case 0x03: |
| newTAP.setFCantSplit (getFlag(sprm.getOperand())); |
| break; |
| case 0x04: |
| newTAP.setFTableHeader (getFlag (sprm.getOperand())); |
| break; |
| case 0x05: |
| { |
| byte[] buf = sprm.getGrpprl(); |
| int offset = sprm.getGrpprlOffset(); |
| newTAP.setBrcTop(new BorderCode(buf, offset)); |
| offset += BorderCode.SIZE; |
| newTAP.setBrcLeft(new BorderCode(buf, offset)); |
| offset += BorderCode.SIZE; |
| newTAP.setBrcBottom(new BorderCode(buf, offset)); |
| offset += BorderCode.SIZE; |
| newTAP.setBrcRight(new BorderCode(buf, offset)); |
| offset += BorderCode.SIZE; |
| newTAP.setBrcHorizontal(new BorderCode(buf, offset)); |
| offset += BorderCode.SIZE; |
| newTAP.setBrcVertical(new BorderCode(buf, offset)); |
| break; |
| } |
| case 0x06: |
| |
| //obsolete, used in word 1.x |
| break; |
| case 0x07: |
| newTAP.setDyaRowHeight (sprm.getOperand()); |
| break; |
| case 0x08: |
| { |
| byte[] grpprl = sprm.getGrpprl(); |
| int offset = sprm.getGrpprlOffset(); |
| short itcMac = grpprl[offset]; |
| short[] rgdxaCenter = new short[itcMac + 1]; |
| TableCellDescriptor[] rgtc = new TableCellDescriptor[itcMac]; |
| //I use varParam[0] and newTAP._itcMac interchangably |
| newTAP.setItcMac (itcMac); |
| newTAP.setRgdxaCenter (rgdxaCenter); |
| newTAP.setRgtc (rgtc); |
| |
| // get the rgdxaCenters |
| for (int x = 0; x < itcMac; x++) |
| { |
| rgdxaCenter[x] = LittleEndian.getShort (grpprl, offset + (1 + (x * 2))); |
| } |
| |
| // only try to get the TC entries if they exist... |
| int endOfSprm = offset+sprm.size()-6; // -2 bytes for sprm - 2 for size short - 2 to correct offsets being 0 based |
| int startOfTCs = offset + (1 + (itcMac + 1) * 2); |
| |
| boolean hasTCs = startOfTCs < endOfSprm; |
| |
| for (int x = 0; x < itcMac; x++) |
| { |
| // Sometimes, the grpprl does not contain data at every offset. I have no idea why this happens. |
| if(hasTCs && offset + (1 + ( (itcMac + 1) * 2) + (x * 20)) < grpprl.length) |
| rgtc[x] = TableCellDescriptor.convertBytesToTC(grpprl, |
| offset + (1 + ( (itcMac + 1) * 2) + (x * 20))); |
| else |
| rgtc[x] = new TableCellDescriptor(); |
| } |
| |
| rgdxaCenter[itcMac] = LittleEndian.getShort (grpprl, offset + (1 + (itcMac * 2))); |
| break; |
| } |
| case 0x09: |
| |
| /** @todo handle cell shading*/ |
| break; |
| case 0x0a: |
| |
| /** @todo handle word defined table styles*/ |
| break; |
| case 0x20: |
| // { |
| // TableCellDescriptor[] rgtc = newTAP.getRgtc(); |
| // |
| // for (int x = varParam[0]; x < varParam[1]; x++) |
| // { |
| // |
| // if ((varParam[2] & 0x08) > 0) |
| // { |
| // short[] brcRight = rgtc[x].getBrcRight (); |
| // brcRight[0] = LittleEndian.getShort (varParam, 6); |
| // brcRight[1] = LittleEndian.getShort (varParam, 8); |
| // } |
| // else if ((varParam[2] & 0x04) > 0) |
| // { |
| // short[] brcBottom = rgtc[x].getBrcBottom (); |
| // brcBottom[0] = LittleEndian.getShort (varParam, 6); |
| // brcBottom[1] = LittleEndian.getShort (varParam, 8); |
| // } |
| // else if ((varParam[2] & 0x02) > 0) |
| // { |
| // short[] brcLeft = rgtc[x].getBrcLeft (); |
| // brcLeft[0] = LittleEndian.getShort (varParam, 6); |
| // brcLeft[1] = LittleEndian.getShort (varParam, 8); |
| // } |
| // else if ((varParam[2] & 0x01) > 0) |
| // { |
| // short[] brcTop = rgtc[x].getBrcTop (); |
| // brcTop[0] = LittleEndian.getShort (varParam, 6); |
| // brcTop[1] = LittleEndian.getShort (varParam, 8); |
| // } |
| // } |
| // break; |
| // } |
| break; |
| case 0x21: |
| { |
| int param = sprm.getOperand(); |
| int index = (param & 0xff000000) >> 24; |
| int count = (param & 0x00ff0000) >> 16; |
| int width = (param & 0x0000ffff); |
| int itcMac = newTAP.getItcMac(); |
| |
| short[] rgdxaCenter = new short[itcMac + count + 1]; |
| TableCellDescriptor[] rgtc = new TableCellDescriptor[itcMac + count]; |
| if (index >= itcMac) |
| { |
| index = itcMac; |
| System.arraycopy(newTAP.getRgdxaCenter(), 0, rgdxaCenter, 0, |
| itcMac + 1); |
| System.arraycopy(newTAP.getRgtc(), 0, rgtc, 0, itcMac); |
| } |
| else |
| { |
| //copy rgdxaCenter |
| System.arraycopy(newTAP.getRgdxaCenter(), 0, rgdxaCenter, 0, |
| index + 1); |
| System.arraycopy(newTAP.getRgdxaCenter(), index + 1, rgdxaCenter, |
| index + count, itcMac - (index)); |
| //copy rgtc |
| System.arraycopy(newTAP.getRgtc(), 0, rgtc, 0, index); |
| System.arraycopy(newTAP.getRgtc(), index, rgtc, index + count, |
| itcMac - index); |
| } |
| |
| for (int x = index; x < index + count; x++) |
| { |
| rgtc[x] = new TableCellDescriptor(); |
| rgdxaCenter[x] = (short)(rgdxaCenter[x - 1] + width); |
| } |
| rgdxaCenter[index + |
| count] = (short)(rgdxaCenter[(index + count) - 1] + width); |
| break; |
| } |
| /**@todo handle table sprms from complex files*/ |
| case 0x22: |
| case 0x23: |
| case 0x24: |
| case 0x25: |
| case 0x26: |
| case 0x27: |
| case 0x28: |
| case 0x29: |
| case 0x2a: |
| case 0x2b: |
| case 0x2c: |
| break; |
| case 0x34: |
| // sprmTCellPaddingDefault -- (0xd634) |
| // TODO: extract into CSSA structure |
| byte itcFirst = sprm.getGrpprl()[sprm.getGrpprlOffset()]; |
| byte itcLim = sprm.getGrpprl()[sprm.getGrpprlOffset() + 1]; |
| byte grfbrc = sprm.getGrpprl()[sprm.getGrpprlOffset() + 2]; |
| byte ftsWidth = sprm.getGrpprl()[sprm.getGrpprlOffset() + 3]; |
| short wWidth = LittleEndian.getShort(sprm.getGrpprl(), |
| sprm.getGrpprlOffset() + 4); |
| |
| for (int c = itcFirst; c < itcLim; c++) { |
| TableCellDescriptor tableCellDescriptor = newTAP.getRgtc()[c]; |
| |
| if ((grfbrc & 0x01) != 0) { |
| tableCellDescriptor.setFtsCellPaddingTop(ftsWidth); |
| tableCellDescriptor.setWCellPaddingTop(wWidth); |
| } |
| if ((grfbrc & 0x02) != 0) { |
| tableCellDescriptor.setFtsCellPaddingLeft(ftsWidth); |
| tableCellDescriptor.setWCellPaddingLeft(wWidth); |
| } |
| if ((grfbrc & 0x04) != 0) { |
| tableCellDescriptor.setFtsCellPaddingBottom(ftsWidth); |
| tableCellDescriptor.setWCellPaddingBottom(wWidth); |
| } |
| if ((grfbrc & 0x08) != 0) { |
| tableCellDescriptor.setFtsCellPaddingRight(ftsWidth); |
| tableCellDescriptor.setWCellPaddingRight(wWidth); |
| } |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| |
| |
| |
| } |