From: Andreas Beeker Date: Sun, 30 Jul 2017 23:11:36 +0000 (+0000) Subject: #61363 - Unify escher shape id allocation X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ff2bcdf62db568ccc638091f8669a9b2cc9483d6;p=poi.git #61363 - Unify escher shape id allocation git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1803483 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/ddf/EscherDggRecord.java b/src/java/org/apache/poi/ddf/EscherDggRecord.java index 8675fa776d..5aac513c25 100644 --- a/src/java/org/apache/poi/ddf/EscherDggRecord.java +++ b/src/java/org/apache/poi/ddf/EscherDggRecord.java @@ -19,6 +19,7 @@ package org.apache.poi.ddf; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -32,38 +33,37 @@ import org.apache.poi.util.RecordFormatException; public final class EscherDggRecord extends EscherRecord { public static final short RECORD_ID = (short) 0xF006; public static final String RECORD_DESCRIPTION = "MsofbtDgg"; - + private int field_1_shapeIdMax; -// private int field_2_numIdClusters; // for some reason the number of clusters is actually the real number + 1 + // for some reason the number of clusters is actually the real number + 1 + // private int field_2_numIdClusters; private int field_3_numShapesSaved; private int field_4_drawingsSaved; - private FileIdCluster[] field_5_fileIdClusters; + private final List field_5_fileIdClusters = new ArrayList(); private int maxDgId; - public static class FileIdCluster - { - public FileIdCluster( int drawingGroupId, int numShapeIdsUsed ) - { + public static class FileIdCluster { + private int field_1_drawingGroupId; + private int field_2_numShapeIdsUsed; + + public FileIdCluster( int drawingGroupId, int numShapeIdsUsed ) { this.field_1_drawingGroupId = drawingGroupId; this.field_2_numShapeIdsUsed = numShapeIdsUsed; } - private int field_1_drawingGroupId; - private int field_2_numShapeIdsUsed; - - public int getDrawingGroupId() - { + public int getDrawingGroupId() { return field_1_drawingGroupId; } - public int getNumShapeIdsUsed() - { + public int getNumShapeIdsUsed() { return field_2_numShapeIdsUsed; } - public void incrementShapeId( ) - { - this.field_2_numShapeIdsUsed++; + /** + * @return the current used shape ids value and increases it afterwards + */ + private void incrementUsedShapeId() { + field_2_numShapeIdsUsed++; } } @@ -77,18 +77,24 @@ public final class EscherDggRecord extends EscherRecord { size+=4; field_3_numShapesSaved = LittleEndian.getInt( data, pos + size );size+=4; field_4_drawingsSaved = LittleEndian.getInt( data, pos + size );size+=4; - field_5_fileIdClusters = new FileIdCluster[(bytesRemaining-size) / 8]; // Can't rely on field_2_numIdClusters - for (int i = 0; i < field_5_fileIdClusters.length; i++) - { - field_5_fileIdClusters[i] = new FileIdCluster(LittleEndian.getInt( data, pos + size ), LittleEndian.getInt( data, pos + size + 4 )); - maxDgId = Math.max(maxDgId, field_5_fileIdClusters[i].getDrawingGroupId()); + + field_5_fileIdClusters.clear(); + // Can't rely on field_2_numIdClusters + int numIdClusters = (bytesRemaining-size) / 8; + + for (int i = 0; i < numIdClusters; i++) { + int drawingGroupId = LittleEndian.getInt( data, pos + size ); + int numShapeIdsUsed = LittleEndian.getInt( data, pos + size + 4 ); + FileIdCluster fic = new FileIdCluster(drawingGroupId, numShapeIdsUsed); + field_5_fileIdClusters.add(fic); + maxDgId = Math.max(maxDgId, drawingGroupId); size += 8; } - bytesRemaining -= size; + bytesRemaining -= size; if (bytesRemaining != 0) { throw new RecordFormatException("Expecting no remaining data but got " + bytesRemaining + " byte(s)."); } - return 8 + size + bytesRemaining; + return 8 + size; } @Override @@ -105,9 +111,10 @@ public final class EscherDggRecord extends EscherRecord { LittleEndian.putInt( data, pos, getNumIdClusters() ); pos += 4; LittleEndian.putInt( data, pos, field_3_numShapesSaved ); pos += 4; LittleEndian.putInt( data, pos, field_4_drawingsSaved ); pos += 4; - for (int i = 0; i < field_5_fileIdClusters.length; i++) { - LittleEndian.putInt( data, pos, field_5_fileIdClusters[i].field_1_drawingGroupId ); pos += 4; - LittleEndian.putInt( data, pos, field_5_fileIdClusters[i].field_2_numShapeIdsUsed ); pos += 4; + + for (FileIdCluster fic : field_5_fileIdClusters) { + LittleEndian.putInt( data, pos, fic.getDrawingGroupId() ); pos += 4; + LittleEndian.putInt( data, pos, fic.getNumShapeIdsUsed() ); pos += 4; } listener.afterRecordSerialize( pos, getRecordId(), getRecordSize(), this ); @@ -116,7 +123,7 @@ public final class EscherDggRecord extends EscherRecord { @Override public int getRecordSize() { - return 8 + 16 + (8 * field_5_fileIdClusters.length); + return 8 + 16 + (8 * field_5_fileIdClusters.size()); } @Override @@ -153,7 +160,7 @@ public final class EscherDggRecord extends EscherRecord { * @return the number of id clusters + 1 */ public int getNumIdClusters() { - return (field_5_fileIdClusters == null ? 0 : (field_5_fileIdClusters.length + 1)); + return (field_5_fileIdClusters.isEmpty() ? 0 : field_5_fileIdClusters.size() + 1); } /** @@ -201,20 +208,11 @@ public final class EscherDggRecord extends EscherRecord { return maxDgId; } - /** - * Sets the maximum drawing group ID - * - * @param id the maximum drawing group ID - */ - public void setMaxDrawingGroupId(int id) { - maxDgId = id; - } - /** * @return the file id clusters */ public FileIdCluster[] getFileIdClusters() { - return field_5_fileIdClusters; + return field_5_fileIdClusters.toArray(new FileIdCluster[field_5_fileIdClusters.size()]); } /** @@ -223,7 +221,10 @@ public final class EscherDggRecord extends EscherRecord { * @param fileIdClusters the file id clusters */ public void setFileIdClusters(FileIdCluster[] fileIdClusters) { - this.field_5_fileIdClusters = fileIdClusters.clone(); + field_5_fileIdClusters.clear(); + if (fileIdClusters != null) { + field_5_fileIdClusters.addAll(Arrays.asList(fileIdClusters)); + } } @@ -232,9 +233,11 @@ public final class EscherDggRecord extends EscherRecord { * * @param dgId id of the drawing group (stored in the record options) * @param numShapedUsed initial value of the numShapedUsed field + * + * @return the new {@link FileIdCluster} */ - public void addCluster(int dgId, int numShapedUsed) { - addCluster(dgId, numShapedUsed, true); + public FileIdCluster addCluster(int dgId, int numShapedUsed) { + return addCluster(dgId, numShapedUsed, true); } /** @@ -244,40 +247,98 @@ public final class EscherDggRecord extends EscherRecord { * @param numShapedUsed initial value of the numShapedUsed field * @param sort if true then sort clusters by drawing group id.( * In Excel the clusters are sorted but in PPT they are not) + * + * @return the new {@link FileIdCluster} */ - public void addCluster( int dgId, int numShapedUsed, boolean sort ) { - List clusters = new ArrayList(Arrays.asList(field_5_fileIdClusters)); - clusters.add(new FileIdCluster(dgId, numShapedUsed)); - if(sort) { - Collections.sort(clusters, MY_COMP ); - } + public FileIdCluster addCluster( int dgId, int numShapedUsed, boolean sort ) { + FileIdCluster ficNew = new FileIdCluster(dgId, numShapedUsed); + field_5_fileIdClusters.add(ficNew); maxDgId = Math.min(maxDgId, dgId); - field_5_fileIdClusters = clusters.toArray( new FileIdCluster[clusters.size()] ); + + if (sort) { + sortCluster(); + } + + return ficNew; } - private static final Comparator MY_COMP = new Comparator() { - @Override - public int compare(FileIdCluster f1, FileIdCluster f2) { - if (f1.getDrawingGroupId() == f2.getDrawingGroupId()) { - return 0; + private void sortCluster() { + Collections.sort(field_5_fileIdClusters, new Comparator() { + @Override + public int compare(FileIdCluster f1, FileIdCluster f2) { + int dgDif = f1.getDrawingGroupId() - f2.getDrawingGroupId(); + int cntDif = f2.getNumShapeIdsUsed() - f1.getNumShapeIdsUsed(); + return (dgDif != 0) ? dgDif : cntDif; } - if (f1.getDrawingGroupId() < f2.getDrawingGroupId()) { - return -1; + }); + } + + /** + * Finds the next available (1 based) drawing group id + * + * @return the next available drawing group id + */ + public short findNewDrawingGroupId() { + BitSet bs = new BitSet(); + bs.set(0); + for (FileIdCluster fic : field_5_fileIdClusters) { + bs.set(fic.getDrawingGroupId()); + } + return (short)bs.nextClearBit(0); + } + + /** + * Allocates new shape id for the drawing group + * + * @param drawingGroupId the drawing group id + * @param dg the EscherDgRecord which receives the new shape + * @param sort if true then sort clusters by drawing group id.( + * In Excel the clusters are sorted but in PPT they are not) + * + * @return a new shape id. + */ + public int allocateShapeId(EscherDgRecord dg, boolean sort) { + final short drawingGroupId = dg.getDrawingGroupId(); + field_3_numShapesSaved++; + + // check for an existing cluster, which has space available + // see 2.2.46 OfficeArtIDCL (cspidCur) for the 1024 limitation + // multiple clusters can belong to the same drawing group + FileIdCluster ficAdd = null; + int index = 1; + for (FileIdCluster fic : field_5_fileIdClusters) { + if (fic.getDrawingGroupId() == drawingGroupId + && fic.getNumShapeIdsUsed() < 1024) { + ficAdd = fic; + break; } - return +1; + index++; } - }; + if (ficAdd == null) { + ficAdd = addCluster( drawingGroupId, 0, sort ); + maxDgId = Math.max(maxDgId, drawingGroupId); + } + + int shapeId = index*1024 + ficAdd.getNumShapeIdsUsed(); + ficAdd.incrementUsedShapeId(); + + dg.setNumShapes( dg.getNumShapes() + 1 ); + dg.setLastMSOSPID( shapeId ); + field_1_shapeIdMax = Math.max(field_1_shapeIdMax, shapeId + 1); + + return shapeId; + } + + @Override protected Object[][] getAttributeMap() { List fldIds = new ArrayList(); fldIds.add("FileId Clusters"); - fldIds.add(field_5_fileIdClusters.length); - if(field_5_fileIdClusters != null) { - for (FileIdCluster fic : field_5_fileIdClusters) { - fldIds.add("Group"+fic.field_1_drawingGroupId); - fldIds.add(fic.field_2_numShapeIdsUsed); - } + fldIds.add(field_5_fileIdClusters.size()); + for (FileIdCluster fic : field_5_fileIdClusters) { + fldIds.add("Group"+fic.field_1_drawingGroupId); + fldIds.add(fic.field_2_numShapeIdsUsed); } return new Object[][] { diff --git a/src/java/org/apache/poi/hssf/model/DrawingManager.java b/src/java/org/apache/poi/hssf/model/DrawingManager.java deleted file mode 100644 index 468f6b4f51..0000000000 --- a/src/java/org/apache/poi/hssf/model/DrawingManager.java +++ /dev/null @@ -1,155 +0,0 @@ -/* ==================================================================== - 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.hssf.model; - -import org.apache.poi.ddf.EscherDggRecord; -import org.apache.poi.ddf.EscherDgRecord; - -import java.util.Map; -import java.util.HashMap; - -/** - * Provides utilities to manage drawing groups. - * - * @deprecated in POI 3.15-beta2, scheduled for removal in 3.17, use DrawingManager2 instead - */ -@Deprecated -public class DrawingManager -{ - EscherDggRecord dgg; - Map dgMap = new HashMap(); // key = Short(drawingId), value=EscherDgRecord - - public DrawingManager( EscherDggRecord dgg ) - { - this.dgg = dgg; - } - - public EscherDgRecord createDgRecord() - { - EscherDgRecord dg = new EscherDgRecord(); - dg.setRecordId( EscherDgRecord.RECORD_ID ); - short dgId = findNewDrawingGroupId(); - dg.setOptions( (short) ( dgId << 4 ) ); - dg.setNumShapes( 0 ); - dg.setLastMSOSPID( -1 ); - dgg.addCluster( dgId, 0 ); - dgg.setDrawingsSaved( dgg.getDrawingsSaved() + 1 ); - dgMap.put( dgId, dg ); - return dg; - } - - /** - * Allocates new shape id for the new drawing group id. - * - * @param drawingGroupId The drawing group id - * @return a new shape id. - */ - public int allocateShapeId(short drawingGroupId) - { - // Get the last shape id for this drawing group. - EscherDgRecord dg = dgMap.get(drawingGroupId); - int lastShapeId = dg.getLastMSOSPID(); - - - // Have we run out of shapes for this cluster? - int newShapeId = 0; - if (lastShapeId % 1024 == 1023) - { - // Yes: - // Find the starting shape id of the next free cluster - newShapeId = findFreeSPIDBlock(); - // Create a new cluster in the dgg record. - dgg.addCluster(drawingGroupId, 1); - } - else - { - // No: - // Find the cluster for this drawing group with free space. - for (int i = 0; i < dgg.getFileIdClusters().length; i++) - { - EscherDggRecord.FileIdCluster c = dgg.getFileIdClusters()[i]; - if (c.getDrawingGroupId() == drawingGroupId) - { - if (c.getNumShapeIdsUsed() != 1024) - { - // Increment the number of shapes used for this cluster. - c.incrementShapeId(); - } - } - // If the last shape id = -1 then we know to find a free block; - if (dg.getLastMSOSPID() == -1) - { - newShapeId = findFreeSPIDBlock(); - } - else - { - // The new shape id to be the last shapeid of this cluster + 1 - newShapeId = dg.getLastMSOSPID() + 1; - } - } - } - // Increment the total number of shapes used in the dgg. - dgg.setNumShapesSaved(dgg.getNumShapesSaved() + 1); - // Is the new shape id >= max shape id for dgg? - if (newShapeId >= dgg.getShapeIdMax()) - { - // Yes: - // Set the max shape id = new shape id + 1 - dgg.setShapeIdMax(newShapeId + 1); - } - // Set last shape id for this drawing group. - dg.setLastMSOSPID(newShapeId); - // Increased the number of shapes used for this drawing group. - dg.incrementShapeCount(); - - - return newShapeId; - } - - //////////// Non-public methods ///////////// - short findNewDrawingGroupId() - { - short dgId = 1; - while ( drawingGroupExists( dgId ) ) - dgId++; - return dgId; - } - - boolean drawingGroupExists( short dgId ) - { - for ( int i = 0; i < dgg.getFileIdClusters().length; i++ ) - { - if ( dgg.getFileIdClusters()[i].getDrawingGroupId() == dgId ) - return true; - } - return false; - } - - int findFreeSPIDBlock() - { - int max = dgg.getShapeIdMax(); - int next = ( ( max / 1024 ) + 1 ) * 1024; - return next; - } - - public EscherDggRecord getDgg() - { - return dgg; - } - -} diff --git a/src/java/org/apache/poi/hssf/model/DrawingManager2.java b/src/java/org/apache/poi/hssf/model/DrawingManager2.java index e5deeb02e5..f734cca431 100644 --- a/src/java/org/apache/poi/hssf/model/DrawingManager2.java +++ b/src/java/org/apache/poi/hssf/model/DrawingManager2.java @@ -17,24 +17,23 @@ package org.apache.poi.hssf.model; +import java.util.ArrayList; +import java.util.List; + import org.apache.poi.ddf.EscherDgRecord; import org.apache.poi.ddf.EscherDggRecord; - -import java.util.List; -import java.util.ArrayList; +import org.apache.poi.util.Removal; /** * Provides utilities to manage drawing groups. */ -public class DrawingManager2 -{ - EscherDggRecord dgg; - List drawingGroups = new ArrayList(); +public class DrawingManager2 { + private final EscherDggRecord dgg; + private final List drawingGroups = new ArrayList(); - public DrawingManager2( EscherDggRecord dgg ) - { + public DrawingManager2( EscherDggRecord dgg ) { this.dgg = dgg; } @@ -50,8 +49,7 @@ public class DrawingManager2 * * @return a new drawing group */ - public EscherDgRecord createDgRecord() - { + public EscherDgRecord createDgRecord() { EscherDgRecord dg = new EscherDgRecord(); dg.setRecordId( EscherDgRecord.RECORD_ID ); short dgId = findNewDrawingGroupId(); @@ -70,11 +68,18 @@ public class DrawingManager2 * @param drawingGroupId the drawing group id * * @return a new shape id + * + * @deprecated in POI 3.17-beta2, use allocateShapeId(EscherDgRecord) */ - public int allocateShapeId(short drawingGroupId) - { - EscherDgRecord dg = getDrawingGroup(drawingGroupId); - return allocateShapeId(drawingGroupId, dg); + @Deprecated + @Removal(version="4.0") + public int allocateShapeId(short drawingGroupId) { + for (EscherDgRecord dg : drawingGroups) { + if (dg.getDrawingGroupId() == drawingGroupId) { + return allocateShapeId(dg); + } + } + throw new IllegalStateException("Drawing group id "+drawingGroupId+" doesn't exist."); } /** @@ -84,72 +89,34 @@ public class DrawingManager2 * @param dg the EscherDgRecord which receives the new shape * * @return a new shape id. + * + * @deprecated in POI 3.17-beta2, use allocateShapeId(EscherDgRecord) */ - public int allocateShapeId(short drawingGroupId, EscherDgRecord dg) - { - dgg.setNumShapesSaved( dgg.getNumShapesSaved() + 1 ); - - // Add to existing cluster if space available - for (int i = 0; i < dgg.getFileIdClusters().length; i++) - { - EscherDggRecord.FileIdCluster c = dgg.getFileIdClusters()[i]; - if (c.getDrawingGroupId() == drawingGroupId && c.getNumShapeIdsUsed() != 1024) - { - int result = c.getNumShapeIdsUsed() + (1024 * (i+1)); - c.incrementShapeId(); - dg.setNumShapes( dg.getNumShapes() + 1 ); - dg.setLastMSOSPID( result ); - if (result >= dgg.getShapeIdMax()) - dgg.setShapeIdMax( result + 1 ); - return result; - } - } + @Deprecated + @Removal(version="4.0") + public int allocateShapeId(short drawingGroupId, EscherDgRecord dg) { + return allocateShapeId(dg); + } - // Create new cluster - dgg.addCluster( drawingGroupId, 0 ); - dgg.getFileIdClusters()[dgg.getFileIdClusters().length-1].incrementShapeId(); - dg.setNumShapes( dg.getNumShapes() + 1 ); - int result = (1024 * dgg.getFileIdClusters().length); - dg.setLastMSOSPID( result ); - if (result >= dgg.getShapeIdMax()) - dgg.setShapeIdMax( result + 1 ); - return result; + /** + * Allocates new shape id for the drawing group + * + * @param drawingGroupId the drawing group id + * @param dg the EscherDgRecord which receives the new shape + * + * @return a new shape id. + */ + public int allocateShapeId(EscherDgRecord dg) { + return dgg.allocateShapeId(dg, true); } - //////////// Non-public methods ///////////// /** * Finds the next available (1 based) drawing group id * * @return the next available drawing group id */ - public short findNewDrawingGroupId() - { - short dgId = 1; - while ( drawingGroupExists( dgId ) ) - dgId++; - return dgId; - } - - EscherDgRecord getDrawingGroup(int drawingGroupId) - { - return drawingGroups.get(drawingGroupId-1); - } - - boolean drawingGroupExists( short dgId ) - { - for ( int i = 0; i < dgg.getFileIdClusters().length; i++ ) - { - if ( dgg.getFileIdClusters()[i].getDrawingGroupId() == dgId ) - return true; - } - return false; - } - - int findFreeSPIDBlock() - { - int max = dgg.getShapeIdMax(); - int next = ( ( max / 1024 ) + 1 ) * 1024; - return next; + public short findNewDrawingGroupId() { + return dgg.findNewDrawingGroupId(); } /** @@ -157,8 +124,7 @@ public class DrawingManager2 * * @return the drawing group container record */ - public EscherDggRecord getDgg() - { + public EscherDggRecord getDgg() { return dgg; } diff --git a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java index 1538ca5835..9137e69843 100644 --- a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java +++ b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java @@ -2163,7 +2163,7 @@ public final class InternalWorkbook { throw new RecordFormatException("EscherDgRecord wasn't set/processed before."); } EscherSpRecord sp = (EscherSpRecord)shapeChildRecord; - int shapeId = drawingManager.allocateShapeId((short)dgId, dg); + int shapeId = drawingManager.allocateShapeId(dg); //allocateShapeId increments the number of shapes. roll back to the previous value dg.setNumShapes(dg.getNumShapes()-1); sp.setShapeId(shapeId); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index d7baeb58e0..0b916aa87a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -429,8 +429,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, DrawingA1.. - * @deprecated 3.14beta2 (circa 2015-12-05). Use {@link #setActiveCell(CellAddress)} instead. - */ - @Deprecated - @Removal(version="3.16") - public void setActiveCell(String cellRef) { - CTSelection ctsel = getSheetTypeSelection(); - ctsel.setActiveCell(cellRef); - ctsel.setSqref(Arrays.asList(cellRef)); - } - /** * {@inheritDoc} */ diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java index cc41706347..a8583bb574 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java @@ -212,40 +212,10 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet= dgg.getShapeIdMax()) { - dgg.setShapeIdMax( result + 1 ); - } - return result; - } - } - - // Create new cluster - dgg.addCluster( dg.getDrawingGroupId(), 0, false ); - dgg.getFileIdClusters()[dgg.getFileIdClusters().length-1].incrementShapeId(); - dg.setNumShapes( dg.getNumShapes() + 1 ); - int result = (1024 * dgg.getFileIdClusters().length); - dg.setLastMSOSPID( result ); - if (result >= dgg.getShapeIdMax()) { - dgg.setShapeIdMax( result + 1 ); - } - return result; + return dgg.allocateShapeId(dg, false); } /** diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java index 2a3e4fae1b..793c790fdf 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java @@ -166,7 +166,6 @@ public final class HSLFSlide extends HSLFSheet implements Slide