Bug 54210 - Fixed rendering text in flipped shapes in PPT2PNG and PPTX2PNG

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1416165 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2012-12-02 12:24:55 +00:00
parent b78b16dac5
commit 7adad438bf
3 changed files with 68 additions and 1 deletions

View File

@ -34,6 +34,8 @@
<changes> <changes>
<release version="4.0-beta1" date="2013-??-??"> <release version="4.0-beta1" date="2013-??-??">
<action dev="poi-developers" type="fix">Synchronize table headers with parent sheet in XSSF</action>
<action dev="poi-developers" type="fix">54210 - Fixed rendering text in flipped shapes in PPT2PNG and PPTX2PNG</action>
</release> </release>
<release version="3.9" date="2012-12-03"> <release version="3.9" date="2012-12-03">
<action dev="poi-developers" type="fix">54188 - Avoid NPE in PPT2PNG</action> <action dev="poi-developers" type="fix">54188 - Avoid NPE in PPT2PNG</action>

View File

@ -37,6 +37,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.ArrayList; import java.util.ArrayList;
@ -493,6 +494,36 @@ public abstract class XSLFTextShape extends XSLFSimpleShape implements Iterable<
double x = anchor.getX() + getLeftInset(); double x = anchor.getX() + getLeftInset();
double y = anchor.getY(); double y = anchor.getY();
// remember the initial transform
AffineTransform tx = graphics.getTransform();
// Transform of text in flipped shapes is special.
// At this point the flip and rotation transform is already applied
// (see XSLFShape#applyTransform ), but we need to restore it to avoid painting "upside down".
// See Bugzilla 54210.
if(getFlipVertical()){
graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
graphics.scale(1, -1);
graphics.translate(-anchor.getX(), -anchor.getY());
// text in vertically flipped shapes is rotated by 180 degrees
double centerX = anchor.getX() + anchor.getWidth()/2;
double centerY = anchor.getY() + anchor.getHeight()/2;
graphics.translate(centerX, centerY);
graphics.rotate(Math.toRadians(180));
graphics.translate(-centerX, -centerY);
}
// Horizontal flipping applies only to shape outline and not to the text in the shape.
// Applying flip second time restores the original not-flipped transform
if(getFlipHorizontal()){
graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
graphics.scale(-1, 1);
graphics.translate(-anchor.getX() , -anchor.getY());
}
// first dry-run to calculate the total height of the text // first dry-run to calculate the total height of the text
double textHeight = getTextHeight(); double textHeight = getTextHeight();
@ -512,11 +543,14 @@ public abstract class XSLFTextShape extends XSLFSimpleShape implements Iterable<
} }
drawParagraphs(graphics, x, y); drawParagraphs(graphics, x, y);
// restore the transform
graphics.setTransform(tx);
} }
/** /**
* pain the paragraphs starting from top left (x,y) * paint the paragraphs starting from top left (x,y)
* *
* @return the vertical advance, i.e. the cumulative space occupied by the text * @return the vertical advance, i.e. the cumulative space occupied by the text
*/ */

View File

@ -24,6 +24,7 @@ import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer; import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute; import java.awt.font.TextAttribute;
import java.awt.font.TextLayout; import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.text.AttributedCharacterIterator; import java.text.AttributedCharacterIterator;
@ -94,6 +95,8 @@ public final class TextPainter {
} }
public void paint(Graphics2D graphics){ public void paint(Graphics2D graphics){
AffineTransform tx = graphics.getTransform();
Rectangle2D anchor = _shape.getLogicalAnchor2D(); Rectangle2D anchor = _shape.getLogicalAnchor2D();
TextElement[] elem = getTextElements((float)anchor.getWidth(), graphics.getFontRenderContext()); TextElement[] elem = getTextElements((float)anchor.getWidth(), graphics.getFontRenderContext());
if(elem == null) return; if(elem == null) return;
@ -120,6 +123,32 @@ public final class TextPainter {
break; break;
} }
// Transform of text in flipped shapes is special.
// At this point the flip and rotation transform is already applied
// (see XSLFShape#applyTransform ), but we need to restore it to avoid painting "upside down".
// See Bugzilla 54210.
if(_shape.getFlipVertical()){
graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
graphics.scale(1, -1);
graphics.translate(-anchor.getX(), -anchor.getY());
// text in vertically flipped shapes is rotated by 180 degrees
double centerX = anchor.getX() + anchor.getWidth()/2;
double centerY = anchor.getY() + anchor.getHeight()/2;
graphics.translate(centerX, centerY);
graphics.rotate(Math.toRadians(180));
graphics.translate(-centerX, -centerY);
}
// Horizontal flipping applies only to shape outline and not to the text in the shape.
// Applying flip second time restores the original not-flipped transform
if(_shape.getFlipHorizontal()){
graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
graphics.scale(-1, 1);
graphics.translate(-anchor.getX() , -anchor.getY());
}
//finally draw the text fragments //finally draw the text fragments
for (int i = 0; i < elem.length; i++) { for (int i = 0; i < elem.length; i++) {
y0 += elem[i].ascent; y0 += elem[i].ascent;
@ -149,6 +178,8 @@ public final class TextPainter {
} }
y0 += elem[i].descent; y0 += elem[i].descent;
} }
graphics.setTransform(tx);
} }
public TextElement[] getTextElements(float textWidth, FontRenderContext frc){ public TextElement[] getTextElements(float textWidth, FontRenderContext frc){