git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1648335 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_12_BETA1
@@ -22,6 +22,9 @@ import org.apache.poi.hslf.model.Picture; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.POILogFactory; | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -39,7 +42,9 @@ import org.apache.poi.util.POILogFactory; | |||
limitations under the License. | |||
==================================================================== */ | |||
import javax.imageio.ImageIO; | |||
import java.awt.*; | |||
import java.awt.geom.AffineTransform; | |||
import java.awt.image.BufferedImage; | |||
import java.io.ByteArrayInputStream; | |||
@@ -54,15 +59,36 @@ public final class BitmapPainter implements ImagePainter { | |||
public void paint(Graphics2D graphics, PictureData pict, Picture parent) { | |||
BufferedImage img; | |||
try { | |||
img = ImageIO.read(new ByteArrayInputStream(pict.getData())); | |||
} | |||
catch (Exception e){ | |||
img = ImageIO.read(new ByteArrayInputStream(pict.getData())); | |||
} catch (Exception e) { | |||
logger.log(POILogger.WARN, "ImageIO failed to create image. image.type: " + pict.getType()); | |||
return; | |||
} | |||
boolean isClipped = true; | |||
Insets clip = parent.getBlipClip(); | |||
if (clip == null) { | |||
isClipped = false; | |||
clip = new Insets(0,0,0,0); | |||
} | |||
int iw = img.getWidth(); | |||
int ih = img.getHeight(); | |||
Rectangle anchor = parent.getLogicalAnchor2D().getBounds(); | |||
graphics.drawImage(img, anchor.x, anchor.y, anchor.width, anchor.height, null); | |||
double cw = (100000-clip.left-clip.right) / 100000.0; | |||
double ch = (100000-clip.top-clip.bottom) / 100000.0; | |||
double sx = anchor.getWidth()/(iw*cw); | |||
double sy = anchor.getHeight()/(ih*ch); | |||
double tx = anchor.getX()-(iw*sx*clip.left/100000.0); | |||
double ty = anchor.getY()-(ih*sy*clip.top/100000.0); | |||
AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ; | |||
Shape clipOld = graphics.getClip(); | |||
if (isClipped) graphics.clip(anchor.getBounds2D()); | |||
graphics.drawRenderedImage(img, at); | |||
graphics.setClip(clipOld); | |||
} | |||
} |
@@ -18,6 +18,7 @@ | |||
package org.apache.poi.hslf.model; | |||
import java.awt.Graphics2D; | |||
import java.awt.Insets; | |||
import java.awt.geom.AffineTransform; | |||
import java.awt.image.BufferedImage; | |||
import java.io.ByteArrayInputStream; | |||
@@ -264,4 +265,40 @@ public class Picture extends SimpleShape { | |||
graphics.setTransform(at); | |||
} | |||
} | |||
/** | |||
* Returns the clipping values as percent ratio relatively to the image size. | |||
* The anchor specified by {@link #getLogicalAnchor2D()} is the displayed size, | |||
* i.e. the size of the already clipped image | |||
* | |||
* @return the clipping as insets converted/scaled to 100000 (=100%) | |||
*/ | |||
public Insets getBlipClip() { | |||
EscherOptRecord opt = getEscherOptRecord(); | |||
double top = getFractProp(opt, EscherProperties.BLIP__CROPFROMTOP); | |||
double bottom = getFractProp(opt, EscherProperties.BLIP__CROPFROMBOTTOM); | |||
double left = getFractProp(opt, EscherProperties.BLIP__CROPFROMLEFT); | |||
double right = getFractProp(opt, EscherProperties.BLIP__CROPFROMRIGHT); | |||
// if all crop values are zero (the default) then no crop rectangle is set, return null | |||
return (top==0 && bottom==0 && left==0 && right==0) | |||
? null | |||
: new Insets((int)(top*100000), (int)(left*100000), (int)(bottom*100000), (int)(right*100000)); | |||
} | |||
/** | |||
* @return the fractional property or 0 if not defined | |||
* | |||
* @see <a href="http://msdn.microsoft.com/en-us/library/dd910765(v=office.12).aspx">2.2.1.6 FixedPoint</a> | |||
*/ | |||
private static double getFractProp(EscherOptRecord opt, short propertyId) { | |||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, propertyId); | |||
if (prop == null) return 0; | |||
int fixedPoint = prop.getPropertyValue(); | |||
int i = (fixedPoint >> 16); | |||
int f = (fixedPoint >> 0) & 0xFFFF; | |||
double fp = i + f/65536.0; | |||
return fp; | |||
} | |||
} |
@@ -17,39 +17,35 @@ | |||
package org.apache.poi.hslf.model; | |||
import junit.framework.Test; | |||
import junit.framework.TestSuite; | |||
import org.junit.runner.RunWith; | |||
import org.junit.runners.Suite; | |||
/** | |||
* Collects all tests from the package <tt>org.apache.poi.hslf.model</tt>. | |||
* | |||
* @author Josh Micich | |||
*/ | |||
@RunWith(Suite.class) | |||
@Suite.SuiteClasses({ | |||
TestBackground.class, | |||
TestFreeform.class, | |||
TestHeadersFooters.class, | |||
TestHyperlink.class, | |||
TestImagePainter.class, | |||
TestLine.class, | |||
TestMovieShape.class, | |||
TestOleEmbedding.class, | |||
TestPPFont.class, | |||
TestPPGraphics2D.class, | |||
TestPicture.class, | |||
TestSetBoldItalic.class, | |||
TestShapes.class, | |||
TestSheet.class, | |||
TestSlideChangeNotes.class, | |||
TestSlideMaster.class, | |||
TestSlides.class, | |||
TestTable.class, | |||
TestTextRun.class, | |||
TestTextRunReWrite.class, | |||
TestTextShape.class | |||
}) | |||
public class AllHSLFModelTests { | |||
public static Test suite() { | |||
TestSuite result = new TestSuite(AllHSLFModelTests.class.getName()); | |||
result.addTestSuite(TestBackground.class); | |||
result.addTestSuite(TestFreeform.class); | |||
result.addTestSuite(TestHeadersFooters.class); | |||
result.addTestSuite(TestHyperlink.class); | |||
result.addTestSuite(TestImagePainter.class); | |||
result.addTestSuite(TestLine.class); | |||
result.addTestSuite(TestMovieShape.class); | |||
result.addTestSuite(TestOleEmbedding.class); | |||
result.addTestSuite(TestPPFont.class); | |||
result.addTestSuite(TestPPGraphics2D.class); | |||
result.addTestSuite(TestPicture.class); | |||
result.addTestSuite(TestSetBoldItalic.class); | |||
result.addTestSuite(TestShapes.class); | |||
result.addTestSuite(TestSheet.class); | |||
result.addTestSuite(TestSlideChangeNotes.class); | |||
result.addTestSuite(TestSlideMaster.class); | |||
result.addTestSuite(TestSlides.class); | |||
result.addTestSuite(TestTable.class); | |||
result.addTestSuite(TestTextRun.class); | |||
result.addTestSuite(TestTextRunReWrite.class); | |||
result.addTestSuite(TestTextShape.class); | |||
return result; | |||
} | |||
} |
@@ -17,26 +17,38 @@ | |||
package org.apache.poi.hslf.model; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertNull; | |||
import static org.junit.Assert.assertSame; | |||
import java.awt.Dimension; | |||
import java.awt.Graphics2D; | |||
import java.awt.Rectangle; | |||
import java.awt.image.BufferedImage; | |||
import java.io.ByteArrayInputStream; | |||
import javax.imageio.ImageIO; | |||
import java.io.File; | |||
import java.io.InputStream; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import junit.framework.TestCase; | |||
import javax.imageio.ImageIO; | |||
import org.apache.poi.POIDataSamples; | |||
import org.apache.poi.ddf.EscherBSERecord; | |||
import org.apache.poi.hslf.HSLFSlideShow; | |||
import org.apache.poi.hslf.usermodel.PictureData; | |||
import org.apache.poi.hslf.usermodel.SlideShow; | |||
import org.apache.poi.POIDataSamples; | |||
import org.apache.poi.util.JvmBugs; | |||
import org.junit.Ignore; | |||
import org.junit.Test; | |||
/** | |||
* Test Picture shape. | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public final class TestPicture extends TestCase { | |||
public final class TestPicture { | |||
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); | |||
/** | |||
@@ -44,7 +56,8 @@ public final class TestPicture extends TestCase { | |||
* This is important when the same image appears multiple times in a slide show. | |||
* | |||
*/ | |||
public void testMultiplePictures() throws Exception { | |||
@Test | |||
public void multiplePictures() throws Exception { | |||
SlideShow ppt = new SlideShow(); | |||
Slide s = ppt.createSlide(); | |||
@@ -78,7 +91,8 @@ public final class TestPicture extends TestCase { | |||
* Picture#getEscherBSERecord threw NullPointerException if EscherContainerRecord.BSTORE_CONTAINER | |||
* was not found. The correct behaviour is to return null. | |||
*/ | |||
public void test46122() { | |||
@Test | |||
public void bug46122() { | |||
SlideShow ppt = new SlideShow(); | |||
Slide slide = ppt.createSlide(); | |||
@@ -92,7 +106,8 @@ public final class TestPicture extends TestCase { | |||
pict.draw(graphics); | |||
} | |||
public void testMacImages() throws Exception { | |||
@Test | |||
public void macImages() throws Exception { | |||
HSLFSlideShow hss = new HSLFSlideShow(_slTests.openResourceAsStream("53446.ppt")); | |||
PictureData[] pictures = hss.getPictures(); | |||
@@ -128,4 +143,47 @@ public final class TestPicture extends TestCase { | |||
} | |||
} | |||
} | |||
@Test | |||
@Ignore("Just for visual validation - antialiasing is different on various systems") | |||
public void bug54541() throws Exception { | |||
// InputStream xis = _slTests.openResourceAsStream("54542_cropped_bitmap.pptx"); | |||
// XMLSlideShow xss = new XMLSlideShow(xis); | |||
// xis.close(); | |||
// | |||
// Dimension xpg = xss.getPageSize(); | |||
// for(XSLFSlide slide : xss.getSlides()) { | |||
// BufferedImage img = new BufferedImage(xpg.width, xpg.height, BufferedImage.TYPE_INT_RGB); | |||
// Graphics2D graphics = img.createGraphics(); | |||
// fixFonts(graphics); | |||
// slide.draw(graphics); | |||
// ImageIO.write(img, "PNG", new File("testx.png")); | |||
// } | |||
// | |||
// System.out.println("########################"); | |||
InputStream is = _slTests.openResourceAsStream("54541_cropped_bitmap.ppt"); | |||
SlideShow ss = new SlideShow(is); | |||
is.close(); | |||
Dimension pg = ss.getPageSize(); | |||
int i=1; | |||
for(Slide slide : ss.getSlides()) { | |||
BufferedImage img = new BufferedImage(pg.width, pg.height, BufferedImage.TYPE_INT_RGB); | |||
Graphics2D graphics = img.createGraphics(); | |||
fixFonts(graphics); | |||
slide.draw(graphics); | |||
ImageIO.write(img, "PNG", new File("test"+(i++)+".png")); | |||
} | |||
} | |||
@SuppressWarnings("unchecked") | |||
private void fixFonts(Graphics2D graphics) { | |||
if (!JvmBugs.hasLineBreakMeasurerBug()) return; | |||
Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(TextPainter.KEY_FONTMAP); | |||
if (fontMap == null) fontMap = new HashMap<String,String>(); | |||
fontMap.put("Calibri", "Lucida Sans"); | |||
fontMap.put("Cambria", "Lucida Bright"); | |||
graphics.setRenderingHint(TextPainter.KEY_FONTMAP, fontMap); | |||
} | |||
} |