From 1b4416d11645031af412b5f49a298d0dbcbe9b52 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Sat, 3 Nov 2007 19:36:10 +0000 Subject: [PATCH] Fix for handling rotated text in HSSFSheet.autoSizeColumn. Thanks to Jeff Williams. See Bug 43751 for details. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@591666 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/changes.xml | 1 + .../apache/poi/hssf/usermodel/HSSFSheet.java | 46 +++++++++++++++++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index 69c3eb8701..29df020f3c 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -36,6 +36,7 @@ + 43751 - [PATCH] - Fix for handling rotated text in HSSFSheet.autoSizeColumn Include an Excel text extractor, and put all existing text extractors under a common superclass Improvements to the LZW compression engine used by HDGF HSSFPicture.resize() - a handy method to reset a picture to its original width and height diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index 069e4efd82..c9124b4cf8 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -43,6 +43,8 @@ import java.awt.font.TextLayout; import java.awt.font.FontRenderContext; import java.awt.font.TextAttribute; +import java.awt.geom.AffineTransform; + /** * High level representation of a worksheet. * @author Andrew C. Oliver (acoliver at apache dot org) @@ -1443,6 +1445,14 @@ public class HSSFSheet */ char defaultChar = '0'; + /** + * This is the multiple of the scale measure that is added to the height + * of rotated text. + * + * TODO: research if this constant works well with different font sizes and different dpi + */ + double rotationLeadingMultiple = 40.0; + FontRenderContext frc = new FontRenderContext(null, true, true); HSSFWorkbook wb = new HSSFWorkbook(book); @@ -1462,6 +1472,7 @@ public class HSSFSheet HSSFCellStyle style = cell.getCellStyle(); HSSFFont font = wb.getFontAt(style.getFontIndex()); + if (cell.getCellType() == HSSFCell.CELL_TYPE_STRING) { HSSFRichTextString rt = cell.getRichStringCellValue(); String[] lines = rt.getString().split("\\n"); @@ -1480,8 +1491,21 @@ public class HSSFSheet } } } + layout = new TextLayout(str.getIterator(), frc); - width = Math.max(width, layout.getAdvance() / defaultCharWidth); + /* + * Transform the text using a scale so that it's height is increased by a multiple of the leading, + * and then rotate the text before computing the bounds. The scale results in some whitespace around + * the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but + * is added by the standard Excel autosize. + */ + AffineTransform trans = new AffineTransform(); + double height = layout.getOutline(trans).getBounds().getHeight(); + trans.concatenate(AffineTransform.getRotateInstance(style.getRotation()*2.0*Math.PI/360.0)); + trans.concatenate( + AffineTransform.getScaleInstance(1, (layout.getLeading()*rotationLeadingMultiple+height)/height) + ); + width = Math.max(width, layout.getOutline(trans).getBounds().getWidth() / defaultCharWidth); } } else { String sval = null; @@ -1493,10 +1517,12 @@ public class HSSFSheet try { NumberFormat fmt; if ("General".equals(format)) - fmt = new DecimalFormat(); + sval = "" + value; else + { fmt = new DecimalFormat(format); - sval = fmt.format(value); + sval = fmt.format(value); + } } catch (Exception e) { sval = "" + value; } @@ -1508,7 +1534,19 @@ public class HSSFSheet str.addAttribute(TextAttribute.FAMILY, font.getFontName()); str.addAttribute(TextAttribute.SIZE, new Float(font.getFontHeightInPoints())); layout = new TextLayout(str.getIterator(), frc); - width = Math.max(width, layout.getAdvance() / defaultCharWidth); + /* + * Transform the text using a scale so that it's height is increased by a multiple of the leading, + * and then rotate the text before computing the bounds. The scale results in some whitespace around + * the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but + * is added by the standard Excel autosize. + */ + AffineTransform trans = new AffineTransform(); + double height = layout.getOutline(trans).getBounds().getHeight(); + trans.concatenate(AffineTransform.getRotateInstance(style.getRotation()*2.0*Math.PI/360.0)); + trans.concatenate( + AffineTransform.getScaleInstance(1, (layout.getLeading()*rotationLeadingMultiple+height)/height) + ); + width = Math.max(width, layout.getOutline(trans).getBounds().getWidth() / defaultCharWidth); } if (width != -1) {