Skip to content

Commit 8819952

Browse files
committed
[bug-68094] try to improve cell width derivation by not rounding
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1913676 13f79535-47bb-0310-9956-ffa450edef68
1 parent e95a4d8 commit 8819952

File tree

3 files changed

+64
-8
lines changed

3 files changed

+64
-8
lines changed

poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/AutoSizeColumnTracker.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more
4747
*/
4848
@Internal
4949
/*package*/ class AutoSizeColumnTracker {
50-
private final int defaultCharWidth;
50+
private final float defaultCharWidth;
5151
private final DataFormatter dataFormatter = new DataFormatter();
5252

5353
// map of tracked columns, with values containing the best-fit width for the column
@@ -114,7 +114,7 @@ public void setMaxColumnWidths(double unmergedWidth, double mergedWidth) {
114114
*/
115115
public AutoSizeColumnTracker(final Sheet sheet) {
116116
// If sheet needs to be saved, use a java.lang.ref.WeakReference to avoid garbage collector gridlock.
117-
defaultCharWidth = SheetUtil.getDefaultCharWidth(sheet.getWorkbook());
117+
defaultCharWidth = SheetUtil.getDefaultCharWidthAsFloat(sheet.getWorkbook());
118118
}
119119

120120
/**

poi/src/main/java/org/apache/poi/ss/util/SheetUtil.java

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,24 @@ public void evaluateAll() {}
117117
* @param formatter formatter used to prepare the text to be measured
118118
* @param useMergedCells whether to use merged cells
119119
* @return the width in pixels or -1 if cell is empty
120+
* @deprecated since POI 5.2.5, it is better to pass defaultCharWidth as a float
120121
*/
121122
public static double getCellWidth(Cell cell, int defaultCharWidth, DataFormatter formatter, boolean useMergedCells) {
123+
return getCellWidth(cell, (float) defaultCharWidth, formatter, useMergedCells);
124+
}
125+
126+
127+
/**
128+
* Compute width of a single cell
129+
*
130+
* @param cell the cell whose width is to be calculated
131+
* @param defaultCharWidth the width of a single character
132+
* @param formatter formatter used to prepare the text to be measured
133+
* @param useMergedCells whether to use merged cells
134+
* @return the width in pixels or -1 if cell is empty
135+
* @since POI 5.2.5
136+
*/
137+
public static double getCellWidth(Cell cell, float defaultCharWidth, DataFormatter formatter, boolean useMergedCells) {
122138
List<CellRangeAddress> mergedRegions = cell.getSheet().getMergedRegions();
123139
return getCellWidth(cell, defaultCharWidth, formatter, useMergedCells, mergedRegions);
124140
}
@@ -136,9 +152,30 @@ public static double getCellWidth(Cell cell, int defaultCharWidth, DataFormatter
136152
* @param useMergedCells whether to use merged cells
137153
* @param mergedRegions The list of merged regions as received via cell.getSheet().getMergedRegions()
138154
* @return the width in pixels or -1 if cell is empty
155+
* @deprecated since POI 5.2.5, it is better to pass defaultCharWidth as a float
139156
*/
140157
public static double getCellWidth(Cell cell, int defaultCharWidth, DataFormatter formatter, boolean useMergedCells,
141158
List<CellRangeAddress> mergedRegions) {
159+
return getCellWidth(cell, (float) defaultCharWidth, formatter, useMergedCells, mergedRegions);
160+
}
161+
162+
/**
163+
* Compute width of a single cell
164+
*
165+
* This method receives the list of merged regions as querying it from the cell/sheet
166+
* is time-consuming and thus caching the list across cells speeds up certain operations
167+
* considerably.
168+
*
169+
* @param cell the cell whose width is to be calculated
170+
* @param defaultCharWidth the width of a single character
171+
* @param formatter formatter used to prepare the text to be measured
172+
* @param useMergedCells whether to use merged cells
173+
* @param mergedRegions The list of merged regions as received via cell.getSheet().getMergedRegions()
174+
* @return the width in pixels or -1 if cell is empty
175+
* @since POI 5.2.5
176+
*/
177+
public static double getCellWidth(Cell cell, float defaultCharWidth, DataFormatter formatter, boolean useMergedCells,
178+
List<CellRangeAddress> mergedRegions) {
142179
Sheet sheet = cell.getSheet();
143180
Workbook wb = sheet.getWorkbook();
144181
Row row = cell.getRow();
@@ -219,11 +256,11 @@ public static double getCellWidth(Cell cell, int defaultCharWidth, DataFormatter
219256
* @param str the text contained in the cell
220257
* @return the best fit cell width
221258
*/
222-
private static double getCellWidth(int defaultCharWidth, int colspan,
259+
private static double getCellWidth(float defaultCharWidth, int colspan,
223260
CellStyle style, double minWidth, AttributedString str) {
224261
TextLayout layout = new TextLayout(str.getIterator(), fontRenderContext);
225262
final Rectangle2D bounds;
226-
if(style.getRotation() != 0){
263+
if (style.getRotation() != 0) {
227264
/*
228265
* Transform the text using a scale so that its height is increased by a multiple of the leading,
229266
* and then rotate the text before computing the bounds. The scale results in some whitespace around
@@ -270,7 +307,7 @@ public static double getColumnWidth(Sheet sheet, int column, boolean useMergedCe
270307
*/
271308
public static double getColumnWidth(Sheet sheet, int column, boolean useMergedCells, int firstRow, int lastRow){
272309
DataFormatter formatter = new DataFormatter();
273-
int defaultCharWidth = getDefaultCharWidth(sheet.getWorkbook());
310+
float defaultCharWidth = getDefaultCharWidthAsFloat(sheet.getWorkbook());
274311

275312
List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
276313
double width = -1;
@@ -290,16 +327,30 @@ public static double getColumnWidth(Sheet sheet, int column, boolean useMergedCe
290327
*
291328
* @param wb the workbook to get the default character width from
292329
* @return default character width in pixels
330+
* @deprecated since POI 5.2.5, it is recommended to switch to {@link #getDefaultCharWidthAsFloat(Workbook)}.
293331
*/
294332
@Internal
295333
public static int getDefaultCharWidth(final Workbook wb) {
334+
return Math.round(getDefaultCharWidthAsFloat(wb));
335+
}
336+
337+
/**
338+
* Get default character width using the Workbook's default font. Note that this can
339+
* fail if your OS does not have the right fonts installed.
340+
*
341+
* @param wb the workbook to get the default character width from
342+
* @return default character width in pixels (as a float)
343+
* @since POI 5.2.5
344+
*/
345+
@Internal
346+
public static float getDefaultCharWidthAsFloat(final Workbook wb) {
296347
Font defaultFont = wb.getFontAt( 0);
297348

298349
AttributedString str = new AttributedString(String.valueOf(defaultChar));
299350
copyAttributes(defaultFont, str, 0, 1);
300351
try {
301352
TextLayout layout = new TextLayout(str.getIterator(), fontRenderContext);
302-
return Math.round(layout.getAdvance());
353+
return layout.getAdvance();
303354
} catch (UnsatisfiedLinkError | NoClassDefFoundError | InternalError e) {
304355
if (ignoreMissingFontSystem) {
305356
return DEFAULT_CHAR_WIDTH;
@@ -321,7 +372,7 @@ public static int getDefaultCharWidth(final Workbook wb) {
321372
* @return the width in pixels or -1 if cell is empty
322373
*/
323374
private static double getColumnWidthForRow(
324-
Row row, int column, int defaultCharWidth, DataFormatter formatter, boolean useMergedCells,
375+
Row row, int column, float defaultCharWidth, DataFormatter formatter, boolean useMergedCells,
325376
List<CellRangeAddress> mergedRegions) {
326377
if( row == null ) {
327378
return -1;

poi/src/test/java/org/apache/poi/ss/util/TestSheetUtil.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ void testGetCellWidthEmpty() throws IOException {
108108

109109
// no contents: cell.setCellValue("sometext");
110110
assertEquals(-1.0, SheetUtil.getCellWidth(cell, 1, null, true), 0.01);
111+
assertEquals(-1.0, SheetUtil.getCellWidth(cell, 1.0f, null, true), 0.01);
112+
113+
assertEquals(-1.0, SheetUtil.getCellWidth(cell, 1.5f, null, true), 0.01);
111114
}
112115
}
113116

@@ -120,7 +123,9 @@ void testGetCellWidthString() throws IOException {
120123

121124
cell.setCellValue("sometext");
122125

123-
assertTrue(SheetUtil.getCellWidth(cell, 1, null, true) > 0);
126+
final double width = SheetUtil.getCellWidth(cell, 1.0f, null, true);
127+
assertTrue(width > 0);
128+
assertEquals(width, SheetUtil.getCellWidth(cell, 1, null, true));
124129
}
125130
}
126131

0 commit comments

Comments
 (0)